UNPKG

node-red-contrib-boolean-logic-ultimate

Version:

A set of Node-RED enhanced boolean logic and utility nodes, flow interruption, blinker, invert, filter, toggle etc.., with persistent values after reboot. Compatible also with Homeassistant values.

135 lines (114 loc) 4.16 kB
module.exports = function (RED) { function ImpulseUltimate(config) { RED.nodes.createNode(this, config); var node = this; node.commandText = config.commandText === undefined ? "" : config.commandText; node.name = config.name === undefined || config.name === "" ? "Impulse" : config.name; node.topic = node.name; node.commands = []; node.timerWait = null; node.isPlaying = false; node.setNodeStatus = ({ fill, shape, text }) => { let dDate = new Date(); node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" }) } async function delay(ms) { return new Promise(function (resolve, reject) { try { node.timerWait = setTimeout(resolve, ms); } catch (error) { reject(); } }); } function isNumeric(str) { if (typeof str != "string") return false // we only process strings! return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)... !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail } node.commands = node.commandText.split("\n"); async function avvio() { node.isPlaying = true; node.setNodeStatus({ fill: "green", shape: "ring", text: "Start" }); for (let index = 0; index < node.commands.length; index++) { const element = node.commands[index]; let msg = { topic: node.name }; if (!element.toString().startsWith("//")) { if (node.isPlaying === false) return; // STOP called try { var sCommand = element.split(":")[0].toString().toLowerCase().trim(); if (sCommand !== "restart") { // Get the value of the command //var sVal = element.split(":")[1].toString().toLowerCase().trim(); const idx = element.indexOf(":"); var sVal = (idx !== -1 ? element.substring(idx + 1) : "") .toString() .trim(); // toLowerCase() would destroy JSON keys try { const parsed = JSON.parse(sVal); if (parsed && typeof parsed === "object") { sVal = parsed; // sVal is real object now } } catch (e) { // no valid JSON - sVal stays String. toLowerCase() could be done here if really needed, // but it could surprise the enduser that the foreseen value is manipulated } } else { var sVal = ""; } } catch (error) { node.isPlaying = false; node.setNodeStatus({ fill: "red", shape: "dot", text: "ERROR: check the row " + element }); return; } node.setNodeStatus({ fill: "green", shape: "dot", text: sCommand + ":" + sVal }); if (sCommand === "send") { try { if (sVal === "true") sVal = true; if (sVal === "false") sVal = false; msg.payload = sVal; } catch (error) { } node.send(msg); } if (sCommand === "wait") { // Wait try { if (!isNumeric(sVal)) throw (new error("Not number")); await delay(Number(sVal)); } catch (error) { node.isPlaying = false; node.setNodeStatus({ fill: "red", shape: "dot", text: "ERROR: check the row " + element }); return; } } if (sCommand === "restart") { // Restart node.isPlaying = false; node.setNodeStatus({ fill: "green", shape: "ring", text: "Restart" }); await avvio(); } } } node.isPlaying = false; node.setNodeStatus({ fill: "green", shape: "ring", text: "End" }); } this.on('input', function (msg) { const utils = require("./utils.js"); let sPayload = utils.fetchFromObject(msg, config.payloadPropName || "payload"); if (sPayload === true) { if (node.isPlaying) { node.setNodeStatus({ fill: "yellow", shape: "ring", text: "Already running. Stop me first." }); return; } avvio(); } else if (sPayload === false) { node.isPlaying = false; if (node.timerWait !== null) clearTimeout(node.timerWait); node.setNodeStatus({ fill: "red", shape: "dot", text: "Forced stop" }); } }); node.on("close", function (done) { done(); }); } RED.nodes.registerType("ImpulseUltimate", ImpulseUltimate); }