<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. | <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> | <p> | ||||
<b>Version 1.0.16</b> May 2020<br/> | <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> | - BlinkerUltimate: if you set the interval while the blinker is running, yet the new interval is applied immediately.</br> |
</code> | </code> | ||||
</details> | </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 | # INVERT ULTIMATE | ||||
Outputs the inverted input. For example true -> false<br /> | Outputs the inverted input. For example true -> false<br /> |
<div class="form-row"> | <div class="form-row"> | ||||
<label for="node-input-triggertopic"><i class="icon-tag"></i> Trigger by topic</label> | <label for="node-input-triggertopic"><i class="icon-tag"></i> Trigger by topic</label> | ||||
<input type="text" id="node-input-triggertopic" placeholder="Name"> | <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> | </div> | ||||
</script> | </script> | ||||
<a href="http://eepurl.com/gJm095" target="_blank">Subscribe to my channel</a> for news about my nodes. | <a href="http://eepurl.com/gJm095" target="_blank">Subscribe to my channel</a> for news about my nodes. | ||||
</p> | </p> | ||||
<p>The meaning of this node is to interrupt/reactivate flow messages.<br/> | <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> | </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> | <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> | ||||
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; | this.config = config; | ||||
var node = this; | 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) { | this.on('input', function (msg) { | ||||
var sTriggerTopic = node.config.triggertopic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '') || "trigger"; // Topic controlling the bInviaMessaggio | |||||
var sIncomingTopic = ""; | var sIncomingTopic = ""; | ||||
if (msg.hasOwnProperty("topic")) { | if (msg.hasOwnProperty("topic")) { | ||||
// 06/11/2019 | // 06/11/2019 | ||||
sIncomingTopic = msg.topic.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, ''); // Cut unwanted Characters | 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(); | 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; | var res = false; | ||||
if (typeof value === 'boolean') { | if (typeof value === 'boolean') { | ||||
res = value; | 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? | // 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; | res = v != 0; | ||||
} | } | ||||
else { | else { | ||||
res = value.toLowerCase() === "true"; | res = value.toLowerCase() === "true"; | ||||
} | } | ||||
} | } | ||||
return res; | return res; | ||||
}; | }; | ||||
} | |||||
} | |||||
RED.nodes.registerType("InterruptFlowUltimate",InterruptFlowUltimate); | |||||
RED.nodes.registerType("InterruptFlowUltimate", InterruptFlowUltimate); | |||||
} | } |
{ | { | ||||
"name": "node-red-contrib-boolean-logic-ultimate", | "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)", | "author": "Supergiovane (https://github.com/Supergiovane)", | ||||
"dependencies": { | "dependencies": { | ||||
"fs": "0.0.1-security" | "fs": "0.0.1-security" |