256 lines
5.9 KiB
TypeScript
256 lines
5.9 KiB
TypeScript
import type { UnifiController } from './classes.unifi-controller.js';
|
|
import type { INetworkDevice, IPortConfig } from './interfaces/index.js';
|
|
|
|
/**
|
|
* Represents a UniFi network device (AP, switch, gateway, etc.)
|
|
*/
|
|
export class UnifiDevice implements INetworkDevice {
|
|
/** Reference to parent controller */
|
|
private controller?: UnifiController;
|
|
/** Site ID for API calls */
|
|
private siteId?: string;
|
|
|
|
// INetworkDevice properties
|
|
public _id: string;
|
|
public mac: string;
|
|
public model: string;
|
|
public type: string;
|
|
public name?: string;
|
|
public site_id: string;
|
|
public adopted: boolean;
|
|
public ip: string;
|
|
public state: number;
|
|
public serial?: string;
|
|
public version?: string;
|
|
public uptime?: number;
|
|
public last_seen?: number;
|
|
public upgradable?: boolean;
|
|
public upgrade_to_firmware?: string;
|
|
public config_network?: {
|
|
type?: string;
|
|
ip?: string;
|
|
};
|
|
public ethernet_table?: Array<{
|
|
name: string;
|
|
mac: string;
|
|
num_port?: number;
|
|
}>;
|
|
public port_overrides?: Array<{
|
|
port_idx: number;
|
|
name?: string;
|
|
poe_mode?: string;
|
|
}>;
|
|
public sys_stats?: {
|
|
loadavg_1?: number;
|
|
loadavg_5?: number;
|
|
loadavg_15?: number;
|
|
mem_total?: number;
|
|
mem_used?: number;
|
|
};
|
|
public led_override?: string;
|
|
public led_override_color?: string;
|
|
public led_override_color_brightness?: number;
|
|
|
|
constructor() {
|
|
this._id = '';
|
|
this.mac = '';
|
|
this.model = '';
|
|
this.type = '';
|
|
this.site_id = '';
|
|
this.adopted = false;
|
|
this.ip = '';
|
|
this.state = 0;
|
|
}
|
|
|
|
/**
|
|
* Create a device instance from API response object
|
|
*/
|
|
public static createFromApiObject(
|
|
apiObject: INetworkDevice,
|
|
controller?: UnifiController,
|
|
siteId?: string
|
|
): UnifiDevice {
|
|
const device = new UnifiDevice();
|
|
Object.assign(device, apiObject);
|
|
device.controller = controller;
|
|
device.siteId = siteId || apiObject.site_id;
|
|
return device;
|
|
}
|
|
|
|
/**
|
|
* Get the raw API object representation
|
|
*/
|
|
public toApiObject(): INetworkDevice {
|
|
return {
|
|
_id: this._id,
|
|
mac: this.mac,
|
|
model: this.model,
|
|
type: this.type,
|
|
name: this.name,
|
|
site_id: this.site_id,
|
|
adopted: this.adopted,
|
|
ip: this.ip,
|
|
state: this.state,
|
|
serial: this.serial,
|
|
version: this.version,
|
|
uptime: this.uptime,
|
|
last_seen: this.last_seen,
|
|
upgradable: this.upgradable,
|
|
upgrade_to_firmware: this.upgrade_to_firmware,
|
|
config_network: this.config_network,
|
|
ethernet_table: this.ethernet_table,
|
|
port_overrides: this.port_overrides,
|
|
sys_stats: this.sys_stats,
|
|
led_override: this.led_override,
|
|
led_override_color: this.led_override_color,
|
|
led_override_color_brightness: this.led_override_color_brightness,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Check if device is online (state 1 = connected)
|
|
*/
|
|
public isOnline(): boolean {
|
|
return this.state === 1;
|
|
}
|
|
|
|
/**
|
|
* Check if device is an access point
|
|
*/
|
|
public isAccessPoint(): boolean {
|
|
return this.type === 'uap';
|
|
}
|
|
|
|
/**
|
|
* Check if device is a switch
|
|
*/
|
|
public isSwitch(): boolean {
|
|
return this.type === 'usw';
|
|
}
|
|
|
|
/**
|
|
* Check if device is a gateway/router
|
|
*/
|
|
public isGateway(): boolean {
|
|
return this.type === 'ugw' || this.type === 'udm';
|
|
}
|
|
|
|
/**
|
|
* Check if device has available firmware upgrade
|
|
*/
|
|
public hasUpgrade(): boolean {
|
|
return this.upgradable === true && !!this.upgrade_to_firmware;
|
|
}
|
|
|
|
/**
|
|
* Get device display name (name or MAC if no name)
|
|
*/
|
|
public getDisplayName(): string {
|
|
return this.name || this.mac;
|
|
}
|
|
|
|
/**
|
|
* Restart the device
|
|
*/
|
|
public async restart(): Promise<void> {
|
|
if (!this.controller || !this.siteId) {
|
|
throw new Error('Cannot restart device: no controller reference');
|
|
}
|
|
|
|
await this.controller.request(
|
|
'POST',
|
|
`/api/s/${this.siteId}/cmd/devmgr`,
|
|
{
|
|
cmd: 'restart',
|
|
mac: this.mac,
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Upgrade the device firmware
|
|
*/
|
|
public async upgrade(): Promise<void> {
|
|
if (!this.controller || !this.siteId) {
|
|
throw new Error('Cannot upgrade device: no controller reference');
|
|
}
|
|
|
|
await this.controller.request(
|
|
'POST',
|
|
`/api/s/${this.siteId}/cmd/devmgr`,
|
|
{
|
|
cmd: 'upgrade',
|
|
mac: this.mac,
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Set LED override
|
|
*/
|
|
public async setLedOverride(mode: 'default' | 'on' | 'off'): Promise<void> {
|
|
if (!this.controller || !this.siteId) {
|
|
throw new Error('Cannot set LED: no controller reference');
|
|
}
|
|
|
|
await this.controller.request(
|
|
'PUT',
|
|
`/api/s/${this.siteId}/rest/device/${this._id}`,
|
|
{
|
|
led_override: mode,
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Rename the device
|
|
*/
|
|
public async rename(newName: string): Promise<void> {
|
|
if (!this.controller || !this.siteId) {
|
|
throw new Error('Cannot rename device: no controller reference');
|
|
}
|
|
|
|
await this.controller.request(
|
|
'PUT',
|
|
`/api/s/${this.siteId}/rest/device/${this._id}`,
|
|
{
|
|
name: newName,
|
|
}
|
|
);
|
|
|
|
this.name = newName;
|
|
}
|
|
|
|
/**
|
|
* Set port configuration
|
|
*/
|
|
public async setPortConfig(portIdx: number, config: Partial<IPortConfig>): Promise<void> {
|
|
if (!this.controller || !this.siteId) {
|
|
throw new Error('Cannot set port config: no controller reference');
|
|
}
|
|
|
|
const portOverride = {
|
|
port_idx: portIdx,
|
|
...config,
|
|
};
|
|
|
|
// Get existing port overrides and update
|
|
const existingOverrides = this.port_overrides || [];
|
|
const overrideIndex = existingOverrides.findIndex((p) => p.port_idx === portIdx);
|
|
|
|
if (overrideIndex >= 0) {
|
|
existingOverrides[overrideIndex] = { ...existingOverrides[overrideIndex], ...portOverride };
|
|
} else {
|
|
existingOverrides.push(portOverride);
|
|
}
|
|
|
|
await this.controller.request(
|
|
'PUT',
|
|
`/api/s/${this.siteId}/rest/device/${this._id}`,
|
|
{
|
|
port_overrides: existingOverrides,
|
|
}
|
|
);
|
|
}
|
|
}
|