homebridge-sensor-cmd-polling
Version:
Fork of apexad/homebridge-sensor-cmd with automatic polling support (configurable interval) – original minimal contact sensor via shell command
96 lines • 3.6 kB
JavaScript
"use strict";
const child_process_1 = require("child_process");
let hap;
class SensorCmd {
constructor(log, config) {
this.log = log;
this.config = config;
// Determine which sensor type to create
switch (this.config.type) {
case "motion":
this.sensorService = new hap.Service.MotionSensor(this.config.name);
break;
case "occupancy":
this.sensorService = new hap.Service.OccupancySensor(this.config.name);
break;
case "contact":
default:
this.sensorService = new hap.Service.ContactSensor(this.config.name);
}
// Register the on-demand GET handler
const characteristic = this.getRelevantCharacteristic();
characteristic.on("get" /* GET */, (callback) => {
this.runCommand((err, value) => callback(null, err ? 0 : value));
});
// Accessory info
this.infoService = new hap.Service.AccessoryInformation()
.setCharacteristic(hap.Characteristic.Manufacturer, 'apexad')
.setCharacteristic(hap.Characteristic.Model, 'sensor-cmd');
// Polling interval (default 60s)
this.pollingInterval = this.config.pollingInterval ? this.config.pollingInterval : 60;
if (this.pollingInterval > 0) {
this.log(`Starting automatic polling every ${this.pollingInterval}s`);
this.startPolling();
}
}
/** Get the correct characteristic based on sensor type */
getRelevantCharacteristic() {
switch (this.config.type) {
case "motion":
return this.sensorService.getCharacteristic(hap.Characteristic.MotionDetected);
case "occupancy":
return this.sensorService.getCharacteristic(hap.Characteristic.OccupancyDetected);
case "contact":
default:
return this.sensorService.getCharacteristic(hap.Characteristic.ContactSensorState);
}
}
/** Run the configured command and return parsed result */
runCommand(callback) {
child_process_1.exec(this.config.command, (err, stdout) => {
if (err) {
this.log(`Command failed: ${err.message}`);
callback(true, 0);
return;
}
let parsed = parseInt(stdout.trim(), 10);
if (isNaN(parsed))
parsed = 0;
callback(false, parsed);
});
}
/** Start polling periodically */
startPolling() {
const characteristic = this.getRelevantCharacteristic();
const poll = () => {
this.runCommand((err, value) => {
if (!err) {
this.log(`Polled value: ${value}`);
characteristic.updateValue(value);
}
else {
this.log(`Polling error, keeping previous value`);
}
});
};
// Initial poll
poll();
// Set recurring interval
this.pollingTimer = setInterval(poll, this.pollingInterval * 1000);
}
/** Clean up when accessory is unloaded */
shutdown() {
if (this.pollingTimer) {
clearInterval(this.pollingTimer);
this.pollingTimer = undefined;
}
}
getServices() {
return [this.infoService, this.sensorService];
}
}
module.exports = (api) => {
hap = api.hap;
api.registerAccessory('SensorCmd', SensorCmd);
};
//# sourceMappingURL=accessory.js.map