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:
168
ts/classes.doormanager.ts
Normal file
168
ts/classes.doormanager.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user