@@ -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" |