homebridge-hca
Version:
HCA plugin for Homebridge
157 lines (115 loc) • 4.71 kB
JavaScript
// 'use strict';
const inherits = require('util').inherits;
const AccessoryBase = require('../AccessoryBase');
class HcaFan 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).', item.name, item.id);
callback();
}
}
function init(accessory) {
const item = accessory.context.item;
const service =
accessory.getService(Service.Fan) ||
accessory.addService(Service.Fan, accessory.displayName);
service
.getCharacteristic(Characteristic.On)
.onGet(getPowerState.bind(accessory))
.onSet(setPowerState.bind(accessory));
if (item.isDimmable) {
service
.getCharacteristic(Characteristic.RotationSpeed)
.onGet(getRotationSpeed.bind(accessory))
.onSet(setRotationSpeed.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;
const isOn = item.state > 0;
const rotationSpeed = item.state;
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.Fan)
.getCharacteristic(Characteristic.On)
.updateValue(isOn);
if (item.isDimmable) {
accessory.log.debug('Updating %s (%s) rotation speed to \'%s\'.', accessory.displayName, item.id, rotationSpeed);
accessory
.getService(Service.Fan)
.getCharacteristic(Characteristic.RotationSpeed)
.updateValue(rotationSpeed);
}
});
}
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);
// prevent excessive updates when changing rotation speed
if (currentState === targetState) {
return Promise.resolve();
}
const command = targetState == true ? 'Device.On' : 'Device.Off',
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();
}
async function getRotationSpeed() {
const accessory = this;
const item = accessory.context.item;
accessory.log.debug("%s (%s) speed is %s.", accessory.displayName, item.id, item.state);
return Promise.resolve(item.state);
}
async function setRotationSpeed(value) {
const accessory = this;
const item = accessory.context.item;
const targetSpeed = value;
// const targetSpeed = Math.ceil(value / 25) * 25; // 0, 25, 50, 75, or 100
// if (item.state == targetSpeed) { // prevent excessive updates
// accessory.log.warn("Ignoring request. %s (%s) is already set to speed %s.", accessory.displayName, item.id, targetSpeed)
// callback();
// return;
// }
accessory.log.info("Setting %s (%s) speed to %s.", accessory.displayName, item.id, targetSpeed);
const params = ['HCAObject', 'Device.DimToPercent', item.id, targetSpeed];
accessory.client.send(params);
return Promise.resolve();
}
module.exports = function (accessory, service, characteristic, ouuid) {
this.Accessory = accessory;
this.Service = service;
this.Characteristic = characteristic;
this.uuid = ouuid;
inherits(HcaFan, Accessory);
return HcaFan;
};
module.exports.HcaFan = HcaFan;
module.exports.HcaFan.init = init;