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 { logger.log('debug', 'Fetching doors from Access'); const response = await this.access.request>( '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 { logger.log('debug', `Fetching door: ${doorId}`); try { const response = await this.access.request>( '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 { 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 { const doors = await this.listDoors(); return doors.filter((door) => door.isLocked()); } /** * Get unlocked doors only */ public async getUnlockedDoors(): Promise { const doors = await this.listDoors(); return doors.filter((door) => !door.isLocked()); } /** * Get open doors only */ public async getOpenDoors(): Promise { const doors = await this.listDoors(); return doors.filter((door) => door.isOpen()); } /** * Get doors by location */ public async getDoorsByLocation(locationId: string): Promise { const doors = await this.listDoors(); return doors.filter((door) => door.location_id === locationId); } /** * Unlock a door by ID */ public async unlockDoor(doorId: string): Promise { 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 { logger.log('info', `Locking door: ${doorId}`); await this.access.request('PUT', `/door/${doorId}/lock`); } /** * Unlock all doors */ public async unlockAllDoors(): Promise { 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 { 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 { 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>( 'GET', `/event?${params.toString()}` ); return response.data || []; } /** * Update door settings */ public async updateDoor(doorId: string, settings: Partial): Promise { logger.log('info', `Updating door: ${doorId}`); await this.access.request('PUT', `/door/${doorId}`, settings); } }