UNPKG

redmatic-homekit

Version:

HAP-Nodejs based Node-RED nodes to create HomeKit Accessories

182 lines (153 loc) 6.77 kB
/* eslint-disable no-new */ const Accessory = require('./accessory'); function createService(channel) { let intermediatePosition; // 0-100 let LEVEL = 0; // 0.0-1.0 let LEVEL_2 = 0; // 0.0-1.0 const channelIndex = channel.channel.split(':')[1]; this.ccu.subscribe({ datapointName: this.config.deviceAddress + ':' + channelIndex + '.LEVEL', cache: true, stable: false }, msg => { intermediatePosition = msg.value * 100; }); const service = this.addService('WindowCovering', channel.name, channelIndex); service .get('CurrentPosition', this.config.deviceAddress + ':' + channelIndex + '.LEVEL', value => { LEVEL = value; intermediatePosition = value * 100; return LEVEL * 100; }) .get('TargetPosition', this.config.deviceAddress + ':' + channelIndex + '.LEVEL', value => { if (typeof LEVEL === 'undefined') { LEVEL = value; } return LEVEL * 100; }) .set('TargetPosition', (value, callback) => { LEVEL = value / 100; if (value === 0 && intermediatePosition === 0) { intermediatePosition = 1; } else if (value === 100 && intermediatePosition === 100) { intermediatePosition = 99; } this.node.debug(channel.name + ' intermediatePosition ' + intermediatePosition); service.update('CurrentPosition', intermediatePosition); const params = { LEVEL }; if (channel.tilt) { params.LEVEL_2 = LEVEL_2; } if (channel.tilt || this.config.type === 'BLIND_VIRTUAL_RECEIVER') { if (LEVEL === 0) { params.LEVEL_2 = 0; } if (LEVEL === 1) { params.LEVEL_2 = 1; } } this.node.debug('set ' + this.config.name + ' (WindowCovering) TargetPosition ' + value + ' -> ' + this.config.description.ADDRESS + ':' + channelIndex + ' ' + JSON.stringify(params)); this.ccu.methodCall(this.config.iface, 'putParamset', [this.config.description.ADDRESS + ':' + channelIndex, 'VALUES', params]) .then(() => { callback(); }) .catch(() => { callback(new Error(this.hap.HAPServer.Status.SERVICE_COMMUNICATION_FAILURE)); }); }) .get('PositionState', this.config.deviceAddress + ':' + channelIndex + '.ACTIVITY_STATE', (value, c) => { switch (value) { case 1: return c.INCREASING; case 2: return c.DECREASING; default: return c.STOPPED; } }); if (channel.tilt) { service .get('CurrentVerticalTiltAngle', this.config.deviceAddress + ':' + channelIndex + '.LEVEL_2', value => { LEVEL_2 = value; value = (value * 180) - 90; this.node.debug('get CurrentVerticalTiltAngle ' + this.config.name + ' LEVEL_2 ' + LEVEL_2 + ' ' + value); return value; }) .get('TargetVerticalTiltAngle', this.config.deviceAddress + ':' + channelIndex + '.LEVEL_2', value => { LEVEL_2 = value; value = (value * 180) - 90; this.node.debug('get TargetVerticalTiltAngle ' + this.config.name + ' LEVEL_2 ' + LEVEL_2 + ' ' + value); return value; }) .set('TargetVerticalTiltAngle', (value, callback) => { LEVEL_2 = (value + 90) / 180; this.node.debug('set TargetVerticalTiltAngle ' + this.config.name + ' LEVEL_2 ' + LEVEL_2 + ' ' + value); const params = { LEVEL, LEVEL_2 }; this.node.debug('set ' + channel.name + ' (WindowCovering) TargetVerticalTiltAngle ' + value + ' -> ' + this.config.description.ADDRESS + ':' + channelIndex + ' ' + JSON.stringify(params)); this.ccu.methodCall(this.config.iface, 'putParamset', [this.config.description.ADDRESS + ':' + channelIndex, 'VALUES', params]) .then(() => { callback(); }) .catch(() => { callback(new Error(this.hap.HAPServer.Status.SERVICE_COMMUNICATION_FAILURE)); }); }); } } class GenericHmipBlindAcc extends Accessory { constructor(config, node, channels) { super(config, node); this.channels = channels; node.debug('creating accessory for ' + channels.length + ' channels'); } init() { this.channels.forEach(channel => { createService.call(this, channel); }); } } class GenericHmipBlind { constructor(config, node) { const {ccu} = node; this.ccu = ccu; this.config = config; let acc = 0; let pos = 0; const channels = []; this.config.description.CHILDREN.forEach(channel => { const desc = this.ccu.metadata.devices['HmIP-RF'][channel]; if (desc.TYPE === 'BLIND_VIRTUAL_RECEIVER' || desc.TYPE === 'SHUTTER_VIRTUAL_RECEIVER') { if (!channels[acc]) { channels[acc] = []; } const name = this.ccu.channelNames[channel]; const tilt = desc.TYPE === 'BLIND_VIRTUAL_RECEIVER' && (!this.config.options[channel] || this.config.options[channel].type !== 'VerticalTilt Disabled'); if (pos === 0) { if (!this.config.options[channel] || !this.config.options[channel].disabled) { channels[acc].push({channel, name, tilt}); } } else if (this.config.options[channel] && this.config.options[channel].enabled) { channels[acc].push({channel, name, tilt, type: desc.TYPE}); } if (++pos > 2) { pos = 0; acc += 1; } } }); channels.forEach(accChannels => { if (accChannels.length > 0) { const conf = Object.assign({}, config, {name: accChannels[0].name}); conf.description = Object.assign({}, config.description, {ADDRESS: accChannels[0].channel}); new GenericHmipBlindAcc(conf, node, accChannels); } }); } } module.exports = GenericHmipBlind;