UNPKG

@ronniepettersson/homebridge-dummy

Version:

Create Homebridge accessories to help with automation and control — scheduling, delays, sensors, commands, webhooks, and more

138 lines 5.47 kB
import { exec } from 'child_process'; import { promisify } from 'util'; import { PLATFORM_NAME, PLUGIN_ALIAS } from '../homebridge/settings.js'; import { SensorAccessory } from './sensor.js'; import { strings } from '../i18n/i18n.js'; import { AccessoryType } from '../model/enums.js'; import Limiter from '../timeout/limiter.js'; import { Schedule } from '../timeout/schedule.js'; import { Timer } from '../timeout/timer.js'; import getVersion from '../tools/version.js'; export class DummyAccessory { Service; Characteristic; accessory; config; log; sensor; static identifier(config) { return config.id ?? `${PLATFORM_NAME}:${config.type}:${config.name.replace(/\s+/g, '')}`; } accessoryService; _schedule; _timer; _limiter; execAsync = promisify(exec); constructor(Service, Characteristic, accessory, config, log, isGrouped) { this.Service = Service; this.Characteristic = Characteristic; this.accessory = accessory; this.config = config; this.log = log; this.sensor = SensorAccessory.new(Service, Characteristic, accessory, this.name, log, this.config.disableLogging === true, config.sensor); if (config.timer) { this._timer = Timer.new(config.timer, this.identifier, config.name, log, config.disableLogging === true); } if (config.schedule) { this._schedule = Schedule.new(config.schedule, config.name, log, config.disableLogging === true, this.schedule.bind(this)); } if (config.limiter) { this._limiter = Limiter.new(config.limiter, config.name, log, config.disableLogging === true); } const serviceInstance = Service[this.getAccessoryType()]; if (isGrouped) { let accessoryService = accessory.getServiceById(serviceInstance, this.identifier); if (!accessoryService) { accessoryService = accessory.addService(serviceInstance, config.name, this.identifier); accessoryService.setCharacteristic(Characteristic.ConfiguredName, config.name); } this.accessoryService = accessoryService; return; } accessory.getService(Service.AccessoryInformation) .setCharacteristic(Characteristic.Name, config.name) .setCharacteristic(Characteristic.ConfiguredName, config.name) .setCharacteristic(Characteristic.Manufacturer, PLUGIN_ALIAS) .setCharacteristic(Characteristic.Model, config.type) .setCharacteristic(Characteristic.SerialNumber, this.identifier) .setCharacteristic(Characteristic.FirmwareRevision, getVersion()); this.accessoryService = accessory.getService(serviceInstance) || accessory.addService(serviceInstance); for (const type of Object.values(AccessoryType)) { const existingService = accessory.getService(Service[type]); if (existingService && type !== this.getAccessoryType()) { accessory.removeService(existingService); } } } get subtype() { return this.accessoryService.subtype; } teardown() { this._timer?.teardown(); this._schedule?.teardown(); this._limiter?.teardown(); } get identifier() { return DummyAccessory.identifier(this.config); } get name() { return this.config.name; } get isStateful() { return this._schedule === undefined && !this.config.resetOnRestart; } get defaultStateStorageKey() { return `${this.identifier}:DefaultState`; } startTimer() { this._timer?.start(this.reset.bind(this)); this._limiter?.start(this.reset.bind(this)); } cancelTimer() { this._timer?.cancel(); this._limiter?.cancel(); } async executeCommand(command) { try { const { stdout } = await this.execAsync(command); const output = stdout.trim(); if (output) { this.logIfDesired(`${strings.command.executed}: %s\n%s`, command, output); } } catch (err) { if (!this.isExecException(err)) { const message = err instanceof Error ? err.message : JSON.stringify(err); this.log.error(`${strings.command.error}: %s`, this.name, message); return; } const exitCode = err.code ?? -1; const output = (err.stdout ?? '').trim(); const error = (err.stderr ?? '').trim(); if (exitCode === 0) { if (output) { this.logIfDesired(`${strings.command.executed}: %s\n%s`, command, output); } } else { this.log.error(`${strings.command.error}: %s (%s)`, this.name, command, exitCode, error ? `\n${error}` : undefined); } } } isExecException(err) { return err instanceof Error && 'code' in err && typeof err.code === 'number' && 'stdout' in err && typeof err.stdout === 'string' && 'stderr' in err && typeof err.stderr === 'string'; } logIfDesired(message, ...parameters) { if (this.config.disableLogging) { return; } this.log.always(message, this.name, ...parameters); } } //# sourceMappingURL=base.js.map