feat(unifi): implement comprehensive UniFi API client with controllers, protect, access, account, managers, resources, HTTP client, interfaces, logging, plugins, and tests

This commit is contained in:
2026-02-02 15:46:41 +00:00
parent aaa9e67835
commit 740b70cd83
38 changed files with 6275 additions and 15 deletions

168
ts/classes.doormanager.ts Normal file
View File

@@ -0,0 +1,168 @@
import type { UnifiAccess } from './classes.unifi-access.js';
import { UnifiDoor } from './classes.door.js';
import type { IAccessDoor, IAccessApiResponse, IAccessEvent } from './interfaces/index.js';
import { logger } from './unifi.logger.js';
/**
* Manager for UniFi Access doors
*/
export class DoorManager {
private access: UnifiAccess;
constructor(access: UnifiAccess) {
this.access = access;
}
/**
* List all doors
*/
public async listDoors(): Promise<UnifiDoor[]> {
logger.log('debug', 'Fetching doors from Access');
const response = await this.access.request<IAccessApiResponse<IAccessDoor[]>>(
'GET',
'/door'
);
const doors: UnifiDoor[] = [];
for (const doorData of response.data || []) {
doors.push(UnifiDoor.createFromApiObject(doorData, this.access));
}
logger.log('info', `Found ${doors.length} doors`);
return doors;
}
/**
* Get a door by ID
*/
public async getDoorById(doorId: string): Promise<UnifiDoor | null> {
logger.log('debug', `Fetching door: ${doorId}`);
try {
const response = await this.access.request<IAccessApiResponse<IAccessDoor>>(
'GET',
`/door/${doorId}`
);
return UnifiDoor.createFromApiObject(response.data, this.access);
} catch (error) {
logger.log('warn', `Door not found: ${doorId}`);
return null;
}
}
/**
* Find a door by name
*/
public async getDoorByName(name: string): Promise<UnifiDoor | null> {
const doors = await this.listDoors();
return doors.find(
(door) =>
door.name.toLowerCase() === name.toLowerCase() ||
door.alias?.toLowerCase() === name.toLowerCase()
) || null;
}
/**
* Get locked doors only
*/
public async getLockedDoors(): Promise<UnifiDoor[]> {
const doors = await this.listDoors();
return doors.filter((door) => door.isLocked());
}
/**
* Get unlocked doors only
*/
public async getUnlockedDoors(): Promise<UnifiDoor[]> {
const doors = await this.listDoors();
return doors.filter((door) => !door.isLocked());
}
/**
* Get open doors only
*/
public async getOpenDoors(): Promise<UnifiDoor[]> {
const doors = await this.listDoors();
return doors.filter((door) => door.isOpen());
}
/**
* Get doors by location
*/
public async getDoorsByLocation(locationId: string): Promise<UnifiDoor[]> {
const doors = await this.listDoors();
return doors.filter((door) => door.location_id === locationId);
}
/**
* Unlock a door by ID
*/
public async unlockDoor(doorId: string): Promise<void> {
logger.log('info', `Unlocking door: ${doorId}`);
await this.access.request('PUT', `/door/${doorId}/unlock`);
}
/**
* Lock a door by ID
*/
public async lockDoor(doorId: string): Promise<void> {
logger.log('info', `Locking door: ${doorId}`);
await this.access.request('PUT', `/door/${doorId}/lock`);
}
/**
* Unlock all doors
*/
public async unlockAllDoors(): Promise<void> {
logger.log('info', 'Unlocking all doors');
const doors = await this.listDoors();
await Promise.all(doors.map((door) => this.unlockDoor(door.unique_id)));
}
/**
* Lock all doors
*/
public async lockAllDoors(): Promise<void> {
logger.log('info', 'Locking all doors');
const doors = await this.listDoors();
await Promise.all(doors.map((door) => this.lockDoor(door.unique_id)));
}
/**
* Get access events for a door
*/
public async getDoorEvents(
doorId: string,
options: { start?: number; end?: number; limit?: number } = {}
): Promise<IAccessEvent[]> {
logger.log('debug', `Fetching events for door: ${doorId}`);
const params = new URLSearchParams();
params.append('door_id', doorId);
if (options.start) params.append('start', options.start.toString());
if (options.end) params.append('end', options.end.toString());
if (options.limit) params.append('limit', options.limit.toString());
const response = await this.access.request<IAccessApiResponse<IAccessEvent[]>>(
'GET',
`/event?${params.toString()}`
);
return response.data || [];
}
/**
* Update door settings
*/
public async updateDoor(doorId: string, settings: Partial<IAccessDoor>): Promise<void> {
logger.log('info', `Updating door: ${doorId}`);
await this.access.request('PUT', `/door/${doorId}`, settings);
}
}