/** * Power Feature * Provides UPS/power monitoring and control capability */ import { Feature, type TDeviceReference } from './feature.abstract.js'; import type { TPowerProtocol, TPowerStatus, IBatteryInfo, IPowerInfo, IPowerFeatureInfo, IFeatureOptions, } from '../interfaces/feature.interfaces.js'; /** * Options for creating a PowerFeature */ export interface IPowerFeatureOptions extends IFeatureOptions { protocol: TPowerProtocol; hasBattery?: boolean; supportsShutdown?: boolean; supportsTest?: boolean; /** For NUT protocol: UPS name */ upsName?: string; /** For SNMP: community string */ community?: string; } /** * Power Feature - provides UPS/power monitoring and control * * Supports NUT (Network UPS Tools) and SNMP protocols for monitoring * UPS devices and smart power equipment. * * @example * ```typescript * const power = device.getFeature('power'); * if (power) { * const status = await power.getStatus(); * const battery = await power.getBatteryInfo(); * console.log(`Status: ${status}, Battery: ${battery.charge}%`); * } * ``` */ export class PowerFeature extends Feature { public readonly type = 'power' as const; public readonly protocol: TPowerProtocol; // Configuration public readonly upsName: string; public readonly community: string; // Capabilities public readonly hasBattery: boolean; public readonly supportsShutdown: boolean; public readonly supportsTest: boolean; // Current state protected _status: TPowerStatus = 'unknown'; protected _batteryCharge: number = 0; protected _batteryRuntime: number = 0; protected _load: number = 0; constructor( device: TDeviceReference, port: number, options: IPowerFeatureOptions ) { super(device, port, options); this.protocol = options.protocol; this.upsName = options.upsName ?? 'ups'; this.community = options.community ?? 'public'; this.hasBattery = options.hasBattery ?? true; this.supportsShutdown = options.supportsShutdown ?? false; this.supportsTest = options.supportsTest ?? false; } // ============================================================================ // Properties // ============================================================================ public get powerStatus(): TPowerStatus { return this._status; } public get batteryCharge(): number { return this._batteryCharge; } public get batteryRuntime(): number { return this._batteryRuntime; } public get load(): number { return this._load; } // ============================================================================ // Connection // ============================================================================ protected async doConnect(): Promise { // Protocol-specific connection would be implemented here // For now, just verify the port is reachable } protected async doDisconnect(): Promise { // Protocol-specific disconnection } // ============================================================================ // Status Monitoring // ============================================================================ /** * Get current power status */ public async getStatus(): Promise { // Protocol-specific implementation would fetch status return this._status; } /** * Get battery information */ public async getBatteryInfo(): Promise { return { charge: this._batteryCharge, runtime: this._batteryRuntime, }; } /** * Get power information */ public async getPowerInfo(): Promise { return { load: this._load, }; } // ============================================================================ // Control Commands // ============================================================================ /** * Initiate shutdown */ public async shutdown(delay?: number): Promise { if (!this.supportsShutdown) { throw new Error('Shutdown not supported'); } this.emit('power:shutdown', { delay }); } /** * Start battery test */ public async testBattery(): Promise { if (!this.supportsTest) { throw new Error('Battery test not supported'); } this.emit('power:test:started'); } // ============================================================================ // State Updates // ============================================================================ protected updateStatus(status: TPowerStatus): void { const oldStatus = this._status; this._status = status; if (oldStatus !== status) { this.emit('power:status:changed', { oldStatus, newStatus: status }); // Emit specific events if (status === 'onbattery') { this.emit('power:onbattery'); } else if (status === 'online' && oldStatus === 'onbattery') { this.emit('power:restored'); } else if (status === 'lowbattery') { this.emit('power:lowbattery'); } } } protected updateBattery(charge: number, runtime: number): void { const oldCharge = this._batteryCharge; this._batteryCharge = charge; this._batteryRuntime = runtime; if (oldCharge !== charge) { this.emit('battery:changed', { charge, runtime }); } } // ============================================================================ // Serialization // ============================================================================ public getFeatureInfo(): IPowerFeatureInfo { return { ...this.getBaseFeatureInfo(), type: 'power', protocol: this.protocol, hasBattery: this.hasBattery, supportsShutdown: this.supportsShutdown, supportsTest: this.supportsTest, }; } // ============================================================================ // Static Factory // ============================================================================ public static fromDiscovery( device: TDeviceReference, port: number, protocol: TPowerProtocol, metadata: Record ): PowerFeature { return new PowerFeature(device, port, { protocol, upsName: metadata.upsName as string, hasBattery: metadata.hasBattery as boolean ?? true, supportsShutdown: metadata.supportsShutdown as boolean ?? false, supportsTest: metadata.supportsTest as boolean ?? false, }); } }