UNPKG

node-red-contrib-knx-ultimate

Version:

Control your KNX and KNX Secure intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control and ETS group address importer. Easy to use and highly configurable.

144 lines (126 loc) 6.1 kB
module.exports = function (RED) { function knxUltimateHueLightSensor(config) { RED.nodes.createNode(this, config); const node = this; node.serverKNX = RED.nodes.getNode(config.server) || undefined; node.serverHue = RED.nodes.getNode(config.serverHue) || undefined; node.topic = node.name; node.name = config.name === undefined ? 'Hue' : config.name; node.dpt = ''; node.notifyreadrequest = true; node.notifyreadrequestalsorespondtobus = 'false'; node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''; node.notifyresponse = false; node.notifywrite = true; node.initialread = true; node.listenallga = true; // Don't remove node.outputtype = 'write'; node.outputRBE = 'false'; // Apply or not RBE to the output (Messages coming from flow) node.inputRBE = 'false'; // Apply or not RBE to the input (Messages coming from BUS) node.currentPayload = ''; // Current value for the RBE input and for the .previouspayload msg node.passthrough = 'no'; node.formatmultiplyvalue = 1; node.formatnegativevalue = 'leave'; node.formatdecimalsvalue = 2; node.hueDevice = config.hueDevice; node.initializingAtStart = (config.readStatusAtStartup === undefined || config.readStatusAtStartup === "yes"); node.currentDeviceValue = 0; // Used to call the status update from the config node. node.setNodeStatus = ({ fill, shape, text, payload, }) => { try { if (payload === undefined) payload = ''; const dDate = new Date(); payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString(); node.sKNXNodeStatusText = `|KNX: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`; node.status({ fill, shape, text: (node.sHUENodeStatusText || '') + ' ' + (node.sKNXNodeStatusText || '') }); } catch (error) { } }; // Used to call the status update from the HUE config node. node.setNodeStatusHue = ({ fill, shape, text, payload }) => { try { if (payload === undefined) payload = ''; const dDate = new Date(); payload = typeof payload === "object" ? JSON.stringify(payload) : payload.toString(); node.sHUENodeStatusText = `|HUE: ${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})`; node.status({ fill, shape, text: node.sHUENodeStatusText + ' ' + (node.sKNXNodeStatusText || '') }); } catch (error) { } }; // This function is called by the knx-ultimate config node, to output a msg.payload. node.handleSend = msg => { // Respond to KNX read telegram, by sending the current value as response telegram. if (msg.knx.event === "GroupValue_Read") { switch (msg.knx.destination) { case config.GAlightsensor: // To the KNX bus wires node.sendResponseToKNX(node.currentDeviceValue); break; default: break; } } }; node.handleSendHUE = _event => { try { if (_event.id === config.hueDevice) { if (!_event.hasOwnProperty('light') || _event.light.light_level === undefined) return; const knxMsgPayload = {}; knxMsgPayload.topic = config.GAlightsensor; knxMsgPayload.dpt = config.dptlightsensor; if (_event.hasOwnProperty('light') && _event.light.hasOwnProperty('light_level')) { //console.log(Math.round(10 ** ((_event.light.light_level - 1) / 10000))) //console.log(_event.light.light_level === 0 ? 0 : Math.round(Math.pow(10, (_event.light.light_level - 1) / 10000))) knxMsgPayload.payload = _event.light.light_level === 0 ? 0 : Math.round(Math.pow(10, (_event.light.light_level - 1) / 10000)); // Send to KNX bus if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id }); node.currentDeviceValue = knxMsgPayload.payload; node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX ' + JSON.stringify(knxMsgPayload.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' }); // Setup the output msg knxMsgPayload.name = node.name; knxMsgPayload.event = 'light_level'; // Send payload knxMsgPayload.rawEvent = _event; node.send(knxMsgPayload); node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload }); } } } catch (error) { node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' }); } }; node.sendResponseToKNX = (_level) => { const knxMsgPayload = {}; knxMsgPayload.topic = config.GAlightsensor; knxMsgPayload.dpt = config.dptlightsensor; knxMsgPayload.payload = _level; // Send to KNX bus if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) { node.serverKNX.sendKNXTelegramToKNXEngine({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'response', nodecallerid: node.id, }); } }; // On each deploy, unsubscribe+resubscribe if (node.serverKNX) { node.serverKNX.removeClient(node); node.serverKNX.addClient(node); } if (node.serverHue) { node.serverHue.removeClient(node); node.serverHue.addClient(node); } node.on('input', function (msg) { }); node.on('close', function (done) { if (node.serverKNX) { node.serverKNX.removeClient(node); } if (node.serverHue) { node.serverHue.removeClient(node); } done(); }); } RED.nodes.registerType('knxUltimateHueLightSensor', knxUltimateHueLightSensor); };