UNPKG

smithtek-node-red-meter

Version:

Adds record function to node-red

224 lines (201 loc) 8.41 kB
module.exports = function (RED) { function SmithtekRecord(config) { RED.nodes.createNode(this, config); // this.ThresholdType = config.ThresholdType || 'upper'; this.recordType = config.recordType || 'time'; this.startType = config.startType; this.stopType = config.stopType; this.savetoType = config.savetoType; // record time this.start = config.start; this.stop = config.stop; this.saveto = config.saveto; // record unit this.multiplier = config.multiplier; var node = this; var isRecording = false; var currentMultiplier = Number.NaN; // caculate multiplier if ('unit' === node.recordType) { if (!Number.isNaN(parseFloat(node.multiplier))) currentMultiplier = parseFloat(node.multiplier); } // print all data for debug // node.log("start type: " + node.startType); // node.log("stop type: " + node.stopType); // node.log("Saveto type: " + node.savetoType); // node.log("Start: " + node.start); // node.log("Stop: " + node.stop); // node.log("Saveto: " + node.saveto); // node.log("recordType: " + node.recordType); // node.log("multiplier: " + node.multiplier); const defautUpdateTimer = 1000; var timerUpdate = null; // init variable to save records var nodeRecord = null; if ('global' === node.savetoType) { nodeRecord = this.context().global; } else if ('flow' === node.savetoType) { nodeRecord = this.context().flow; } else { // should never go to this loop } // get value or default 0 // asum that node.saveto is a valid String nodeRecord.get(node.saveto) || 0; // Set initial status showStatus(node.recordType, isRecording); node.on('input', function (msg) { // this.log(JSON.stringify(msg)); if ( Object.prototype.hasOwnProperty.call(msg, 'payload') && Object.prototype.hasOwnProperty.call(msg.payload, 'reset') ) { resetRecorder(); } else if ( Object.prototype.hasOwnProperty.call(msg, 'payload') && Object.prototype.hasOwnProperty.call(msg.payload, 'multiplier') ) { // update multiplier updateMultiplier(msg); } else { if ('time' === node.recordType) { timeRecorder(msg); } else if ('unit' === node.recordType) { // record every for every imcoming msg with multiplier unitRecorder(msg); } } }); node.on('close', function (done) { if (timerUpdate) { clearInterval(timerUpdate); timerUpdate = null; } done(); }); function resetRecorder() { // reset record if msg.payload.reset is existed nodeRecord.set(node.saveto, 0); showStatus(node.recordType, isRecording); } function timeRecorder(msg) { // format start signal from config if ( ((node.startType === 'str' && msg.payload === node.start) || (node.startType === 'num' && msg.payload === parseInt(node.start)) || (node.startType === 'bool' && msg.payload === parseBool(node.start))) && !isRecording ) { isRecording = true; // node.log(`Start time record: ${isRecording}`); showStatus(node.recordType, true); if (null === timerUpdate) timerUpdate = setInterval(function () { nodeRecord.set( node.saveto, (nodeRecord.get(node.saveto) || 0) + 1 ); // send to output msg.payload = nodeRecord.get(node.saveto); msg._msgid = RED.util.generateId(); // node.log(`interval time record: ${isRecording} ${timerUpdate}`); node.send(msg); showStatus(node.recordType, true); }, defautUpdateTimer); } else if ( ((node.startType === 'str' && msg.payload === node.stop) || (node.startType === 'num' && msg.payload === parseInt(node.stop)) || (node.startType === 'bool' && msg.payload === parseBool(node.stop))) && isRecording ) { isRecording = false; // node.log(`Stop time record: ${isRecording}`); if (null != timerUpdate) clearInterval(timerUpdate); timerUpdate = null; showStatus(node.recordType, false); } else {} } function unitRecorder(msg) { if (!Number.isNaN(currentMultiplier)) { nodeRecord.set( node.saveto, (nodeRecord.get(node.saveto) || 0) + 1 * currentMultiplier ); // bypass msg msg.payload = parseFloat(nodeRecord.get(node.saveto)); node.send(msg); showStatus(node.recordType, false); } } function updateMultiplier(msg) { // caculate multiplier if ('unit' === node.recordType) { if (!Number.isNaN(parseFloat(msg.payload.multiplier))) currentMultiplier = parseFloat(msg.payload.multiplier); showStatus(node.recordType, false); } } function showStatus(type, status) { if ('time' === type) { if (status) { node.status({ fill: 'green', shape: 'ring', text: `TIME RECORDING: ${node.savetoType}.${ node.saveto }: ${nodeRecord.get(node.saveto) || 0}(s)`, }); } else { node.status({ fill: 'red', shape: 'ring', text: `STOPPED: ${node.savetoType}.${node.saveto}: ${ nodeRecord.get(node.saveto) || 0 }(s)`, }); } } else if ('unit' === type) { if (!Number.isNaN(currentMultiplier)) { node.status({ fill: 'green', shape: 'ring', text: `UNIT RECORDING - Multi:${currentMultiplier.toFixed( 2 )} - ${node.savetoType}.${node.saveto}: ${( nodeRecord.get(node.saveto) || 0 ).toFixed(2)}`, }); } else { node.status({ fill: 'red', shape: 'ring', text: `STOPPED: invalid multiplier input`, }); } } } function parseBool(val) { if ( (typeof val === 'string' && (val.toLowerCase() === 'true' || val.toLowerCase() === 'yes')) || val === 1 ) return true; else if ( (typeof val === 'string' && (val.toLowerCase() === 'false' || val.toLowerCase() === 'no')) || val === 0 ) return false; return null; } } RED.nodes.registerType('Smithtek-Metering', SmithtekRecord); };