diff --git a/node-red-contrib-xiaomi-gateway/xiaomi-gateway.js b/node-red-contrib-xiaomi-gateway/xiaomi-gateway.js index 112e0af..d041e9a 100644 --- a/node-red-contrib-xiaomi-gateway/xiaomi-gateway.js +++ b/node-red-contrib-xiaomi-gateway/xiaomi-gateway.js @@ -56,7 +56,12 @@ module.exports = function(RED) { server.on('message', function (message, remote) { var msg; if(remote.address == node.addr) { - msg = { payload: JSON.parse(message.toString('utf8')) }; + var msg = message.toString('utf8'); + var jsonMsg = JSON.parse(msg); + if(jsonMsg.data) { + jsonMsg.data = JSON.parse(jsonMsg.data) || jsonMsg.data; + } + msg = { payload: jsonMsg }; node.send(msg); } }); diff --git a/node-red-contrib-xiaomi-ht/xiaomi-ht.js b/node-red-contrib-xiaomi-ht/xiaomi-ht.js index 32b867d..aefd12e 100644 --- a/node-red-contrib-xiaomi-ht/xiaomi-ht.js +++ b/node-red-contrib-xiaomi-ht/xiaomi-ht.js @@ -2,6 +2,7 @@ module.exports = function(RED) { "use strict"; var mustache = require("mustache"); var dgram = require('dgram'); + var miDevicesUtils = require('../utils'); function XiaomiHtNode(config) { RED.nodes.createNode(this, config); @@ -13,8 +14,7 @@ module.exports = function(RED) { this.divide = config.divide; var node = this; - - node.status({fill:"grey",shape:"ring",text:"battery"}); + node.status({fill:"grey", shape:"ring", text:"battery - na"}); if (this.gateway) { node.on('input', function(msg) { @@ -23,20 +23,11 @@ module.exports = function(RED) { node.log("Received message from: " + payload.model + " sid: " + payload.sid + " payload: " + payload.data); if (payload.sid == node.sid && ["sensor_ht", "weather.v1"].indexOf(payload.model) >= 0) { - var data = JSON.parse(payload.data) - - if (data.voltage) { - if (data.voltage < 2500) { - node.status({fill:"red",shape:"dot",text:"battery"}); - } else if (data.voltage < 2900) { - node.status({fill:"yellow",shape:"dot",text:"battery"}); - } else { - node.status({fill:"green",shape:"dot",text:"battery"}); - } - } + var data = payload.data; + miDevicesUtils.setStatus(node, data); if (node.output == "0") { - msg.payload = payload; + miDevicesUtils.prepareFullDataOutput(payload); node.send([msg]); } else if (node.output == "1") { var temp = null; @@ -76,7 +67,7 @@ module.exports = function(RED) { if (data.pressure) { if (this.divide) { - data.pressure = String(data.pressure / 1000); + data.pressure = String(data.pressure / 100); } pressure = {"payload": mustache.render(node.pressure, data)} } diff --git a/node-red-contrib-xiaomi-magnet/xiaomi-magnet.js b/node-red-contrib-xiaomi-magnet/xiaomi-magnet.js index 5908891..b4433cd 100644 --- a/node-red-contrib-xiaomi-magnet/xiaomi-magnet.js +++ b/node-red-contrib-xiaomi-magnet/xiaomi-magnet.js @@ -1,6 +1,7 @@ module.exports = function(RED) { "use strict"; var mustache = require("mustache"); + var miDevicesUtils = require('../utils'); function XiaomiMagnetNode(config) { RED.nodes.createNode(this, config); @@ -14,7 +15,7 @@ module.exports = function(RED) { var state = ""; // node.status({fill:"yellow", shape:"dot", text:"unknown state"}); - node.status({fill:"grey",shape:"ring",text:"battery"}); + node.status({fill:"grey", shape:"ring", text:"battery - na"}); if (this.gateway) { node.on('input', function(msg) { @@ -22,7 +23,7 @@ module.exports = function(RED) { var payload = msg.payload; if (payload.sid == node.sid && ["magnet", "sensor_magnet.aq2"].indexOf(payload.model) >= 0) { - var data = JSON.parse(payload.data) + var data = payload.data; // if (data.status && data.status == "open") { // node.status({fill:"green", shape:"dot", text:"open"}); @@ -31,20 +32,11 @@ module.exports = function(RED) { // node.status({fill:"red", shape:"dot", text:"closed"}); // state = "closed"; // } - - if (data.voltage) { - if (data.voltage < 2500) { - node.status({fill:"red",shape:"dot",text:"battery"}); - } else if (data.voltage < 2900) { - node.status({fill:"yellow",shape:"dot",text:"battery"}); - } else { - node.status({fill:"green",shape:"dot",text:"battery"}); - } - } + miDevicesUtils.setStatus(node, data); if (node.output == "0") { - msg.payload = payload; + miDevicesUtils.prepareFullDataOutput(payload); node.send([msg]); } else if (node.output == "1") { var status = null; diff --git a/node-red-contrib-xiaomi-motion/xiaomi-motion.js b/node-red-contrib-xiaomi-motion/xiaomi-motion.js index 10ea602..3756bb7 100644 --- a/node-red-contrib-xiaomi-motion/xiaomi-motion.js +++ b/node-red-contrib-xiaomi-motion/xiaomi-motion.js @@ -1,6 +1,7 @@ module.exports = function(RED) { "use strict"; var mustache = require("mustache"); + var miDevicesUtils = require('../utils'); function XiaomiMotionNode(config) { RED.nodes.createNode(this, config); @@ -14,7 +15,7 @@ module.exports = function(RED) { var state = ""; // node.status({fill:"yellow", shape:"dot", text:"unknown state"}); - node.status({fill:"grey",shape:"ring",text:"battery"}); + node.status({fill:"grey", shape:"ring", text:"battery - na"}); if (this.gateway) { node.on('input', function(msg) { @@ -22,7 +23,7 @@ module.exports = function(RED) { var payload = msg.payload; if (payload.sid == node.sid && payload.model == "motion") { - var data = JSON.parse(payload.data) + var data = payload.data; // if (data.status && data.status == "open") { // node.status({fill:"green", shape:"dot", text:"open"}); @@ -31,20 +32,11 @@ module.exports = function(RED) { // node.status({fill:"red", shape:"dot", text:"closed"}); // state = "closed"; // } - - if (data.voltage) { - if (data.voltage < 2500) { - node.status({fill:"red",shape:"dot",text:"battery"}); - } else if (data.voltage < 2900) { - node.status({fill:"yellow",shape:"dot",text:"battery"}); - } else { - node.status({fill:"green",shape:"dot",text:"battery"}); - } - } + miDevicesUtils.setStatus(node, data); if (node.output == "0") { - msg.payload = payload; + miDevicesUtils.prepareFullDataOutput(payload); node.send([msg]); } else if (node.output == "1") { var status = null; diff --git a/node-red-contrib-xiaomi-switch/xiaomi-switch.js b/node-red-contrib-xiaomi-switch/xiaomi-switch.js index d6ab6f6..aa2a3de 100644 --- a/node-red-contrib-xiaomi-switch/xiaomi-switch.js +++ b/node-red-contrib-xiaomi-switch/xiaomi-switch.js @@ -1,6 +1,7 @@ module.exports = function(RED) { "use strict"; var mustache = require("mustache"); + var miDevicesUtils = require('../utils'); function XiaomiSwitchNode(config) { RED.nodes.createNode(this, config); @@ -12,7 +13,7 @@ module.exports = function(RED) { var node = this; - node.status({fill:"grey",shape:"ring",text:"battery"}); + node.status({fill:"grey", shape:"ring", text:"battery - na"}); if (this.gateway) { node.on('input', function(msg) { @@ -20,20 +21,11 @@ module.exports = function(RED) { var payload = msg.payload; if (payload.sid == node.sid && ["switch", "sensor_switch.aq2"].indexOf(payload.model) >= 0) { - var data = JSON.parse(payload.data) - - if (data.voltage) { - if (data.voltage < 2500) { - node.status({fill:"red",shape:"dot",text:"battery"}); - } else if (data.voltage < 2900) { - node.status({fill:"yellow",shape:"dot",text:"battery"}); - } else { - node.status({fill:"green",shape:"dot",text:"battery"}); - } - } + var data = payload.data; + miDevicesUtils.setStatus(node, data); if (node.output == "0") { - msg.payload = payload; + miDevicesUtils.prepareFullDataOutput(payload); node.send([msg]); } else if (node.output == "1") { var status = null; diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..9af9266 --- /dev/null +++ b/utils.js @@ -0,0 +1,33 @@ + + +module.exports = { + computeBatteryLevel: function(voltage) { + /* + When full, CR2032 batteries are between 3 and 3.4V + http://farnell.com/datasheets/1496885.pdf + */ + return Math.min(Math.round((voltage - 2200) / 14), 100); + }, + setStatus: function(node, data) { + if (data.voltage) { + var batteryPercent = Math.min(Math.round((data.voltage - 2200) / 14), 100); + var status = { + fill: "green", shape: "dot", + text: "battery - " + batteryPercent + "%" + }; + + if (data.voltage < 2500) { + status.color = "red"; + } else if (data.voltage < 2900) { + status.color = "yellow"; + } + node.status(status); + } + }, + prepareFullDataOutput: function(payload) { + if(payload.data.voltage) { + payload.data.batteryLevel = this.computeBatteryLevel(payload.data.voltage); + } + return payload; + } +}