189 lines
5.0 KiB
TypeScript
189 lines
5.0 KiB
TypeScript
|
|
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<UnifiDevice[]> {
|
||
|
|
logger.log('debug', `Fetching devices for site: ${siteId}`);
|
||
|
|
|
||
|
|
const response = await this.controller.request<IUnifiApiResponse<INetworkDevice>>(
|
||
|
|
'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<UnifiDevice | null> {
|
||
|
|
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<UnifiDevice | null> {
|
||
|
|
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<UnifiDevice[]> {
|
||
|
|
const devices = await this.listDevices(siteId);
|
||
|
|
return devices.filter((device) => device.isAccessPoint());
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get switches only
|
||
|
|
*/
|
||
|
|
public async getSwitches(siteId: string = 'default'): Promise<UnifiDevice[]> {
|
||
|
|
const devices = await this.listDevices(siteId);
|
||
|
|
return devices.filter((device) => device.isSwitch());
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get gateways only
|
||
|
|
*/
|
||
|
|
public async getGateways(siteId: string = 'default'): Promise<UnifiDevice[]> {
|
||
|
|
const devices = await this.listDevices(siteId);
|
||
|
|
return devices.filter((device) => device.isGateway());
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get devices with available upgrades
|
||
|
|
*/
|
||
|
|
public async getUpgradableDevices(siteId: string = 'default'): Promise<UnifiDevice[]> {
|
||
|
|
const devices = await this.listDevices(siteId);
|
||
|
|
return devices.filter((device) => device.hasUpgrade());
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get offline devices
|
||
|
|
*/
|
||
|
|
public async getOfflineDevices(siteId: string = 'default'): Promise<UnifiDevice[]> {
|
||
|
|
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<void> {
|
||
|
|
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<void> {
|
||
|
|
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<void> {
|
||
|
|
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<void> {
|
||
|
|
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<void> {
|
||
|
|
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<void> {
|
||
|
|
logger.log('info', `Provisioning device: ${mac}`);
|
||
|
|
|
||
|
|
await this.controller.request(
|
||
|
|
'POST',
|
||
|
|
`/api/s/${siteId}/cmd/devmgr`,
|
||
|
|
{
|
||
|
|
cmd: 'force-provision',
|
||
|
|
mac: mac.toLowerCase(),
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|