homebridge-hca
Version:
HCA plugin for Homebridge
134 lines (101 loc) • 3.78 kB
JavaScript
// 'use strict';
const inherits = require('util').inherits;
const AccessoryBase = require('../AccessoryBase');
const itemType = require('node-hca/lib/Design/itemType');
class HcaSwitch extends AccessoryBase {
constructor(log, item, client) {
super(log, item, client);
}
// TODO: Move outside of class so it's callable when restored.
identify(paired, callback) {
const item = this.context.item;
this.log.info('Identifying %s (%s).', this.displayName, item.id);
callback();
}
}
function init(accessory) {
const service =
accessory.getService(Service.Switch) ||
accessory.addService(Service.Switch, accessory.displayName);
service
.getCharacteristic(Characteristic.On)
.onGet(getPowerState.bind(accessory))
.onSet(setPowerState.bind(accessory));
bindUpdates(accessory);
}
// Inform HomeKit about changes that occurred outside of HomeKit
function bindUpdates(accessory) {
const item = accessory.context.item;
accessory.client.designManager
.on('Design:Updated:' + item.id, function (e) {
const lastKnownState = accessory.context.lastKnownState;
const currentState = item.state;
// Ignore duplicate messages. (HCA may send the same message when device or room state changes, based on a change from the other).
if (lastKnownState === currentState) return;
accessory.context.lastKnownState = currentState;
const isReachable = e.errorState == 0;
let isOn = item.state > 0;
// programs require additional evaluation
if (item.type == itemType.program && item.currentIconName.length > 0) {
isOn = parseInt(item.currentIconRepresentation) > 0;
}
accessory.log.debug('%s (%s) has been updated:', accessory.displayName, item.id, JSON.stringify(item));
if (!isReachable)
accessory.log.warn('%s (%s) did not acknowledge receipt of this request.', accessory.displayName, item.id)
accessory.log.info("%s (%s) has been turned %s.", accessory.displayName, item.id, isOn ? "on" : "off");
accessory.log.debug('Updating %s (%s) power state to \'%s\'.', accessory.displayName, item.id, isOn);
accessory
.getService(Service.Switch)
.getCharacteristic(Characteristic.On)
.updateValue(isOn);
});
}
async function getPowerState() {
const accessory = this;
const item = accessory.context.item;
const isOn = item.state > 0;
accessory.log.debug("%s (%s) is %s.", accessory.displayName, item.id, isOn ? "on" : "off");
return Promise.resolve(isOn);
}
async function setPowerState(value) {
const accessory = this;
const item = accessory.context.item;
const currentState = item.state > 0;
const targetState = Boolean(value);
const typeName = getTypeName(item);
const command = targetState == true ? `${typeName}.On` : `${typeName}.Off`;
const params = ['HCAObject', command, item.id];
accessory.log.info("Turning %s (%s) %s.", accessory.displayName, item.id, targetState ? "on" : "off");
accessory.client.send(params);
return Promise.resolve();
}
function getTypeName(item) {
let typeName;
switch (item.type) {
case itemType.device:
typeName = 'Device';
break;
case itemType.program:
typeName = 'Program';
break;
case itemType.group:
typeName = 'Group';
break;
case itemType.controller:
typeName = 'Controller';
break;
default:
break;
}
return typeName;
}
module.exports = function (accessory, service, characteristic, ouuid) {
this.Accessory = accessory;
this.Service = service;
this.Characteristic = characteristic;
this.uuid = ouuid;
inherits(HcaSwitch, Accessory);
return HcaSwitch;
};
module.exports.HcaSwitch = HcaSwitch;
module.exports.HcaSwitch.init = init;