node-red-contrib-3dm-space 1.0.0 → 1.0.3

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.
@@ -1,108 +1,295 @@
1
1
  <script type="text/javascript">
2
- RED.nodes.registerType("3dm-cloud-config", {
3
- category: "config",
2
+ (function () {
3
+ "use strict";
4
+
5
+ function clampOutputs(value) {
6
+ var n = parseInt(value, 10);
7
+
8
+ if (isNaN(n)) {
9
+ n = 24;
10
+ }
11
+
12
+ return Math.max(1, Math.min(n, 24));
13
+ }
14
+
15
+ function populateConfigOutputOptions(maxOutputs, currentValue) {
16
+ var select = $("#node-input-configOutput");
17
+ var current = parseInt(currentValue, 10);
18
+
19
+ if (isNaN(current)) {
20
+ current = 0;
21
+ }
22
+
23
+ select.empty();
24
+ select.append(
25
+ $("<option></option>")
26
+ .attr("value", "0")
27
+ .text("Disabled")
28
+ );
29
+
30
+ for (var i = 1; i <= maxOutputs; i += 1) {
31
+ select.append(
32
+ $("<option></option>")
33
+ .attr("value", String(i))
34
+ .text("Output " + i)
35
+ );
36
+ }
37
+
38
+ if (current > maxOutputs) {
39
+ current = 0;
40
+ }
41
+
42
+ select.val(String(current));
43
+ }
44
+
45
+ RED.nodes.registerType("3dm-config-store", {
46
+ category: "3DM.space",
47
+ color: "#6D6D6D",
4
48
  defaults: {
5
49
  name: { value: "" },
6
- clientid: { value: "" }
7
- },
8
- credentials: {
9
- username: { type: "text" },
10
- password: { type: "password" }
50
+ configName: { value: "" },
51
+ outputs: {
52
+ value: 24,
53
+ validate: function (v) {
54
+ var n = Number(v);
55
+ return !isNaN(n) && n >= 1 && n <= 24;
56
+ }
57
+ },
58
+ tickSeconds: {
59
+ value: 20,
60
+ validate: function (v) {
61
+ var n = Number(v);
62
+ return !isNaN(n) && n >= 1 && n <= 60;
63
+ }
64
+ },
65
+ outputMode: { value: "change" },
66
+ configOutput: { value: 0 },
67
+ emitConfigOnUpdate: { value: false }
11
68
  },
69
+ inputs: 1,
70
+ outputs: 24,
71
+ icon: "font-awesome/fa-database",
12
72
  label: function () {
13
- return this.name || this.clientid || "3DM Cloud Login";
73
+ return this.name || "3DM config store";
74
+ },
75
+ paletteLabel: "3DM config store",
76
+ outputLabels: function (index) {
77
+ return "Output " + (index + 1);
78
+ },
79
+ oneditprepare: function () {
80
+ var outputCount = clampOutputs(this.outputs || 24);
81
+
82
+ $("#node-input-outputs").val(outputCount);
83
+ populateConfigOutputOptions(outputCount, this.configOutput || 0);
84
+
85
+ $("#node-input-outputs").on("input change", function () {
86
+ var count = clampOutputs($(this).val());
87
+ populateConfigOutputOptions(count, $("#node-input-configOutput").val());
88
+ });
89
+ },
90
+ oneditsave: function () {
91
+ var outputCount = clampOutputs($("#node-input-outputs").val());
92
+ var configOutput = parseInt($("#node-input-configOutput").val(), 10);
93
+
94
+ this.outputs = outputCount;
95
+
96
+ if (isNaN(configOutput) || configOutput > outputCount) {
97
+ this.configOutput = 0;
98
+ $("#node-input-configOutput").val("0");
99
+ }
14
100
  }
15
101
  });
102
+ })();
16
103
  </script>
17
104
 
18
- <script type="text/html" data-template-name="3dm-cloud-config">
19
- <style>
20
- .three-dm-login-panel {
21
- background: #2f3544;
22
- border-radius: 10px;
23
- padding: 14px;
24
- margin-bottom: 12px;
25
- }
26
-
27
- .three-dm-login-row {
28
- background: #3a4152;
29
- border-radius: 8px;
30
- padding: 10px 12px;
31
- margin-bottom: 12px;
32
- }
105
+ <script type="text/html" data-template-name="3dm-config-store">
106
+ <div class="form-row">
107
+ <label for="node-input-name">
108
+ <i class="fa fa-tag"></i> Node Name
109
+ </label>
110
+ <input type="text" id="node-input-name" placeholder="Optional, e.g. Pump Config Store">
111
+ </div>
33
112
 
34
- .three-dm-login-row label {
35
- display: block;
36
- width: 100%;
37
- color: #69d36f;
38
- font-weight: bold;
39
- margin-bottom: 6px;
40
- }
113
+ <div class="form-row">
114
+ <label for="node-input-configName">
115
+ <i class="fa fa-folder-open"></i> Config Name
116
+ </label>
117
+ <input type="text" id="node-input-configName" placeholder="Optional, e.g. mainScheduler">
118
+ </div>
41
119
 
42
- .three-dm-login-row input {
43
- width: 100%;
44
- box-sizing: border-box;
45
- background: #3a4152;
46
- color: #ffffff;
47
- border: none;
48
- font-size: 15px;
49
- padding: 4px 0;
50
- }
120
+ <div class="form-row">
121
+ <label for="node-input-outputs">
122
+ <i class="fa fa-random"></i> Active Outputs
123
+ </label>
124
+ <input type="number" id="node-input-outputs" min="1" max="24" placeholder="24" style="width:100px;">
125
+ <span> outputs</span>
126
+ </div>
51
127
 
52
- .three-dm-login-row input::placeholder {
53
- color: #b8beca;
54
- }
128
+ <div class="form-row">
129
+ <label for="node-input-tickSeconds">
130
+ <i class="fa fa-clock-o"></i> Check Every
131
+ </label>
132
+ <input type="number" id="node-input-tickSeconds" min="1" max="60" placeholder="20" style="width:100px;">
133
+ <span> seconds</span>
134
+ </div>
55
135
 
56
- .three-dm-login-row input:focus {
57
- outline: none;
58
- box-shadow: none;
59
- }
136
+ <div class="form-row">
137
+ <label for="node-input-outputMode">
138
+ <i class="fa fa-sign-out"></i> Output Mode
139
+ </label>
140
+ <select id="node-input-outputMode" style="width:70%;">
141
+ <option value="change">Only when output changes</option>
142
+ <option value="always">Every check</option>
143
+ </select>
144
+ </div>
60
145
 
61
- .three-dm-login-note {
62
- color: #c8ccd6;
63
- font-size: 12px;
64
- margin-top: 4px;
65
- }
66
- </style>
67
-
68
- <div class="three-dm-login-panel">
69
- <div class="three-dm-login-row">
70
- <label for="node-config-input-clientid">Client ID</label>
71
- <input type="text" id="node-config-input-clientid" placeholder="Paste Client ID from 3DM.space">
72
- </div>
73
-
74
- <div class="three-dm-login-row">
75
- <label for="node-config-input-username">User Name*</label>
76
- <input type="text" id="node-config-input-username" placeholder="Paste User Name from 3DM.space">
77
- </div>
78
-
79
- <div class="three-dm-login-row">
80
- <label for="node-config-input-password">Password</label>
81
- <input type="password" id="node-config-input-password" placeholder="Paste Password from 3DM.space">
82
- </div>
146
+ <div class="form-row">
147
+ <label for="node-input-configOutput">
148
+ <i class="fa fa-share-square-o"></i> Config Output
149
+ </label>
150
+ <select id="node-input-configOutput" style="width:70%;"></select>
83
151
  </div>
84
152
 
85
153
  <div class="form-row">
86
- <label for="node-config-input-name">
87
- <i class="fa fa-tag"></i> Node Name
154
+ <label for="node-input-emitConfigOnUpdate">
155
+ <i class="fa fa-refresh"></i> Send Config
88
156
  </label>
89
- <input type="text" id="node-config-input-name" placeholder="Optional, e.g. Main PassPort">
90
- <div class="three-dm-login-note">
91
- This is only the name shown inside Node-RED.
92
- </div>
157
+ <input type="checkbox" id="node-input-emitConfigOnUpdate" style="display:inline-block; width:auto; vertical-align:top;">
158
+ <span> send stored config when updated</span>
159
+ </div>
160
+
161
+ <div class="form-tips">
162
+ <b>Tip:</b> Leave Config Name blank to allow this node to store and use all config blocks sent under <code>configStore</code>.
93
163
  </div>
94
164
  </script>
95
165
 
96
- <script type="text/html" data-help-name="3dm-cloud-config">
97
- <p>Login details for 3DM.space SCADA Cloud.</p>
166
+ <script type="text/html" data-help-name="3dm-config-store">
167
+ <p>
168
+ Stores configuration sent from 3DM.space and runs local schedule/control logic.
169
+ </p>
170
+
171
+ <p>
172
+ This node is normally placed after a <b>3DM In</b> node.
173
+ </p>
174
+
175
+ <pre>3DM In → 3DM Config Store → active outputs</pre>
176
+
177
+ <h3>Config Store Format</h3>
178
+
179
+ <p>
180
+ Incoming messages should contain a main <code>configStore</code> object.
181
+ Each config block inside it should have its own name.
182
+ </p>
183
+
184
+ <pre>{
185
+ "configStore": {
186
+ "mainScheduler": {
187
+ "type": "scheduler",
188
+ "data": []
189
+ },
190
+ "pumpSetpoints": {
191
+ "type": "setpoints",
192
+ "data": {
193
+ "startLevel": 30,
194
+ "stopLevel": 80
195
+ }
196
+ }
197
+ }
198
+ }</pre>
199
+
200
+ <h3>Scheduler Config</h3>
201
+
202
+ <p>
203
+ Scheduler blocks use <code>type: "scheduler"</code>.
204
+ </p>
205
+
206
+ <pre>{
207
+ "configStore": {
208
+ "mainScheduler": {
209
+ "type": "scheduler",
210
+ "data": [
211
+ {
212
+ "name": "Pump 1 Morning Run",
213
+ "output": "output1",
214
+ "controlType": "schedule",
215
+ "mode": "Auto Schedule",
216
+ "days": ["mon", "tue", "wed", "thu", "fri"],
217
+ "startHour": 6,
218
+ "startMinute": 0,
219
+ "runHour": 1,
220
+ "runMinute": 30
221
+ }
222
+ ]
223
+ }
224
+ }
225
+ }</pre>
226
+
227
+ <h3>Control Config</h3>
228
+
229
+ <p>
230
+ Control entries can use live input values and stored setpoints.
231
+ </p>
232
+
233
+ <pre>{
234
+ "name": "Tank Level Control",
235
+ "output": "output1",
236
+ "controlType": "control",
237
+ "mode": "AUTO",
238
+ "variable": "tank_level",
239
+ "lowSetpointKey": "pumpSetpoints.data.startLevel",
240
+ "highSetpointKey": "pumpSetpoints.data.stopLevel",
241
+ "direction": "in"
242
+ }</pre>
243
+
244
+ <h3>Config Name</h3>
245
+
246
+ <p>
247
+ Leave <b>Config Name</b> blank to allow all config blocks.
248
+ </p>
249
+
250
+ <p>
251
+ Enter a name such as <code>mainScheduler</code> if this node should only use one config block.
252
+ </p>
253
+
254
+ <h3>Outputs</h3>
255
+
256
+ <p>
257
+ The node can be set from 1 to 24 active outputs.
258
+ </p>
259
+
260
+ <p>
261
+ Scheduler and control items use output names such as:
262
+ </p>
263
+
264
+ <pre>output1
265
+ output2
266
+ output3</pre>
267
+
268
+ <p>
269
+ If an item uses an output higher than the active output count, that item is skipped.
270
+ </p>
271
+
272
+ <p>
273
+ If multiple schedule/control entries use the same output, they are combined using OR logic.
274
+ If any entry wants the output ON, the final output is ON.
275
+ </p>
276
+
277
+ <h3>Local Storage</h3>
278
+
279
+ <p>
280
+ Config is saved locally on the gateway. If Node-RED restarts, the last saved config is loaded again.
281
+ </p>
282
+
283
+ <h3>Output Mode</h3>
98
284
 
99
- <p>Copy the details from 3DM.space in this order:</p>
285
+ <ul>
286
+ <li><b>Only when output changes</b>: sends an output only when the final state changes.</li>
287
+ <li><b>Every check</b>: sends outputs every check cycle.</li>
288
+ </ul>
100
289
 
101
- <ol>
102
- <li>Client ID</li>
103
- <li>User Name*</li>
104
- <li>Password</li>
105
- </ol>
290
+ <h3>Config Output</h3>
106
291
 
107
- <p>Node Name is optional and is only used inside Node-RED.</p>
292
+ <p>
293
+ Optional. Select an active output if you want the full stored config sent out as a message.
294
+ </p>
108
295
  </script>