@bldgblocks/node-red-contrib-control 0.1.33 → 0.1.36

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.
Files changed (113) hide show
  1. package/nodes/accumulate-block.html +18 -8
  2. package/nodes/accumulate-block.js +39 -44
  3. package/nodes/add-block.html +1 -1
  4. package/nodes/add-block.js +18 -11
  5. package/nodes/alarm-collector.html +260 -0
  6. package/nodes/alarm-collector.js +292 -0
  7. package/nodes/alarm-config.html +129 -0
  8. package/nodes/alarm-config.js +126 -0
  9. package/nodes/alarm-service.html +96 -0
  10. package/nodes/alarm-service.js +142 -0
  11. package/nodes/analog-switch-block.js +25 -36
  12. package/nodes/and-block.js +44 -15
  13. package/nodes/average-block.js +46 -41
  14. package/nodes/boolean-switch-block.js +10 -28
  15. package/nodes/boolean-to-number-block.html +18 -5
  16. package/nodes/boolean-to-number-block.js +24 -16
  17. package/nodes/cache-block.js +24 -37
  18. package/nodes/call-status-block.html +91 -32
  19. package/nodes/call-status-block.js +398 -115
  20. package/nodes/changeover-block.html +5 -0
  21. package/nodes/changeover-block.js +167 -162
  22. package/nodes/comment-block.html +1 -1
  23. package/nodes/comment-block.js +14 -9
  24. package/nodes/compare-block.html +14 -4
  25. package/nodes/compare-block.js +23 -18
  26. package/nodes/contextual-label-block.html +5 -0
  27. package/nodes/contextual-label-block.js +6 -16
  28. package/nodes/convert-block.html +25 -39
  29. package/nodes/convert-block.js +31 -16
  30. package/nodes/count-block.html +11 -5
  31. package/nodes/count-block.js +34 -32
  32. package/nodes/delay-block.js +58 -53
  33. package/nodes/divide-block.js +43 -45
  34. package/nodes/edge-block.html +17 -10
  35. package/nodes/edge-block.js +43 -41
  36. package/nodes/enum-switch-block.js +6 -6
  37. package/nodes/frequency-block.html +6 -1
  38. package/nodes/frequency-block.js +64 -74
  39. package/nodes/global-getter.html +51 -15
  40. package/nodes/global-getter.js +74 -67
  41. package/nodes/global-setter.html +1 -1
  42. package/nodes/global-setter.js +168 -188
  43. package/nodes/history-buffer.html +96 -0
  44. package/nodes/history-buffer.js +461 -0
  45. package/nodes/history-collector.html +29 -1
  46. package/nodes/history-collector.js +37 -16
  47. package/nodes/history-config.html +13 -1
  48. package/nodes/history-service.html +84 -0
  49. package/nodes/history-service.js +52 -0
  50. package/nodes/hysteresis-block.html +5 -0
  51. package/nodes/hysteresis-block.js +13 -16
  52. package/nodes/interpolate-block.html +20 -2
  53. package/nodes/interpolate-block.js +39 -50
  54. package/nodes/join.html +78 -0
  55. package/nodes/join.js +78 -0
  56. package/nodes/latch-block.js +12 -14
  57. package/nodes/load-sequence-block.js +102 -110
  58. package/nodes/max-block.js +26 -26
  59. package/nodes/memory-block.js +57 -58
  60. package/nodes/min-block.js +26 -25
  61. package/nodes/minmax-block.js +35 -34
  62. package/nodes/modulo-block.js +45 -43
  63. package/nodes/multiply-block.js +43 -41
  64. package/nodes/negate-block.html +17 -7
  65. package/nodes/negate-block.js +25 -19
  66. package/nodes/network-point-read.html +128 -0
  67. package/nodes/network-point-read.js +230 -0
  68. package/nodes/{network-register.html → network-point-register.html} +94 -7
  69. package/nodes/network-point-register.js +126 -0
  70. package/nodes/network-point-write.html +149 -0
  71. package/nodes/network-point-write.js +222 -0
  72. package/nodes/network-service-bridge.html +131 -0
  73. package/nodes/network-service-bridge.js +376 -0
  74. package/nodes/network-service-read.html +81 -0
  75. package/nodes/network-service-read.js +58 -0
  76. package/nodes/{network-point-registry.html → network-service-registry.html} +19 -4
  77. package/nodes/{network-point-registry.js → network-service-registry.js} +7 -2
  78. package/nodes/network-service-write.html +89 -0
  79. package/nodes/network-service-write.js +83 -0
  80. package/nodes/nullify-block.js +13 -15
  81. package/nodes/on-change-block.html +17 -9
  82. package/nodes/on-change-block.js +49 -46
  83. package/nodes/oneshot-block.html +13 -10
  84. package/nodes/oneshot-block.js +57 -75
  85. package/nodes/or-block.js +44 -15
  86. package/nodes/pid-block.html +54 -4
  87. package/nodes/pid-block.js +459 -248
  88. package/nodes/priority-block.js +24 -35
  89. package/nodes/rate-limit-block.js +70 -72
  90. package/nodes/rate-of-change-block.html +33 -14
  91. package/nodes/rate-of-change-block.js +74 -62
  92. package/nodes/round-block.html +14 -9
  93. package/nodes/round-block.js +32 -25
  94. package/nodes/saw-tooth-wave-block.js +49 -76
  95. package/nodes/scale-range-block.html +12 -6
  96. package/nodes/scale-range-block.js +46 -39
  97. package/nodes/sine-wave-block.js +49 -57
  98. package/nodes/string-builder-block.js +6 -6
  99. package/nodes/subtract-block.js +38 -34
  100. package/nodes/thermistor-block.js +44 -44
  101. package/nodes/tick-tock-block.js +32 -32
  102. package/nodes/time-sequence-block.js +30 -42
  103. package/nodes/triangle-wave-block.js +49 -69
  104. package/nodes/tstat-block.js +34 -44
  105. package/nodes/units-block.html +90 -69
  106. package/nodes/units-block.js +22 -30
  107. package/nodes/utils.js +275 -3
  108. package/package.json +14 -6
  109. package/nodes/network-read.html +0 -56
  110. package/nodes/network-read.js +0 -59
  111. package/nodes/network-register.js +0 -161
  112. package/nodes/network-write.html +0 -64
  113. package/nodes/network-write.js +0 -126
