node-red-contrib-boolean-logic-ultimate 1.0.62 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +11 -10
- package/boolean-logic-ultimate/BlinkerUltimate.html +1 -1
- package/boolean-logic-ultimate/BooleanLogicUltimate.html +13 -2
- package/boolean-logic-ultimate/BooleanLogicUltimate.js +488 -338
- package/boolean-logic-ultimate/Comparator.html +102 -0
- package/boolean-logic-ultimate/Comparator.js +99 -0
- package/boolean-logic-ultimate/FilterUltimate.html +16 -4
- package/boolean-logic-ultimate/FilterUltimate.js +67 -46
- package/boolean-logic-ultimate/ImpulseUltimate.html +1 -1
- package/boolean-logic-ultimate/InterruptFlowUltimate.html +15 -3
- package/boolean-logic-ultimate/InterruptFlowUltimate.js +155 -93
- package/boolean-logic-ultimate/InvertUltimate.html +14 -5
- package/boolean-logic-ultimate/InvertUltimate.js +74 -46
- package/boolean-logic-ultimate/RailwaySwitchUltimate.html +13 -2
- package/boolean-logic-ultimate/RailwaySwitchUltimate.js +110 -71
- package/boolean-logic-ultimate/SimpleOutputUltimate.html +1 -1
- package/boolean-logic-ultimate/SumUltimate.html +1 -1
- package/boolean-logic-ultimate/toggleUltimate.html +13 -3
- package/boolean-logic-ultimate/toggleUltimate.js +1 -1
- package/boolean-logic-ultimate/translator-config.html +63 -0
- package/boolean-logic-ultimate/translator-config.js +8 -0
- package/boolean-logic-ultimate/utils.js +52 -43
- package/package.json +4 -2
|
@@ -1,101 +1,163 @@
|
|
|
1
1
|
module.exports = function (RED) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
function InterruptFlowUltimate(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
this.config = config;
|
|
5
|
+
var node = this;
|
|
6
|
+
node.currentMsg = {}; // Stores current payload
|
|
7
|
+
node.sTriggerTopic =
|
|
8
|
+
node.config.triggertopic.replace(
|
|
9
|
+
/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi,
|
|
10
|
+
""
|
|
11
|
+
) || "trigger"; // Topic controlling the bInviaMessaggio
|
|
12
|
+
node.bInviaMessaggio =
|
|
13
|
+
node.config.initializewith === undefined ||
|
|
14
|
+
node.config.initializewith === "1"
|
|
15
|
+
? true
|
|
16
|
+
: false; // Send the message or not
|
|
17
|
+
node.autoToggle =
|
|
18
|
+
config.autoToggle === undefined ? 0 : parseInt(config.autoToggle); // Auto toggle the selected "initializewith" after a while (useful for homekit bridged, that sends junk after start)
|
|
19
|
+
node.timerAutoToggle = null;
|
|
11
20
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
function setNodeStatus({ fill, shape, text }) {
|
|
22
|
+
let dDate = new Date();
|
|
23
|
+
node.status({
|
|
24
|
+
fill: fill,
|
|
25
|
+
shape: shape,
|
|
26
|
+
text:
|
|
27
|
+
text +
|
|
28
|
+
" (" +
|
|
29
|
+
dDate.getDate() +
|
|
30
|
+
", " +
|
|
31
|
+
dDate.toLocaleTimeString() +
|
|
32
|
+
")",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
setNodeStatus({ fill: "green", shape: "ring", text: "-> pass" });
|
|
17
36
|
|
|
37
|
+
node.alignStatus = () => {
|
|
38
|
+
let sAutoToggle =
|
|
39
|
+
node.autoToggle > 0 ? " (Autotoggle in " + node.autoToggle + "s)" : "";
|
|
40
|
+
if (node.bInviaMessaggio) {
|
|
41
|
+
setNodeStatus({
|
|
42
|
+
fill: "green",
|
|
43
|
+
shape: "dot",
|
|
44
|
+
text: "-> pass" + sAutoToggle,
|
|
45
|
+
});
|
|
46
|
+
} else {
|
|
47
|
+
setNodeStatus({
|
|
48
|
+
fill: "red",
|
|
49
|
+
shape: "dot",
|
|
50
|
+
text: "|| stop" + sAutoToggle,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
18
54
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
55
|
+
if (node.autoToggle > 0) {
|
|
56
|
+
node.timerAutoToggle = setTimeout(() => {
|
|
57
|
+
node.autoToggle = 0;
|
|
58
|
+
node.bInviaMessaggio = !node.bInviaMessaggio;
|
|
59
|
+
node.alignStatus();
|
|
60
|
+
}, node.autoToggle * 1000);
|
|
61
|
+
}
|
|
27
62
|
|
|
28
|
-
|
|
29
|
-
node.timerAutoToggle = setTimeout(() => {
|
|
30
|
-
node.autoToggle = 0;
|
|
31
|
-
node.bInviaMessaggio = !node.bInviaMessaggio;
|
|
32
|
-
node.alignStatus();
|
|
33
|
-
}, node.autoToggle * 1000);
|
|
34
|
-
}
|
|
63
|
+
node.alignStatus();
|
|
35
64
|
|
|
36
|
-
|
|
65
|
+
this.on("input", function (msg) {
|
|
66
|
+
var sIncomingTopic = "";
|
|
67
|
+
if (msg.hasOwnProperty("topic")) {
|
|
68
|
+
// 06/11/2019
|
|
69
|
+
if (!msg.hasOwnProperty("topic") || msg.topic === undefined)
|
|
70
|
+
msg.topic = "NoTopicReceived";
|
|
71
|
+
sIncomingTopic = msg.topic.replace(
|
|
72
|
+
/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi,
|
|
73
|
+
""
|
|
74
|
+
); // Cut unwanted Characters
|
|
75
|
+
if (sIncomingTopic === node.sTriggerTopic) {
|
|
76
|
+
const utils = require("./utils.js");
|
|
77
|
+
let sPayload = utils.fetchFromObject(
|
|
78
|
+
msg,
|
|
79
|
+
config.payloadPropName || "payload"
|
|
80
|
+
);
|
|
81
|
+
// 15/11/2021 inform user about undefined topic or payload
|
|
82
|
+
if (sPayload === undefined) {
|
|
83
|
+
setNodeStatus({
|
|
84
|
+
fill: "red",
|
|
85
|
+
shape: "dot",
|
|
86
|
+
text: "Received invalid payload from " + msg.topic || "",
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
msg.payload = utils.ToBoolean(
|
|
91
|
+
sPayload,
|
|
92
|
+
RED.nodes.getNode(config.translatorConfig) // Retrieve the config node. It can be null, but it's handled in utils.js; // 15/11/2021 Convert input to boolean.
|
|
93
|
+
);
|
|
94
|
+
if (msg.payload === undefined) return null;
|
|
95
|
+
if (node.timerAutoToggle !== null)
|
|
96
|
+
// 28/01/2022 Stop autotoggle
|
|
97
|
+
clearInterval(node.timerAutoToggle);
|
|
37
98
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
99
|
+
if (msg.hasOwnProperty("play")) {
|
|
100
|
+
if (node.currentMsg.payload !== undefined) {
|
|
101
|
+
node.currentMsg.isReplay = true;
|
|
102
|
+
setNodeStatus({
|
|
103
|
+
fill: "yellow",
|
|
104
|
+
shape: "dot",
|
|
105
|
+
text: "-> replay",
|
|
106
|
+
});
|
|
107
|
+
// Restore previous status
|
|
108
|
+
let t = setTimeout(() => {
|
|
109
|
+
if (node.bInviaMessaggio) {
|
|
110
|
+
setNodeStatus({
|
|
111
|
+
fill: "green",
|
|
112
|
+
shape: "dot",
|
|
113
|
+
text: "-> pass",
|
|
114
|
+
});
|
|
115
|
+
} else {
|
|
116
|
+
setNodeStatus({
|
|
117
|
+
fill: "red",
|
|
118
|
+
shape: "dot",
|
|
119
|
+
text: "|| stop (stored last msg)",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}, 1000);
|
|
123
|
+
node.send(node.currentMsg);
|
|
124
|
+
} else {
|
|
125
|
+
setNodeStatus({
|
|
126
|
+
fill: "grey",
|
|
127
|
+
shape: "dot",
|
|
128
|
+
text: "Nothing to replay",
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
} else if (msg.hasOwnProperty("reset")) {
|
|
133
|
+
node.currentMsg = {};
|
|
134
|
+
setNodeStatus({
|
|
135
|
+
fill: "yellow",
|
|
136
|
+
shape: "dot",
|
|
137
|
+
text: "Deleted stored msg",
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
} else if (msg.payload === true) {
|
|
141
|
+
node.bInviaMessaggio = true;
|
|
142
|
+
setNodeStatus({ fill: "green", shape: "dot", text: "-> pass" });
|
|
143
|
+
return;
|
|
144
|
+
} else if (msg.payload === false) {
|
|
145
|
+
node.bInviaMessaggio = false;
|
|
146
|
+
setNodeStatus({
|
|
147
|
+
fill: "red",
|
|
148
|
+
shape: "dot",
|
|
149
|
+
text: "|| stop (stored last msg)",
|
|
150
|
+
});
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
node.currentMsg = RED.util.cloneMessage(msg);
|
|
156
|
+
if (node.bInviaMessaggio) {
|
|
157
|
+
node.send(msg);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
45
161
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// 15/11/2021 inform user about undefined topic or payload
|
|
49
|
-
if (sPayload === undefined ) {
|
|
50
|
-
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
msg.payload = utils.ToBoolean(sPayload); // 15/11/2021 Convert input to boolean.
|
|
54
|
-
|
|
55
|
-
// 28/01/2022 Stop autotoggle
|
|
56
|
-
if (node.timerAutoToggle !== null) clearInterval(node.timerAutoToggle);
|
|
57
|
-
|
|
58
|
-
if (msg.hasOwnProperty("play")) {
|
|
59
|
-
if (node.currentMsg.payload !== undefined) {
|
|
60
|
-
node.currentMsg.isReplay = true;
|
|
61
|
-
setNodeStatus({ fill: "yellow", shape: "dot", text: "-> replay" });
|
|
62
|
-
// Restore previous status
|
|
63
|
-
let t = setTimeout(() => {
|
|
64
|
-
if (node.bInviaMessaggio) {
|
|
65
|
-
setNodeStatus({ fill: "green", shape: "dot", text: "-> pass" });
|
|
66
|
-
} else {
|
|
67
|
-
setNodeStatus({ fill: "red", shape: "dot", text: "|| stop (stored last msg)" });
|
|
68
|
-
}
|
|
69
|
-
}, 1000)
|
|
70
|
-
node.send(node.currentMsg);
|
|
71
|
-
} else {
|
|
72
|
-
setNodeStatus({ fill: "grey", shape: "dot", text: "Nothing to replay" });
|
|
73
|
-
}
|
|
74
|
-
return;
|
|
75
|
-
} else if (msg.hasOwnProperty("reset")) {
|
|
76
|
-
node.currentMsg = {};
|
|
77
|
-
setNodeStatus({ fill: "yellow", shape: "dot", text: "Deleted stored msg" });
|
|
78
|
-
return;
|
|
79
|
-
} else if (msg.payload === true) {
|
|
80
|
-
node.bInviaMessaggio = true;
|
|
81
|
-
setNodeStatus({ fill: "green", shape: "dot", text: "-> pass" });
|
|
82
|
-
return;
|
|
83
|
-
} else if (msg.payload === false) {
|
|
84
|
-
node.bInviaMessaggio = false;
|
|
85
|
-
setNodeStatus({ fill: "red", shape: "dot", text: "|| stop (stored last msg)" });
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
node.currentMsg = RED.util.cloneMessage(msg);
|
|
91
|
-
if (node.bInviaMessaggio) {
|
|
92
|
-
node.send(msg);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
RED.nodes.registerType("InterruptFlowUltimate", InterruptFlowUltimate);
|
|
101
|
-
}
|
|
162
|
+
RED.nodes.registerType("InterruptFlowUltimate", InterruptFlowUltimate);
|
|
163
|
+
};
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
name: {
|
|
7
7
|
value: "Invert"
|
|
8
8
|
},
|
|
9
|
-
payloadPropName: { value: "payload", required: false }
|
|
9
|
+
payloadPropName: { value: "payload", required: false },
|
|
10
|
+
translatorConfig: { type: "translator-config", required: false }
|
|
10
11
|
},
|
|
11
12
|
inputs:1,
|
|
12
13
|
outputs:1,
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
});
|
|
26
27
|
</script>
|
|
27
28
|
|
|
28
|
-
<script type="text/
|
|
29
|
+
<script type="text/html" data-template-name="InvertUltimate">
|
|
29
30
|
<div class="form-row">
|
|
30
31
|
<b>Invert Ultimate</b>    <span style="color:red"><i class="fa fa-question-circle"></i> <a target="_blank" href="https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate"><u>Help online</u></a></span>
|
|
31
32
|
   <span style="color:red"><i class="fa fa-youtube-play"></i> <a target="_blank" href="https://youtu.be/A41x8VevZD8"><u>Youtube Sample</u></a></span>
|
|
@@ -40,6 +41,15 @@
|
|
|
40
41
|
<label for="node-input-payloadPropName"><i class="fa fa-ellipsis-h"></i> Input</label>
|
|
41
42
|
<input type="text" id="node-input-payloadPropName">
|
|
42
43
|
</div>
|
|
44
|
+
<div class="form-row">
|
|
45
|
+
<br />
|
|
46
|
+
<b>Translator</b>
|
|
47
|
+
<br />
|
|
48
|
+
<label for="node-input-translatorConfig">
|
|
49
|
+
<font color="green" size="4px"><i class="fa fa-sign-in" aria-hidden="true"></i></font> Input
|
|
50
|
+
</label>
|
|
51
|
+
<input type="text" id="node-input-translatorConfig" />
|
|
52
|
+
</div>
|
|
43
53
|
</script>
|
|
44
54
|
|
|
45
55
|
<script type="text/markdown" data-help-name="InvertUltimate">
|
|
@@ -49,12 +59,11 @@ The input message is preserved and passed to the output, changing only the topic
|
|
|
49
59
|
|
|
50
60
|
|Property|Description|
|
|
51
61
|
|--|--|
|
|
52
|
-
| Input |
|
|
62
|
+
| Input | It's the msg property to be evaluated. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
63
|
+
| Translator Input | Translates the incoming <code>payload</code> value, to true/false. This allows the compatibility with, for example, **HomeAssistant** nodes. |
|
|
53
64
|
|
|
54
65
|
<br/>
|
|
55
66
|
|
|
56
|
-
[SEE THE README FOR FULL HELP AND SAMPLES](https://github.com/Supergiovane/node-red-contrib-boolean-logic-ultimate)
|
|
57
|
-
|
|
58
67
|
[Find it useful?](https://www.paypal.me/techtoday)
|
|
59
68
|
|
|
60
69
|
</script>
|
|
@@ -1,54 +1,82 @@
|
|
|
1
1
|
module.exports = function (RED) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
function InvertUltimate(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
this.config = config;
|
|
5
|
+
var node = this;
|
|
6
6
|
|
|
7
|
+
function setNodeStatus({ fill, shape, text }) {
|
|
8
|
+
let dDate = new Date();
|
|
9
|
+
node.status({
|
|
10
|
+
fill: fill,
|
|
11
|
+
shape: shape,
|
|
12
|
+
text:
|
|
13
|
+
text +
|
|
14
|
+
" (" +
|
|
15
|
+
dDate.getDate() +
|
|
16
|
+
", " +
|
|
17
|
+
dDate.toLocaleTimeString() +
|
|
18
|
+
")",
|
|
19
|
+
});
|
|
20
|
+
}
|
|
7
21
|
|
|
8
|
-
|
|
9
|
-
let dDate = new Date();
|
|
10
|
-
node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" })
|
|
11
|
-
}
|
|
22
|
+
setNodeStatus({ fill: "grey", shape: "dot", text: "Waiting" });
|
|
12
23
|
|
|
13
|
-
|
|
24
|
+
this.on("input", function (msg) {
|
|
25
|
+
// 11/11/2021 Clone input message and replace only relevant topics
|
|
26
|
+
const utils = require("./utils.js");
|
|
27
|
+
let sPayload = utils.fetchFromObject(
|
|
28
|
+
msg,
|
|
29
|
+
config.payloadPropName || "payload"
|
|
30
|
+
);
|
|
14
31
|
|
|
15
|
-
|
|
32
|
+
// 15/11/2021 inform user about undefined topic or payload
|
|
33
|
+
if (sPayload === undefined) {
|
|
34
|
+
setNodeStatus({
|
|
35
|
+
fill: "red",
|
|
36
|
+
shape: "dot",
|
|
37
|
+
text: "Received invalid payload from " + msg.topic || "",
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
16
41
|
|
|
42
|
+
var bRes = null;
|
|
43
|
+
try {
|
|
44
|
+
bRes = utils.ToBoolean(
|
|
45
|
+
sPayload,
|
|
46
|
+
RED.nodes.getNode(config.translatorConfig) // Retrieve the config node. It can be null, but it's handled in utils.js; // 15/11/2021 Convert input to boolean.);
|
|
47
|
+
);
|
|
48
|
+
} catch (error) {}
|
|
49
|
+
if (bRes === undefined || bRes === null) {
|
|
50
|
+
setNodeStatus({
|
|
51
|
+
fill: "red",
|
|
52
|
+
shape: "dot",
|
|
53
|
+
text:
|
|
54
|
+
"Received non convertible boolean value " +
|
|
55
|
+
sPayload +
|
|
56
|
+
" from " +
|
|
57
|
+
msg.topic,
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
17
61
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
62
|
+
var msgOUt = RED.util.cloneMessage(msg);
|
|
63
|
+
try {
|
|
64
|
+
msgOUt.payload = !bRes;
|
|
65
|
+
setNodeStatus({
|
|
66
|
+
fill: "green",
|
|
67
|
+
shape: "dot",
|
|
68
|
+
text: "(Send) " + msgOUt.payload,
|
|
69
|
+
});
|
|
70
|
+
node.send(msgOUt);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
setNodeStatus({
|
|
73
|
+
fill: "red",
|
|
74
|
+
shape: "dot",
|
|
75
|
+
text: "Unable to invert the input payload " + bRes,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
21
80
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
setNodeStatus({ fill: "red", shape: "dot", text: "Received invalid payload from " + msg.topic || "" });
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
var bRes = null;
|
|
29
|
-
try {
|
|
30
|
-
bRes = utils.ToBoolean(sPayload);
|
|
31
|
-
} catch (error) {
|
|
32
|
-
}
|
|
33
|
-
if (bRes === undefined || bRes === null) {
|
|
34
|
-
setNodeStatus({ fill: "red", shape: "dot", text: "Received non convertible boolean value " + sPayload + " from " + msg.topic });
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
var msgOUt = RED.util.cloneMessage(msg);
|
|
39
|
-
try {
|
|
40
|
-
msgOUt.payload = !bRes;
|
|
41
|
-
setNodeStatus({ fill: "green", shape: "dot", text: "(Send) " + msgOUt.payload });
|
|
42
|
-
node.send(msgOUt);
|
|
43
|
-
} catch (error) {
|
|
44
|
-
setNodeStatus({ fill: "red", shape: "dot", text: "Unable to invert the input payload " + bRes });
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
RED.nodes.registerType("InvertUltimate", InvertUltimate);
|
|
54
|
-
}
|
|
81
|
+
RED.nodes.registerType("InvertUltimate", InvertUltimate);
|
|
82
|
+
};
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
triggertopic: { value: "trigger" },
|
|
8
8
|
initializewith: { value: "0" },
|
|
9
9
|
autoToggle: { value: "0" },
|
|
10
|
-
payloadPropName: { value: "payload", required: false }
|
|
10
|
+
payloadPropName: { value: "payload", required: false },
|
|
11
|
+
translatorConfig: { type: "translator-config", required: false }
|
|
11
12
|
},
|
|
12
13
|
inputs: 1,
|
|
13
14
|
outputs: 2,
|
|
@@ -85,6 +86,15 @@
|
|
|
85
86
|
<option value="120">Toggle above option after 120 seconds</option>
|
|
86
87
|
</select>
|
|
87
88
|
</div>
|
|
89
|
+
<div class="form-row">
|
|
90
|
+
<br />
|
|
91
|
+
<b>Translator</b>
|
|
92
|
+
<br />
|
|
93
|
+
<label for="node-input-translatorConfig">
|
|
94
|
+
<font color="green" size="4px"><i class="fa fa-sign-in" aria-hidden="true"></i></font> Input
|
|
95
|
+
</label>
|
|
96
|
+
<input type="text" id="node-input-translatorConfig" />
|
|
97
|
+
</div>
|
|
88
98
|
</script>
|
|
89
99
|
|
|
90
100
|
<script type="text/markdown" data-help-name="RailwaySwitchUltimate">
|
|
@@ -93,8 +103,9 @@
|
|
|
93
103
|
|Property|Description|
|
|
94
104
|
|--|--|
|
|
95
105
|
| Switcher topic | Whenever the node receives a payload from this **topic**, it switches the input messages to an output. |
|
|
96
|
-
| With Input |
|
|
106
|
+
| With Input | It's the msg property to be evaluated. *By default, it is "payload", but you can also specify other properties, for example "payload.value"* |
|
|
97
107
|
| Then | This property, allow you to auto toggle the selected start state after some time. |
|
|
108
|
+
| Translator Input | Translates the incoming <code>payload</code> value, to true/false. This allows the compatibility with, for example, **HomeAssistant** nodes. |
|
|
98
109
|
|
|
99
110
|
* Input messages
|
|
100
111
|
|
|
@@ -1,81 +1,120 @@
|
|
|
1
1
|
module.exports = function (RED) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
function RailwaySwitchUltimate(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
this.config = config;
|
|
5
|
+
var node = this;
|
|
6
|
+
node.currentMsg = {}; // Stores current payload
|
|
7
|
+
node.sTriggerTopic =
|
|
8
|
+
node.config.triggertopic.replace(
|
|
9
|
+
/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi,
|
|
10
|
+
""
|
|
11
|
+
) || "trigger"; // Topic controlling the iRailway
|
|
12
|
+
node.iRailway = Number(node.config.initializewith); // Railway selector
|
|
13
|
+
node.autoToggle =
|
|
14
|
+
config.autoToggle === undefined ? 0 : parseInt(config.autoToggle); // Auto toggle the selected "initializewith" after a while (useful for homekit bridged, that sends junk after start)
|
|
15
|
+
node.timerAutoToggle = null;
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
function setNodeStatus({ fill, shape, text }) {
|
|
18
|
+
let dDate = new Date();
|
|
19
|
+
node.status({
|
|
20
|
+
fill: fill,
|
|
21
|
+
shape: shape,
|
|
22
|
+
text:
|
|
23
|
+
text +
|
|
24
|
+
" (" +
|
|
25
|
+
dDate.getDate() +
|
|
26
|
+
", " +
|
|
27
|
+
dDate.toLocaleTimeString() +
|
|
28
|
+
")",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
node.alignStatus = () => {
|
|
33
|
+
let sAutoToggle =
|
|
34
|
+
node.autoToggle > 0 ? " (Autotoggle in " + node.autoToggle + "s)" : "";
|
|
35
|
+
if (node.iRailway === 0) {
|
|
36
|
+
setNodeStatus({
|
|
37
|
+
fill: "green",
|
|
38
|
+
shape: "dot",
|
|
39
|
+
text: "-> UPPER PIN" + sAutoToggle,
|
|
40
|
+
});
|
|
41
|
+
} else {
|
|
42
|
+
setNodeStatus({
|
|
43
|
+
fill: "blue",
|
|
44
|
+
shape: "dot",
|
|
45
|
+
text: "-> LOWER PIN" + sAutoToggle,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
25
49
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
if (node.autoToggle > 0) {
|
|
51
|
+
node.timerAutoToggle = setTimeout(() => {
|
|
52
|
+
node.autoToggle = 0;
|
|
53
|
+
node.iRailway === 0 ? (node.iRailway = 1) : (node.iRailway = 0);
|
|
54
|
+
node.alignStatus();
|
|
55
|
+
}, node.autoToggle * 1000);
|
|
56
|
+
}
|
|
33
57
|
|
|
34
|
-
|
|
58
|
+
node.alignStatus();
|
|
35
59
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
this.on("input", function (msg) {
|
|
61
|
+
var sIncomingTopic = "";
|
|
62
|
+
if (msg.hasOwnProperty("topic")) {
|
|
63
|
+
// 06/11/2019
|
|
64
|
+
if (!msg.hasOwnProperty("topic") || msg.topic === undefined)
|
|
65
|
+
msg.topic = "NoTopicReceived";
|
|
66
|
+
sIncomingTopic = msg.topic.replace(
|
|
67
|
+
/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi,
|
|
68
|
+
""
|
|
69
|
+
); // Cut unwanted Characters
|
|
70
|
+
if (sIncomingTopic === node.sTriggerTopic) {
|
|
71
|
+
const utils = require("./utils.js");
|
|
72
|
+
let sPayload = utils.fetchFromObject(
|
|
73
|
+
msg,
|
|
74
|
+
config.payloadPropName || "payload"
|
|
75
|
+
);
|
|
43
76
|
|
|
77
|
+
// 15/11/2021 inform user about undefined topic or payload
|
|
78
|
+
if (sPayload === undefined) {
|
|
79
|
+
setNodeStatus({
|
|
80
|
+
fill: "red",
|
|
81
|
+
shape: "dot",
|
|
82
|
+
text: "Received invalid payload from " + msg.topic || "",
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
44
86
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
msg.payload = utils.ToBoolean(sPayload); // 15/11/2021 Convert input to boolean.
|
|
87
|
+
msg.payload = utils.ToBoolean(
|
|
88
|
+
sPayload,
|
|
89
|
+
RED.nodes.getNode(config.translatorConfig) // Retrieve the config node. It can be null, but it's handled in utils.js;
|
|
90
|
+
);
|
|
91
|
+
if (msg.payload === undefined) return null;
|
|
92
|
+
if (node.timerAutoToggle !== null)
|
|
93
|
+
// 28/01/2022 Stop autotoggle
|
|
94
|
+
clearInterval(node.timerAutoToggle);
|
|
55
95
|
|
|
56
|
-
|
|
57
|
-
|
|
96
|
+
if (msg.payload === false) node.iRailway = 0;
|
|
97
|
+
if (msg.payload === true) node.iRailway = 1;
|
|
98
|
+
if (node.iRailway === 0) {
|
|
99
|
+
setNodeStatus({
|
|
100
|
+
fill: "green",
|
|
101
|
+
shape: "dot",
|
|
102
|
+
text: "-> UPPER PIN",
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
setNodeStatus({ fill: "blue", shape: "dot", text: "-> LOWER PIN" });
|
|
106
|
+
}
|
|
107
|
+
return; // DONT'S SEND THIS MESSAGE
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
node.currentMsg = RED.util.cloneMessage(msg);
|
|
111
|
+
if (node.iRailway === 0) {
|
|
112
|
+
node.send([msg, null]);
|
|
113
|
+
} else {
|
|
114
|
+
node.send([null, msg]);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
58
118
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (node.iRailway === 0) {
|
|
62
|
-
setNodeStatus({ fill: "green", shape: "dot", text: "-> UPPER PIN" });
|
|
63
|
-
} else {
|
|
64
|
-
setNodeStatus({ fill: "blue", shape: "dot", text: "-> LOWER PIN" });
|
|
65
|
-
}
|
|
66
|
-
return; // DONT'S SEND THIS MESSAGE
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
node.currentMsg = RED.util.cloneMessage(msg);
|
|
70
|
-
if (node.iRailway === 0) {
|
|
71
|
-
node.send([msg, null]);
|
|
72
|
-
} else {
|
|
73
|
-
node.send([null, msg]);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
RED.nodes.registerType("RailwaySwitchUltimate", RailwaySwitchUltimate);
|
|
81
|
-
}
|
|
119
|
+
RED.nodes.registerType("RailwaySwitchUltimate", RailwaySwitchUltimate);
|
|
120
|
+
};
|