UNPKG

node-red-contrib-fibaro-devices

Version:
311 lines (280 loc) 12.3 kB
module.exports = function (RED) { function FibaroAPINode(config) { RED.nodes.createNode(this, config); var server = config.server; var serverConfig = RED.nodes.getNode(server); var fibaro = serverConfig.client; var node = this; var output_topic = ""; var nicknames = config.nicknames; node.initialized = false; node.status({}); if (serverConfig) { if (!serverConfig.validateConfig(node)) { node.error("Node has invalid configuration"); return } } else { node.error("Node configuration is not found!"); return } var sendEvent = function (deviceID, event) { var nicnameDeviceID = fibaro.translateDeviceID(deviceID, true); var items = fibaro.nodes.filter(o => String(o.deviceID) === String(deviceID) || String(o.deviceID) == nicnameDeviceID); items.forEach(item => { var node = RED.nodes.getNode(item.nodeId); if (node) { node.emit('event', event); } }); } const defaultPollerPeriod = 1; let pollerPeriod = config.pollingInterval ? parseInt(config.pollingInterval) : defaultPollerPeriod; if (isNaN(pollerPeriod) || pollerPeriod < 0 || pollerPeriod > 10) { pollerPeriod = defaultPollerPeriod; } // Fibaro API evensts fibaro.on('connected', function () { fibaro.sendRequest("/sections", function (sections) { node.send([null, { topic: "/sections", payload: sections }]); fibaro.sendRequest("/rooms", function (rooms) { fibaro.rooms = rooms; node.send([null, { topic: "/rooms", payload: rooms }]); fibaro.sendRequest("/devices", function (devices) { fibaro.devices = devices; node.send([null, { topic: "/devices", payload: devices }]); node.initialized = true; fibaro.isReady = true; }, (e) => node.error(e)) }, (e) => node.error(e)) }, (e) => node.error(e)) node.status({ fill: "green", shape: "dot", text: "connected" }); }); fibaro.on('nodeAdded', function (item) { var target = RED.nodes.getNode(item.nodeId); if (target) { var orgDeviceID = fibaro.translateDeviceID(item.deviceID); var initDeviceValues = function () { var dev = fibaro.devices.find(obj => { return obj.id == orgDeviceID }) if (typeof dev == 'undefined') { // device NOT FOUND?! return; } var currentState = dev.properties; if (target.customProperties) { var index; for (index = 0; index < target.customProperties.length; ++index) { var value = currentState[target.customProperties[index]]; let event = {}; event.topic = `${item.deviceID}`; event.init = true; event.payload = { property: target.customProperties[index], value: value, }; target.emit('event', event); // passthrough if (config.outputs > 0) { let msg = { topic: "DevicePropertyUpdatedEvent", payload: { id: nicknames ? fibaro.translateDeviceID(orgDeviceID, true) : orgDeviceID, property: target.customProperties[index], oldValue: null, // statup newValue: value, } } node.send(msg); } } } if (typeof currentState.value !== 'undefined') { let event = {}; event.topic = `${item.deviceID}`; event.init = true; event.payload = currentState.value; target.emit('event', event); // passthrough if (config.outputs > 0) { let msg = { topic: "DevicePropertyUpdatedEvent", payload: { id: nicknames ? fibaro.translateDeviceID(orgDeviceID, true) : orgDeviceID, property: "value", oldValue: null, // statup newValue: currentState.value, } } node.send(msg); } } } initDeviceValues(); } else { console.debug(`node not found: ${item.nodeId}`); } //console.debug(nodeId) //console.debug(deviceID) }); fibaro.on('failed', function (error) { node.initialized = false; node.status({ fill: 'red', shape: 'ring', text: `error: conection failed` }); node.error(error); if (error.error.code == 401) { // fatal node.status({ fill: 'red', shape: 'ring', text: `error: conection fatal.` }); return; } // trying to re-init again setTimeout(() => { node.status({ fill: 'yellow', shape: 'ring', text: 'force re-connection' }); fibaro.init(); }, 2000); }); fibaro.on('warn', function (warn) { node.warn(warn.text); }); fibaro.on('error', function (error) { if (node.initialized && error.error.code == 401) { node.initialized = false; } node.status({ fill: 'red', shape: 'ring', text: `error: ${error.text}` }); node.error(error); }); fibaro.on('done', function (nodeId) { // console.debug(`core asking to remove ${nodeId} node`); fibaro.removeDevice(nodeId); }); // handle all events. just ONLY for user purposes via MQTT! (output #1) fibaro.on('events', function (msg) { node.status({ fill: "green", shape: "dot", text: "ready" }); setTimeout(() => { node.status({}); }, 2000); // console.debug(msg); // internal post handling... var topic = msg.topic; var payload = msg.payload; try { payload = JSON.parse(payload); } catch (e) { // Ignore malformed } if (topic == "DevicePropertyUpdatedEvent") { if (payload.property) { let event = {}; event.topic = `${payload.id}`; if (payload.property == "value") { event.payload = payload.newValue; } else { event.payload = { property: payload.property, value: payload.newValue }; } // console.debug(event); sendEvent(payload.id, event); // // save state // if (payload.property == "value") { // fibaro.states[event.topic] = { newValue: msg.payload.newValue, oldValue: msg.payload.oldValue }; // } } } else if (topic == "CentralSceneEvent") { let event = {}; event.topic = `${payload.deviceId || payload.id}`; event.payload = { property: topic, value: payload }; // console.debug(event); sendEvent(event.topic, event); } else if (topic == "GlobalVariableChangedEvent") { let event = {}; event.topic = "GlobalVariableUpdatedEvent"; event.payload = payload; sendEvent(event.topic, event); } // passthrough if (config.outputs > 0) { if (nicknames) { if (topic == "DevicePropertyUpdatedEvent") { let nicknameID = fibaro.translateDeviceID(msg.payload.id, true); if (nicknameID) { msg.payload.id = nicknameID; } } if (topic == "CentralSceneEvent") { let nicknameID = fibaro.translateDeviceID(payload.deviceId || payload.id, true); if (nicknameID) { msg.payload.deviceId = nicknameID; } } } msg.topic = output_topic ? `${output_topic}/${msg.topic}` : msg.topic; node.send(msg); } }); // custom response data (output #2) fibaro.on('data', function (msg) { node.status({ fill: "green", shape: "dot", text: "OK" }); setTimeout(() => { node.status({}); }, 1000); //console.debug(msg); node.send([null, msg]); }); // node control node.on('input', function (msg) { if (!node.initialized) { return } // is mqtt message? if (msg.mqtt) { // parse evenets var updates = msg.payload; if (updates.events != undefined) { updates.events.map((s) => { if (s.type) { let event = {}; event.topic = s.type; event.payload = s.data; fibaro.emit('events', event); } }); } } else { // call API node.status({ fill: "blue", shape: "dot", text: "API..." }); fibaro.callAPI(msg.topic, msg.payload); } if (parseInt(msg.payload) === 0) { // TODO } }); var poll = function (onlyGlobals) { if (!node.initialized) { return } // just call poll for a new events fibaro.poll(onlyGlobals); } // init Fibaro connect node.status({ fill: 'yellow', shape: 'ring', text: 'connection...' }); fibaro.init(); if (this.poller) { clearTimeout(this.poller); } if (pollerPeriod != 0) { this.poller = setInterval(function () { poll(); }, pollerPeriod * 1000); } else { this.poller = setInterval(function () { poll(true); }, 1 * 1000); } this.on("close", function () { if (this.poller) { clearTimeout(this.poller); } if (fibaro != null) { fibaro.removeAllListeners(); } }); } RED.nodes.registerType("fibaroAPI", FibaroAPINode); }