| @@ -3,6 +3,10 @@ | |||
| <a href="http://eepurl.com/gJm095" target="_blank">Subscribe to my channel.</a> Only news about my nodes, no spam, no ads. I'm a github developer, not a merchant. | |||
| <p> | |||
| <b>Version 1.0.17</b> May 2020<br/> | |||
| - Interruptflowultimete: msg.play = true sends the current payload See the README on github for an example.</br> | |||
| </p> | |||
| <p> | |||
| <b>Version 1.0.16</b> May 2020<br/> | |||
| - BlinkerUltimate: if you set the interval while the blinker is running, yet the new interval is applied immediately.</br> | |||
| @@ -94,6 +94,18 @@ Whenever this node receives a payload = false from a specific topic, it stops ou | |||
| </code> | |||
| </details> | |||
| <br/> | |||
| In this other example, you can see the property "play" in action. This property allow you to replay the last previously stored message.<br/> | |||
| This allow to save the state of a node and then replay it back whenever you want. | |||
| <img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-boolean-logic-ultimate/master/img/if1.png' width='60%'> | |||
| <details><summary>CLICK HERE, copy and paste it into your flow</summary> | |||
| <code> | |||
| [{"id":"9839dd47.81b2c8","type":"InterruptFlowUltimate","z":"1b769f85.fba14","name":"Interrupt Flow","triggertopic":"trigger","x":520,"y":260,"wires":[["d371d690.1e2fe8"]]},{"id":"568deb73.394fb4","type":"comment","z":"1b769f85.fba14","name":"1) Push buttons to change values","info":"","x":130,"y":100,"wires":[]},{"id":"e1c9f10a.0ba518","type":"inject","z":"1b769f85.fba14","name":"ALLOW","topic":"trigger","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":70,"y":320,"wires":[["9839dd47.81b2c8"]]},{"id":"82ba24f9.0f0bd8","type":"inject","z":"1b769f85.fba14","name":"INTERRUPT","topic":"trigger","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":280,"wires":[["9839dd47.81b2c8"]]},{"id":"23ba4f9c.86de9","type":"comment","z":"1b769f85.fba14","name":"2) Push INTERRUPT, then try again to change value (1)","info":"","x":200,"y":240,"wires":[]},{"id":"24671ef2.4519e2","type":"inject","z":"1b769f85.fba14","name":"","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":70,"y":140,"wires":[["9839dd47.81b2c8"]]},{"id":"d371d690.1e2fe8","type":"debug","z":"1b769f85.fba14","name":"Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":690,"y":260,"wires":[]},{"id":"409ec415.735d74","type":"inject","z":"1b769f85.fba14","name":"REPLAY","topic":"trigger","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":420,"wires":[["6653ed0.7186014"]]},{"id":"6653ed0.7186014","type":"change","z":"1b769f85.fba14","name":"Play","rules":[{"t":"set","p":"play","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":210,"y":420,"wires":[["9839dd47.81b2c8"]]},{"id":"e957a069.0ac458","type":"inject","z":"1b769f85.fba14","name":"","topic":"","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":70,"y":180,"wires":[["9839dd47.81b2c8"]]},{"id":"8f0af608.8fb45","type":"comment","z":"1b769f85.fba14","name":"3) Replay last message stored by the node","info":"","x":160,"y":380,"wires":[]},{"id":"46e6f455.0023ac","type":"comment","z":"1b769f85.fba14","name":"You can use Interruptflow, to save the state of a node, and then replay the last state as you want.","info":"","x":330,"y":60,"wires":[]}] | |||
| </code> | |||
| </details> | |||
| # INVERT ULTIMATE | |||
| Outputs the inverted input. For example true -> false<br /> | |||
| @@ -45,7 +45,9 @@ | |||
| <div class="form-row"> | |||
| <label for="node-input-triggertopic"><i class="icon-tag"></i> Trigger by topic</label> | |||
| <input type="text" id="node-input-triggertopic" placeholder="Name"> | |||
| <div><i>Whenever the node receives a payload = false from this topic, it stops output messages to the flow. As soon it receives payload = true from this topic, the output messages start to flow out again.</i></div> | |||
| <div><i>Whenever the node receives a payload = false from this topic,<br/> it stops output messages to the flow.<br/>As soon it receives payload = true from this topic,<br/>the output messages start to flow out again. | |||
| <br/>The node will output the current stored message<br/>plus an added property "isReplay = true",<br/>as soon as it receives a "play" = true from this topic. | |||
| </i></div> | |||
| </div> | |||
| </script> | |||
| @@ -56,8 +58,15 @@ | |||
| <a href="http://eepurl.com/gJm095" target="_blank">Subscribe to my channel</a> for news about my nodes. | |||
| </p> | |||
| <p>The meaning of this node is to interrupt/reactivate flow messages.<br/> | |||
| <p>The node will stop output messages, if it receives a payload = false from the specified topic.<br/> | |||
| The node will resume output messages, if it receives a payload = true from the specified topic.<br/> | |||
| Normally, passes the input messages to the output. If you send a payload with a specific topic (you can set it on the node properties), the node stops sending output messages.<br/> | |||
| It can also save the last message received and play later. This is useful if you wish to restore previous state to, for example, a light actuator.<br/> | |||
| Please see the <a href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate" target="_blank">README</a> on github for examples. | |||
| </p> | |||
| <p> | |||
| The node will stop output messages, if it receives a payload = false <b>from the specified topic</b>.<br/> | |||
| The node will resume output messages, if it receives a payload = true <b>from the specified topic</b>.<br/> | |||
| Other that that, as soon as you send payload = false <b>from the specified topic</b>, the node stores the last received payload internally | |||
| The node will output the current stored message plus an added property <b>isReplay</b> = true, if it receives a <b>play</b> = true from the specified topic.<br/> | |||
| </p> | |||
| <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a> | |||
| @@ -1,58 +1,75 @@ | |||
| module.exports = function(RED) { | |||
| function InterruptFlowUltimate(config) { | |||
| RED.nodes.createNode(this,config); | |||
| module.exports = function (RED) { | |||
| function InterruptFlowUltimate(config) { | |||
| RED.nodes.createNode(this, config); | |||
| this.config = config; | |||
| var node = this; | |||
| setNodeStatus({ fill: "green", shape: "ring", text: "-> pass" }); | |||
| node.bInviaMessaggio = true; // Send the message or not | |||
| setNodeStatus({ fill: "green", shape: "ring", text: "-> pass" }); | |||
| node.bInviaMessaggio = true; // Send the message or not | |||
| node.currentMsg = {}; // Stores current payload | |||
| node.sTriggerTopic = node.config.triggertopic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '') || "trigger"; // Topic controlling the bInviaMessaggio | |||
| this.on('input', function (msg) { | |||
| var sTriggerTopic = node.config.triggertopic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '') || "trigger"; // Topic controlling the bInviaMessaggio | |||
| var sIncomingTopic = ""; | |||
| if (msg.hasOwnProperty("topic")) { | |||
| // 06/11/2019 | |||
| sIncomingTopic = msg.topic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); // Cut unwanted Characters | |||
| if (sIncomingTopic == sTriggerTopic && ToBoolean(msg.payload) === true) { | |||
| node.bInviaMessaggio = true; | |||
| setNodeStatus({ fill: "green", shape: "dot", text: "-> pass" }); | |||
| return; | |||
| } else if (sIncomingTopic==sTriggerTopic && ToBoolean(msg.payload)===false){ | |||
| node.bInviaMessaggio = false; | |||
| setNodeStatus({ fill: "red", shape: "dot", text: "|| stop" }); | |||
| return; | |||
| } | |||
| } | |||
| if (node.bInviaMessaggio) node.send(msg); | |||
| }); | |||
| function setNodeStatus({fill, shape, text}) | |||
| { | |||
| if (sIncomingTopic == node.sTriggerTopic) { | |||
| if (msg.hasOwnProperty("play")) { | |||
| node.currentMsg.isReplay = true; | |||
| setNodeStatus({ fill: "yellow", shape: "dot", text: "-> replay" }); | |||
| // Restore previous status | |||
| setTimeout(() => { | |||
| if (node.bInviaMessaggio) { | |||
| setNodeStatus({ fill: "green", shape: "dot", text: "-> pass" }); | |||
| } else { | |||
| setNodeStatus({ fill: "red", shape: "dot", text: "|| stop (stored last msg)" }); | |||
| } | |||
| }, 1000) | |||
| node.send(node.currentMsg); | |||
| return; | |||
| } else if (ToBoolean(msg.payload) === true) { | |||
| node.bInviaMessaggio = true; | |||
| setNodeStatus({ fill: "green", shape: "dot", text: "-> pass" }); | |||
| return; | |||
| } else if (ToBoolean(msg.payload) === false) { | |||
| node.bInviaMessaggio = false; | |||
| setNodeStatus({ fill: "red", shape: "dot", text: "|| stop (stored last msg)" }); | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| if (node.bInviaMessaggio) { | |||
| node.currentMsg = msg; | |||
| node.send(msg); | |||
| } | |||
| }); | |||
| function setNodeStatus({ fill, shape, text }) { | |||
| var dDate = new Date(); | |||
| node.status({fill: fill,shape: shape,text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")"}) | |||
| node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" }) | |||
| } | |||
| function ToBoolean( value ) { | |||
| function ToBoolean(value) { | |||
| var res = false; | |||
| if (typeof value === 'boolean') { | |||
| res = value; | |||
| } | |||
| else if( typeof value === 'number' || typeof value === 'string' ) { | |||
| } | |||
| else if (typeof value === 'number' || typeof value === 'string') { | |||
| // Is it formated as a decimal number? | |||
| if( decimal.test( value ) ) { | |||
| var v = parseFloat( value ); | |||
| if (decimal.test(value)) { | |||
| var v = parseFloat(value); | |||
| res = v != 0; | |||
| } | |||
| else { | |||
| res = value.toLowerCase() === "true"; | |||
| } | |||
| } | |||
| return res; | |||
| }; | |||
| } | |||
| } | |||
| RED.nodes.registerType("InterruptFlowUltimate",InterruptFlowUltimate); | |||
| RED.nodes.registerType("InterruptFlowUltimate", InterruptFlowUltimate); | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| { | |||
| "name": "node-red-contrib-boolean-logic-ultimate", | |||
| "version": "1.0.16", | |||
| "description": "A set of Node-RED enhanced boolean logic, with persisten values after reboot and more", | |||
| "version": "1.0.17", | |||
| "description": "A set of Node-RED enhanced boolean logic node, flow interruption node, blinker node, invert node, filter node, with persisten values after reboot and more.", | |||
| "author": "Supergiovane (https://github.com/Supergiovane)", | |||
| "dependencies": { | |||
| "fs": "0.0.1-security" | |||