@bldgblocks/node-red-contrib-control 0.1.27 → 0.1.29
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/README.md +1 -1
- package/nodes/average-block.js +1 -1
- package/nodes/boolean-switch-block.html +2 -1
- package/nodes/boolean-switch-block.js +1 -2
- package/nodes/call-status-block.html +30 -45
- package/nodes/call-status-block.js +81 -195
- package/nodes/changeover-block.html +76 -12
- package/nodes/changeover-block.js +24 -8
- package/nodes/delay-block.html +1 -1
- package/nodes/frequency-block.html +3 -1
- package/nodes/frequency-block.js +64 -7
- package/nodes/global-getter.html +96 -0
- package/nodes/global-getter.js +42 -0
- package/nodes/global-setter.html +72 -0
- package/nodes/global-setter.js +43 -0
- package/nodes/hysteresis-block.js +1 -1
- package/nodes/latch-block.html +55 -0
- package/nodes/latch-block.js +77 -0
- package/nodes/on-change-block.html +0 -1
- package/nodes/on-change-block.js +2 -12
- package/nodes/pid-block.html +102 -80
- package/nodes/pid-block.js +120 -110
- package/nodes/rate-of-change-block.html +110 -0
- package/nodes/rate-of-change-block.js +233 -0
- package/nodes/string-builder-block.html +112 -0
- package/nodes/string-builder-block.js +89 -0
- package/nodes/tstat-block.html +85 -39
- package/nodes/tstat-block.js +66 -30
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ There are TONS of fantastic node libraries out there but usually focusing on one
|
|
|
24
24
|
- Node commands, such as 'reset' or 'mode' or changing setpoints via messages.
|
|
25
25
|
|
|
26
26
|
## How To Use
|
|
27
|
-
|
|
27
|
+
<img width="1049" height="131" alt="Screenshot_20251204_194633" src="https://github.com/user-attachments/assets/d29fb46d-c23d-4185-a9e7-f01ff1efdb81" />
|
|
28
28
|
|
|
29
29
|
The help section of every node describes the expected msg.context (data tag) for the intended msg.payload incoming. You can of course do this as you process data through a 'change' block, or use the provided 'contextual label' block which makes it easier to add and remove tags, more compact (especially if label hidden), and more transparent of the data flowing (ALL nodes contain complete status usage). Most nodes use a simple in1, in2, and so on.
|
|
30
30
|
|
package/nodes/average-block.js
CHANGED
|
@@ -47,7 +47,7 @@ module.exports = function(RED) {
|
|
|
47
47
|
// Acceptable fallbacks
|
|
48
48
|
if (isNaN(node.runtime.maxValues) || node.runtime.maxValues < 1) {
|
|
49
49
|
node.runtime.maxValues = 10;
|
|
50
|
-
node.status({ fill: "
|
|
50
|
+
node.status({ fill: "yellow", shape: "ring", text: "invalid window size, using 10" });
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Validate values
|
|
@@ -4,7 +4,7 @@ module.exports = function(RED) {
|
|
|
4
4
|
const node = this;
|
|
5
5
|
|
|
6
6
|
// Initialize state from config
|
|
7
|
-
node.state = config.state
|
|
7
|
+
node.state = config.state;
|
|
8
8
|
|
|
9
9
|
// Set initial status
|
|
10
10
|
node.status({
|
|
@@ -79,7 +79,6 @@ module.exports = function(RED) {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
node.on("close", function(done) {
|
|
82
|
-
node.status({});
|
|
83
82
|
done();
|
|
84
83
|
});
|
|
85
84
|
}
|
|
@@ -13,15 +13,7 @@
|
|
|
13
13
|
<input type="number" id="node-input-clearDelay" placeholder="10" min="0.01" step="any">
|
|
14
14
|
</div>
|
|
15
15
|
<div class="form-row">
|
|
16
|
-
<label for="node-input-
|
|
17
|
-
<input type="checkbox" id="node-input-normalOff" style="width: auto; vertical-align: middle;">
|
|
18
|
-
</div>
|
|
19
|
-
<div class="form-row">
|
|
20
|
-
<label for="node-input-normalOn" title="Expected status when call is on (boolean)"><i class="fa fa-power-off"></i> Normal On</label>
|
|
21
|
-
<input type="checkbox" id="node-input-normalOn" style="width: auto; vertical-align: middle;">
|
|
22
|
-
</div>
|
|
23
|
-
<div class="form-row">
|
|
24
|
-
<label for="node-input-runLostStatus" title="Alarm if status doesn't match normalOn during call (boolean)"><i class="fa fa-exclamation-triangle"></i> Run Lost Status</label>
|
|
16
|
+
<label for="node-input-runLostStatus" title="Alarm if status is lost during call (boolean)"><i class="fa fa-exclamation-triangle"></i> Run Lost Status</label>
|
|
25
17
|
<input type="checkbox" id="node-input-runLostStatus" style="width: auto; vertical-align: middle;">
|
|
26
18
|
</div>
|
|
27
19
|
<div class="form-row">
|
|
@@ -47,17 +39,15 @@
|
|
|
47
39
|
name: { value: "" },
|
|
48
40
|
statusTimeout: { value: 30, required: true, validate: function(v) { return !isNaN(parseFloat(v)) && parseFloat(v) > 0; } },
|
|
49
41
|
clearDelay: { value: 10, required: true, validate: function(v) { return !isNaN(parseFloat(v)) && parseFloat(v) > 0; } },
|
|
50
|
-
normalOff: { value: false },
|
|
51
|
-
normalOn: { value: true },
|
|
52
42
|
runLostStatus: { value: false },
|
|
53
43
|
noStatusOnRun: { value: true },
|
|
54
44
|
runLostStatusMessage: { value: "Status lost during run" },
|
|
55
45
|
noStatusOnRunMessage: { value: "No status received during run" }
|
|
56
46
|
},
|
|
57
47
|
inputs: 1,
|
|
58
|
-
outputs:
|
|
48
|
+
outputs: 1,
|
|
59
49
|
inputLabels: ["input"],
|
|
60
|
-
outputLabels: ["
|
|
50
|
+
outputLabels: ["output"],
|
|
61
51
|
icon: "font-awesome/fa-phone",
|
|
62
52
|
paletteLabel: "call status",
|
|
63
53
|
label: function() {
|
|
@@ -68,44 +58,39 @@
|
|
|
68
58
|
|
|
69
59
|
<!-- Help Section -->
|
|
70
60
|
<script type="text/markdown" data-help-name="call-status-block">
|
|
71
|
-
|
|
61
|
+
Monitors call and status signals with alarm diagnostics.
|
|
72
62
|
|
|
73
63
|
### Inputs
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
- payload (boolean): Call activation/deactivation signal
|
|
65
|
+
- status (boolean): Status response from equipment (only processed when call is active)
|
|
76
66
|
|
|
77
67
|
### Outputs
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
- call (boolean): Current call state
|
|
69
|
+
- status (object): `{ call: boolean, status: boolean, alarm: boolean, alarmMessage: string, timeout: boolean, neverReceivedStatus: boolean }`
|
|
80
70
|
|
|
81
71
|
### Properties
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
: runLostStatusMessage (string) : Message for run lost status alarm.
|
|
90
|
-
: noStatusOnRunMessage (string) : Message for no status on run alarm.
|
|
72
|
+
- name (string): Display name in editor
|
|
73
|
+
- statusTimeout (number): Time to wait for status response (seconds, > 0)
|
|
74
|
+
- clearDelay (number): Delay before clearing status and alarm after call ends (seconds, > 0)
|
|
75
|
+
- runLostStatus (boolean): Alarm if status is lost during call
|
|
76
|
+
- noStatusOnRun (boolean): Alarm if no status received during call
|
|
77
|
+
- runLostStatusMessage (string): Message for status lost alarm
|
|
78
|
+
- noStatusOnRunMessage (string): Message for no status alarm
|
|
91
79
|
|
|
92
|
-
###
|
|
93
|
-
|
|
80
|
+
### Alarm Conditions
|
|
81
|
+
1. Status without call: Status=true when call=false (immediate alarm)
|
|
82
|
+
2. No status during call: No status received within timeout period (after statusTimeout)
|
|
83
|
+
3. Lost status during call: Status=false when call=true and status was previously received (immediate alarm)
|
|
94
84
|
|
|
95
|
-
|
|
85
|
+
### Behavior
|
|
86
|
+
- When call is activated: Expects status=true response
|
|
87
|
+
- Status is only processed when call is active
|
|
88
|
+
- Clears all state after clearDelay when call ends
|
|
89
|
+
- Timer acts as a blocking gate for status reception
|
|
96
90
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
- Blue (dot): Output, no alarm
|
|
104
|
-
- Red (dot): Output with alarm
|
|
105
|
-
- Red (ring): Errors
|
|
106
|
-
- Yellow (ring): Unknown context
|
|
107
|
-
|
|
108
|
-
### References
|
|
109
|
-
- [Node-RED Documentation](https://nodered.org/docs/)
|
|
110
|
-
- [GitHub Repository](https://github.com/BldgBlocks/node-red-contrib-buildingblocks-control.git)
|
|
111
|
-
</script>
|
|
91
|
+
### Status Indicators
|
|
92
|
+
- Green (ring): Configuration errors
|
|
93
|
+
- Blue (dot): Normal operation, no alarms
|
|
94
|
+
- Red (dot): Active alarm condition
|
|
95
|
+
- Yellow (ring): Invalid input
|
|
96
|
+
</script>
|
|
@@ -3,255 +3,140 @@ module.exports = function(RED) {
|
|
|
3
3
|
RED.nodes.createNode(this, config);
|
|
4
4
|
const node = this;
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// Simplified runtime state
|
|
7
7
|
node.runtime = {
|
|
8
|
-
name: config.name || "",
|
|
9
|
-
statusTimeout: parseFloat(config.statusTimeout),
|
|
10
|
-
clearDelay: parseFloat(config.clearDelay),
|
|
11
|
-
normalOff: config.normalOff === true,
|
|
12
|
-
normalOn: config.normalOn === true,
|
|
13
|
-
runLostStatus: config.runLostStatus === true,
|
|
14
|
-
noStatusOnRun: config.noStatusOnRun === true,
|
|
15
|
-
runLostStatusMessage: config.runLostStatusMessage,
|
|
16
|
-
noStatusOnRunMessage: config.noStatusOnRunMessage,
|
|
17
8
|
call: false,
|
|
18
9
|
status: false,
|
|
19
10
|
alarm: false,
|
|
20
11
|
alarmMessage: "",
|
|
21
12
|
statusTimer: null,
|
|
22
|
-
|
|
13
|
+
neverReceivedStatus: true // Track if we've ever gotten status during this call
|
|
23
14
|
};
|
|
24
15
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
16
|
+
// Configuration with validation
|
|
17
|
+
node.config = {
|
|
18
|
+
statusTimeout: Math.max(parseFloat(config.statusTimeout) || 30, 0.01),
|
|
19
|
+
runLostStatus: config.runLostStatus === true,
|
|
20
|
+
noStatusOnRun: config.noStatusOnRun === true,
|
|
21
|
+
runLostStatusMessage: config.runLostStatusMessage,
|
|
22
|
+
noStatusOnRunMessage: config.noStatusOnRunMessage
|
|
23
|
+
};
|
|
34
24
|
|
|
35
25
|
node.on("input", function(msg, send, done) {
|
|
36
26
|
send = send || function() { node.send.apply(node, arguments); };
|
|
37
27
|
|
|
38
|
-
//
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Handle context updates
|
|
46
|
-
if (msg.hasOwnProperty("context")) {
|
|
47
|
-
if (!msg.hasOwnProperty("payload")) {
|
|
48
|
-
node.status({ fill: "red", shape: "ring", text: `missing payload for ${msg.context}` });
|
|
28
|
+
// Handle status input
|
|
29
|
+
if (msg.hasOwnProperty("context") && msg.context === "status") {
|
|
30
|
+
if (typeof msg.payload !== "boolean") {
|
|
31
|
+
node.status({ fill: "red", shape: "ring", text: "invalid status" });
|
|
49
32
|
if (done) done();
|
|
50
33
|
return;
|
|
51
34
|
}
|
|
52
35
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const value = parseFloat(msg.payload);
|
|
57
|
-
if (isNaN(value) || value <= 0) {
|
|
58
|
-
node.status({ fill: "red", shape: "ring", text: `invalid ${msg.context}` });
|
|
59
|
-
if (done) done();
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
node.runtime[msg.context] = value;
|
|
63
|
-
if (node.runtime.statusTimer) {
|
|
64
|
-
clearTimeout(node.runtime.statusTimer);
|
|
65
|
-
node.runtime.statusTimer = null;
|
|
66
|
-
if (node.runtime.noStatusOnRun && node.runtime.call) {
|
|
67
|
-
node.runtime.statusTimer = setTimeout(() => {
|
|
68
|
-
if (!node.runtime.status) {
|
|
69
|
-
node.runtime.alarm = true;
|
|
70
|
-
node.runtime.alarmMessage = node.runtime.noStatusOnRunMessage;
|
|
71
|
-
node.status({ fill: "red", shape: "dot", text: `no status on run, alarm: true` });
|
|
72
|
-
send(sendOutputs());
|
|
73
|
-
}
|
|
74
|
-
node.runtime.statusTimer = null;
|
|
75
|
-
}, node.runtime.statusTimeout * 1000);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
node.status({
|
|
79
|
-
fill: "green",
|
|
80
|
-
shape: "dot",
|
|
81
|
-
text: `${msg.context}: ${value.toFixed(2)}`
|
|
82
|
-
});
|
|
83
|
-
if (done) done();
|
|
84
|
-
return;
|
|
85
|
-
case "normalOff":
|
|
86
|
-
case "normalOn":
|
|
87
|
-
case "runLostStatus":
|
|
88
|
-
case "noStatusOnRun":
|
|
89
|
-
if (typeof msg.payload !== "boolean") {
|
|
90
|
-
node.status({ fill: "red", shape: "ring", text: `invalid ${msg.context}` });
|
|
91
|
-
if (done) done();
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
node.runtime[msg.context] = msg.payload;
|
|
95
|
-
if (msg.context === "noStatusOnRun" && !msg.payload && node.runtime.statusTimer) {
|
|
96
|
-
clearTimeout(node.runtime.statusTimer);
|
|
97
|
-
node.runtime.statusTimer = null;
|
|
98
|
-
} else if (msg.context === "noStatusOnRun" && msg.payload && node.runtime.call && !node.runtime.status) {
|
|
99
|
-
node.runtime.statusTimer = setTimeout(() => {
|
|
100
|
-
if (!node.runtime.status) {
|
|
101
|
-
node.runtime.alarm = true;
|
|
102
|
-
node.runtime.alarmMessage = node.runtime.noStatusOnRunMessage;
|
|
103
|
-
node.status({ fill: "red", shape: "dot", text: `no status on run, alarm: true` });
|
|
104
|
-
send(sendOutputs());
|
|
105
|
-
}
|
|
106
|
-
node.runtime.statusTimer = null;
|
|
107
|
-
}, node.runtime.statusTimeout * 1000);
|
|
108
|
-
}
|
|
109
|
-
node.status({
|
|
110
|
-
fill: "green",
|
|
111
|
-
shape: "dot",
|
|
112
|
-
text: `${msg.context}: ${msg.payload}`
|
|
113
|
-
});
|
|
114
|
-
send(checkStatusConditions());
|
|
115
|
-
if (done) done();
|
|
116
|
-
return;
|
|
117
|
-
case "runLostStatusMessage":
|
|
118
|
-
case "noStatusOnRunMessage":
|
|
119
|
-
if (typeof msg.payload !== "string") {
|
|
120
|
-
node.status({ fill: "red", shape: "ring", text: `invalid ${msg.context}` });
|
|
121
|
-
if (done) done();
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
node.runtime[msg.context] = msg.payload;
|
|
125
|
-
node.status({
|
|
126
|
-
fill: "green",
|
|
127
|
-
shape: "dot",
|
|
128
|
-
text: `${msg.context} set`
|
|
129
|
-
});
|
|
130
|
-
if (node.runtime.alarm && node.runtime.alarmMessage === (msg.context === "runLostStatusMessage" ? node.runtime.noStatusOnRunMessage : node.runtime.runLostStatusMessage)) {
|
|
131
|
-
node.runtime.alarmMessage = msg.payload;
|
|
132
|
-
send(sendOutputs());
|
|
133
|
-
}
|
|
134
|
-
if (done) done();
|
|
135
|
-
return;
|
|
136
|
-
case "status":
|
|
137
|
-
if (typeof msg.payload !== "boolean") {
|
|
138
|
-
node.status({ fill: "red", shape: "ring", text: "invalid status" });
|
|
139
|
-
if (done) done();
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (!node.runtime.call) {
|
|
143
|
-
node.status({ fill: "red", shape: "ring", text: "status ignored" });
|
|
144
|
-
if (done) done();
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
node.runtime.status = msg.payload;
|
|
148
|
-
if (node.runtime.status && node.runtime.statusTimer) {
|
|
149
|
-
clearTimeout(node.runtime.statusTimer);
|
|
150
|
-
node.runtime.statusTimer = null;
|
|
151
|
-
node.runtime.alarm = false;
|
|
152
|
-
node.runtime.alarmMessage = "";
|
|
153
|
-
}
|
|
154
|
-
send(checkStatusConditions());
|
|
155
|
-
if (done) done();
|
|
156
|
-
return;
|
|
157
|
-
default:
|
|
158
|
-
node.status({ fill: "yellow", shape: "ring", text: "unknown context" });
|
|
159
|
-
if (done) done("Unknown context");
|
|
160
|
-
return;
|
|
36
|
+
if (msg.context === node.runtime.status) {
|
|
37
|
+
if (done) done();
|
|
38
|
+
return;
|
|
161
39
|
}
|
|
40
|
+
|
|
41
|
+
node.runtime.status = msg.payload;
|
|
42
|
+
node.runtime.neverReceivedStatus = false;
|
|
43
|
+
|
|
44
|
+
// Clear any pending status timeout
|
|
45
|
+
if (node.runtime.statusTimer) {
|
|
46
|
+
clearTimeout(node.runtime.statusTimer);
|
|
47
|
+
node.runtime.statusTimer = null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check alarm conditions
|
|
51
|
+
checkAlarmConditions();
|
|
52
|
+
send(sendOutputs());
|
|
53
|
+
updateStatus();
|
|
54
|
+
|
|
55
|
+
if (done) done();
|
|
56
|
+
return;
|
|
162
57
|
}
|
|
163
58
|
|
|
164
|
-
//
|
|
59
|
+
// Handle call input (must be boolean)
|
|
165
60
|
if (typeof msg.payload !== "boolean") {
|
|
166
|
-
node.status({ fill: "red", shape: "ring", text: "invalid call" });
|
|
61
|
+
node.status({ fill: "red", shape: "ring", text: "invalid call payload" });
|
|
167
62
|
if (done) done();
|
|
168
63
|
return;
|
|
169
64
|
}
|
|
170
65
|
|
|
171
|
-
// Process call change
|
|
66
|
+
// Process call state change
|
|
172
67
|
if (msg.payload !== node.runtime.call) {
|
|
173
68
|
node.runtime.call = msg.payload;
|
|
174
69
|
|
|
175
|
-
// Clear existing
|
|
70
|
+
// Clear existing timer
|
|
176
71
|
if (node.runtime.statusTimer) {
|
|
177
72
|
clearTimeout(node.runtime.statusTimer);
|
|
178
73
|
node.runtime.statusTimer = null;
|
|
179
74
|
}
|
|
180
|
-
if (node.runtime.clearTimer) {
|
|
181
|
-
clearTimeout(node.runtime.clearTimer);
|
|
182
|
-
node.runtime.clearTimer = null;
|
|
183
|
-
}
|
|
184
75
|
|
|
185
76
|
if (node.runtime.call) {
|
|
186
|
-
//
|
|
187
|
-
node.runtime.
|
|
77
|
+
// Call activated - reset tracking, set timeout if needed
|
|
78
|
+
node.runtime.neverReceivedStatus = true;
|
|
188
79
|
node.runtime.alarm = false;
|
|
189
80
|
node.runtime.alarmMessage = "";
|
|
190
|
-
|
|
81
|
+
|
|
82
|
+
if (node.config.noStatusOnRun) {
|
|
83
|
+
// Set timer for "never got status" condition
|
|
191
84
|
node.runtime.statusTimer = setTimeout(() => {
|
|
192
|
-
if (
|
|
85
|
+
if (node.runtime.neverReceivedStatus) {
|
|
193
86
|
node.runtime.alarm = true;
|
|
194
|
-
node.runtime.alarmMessage = node.
|
|
195
|
-
node.status({ fill: "red", shape: "dot", text: `no status on run, alarm: true` });
|
|
196
|
-
send(sendOutputs());
|
|
87
|
+
node.runtime.alarmMessage = node.config.noStatusOnRunMessage;
|
|
197
88
|
}
|
|
89
|
+
send(sendOutputs());
|
|
90
|
+
updateStatus();
|
|
198
91
|
node.runtime.statusTimer = null;
|
|
199
|
-
}, node.
|
|
92
|
+
}, node.config.statusTimeout * 1000);
|
|
200
93
|
}
|
|
201
94
|
} else {
|
|
202
|
-
|
|
203
|
-
node.runtime.
|
|
204
|
-
|
|
205
|
-
node.runtime.alarm = false;
|
|
206
|
-
node.runtime.alarmMessage = "";
|
|
207
|
-
send(sendOutputs());
|
|
208
|
-
updateStatus();
|
|
209
|
-
node.runtime.clearTimer = null;
|
|
210
|
-
}, node.runtime.clearDelay * 1000);
|
|
95
|
+
node.runtime.status = false;
|
|
96
|
+
node.runtime.alarm = false;
|
|
97
|
+
node.runtime.alarmMessage = "";
|
|
211
98
|
}
|
|
212
|
-
|
|
213
|
-
|
|
99
|
+
|
|
100
|
+
// Check alarm conditions
|
|
101
|
+
checkAlarmConditions();
|
|
102
|
+
send(sendOutputs());
|
|
214
103
|
updateStatus();
|
|
215
104
|
}
|
|
216
105
|
|
|
217
106
|
if (done) done();
|
|
218
107
|
|
|
219
|
-
function
|
|
220
|
-
if (node.runtime.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
node.status({ fill: "red", shape: "dot", text: `run lost, alarm: true` });
|
|
225
|
-
return sendOutputs();
|
|
226
|
-
}
|
|
108
|
+
function checkAlarmConditions() {
|
|
109
|
+
if (node.runtime.status && !node.runtime.call) {
|
|
110
|
+
node.runtime.alarm = true;
|
|
111
|
+
node.runtime.alarmMessage = "Status active without call";
|
|
112
|
+
return;
|
|
227
113
|
}
|
|
228
|
-
|
|
114
|
+
|
|
115
|
+
if (node.runtime.call && !node.runtime.status && !node.runtime.neverReceivedStatus && node.config.runLostStatus) {
|
|
229
116
|
node.runtime.alarm = true;
|
|
230
|
-
node.runtime.alarmMessage =
|
|
231
|
-
|
|
232
|
-
return sendOutputs();
|
|
117
|
+
node.runtime.alarmMessage = node.config.runLostStatusMessage;
|
|
118
|
+
return;
|
|
233
119
|
}
|
|
234
|
-
|
|
120
|
+
|
|
121
|
+
// No alarm conditions met. Don't clear alarm if timer is still running
|
|
122
|
+
if (!node.runtime.statusTimer) {
|
|
235
123
|
node.runtime.alarm = false;
|
|
236
124
|
node.runtime.alarmMessage = "";
|
|
237
125
|
}
|
|
238
|
-
updateStatus();
|
|
239
|
-
return sendOutputs();
|
|
240
126
|
}
|
|
241
127
|
|
|
242
128
|
function sendOutputs() {
|
|
243
|
-
return
|
|
244
|
-
|
|
245
|
-
{
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
129
|
+
return {
|
|
130
|
+
payload: node.runtime.call,
|
|
131
|
+
status: {
|
|
132
|
+
call: node.runtime.call,
|
|
133
|
+
status: node.runtime.status,
|
|
134
|
+
alarm: node.runtime.alarm,
|
|
135
|
+
alarmMessage: node.runtime.alarmMessage,
|
|
136
|
+
timeout: !!node.runtime.statusTimer,
|
|
137
|
+
neverReceivedStatus: node.runtime.neverReceivedStatus
|
|
253
138
|
}
|
|
254
|
-
|
|
139
|
+
};
|
|
255
140
|
}
|
|
256
141
|
|
|
257
142
|
function updateStatus() {
|
|
@@ -264,11 +149,12 @@ module.exports = function(RED) {
|
|
|
264
149
|
});
|
|
265
150
|
|
|
266
151
|
node.on("close", function(done) {
|
|
267
|
-
if (node.runtime.statusTimer)
|
|
268
|
-
|
|
152
|
+
if (node.runtime.statusTimer) {
|
|
153
|
+
clearTimeout(node.runtime.statusTimer);
|
|
154
|
+
}
|
|
269
155
|
done();
|
|
270
156
|
});
|
|
271
157
|
}
|
|
272
158
|
|
|
273
159
|
RED.nodes.registerType("call-status-block", CallStatusBlockNode);
|
|
274
|
-
};
|
|
160
|
+
};
|