import type { UnifiController } from './classes.unifi-controller.js'; import { UnifiDevice } from './classes.device.js'; import type { INetworkDevice, IUnifiApiResponse } from './interfaces/index.js'; import { logger } from './unifi.logger.js'; /** * Manager for UniFi network devices */ export class DeviceManager { private controller: UnifiController; constructor(controller: UnifiController) { this.controller = controller; } /** * List all devices for a site */ public async listDevices(siteId: string = 'default'): Promise { logger.log('debug', `Fetching devices for site: ${siteId}`); const response = await this.controller.request>( 'GET', `/api/s/${siteId}/stat/device` ); const devices: UnifiDevice[] = []; for (const deviceData of response.data || []) { devices.push(UnifiDevice.createFromApiObject(deviceData, this.controller, siteId)); } logger.log('info', `Found ${devices.length} devices`); return devices; } /** * Get a device by MAC address */ public async getDeviceByMac(mac: string, siteId: string = 'default'): Promise { const normalizedMac = mac.toLowerCase().replace(/[:-]/g, ':'); const devices = await this.listDevices(siteId); return devices.find((device) => device.mac.toLowerCase() === normalizedMac) || null; } /** * Get a device by ID */ public async getDeviceById(deviceId: string, siteId: string = 'default'): Promise { const devices = await this.listDevices(siteId); return devices.find((device) => device._id === deviceId) || null; } /** * Get access points only */ public async getAccessPoints(siteId: string = 'default'): Promise { const devices = await this.listDevices(siteId); return devices.filter((device) => device.isAccessPoint()); } /** * Get switches only */ public async getSwitches(siteId: string = 'default'): Promise { const devices = await this.listDevices(siteId); return devices.filter((device) => device.isSwitch()); } /** * Get gateways only */ public async getGateways(siteId: string = 'default'): Promise { const devices = await this.listDevices(siteId); return devices.filter((device) => device.isGateway()); } /** * Get devices with available upgrades */ public async getUpgradableDevices(siteId: string = 'default'): Promise { const devices = await this.listDevices(siteId); return devices.filter((device) => device.hasUpgrade()); } /** * Get offline devices */ public async getOfflineDevices(siteId: string = 'default'): Promise { const devices = await this.listDevices(siteId); return devices.filter((device) => !device.isOnline()); } /** * Restart a device by MAC */ public async restartDevice(mac: string, siteId: string = 'default'): Promise { logger.log('info', `Restarting device: ${mac}`); await this.controller.request( 'POST', `/api/s/${siteId}/cmd/devmgr`, { cmd: 'restart', mac: mac.toLowerCase(), } ); } /** * Upgrade a device's firmware */ public async upgradeDevice(mac: string, siteId: string = 'default'): Promise { logger.log('info', `Upgrading device: ${mac}`); await this.controller.request( 'POST', `/api/s/${siteId}/cmd/devmgr`, { cmd: 'upgrade', mac: mac.toLowerCase(), } ); } /** * Adopt a device */ public async adoptDevice(mac: string, siteId: string = 'default'): Promise { logger.log('info', `Adopting device: ${mac}`); await this.controller.request( 'POST', `/api/s/${siteId}/cmd/devmgr`, { cmd: 'adopt', mac: mac.toLowerCase(), } ); } /** * Forget a device (remove from controller) */ public async forgetDevice(mac: string, siteId: string = 'default'): Promise { logger.log('info', `Forgetting device: ${mac}`); await this.controller.request( 'POST', `/api/s/${siteId}/cmd/devmgr`, { cmd: 'delete-device', mac: mac.toLowerCase(), } ); } /** * Locate device (flash LEDs) */ public async locateDevice(mac: string, enabled: boolean, siteId: string = 'default'): Promise { logger.log('info', `${enabled ? 'Locating' : 'Stop locating'} device: ${mac}`); await this.controller.request( 'POST', `/api/s/${siteId}/cmd/devmgr`, { cmd: enabled ? 'set-locate' : 'unset-locate', mac: mac.toLowerCase(), } ); } /** * Force provision a device (push config) */ public async provisionDevice(mac: string, siteId: string = 'default'): Promise { logger.log('info', `Provisioning device: ${mac}`); await this.controller.request( 'POST', `/api/s/${siteId}/cmd/devmgr`, { cmd: 'force-provision', mac: mac.toLowerCase(), } ); } }