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, ETS group address importer, and KNX routing between interfaces. Easy to use and highly configurable.

183 lines (167 loc) 7.08 kB
module.exports = function (RED) { function knxUltimateHueZigbeeConnectivity (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 const pinsSetting = (config.enableNodePINS === undefined || config.enableNodePINS === 'yes' || config.enableNodePINS === true) node.enableNodePINS = pinsSetting ? 'yes' : 'no' node.outputs = pinsSetting ? 1 : 0 if (!node.serverKNX && node.outputs === 0) { node.enableNodePINS = 'yes' node.outputs = 1 } const pushStatus = (status) => { if (!status) return const provider = node.serverKNX if (provider && typeof provider.applyStatusUpdate === 'function') { provider.applyStatusUpdate(node, status) } else { node.status(status) } } const updateStatus = (status) => { if (!status) return pushStatus(status) } const formatTs = (date) => { const d = date instanceof Date ? date : new Date(date) const provider = node.serverKNX if (provider && typeof provider.formatStatusTimestamp === 'function') return provider.formatStatusTimestamp(d) return `${d.getDate()}, ${d.toLocaleTimeString()}` } const safeSendToKNX = (telegram, context = 'write') => { try { if (!node.serverKNX || typeof node.serverKNX.sendKNXTelegramToKNXEngine !== 'function') { const now = new Date() updateStatus({ fill: 'red', shape: 'dot', text: `KNX server missing (${context}) (${formatTs(now)})` }) return } node.serverKNX.sendKNXTelegramToKNXEngine({ ...telegram, nodecallerid: node.id }) } catch (error) { updateStatus({ fill: 'red', shape: 'dot', text: `KNX send error ${error.message}` }) } } // 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} (${formatTs(dDate)})` pushStatus({ 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} (${formatTs(dDate)})` pushStatus({ 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.GAzigbeeconnectivity: // To the KNX bus wires node.sendResponseToKNX(node.currentDeviceValue) break default: break } } } node.handleSendHUE = (_event) => { try { // Event status: one of connected, disconnected, connectivity_issue, unidirectional_incoming if (_event.id === config.hueDevice) { if (!_event.hasOwnProperty('status') || _event.status === undefined) return const knxMsgPayload = {} knxMsgPayload.topic = config.GAzigbeeconnectivity knxMsgPayload.dpt = config.dptzigbeeconnectivity knxMsgPayload.payload = (_event.status === 'connected') // Send to KNX bus if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) { safeSendToKNX({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write' }, 'write') } node.currentDeviceValue = knxMsgPayload.payload // Setup the output msg knxMsgPayload.name = node.name knxMsgPayload.status = _event.status knxMsgPayload.event = 'zigbee_connectivity' // Send payload knxMsgPayload.rawEvent = _event node.send(knxMsgPayload) node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload }) } } catch (error) { updateStatus({ fill: 'red', shape: 'dot', text: `HUE->KNX error ${error.message} (${formatTs(new Date())})` }) } } node.sendResponseToKNX = (_level) => { const knxMsgPayload = {} knxMsgPayload.topic = config.GAzigbeeconnectivity knxMsgPayload.dpt = config.dptzigbeeconnectivity knxMsgPayload.payload = _level // Send to KNX bus if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) { safeSendToKNX({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'response' }, 'response') } } // 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', (msg) => { }) node.on('close', (done) => { if (node.serverKNX) { node.serverKNX.removeClient(node) } if (node.serverHue) { node.serverHue.removeClient(node) } done() }) } RED.nodes.registerType('knxUltimateHueZigbeeConnectivity', knxUltimateHueZigbeeConnectivity) }