@@ -1,161 +0,0 @@
1
- module.exports = function(RED) {
2
- function NetworkRegisterNode(config) {
3
- RED.nodes.createNode(this, config);
4
- const node = this;
5
-
6
- // Config
7
- node.registry = RED.nodes.getNode(config.registry);
8
- node.pointId = parseInt(config.pointId);
9
- node.writable = !!config.writable;
10
- node.isRegistered = false;
11
-
12
- // Initial Registration
13
- if (node.registry && !isNaN(node.pointId)) {
14
- const success = node.registry.register(node.pointId, {
15
- nodeId: node.id, // for point registry collision checks
16
- writable: node.writable,
17
- path: "not ready",
18
- store: "not ready"
19
- });
20
-
21
- if (success) {
22
- node.isRegistered = true;
23
- node.status({ fill: "blue", shape: "ring", text: `ID: ${node.pointId} (Waiting)` });
24
- } else {
25
- node.error(`Point ID ${node.pointId} is already in use.`);
26
- node.status({ fill: "red", shape: "dot", text: "ID Conflict" });
27
- }
28
- }
29
-
30
- node.on("input", function(msg, send, done) {
31
- send = send || function() { node.send.apply(node, arguments); };
32
-
33
- // Nothing to do. Return.
34
- if (!node.isRegistered) {
35
- node.status({ fill: "red", shape: "ring", text: `Not registered` });
36
- if (done) done();
37
- return;
38
- }
39
-
40
- if (!msg || typeof msg !== "object") {
41
- const message = `Invalid msg.`;
42
- node.status({ fill: "red", shape: "ring", text: `${message}` });
43
- if (done) done();
44
- return;
45
- }
46
-
47
- if (!node.registry) {
48
- const message = `Registry not found. Create config node.`;
49
- node.status({ fill: "red", shape: "ring", text: `${message}` });
50
- msg.status = { status: "fail", pointId: node.pointId, error: `${message}` };
51
- node.send(msg);
52
- if (done) done();
53
- return;
54
- }
55
-
56
- // Message should contain data & metadata from a global setter node
57
- const missingFields = [];
58
-
59
- if (!msg.metadata) missingFields.push("metadata");
60
- if (msg.value === undefined) missingFields.push("value");
61
- if (msg.units === undefined) missingFields.push("units");
62
- if (!msg.activePriority) missingFields.push("activePriority");
63
-
64
- // Check nested metadata properties
65
- if (msg.metadata) {
66
- if (!msg.metadata.path) missingFields.push("metadata.path");
67
- if (!msg.metadata.store) missingFields.push("metadata.store");
68
- if (!msg.metadata.sourceId) missingFields.push("metadata.sourceId");
69
- } else {
70
- missingFields.push("metadata (entire object)");
71
- }
72
-
73
- if (missingFields.length > 0) {
74
- const specificMessage = `Missing required fields: ${missingFields.join(', ')}`;
75
- node.status({
76
- fill: "red",
77
- shape: "ring",
78
- text: `${missingFields.length} missing: ${missingFields.slice(0, 3).join(', ')}${missingFields.length > 3 ? '...' : ''}`
79
- });
80
-
81
- node.send(msg);
82
- if (done) done();
83
- return;
84
- }
85
-
86
-
87
- // Lookup current registration
88
- let pointData = node.registry.lookup(node.pointId);
89
-
90
- const incoming = {
91
- writable: node.writable,
92
- path: msg.metadata.path,
93
- store: msg.metadata.store
94
- };
95
-
96
- // Update Registry on change
97
- if (!pointData
98
- || pointData.nodeId !== node.nodeId
99
- || pointData.writable !== incoming.writable
100
- || pointData.path !== incoming.path
101
- || pointData.store !== incoming.store) {
102
-
103
- node.registry.register(node.pointId, {
104
- nodeId: node.id, // for point registry collision checks
105
- writable: node.writable,
106
- path: msg.metadata.path,
107
- store: msg.metadata.store
108
- });
109
-
110
- pointData = node.registry.lookup(node.pointId);
111
-
112
- let globalData = {};
113
- globalData = node.context().global.get(pointData.path, pointData.store);
114
-
115
- if (globalData === null || Object.keys(globalData).length === 0) {
116
- const message = `Global data doesn't exist for (${pointData.store ?? "default"})::${pointData.path}::${node.pointId}`;
117
- node.status({ fill: "red", shape: "ring", text: `${message}` });
118
- msg.status = { status: "fail", pointId: node.pointId, error: `${message}` };
119
- if (done) done();
120
- return;
121
- }
122
-
123
- let network = {
124
- registry: node.registry.name,
125
- pointId: node.pointId,
126
- writable: node.writable
127
- }
128
-
129
- const networkObject = { ...globalData, network: network};
130
- const message = `Registered: (${pointData.store ?? "default"})::${pointData.path}::${node.pointId}`;
131
-
132
- node.context().global.set(pointData.path, networkObject, pointData.store);
133
- node.status({ fill: "blue", shape: "dot", text: `${message}` });
134
- msg.status = { status: "success", pointId: node.pointId, error: `${message}` };
135
-
136
- node.send(networkObject);
137
- if (done) done();
138
- return;
139
- }
140
-
141
- // Make it here, then message should match global and ready to go
142
- // Pass through msg
143
- const prefix = msg.activePriority === 'default' ? '' : 'P';
144
- const message = `Passthrough: ${prefix}${msg.activePriority}:${msg.value}${msg.units}`;
145
- node.status({ fill: "blue", shape: "ring", text: message });
146
-
147
- node.send(msg);
148
- if (done) done();
149
- return;
150
- });
151
-
152
- // Cleanup
153
- node.on('close', function(removed, done) {
154
- if (removed && node.registry && node.isRegistered) {
155
- node.registry.unregister(node.pointId, node.pointId);
156
- }
157
- done();
158
- });
159
- }
160
- RED.nodes.registerType("network-register", NetworkRegisterNode);
161
- }
@@ -1,64 +0,0 @@
1
- <script type="text/html" data-template-name="network-write">
2
- <div class="form-row">
3
- <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
4
- <input type="text" id="node-input-name" placeholder="Name">
5
- </div>
6
- <div class="form-row">
7
- <label for="node-input-registry"><i class="fa fa-book"></i> Registry</label>
8
- <input type="text" id="node-input-registry">
9
- </div>
10
-
11
- <div class="form-tips">
12
- <b>Input Payload Format:</b><br>
13
- <pre>
14
- {
15
- "action": "write",
16
- "pointId": 101,
17
- "priority": 8,
18
- "value": 75.5 // or null || "null" to release
19
- }
20
- </pre>
21
- </div>
22
- </script>
23
-
24
- <script type="text/javascript">
25
- RED.nodes.registerType('network-write', {
26
- category: 'bldgblocks network',
27
- color: '#3090C7',
28
- defaults: {
29
- name: { value: "" },
30
- registry: { value: "", type: "network-point-registry", required: true }
31
- },
32
- inputs: 1,
33
- outputs: 1,
34
- icon: "font-awesome/fa-list-ol",
35
- label: function() {
36
- return this.name || "network write";
37
- },
38
- paletteLabel: "network write",
39
- oneditprepare: function() {
40
-
41
- }
42
- });
43
- </script>
44
-
45
- <script type="text/markdown" data-help-name="network-write">
46
- Writes network commands to Global Variables using the Priority Array logic.
47
-
48
- ### Input
49
- : payload (object) : A command object containing
50
- * `pointId` (number): The integer ID of the point.
51
- * `priority` (number): The priority level (1-16) to write to.
52
- * `value` (any): The value to set. Send `null` to relinquish (clear) this priority level.
53
-
54
- ### Output
55
- : payload (object) : Confirmation object containing status, pointId, and the new calculated "Winner" value.
56
-
57
- ### Details
58
- This node acts as the inbound gateway.
59
- 1. It looks up the `pointId` in the selected **Registry** to find the corresponding Global Variable path.
60
- 2. It fetches the current State Object.
61
- 3. It updates the specific slot in the `priority` array based on the command.
62
- 4. It recalculates the "Present Value" (highest priority active).
63
- 5. It saves the Global Variable and emits an update event, triggering any reactive Getters immediately.
64
- </script>
@@ -1,126 +0,0 @@
1
- module.exports = function(RED) {
2
- function NetworkWriteNode(config) {
3
- RED.nodes.createNode(this, config);
4
- const node = this;
5
-
6
- node.registry = RED.nodes.getNode(config.registry);
7
-
8
- node.on("input", function(msg, send, done) {
9
- send = send || function() { node.send.apply(node, arguments); };
10
-
11
- // Expecting: msg.payload = { pointId, priority, value }
12
- if (!msg || !msg.pointId || !msg.priority || msg.value === undefined) {
13
- node.status({ fill: "red", shape: "dot", text: "Invalid msg properties" });
14
- msg.status = { status: "fail", pointId: msg.pointId, error: `Invalid msg properties` };
15
-
16
- node.send(msg);
17
- if (done) done();
18
- return;
19
- }
20
-
21
- // Lookup Path
22
- const entry = node.registry.lookup(msg.pointId);
23
- const store = entry.store ?? "default";
24
- const path = entry.path;
25
- if (!entry || !path) {
26
- node.status({ fill: "red", shape: "dot", text: `Unknown ID: (${store})::${path}::${msg.pointId}` });
27
- msg.status = { status: "fail", pointId: msg.pointId, error: `Unknown ID: (${store})::${path}::${msg.pointId}` };
28
-
29
- node.send(msg);
30
- if (done) done();
31
- return;
32
- }
33
-
34
- // Check Writable
35
- if (!entry.writable) {
36
- node.status({ fill: "red", shape: "dot", text: `Not Writable: (${store})::${path}::${msg.pointId}` });
37
- msg.status = { status: "fail", pointId: msg.pointId, error: `Not Writable: (${store})::${path}::${msg.pointId}` };
38
-
39
- node.send(msg);
40
- if (done) done();
41
- return;
42
- }
43
-
44
- // Get State
45
- const globalContext = node.context().global;
46
- let state = globalContext.get(path, store);
47
-
48
- if (!state || !state.priority) {
49
- node.status({ fill: "red", shape: "ring", text: `Point Not Found: (${store})::${path}::${msg.pointId}` });
50
- msg.status = { status: "fail", pointId: msg.pointId, error: `Point Not Found: (${store})::${path}::${msg.pointId}` };
51
-
52
- node.send(msg);
53
- if (done) done();
54
- return;
55
- }
56
-
57
- // Check Type
58
- if (msg.value === "null" || msg.value === null) {
59
- msg.value = null;
60
- } else {
61
- const inputType = typeof msg.value;
62
- const dataType = state.metadata.type;
63
- if (inputType !== dataType) {
64
- node.status({ fill: "red", shape: "ring", text: `Mismatch type error: ${store}:${path} ID: ${msg.pointId}, ${inputType} !== ${dataType}` });
65
- msg.status = { status: "fail", pointId: msg.pointId, error: `Mismatch type error: ${store}:${path} ID: ${msg.pointId}, ${inputType} !== ${dataType}` };
66
-
67
- node.send(msg);
68
- if (done) done();
69
- return;
70
- }
71
- }
72
-
73
- // Update Priority
74
- if (msg.priority === 'default') {
75
- state.defaultValue = msg.value ?? state.defaultValue;
76
- } else {
77
- const priority = parseInt(msg.priority, 10);
78
- if (isNaN(priority) || priority < 1 || priority > 16) {
79
- node.status({ fill: "red", shape: "ring", text: `Invalid priority: ${msg.priority}` });
80
- msg.status = { status: "fail", pointId: msg.pointId, error: `Invalid Priority: (${store})::${path}::${msg.pointId}` };
81
-
82
- node.send(msg);
83
- if (done) done();
84
- return;
85
- }
86
-
87
- state.priority[msg.priority] = msg.value;
88
- }
89
-
90
- // Calculate Winner (Same logic as Setter)
91
- let winnerValue = state.defaultValue;
92
- let winnerPriority = 'default'
93
- for (let i = 1; i <= 16; i++) {
94
- if (state.priority[i] !== undefined && state.priority[i] !== null) {
95
- winnerValue = state.priority[i];
96
- winnerPriority = `${i}`
97
- break;
98
- }
99
- }
100
- state.value = winnerValue;
101
- state.activePriority = winnerPriority;
102
- state.metadata.lastSet = new Date().toISOString();
103
-
104
- // Save & Emit
105
- const prefix1 = msg.priority === 'default' ? '' : 'P';
106
- const prefix2 = state.activePriority === 'default' ? '' : 'P';
107
- const message = `Wrote: ${prefix1}${msg.priority}:${msg.value} > (${store})::${path}::${msg.pointId} Active: ${prefix2}${winnerPriority}:${winnerValue}`;
108
- node.status({ fill: "blue", shape: "ring", text: message });
109
-
110
- globalContext.set(path, state, store);
111
- msg = { ...state };
112
- msg.status = { status: "ok", pointId: msg.pointId, message: message };
113
-
114
- // Trigger global getters to update on new value
115
- RED.events.emit("bldgblocks-global-update", {
116
- key: path,
117
- store: store,
118
- data: state
119
- });
120
-
121
- node.send(msg);
122
- if (done) done();
123
- });
124
- }
125
- RED.nodes.registerType("network-write", NetworkWriteNode);
126
- }