@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
JavaScript
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