@atelieruldetehnologii/node-red-custome-solutions 0.62.22
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/NOTICE +56 -0
- package/PROPRIETARY-LICENSE.txt +157 -0
- package/README.md +105 -0
- package/TERMS-AND-CONDITIONS.md +311 -0
- package/advantech-read/advantech-read.html +775 -0
- package/advantech-read/advantech-read.js +449 -0
- package/advantech-write/advantech-write.html +413 -0
- package/advantech-write/advantech-write.js +338 -0
- package/bess-control/bess-control.html +569 -0
- package/bess-control/bess-control.js +541 -0
- package/bess-control/lib/allocation.js +149 -0
- package/bess-control/lib/batteries.js +86 -0
- package/bess-control/lib/helpers.js +157 -0
- package/bess-control/lib/messages.js +131 -0
- package/bess-control/lib/runtime.js +156 -0
- package/carlo-gavazzi/carlo-gavazzi.html +4327 -0
- package/carlo-gavazzi/carlo-gavazzi.js +3081 -0
- package/control-export/control-export.html +3644 -0
- package/control-export/control-export.js +2192 -0
- package/control-reactive/control-reactive.html +3136 -0
- package/control-reactive/control-reactive.js +2124 -0
- package/fronius-emulator/README.md +258 -0
- package/fronius-emulator/fronius-emulator.html +170 -0
- package/fronius-emulator/fronius-emulator.js +520 -0
- package/fronius-emulator/lib/binary-codec.js +65 -0
- package/fronius-emulator/lib/fronius-register-map.js +185 -0
- package/fronius-emulator/lib/modbus-parser.js +61 -0
- package/fronius-emulator/lib/modbus-tcp-server.js +224 -0
- package/fronius-emulator/lib/validation.js +206 -0
- package/fronius-emulator/lib/virtual-meter.js +132 -0
- package/fronius-read/fronius-read.html +3944 -0
- package/fronius-read/fronius-read.js +1466 -0
- package/fronius-read/lib/inverter-profiles.js +711 -0
- package/fronius-read/lib/sunspec-core.js +303 -0
- package/fronius-read/lib/sunspec-model-parsers.js +845 -0
- package/fronius-write/fronius-write.html +1789 -0
- package/fronius-write/fronius-write.js +2531 -0
- package/influxdb/influxdb.html +1077 -0
- package/influxdb/influxdb.js +1487 -0
- package/janitza/janitza.html +2562 -0
- package/janitza/janitza.js +1500 -0
- package/janitza/lib/janitza-profiles.js +371 -0
- package/lib/a3-test-server.js +199 -0
- package/lib/adam-6000-profiles.js +173 -0
- package/lib/licensing/constants.js +103 -0
- package/lib/licensing/device-id.js +251 -0
- package/lib/licensing/errors.js +21 -0
- package/lib/licensing/license-client.js +377 -0
- package/lib/licensing/license-state.js +50 -0
- package/lib/licensing/node-guard.js +150 -0
- package/lib/licensing/package-integrity.js +167 -0
- package/lib/licensing/package-integrity.json +513 -0
- package/lib/licensing/public-key.pem +3 -0
- package/lib/licensing/public-key.pem.example +2 -0
- package/lib/licensing/public-keys.js +18 -0
- package/lib/licensing/storage.js +63 -0
- package/lib/licensing/token-verifier.js +84 -0
- package/lib/numbers.js +26 -0
- package/license/atelier-license.html +88 -0
- package/license/atelier-license.js +170 -0
- package/modbus-tcp-discover/modbus-tcp-discover.html +190 -0
- package/modbus-tcp-discover/modbus-tcp-discover.js +706 -0
- package/multi-battery/multi-battery.html +649 -0
- package/multi-battery/multi-battery.js +668 -0
- package/multi-grid/multi-grid.html +745 -0
- package/multi-grid/multi-grid.js +1392 -0
- package/multi-inverter/lib/engine-core.js +237 -0
- package/multi-inverter/multi-inverter.html +2674 -0
- package/multi-inverter/multi-inverter.js +1393 -0
- package/package.json +109 -0
- package/phoenix-contact/lib/eem-ma370-advanced.js +175 -0
- package/phoenix-contact/lib/eem-ma370.js +138 -0
- package/phoenix-contact/lib/integrations.js +149 -0
- package/phoenix-contact/lib/phoenix-contact-profile.js +35030 -0
- package/phoenix-contact/phoenix-contact.html +840 -0
- package/phoenix-contact/phoenix-contact.js +679 -0
- package/pv-generator/pv-generator.html +284 -0
- package/pv-generator/pv-generator.js +387 -0
- package/pylontech-read/pylontech-read.html +763 -0
- package/pylontech-read/pylontech-read.js +518 -0
- package/pylontech-write/pylontech-write.html +405 -0
- package/pylontech-write/pylontech-write.js +546 -0
- package/scada-aggregator/lib/aggregate.js +72 -0
- package/scada-aggregator/lib/groups.js +39 -0
- package/scada-aggregator/scada-aggregator.html +108 -0
- package/scada-aggregator/scada-aggregator.js +117 -0
- package/scada-server/lib/aggregator-map.js +58 -0
- package/scada-server/lib/encoding.js +235 -0
- package/scada-server/lib/modbus-server.js +492 -0
- package/scada-server/lib/object-path.js +18 -0
- package/scada-server/lib/register-map.js +288 -0
- package/scada-server/scada-server.html +1419 -0
- package/scada-server/scada-server.js +704 -0
- package/scripts/check-syntax.js +66 -0
- package/scripts/package-integrity.js +46 -0
- package/scripts/package-release.js +116 -0
- package/scripts/run-tests.js +2178 -0
- package/scripts/tgz-integrity.js +74 -0
- package/sma-read/lib/sunspec-core.js +83 -0
- package/sma-read/lib/sunspec-model-parsers.js +853 -0
- package/sma-read/sma-read.html +659 -0
- package/sma-read/sma-read.js +458 -0
- package/sma-write/sma-write.html +105 -0
- package/sma-write/sma-write.js +270 -0
- package/victron-read/lib/mqtt-state.js +176 -0
- package/victron-read/victron-read.html +1074 -0
- package/victron-read/victron-read.js +1222 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const { encodeMetricDetailed, typeWordLength } = require("./encoding");
|
|
5
|
+
|
|
6
|
+
const VALID_TYPES = ["int16", "uint16", "int32", "uint32", "float32"];
|
|
7
|
+
const VALID_BYTE_ORDERS = ["big_endian", "little_endian"];
|
|
8
|
+
const VALID_WORD_ORDERS = ["msw_first", "lsw_first"];
|
|
9
|
+
const MAX_REGISTER_ADDRESS = 65535;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
function toMetricConfig(metric) {
|
|
13
|
+
|
|
14
|
+
const config = metric || {};
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
|
|
18
|
+
key: String(config.key || "").trim(),
|
|
19
|
+
|
|
20
|
+
label: String(config.label || config.key || "").trim(),
|
|
21
|
+
|
|
22
|
+
address: Math.max(0, Number(config.address || 0)),
|
|
23
|
+
|
|
24
|
+
type: String(config.type || "int32").trim(),
|
|
25
|
+
|
|
26
|
+
scale: Number.isFinite(Number(config.scale)) ? Number(config.scale) : 1,
|
|
27
|
+
|
|
28
|
+
path: String(config.path || "").trim(),
|
|
29
|
+
|
|
30
|
+
unit: String(config.unit || "").trim(),
|
|
31
|
+
|
|
32
|
+
signMode: String(config.signMode || "as_is").trim(),
|
|
33
|
+
|
|
34
|
+
byteOrder: String(config.byteOrder || "big_endian").trim(),
|
|
35
|
+
|
|
36
|
+
wordOrder: String(config.wordOrder || "msw_first").trim()
|
|
37
|
+
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
function normalizeMetricConfigs(metrics) {
|
|
44
|
+
|
|
45
|
+
return (Array.isArray(metrics) ? metrics : []).map(toMetricConfig).filter(function (metric) {
|
|
46
|
+
|
|
47
|
+
return metric.key && metric.path;
|
|
48
|
+
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
function metricRegisterRange(metric) {
|
|
55
|
+
|
|
56
|
+
const start = Math.max(0, Number(metric.address || 0));
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
start: start,
|
|
60
|
+
end: start + typeWordLength(metric.type) - 1
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
function registerSpan(metrics) {
|
|
67
|
+
|
|
68
|
+
return metrics.reduce(function (max, metric) {
|
|
69
|
+
|
|
70
|
+
return Math.max(max, metric.address + typeWordLength(metric.type));
|
|
71
|
+
|
|
72
|
+
}, 0);
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
function buildRegisterImage(metrics, values, onIssue) {
|
|
78
|
+
|
|
79
|
+
const size = Math.max(registerSpan(metrics), 1);
|
|
80
|
+
|
|
81
|
+
const registers = new Uint16Array(size);
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
metrics.forEach(function (metric) {
|
|
85
|
+
|
|
86
|
+
const encoded = encodeMetricDetailed(values[metric.key], metric.type, metric.scale, {
|
|
87
|
+
byteOrder: metric.byteOrder,
|
|
88
|
+
wordOrder: metric.wordOrder
|
|
89
|
+
});
|
|
90
|
+
const words = encoded.words;
|
|
91
|
+
|
|
92
|
+
if (encoded.issues.length && typeof onIssue === "function") {
|
|
93
|
+
encoded.issues.forEach(function (issue) {
|
|
94
|
+
onIssue(Object.assign({
|
|
95
|
+
key: metric.key,
|
|
96
|
+
address: metric.address
|
|
97
|
+
}, issue));
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (let index = 0; index < words.length; index += 1) {
|
|
102
|
+
|
|
103
|
+
const address = metric.address + index;
|
|
104
|
+
|
|
105
|
+
if (address >= 0 && address < registers.length) {
|
|
106
|
+
|
|
107
|
+
registers[address] = words[index];
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
return registers;
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
function normalizeMetricValue(metric, value) {
|
|
122
|
+
|
|
123
|
+
const numeric = Number(value);
|
|
124
|
+
|
|
125
|
+
if (!Number.isFinite(numeric)) {
|
|
126
|
+
|
|
127
|
+
return null;
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if (metric.signMode === "invert") {
|
|
133
|
+
|
|
134
|
+
return -numeric;
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
return numeric;
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
function validateMetricConfigs(metrics) {
|
|
145
|
+
|
|
146
|
+
const list = Array.isArray(metrics) ? metrics : [];
|
|
147
|
+
const issues = [];
|
|
148
|
+
const seenKeys = new Set();
|
|
149
|
+
const ranges = [];
|
|
150
|
+
|
|
151
|
+
if (!list.length) {
|
|
152
|
+
|
|
153
|
+
issues.push({
|
|
154
|
+
code: "empty",
|
|
155
|
+
message: "Configuratia SCADA trebuie sa contina cel putin un registru."
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return issues;
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
list.forEach(function (metric, index) {
|
|
164
|
+
|
|
165
|
+
const rowLabel = "Randul " + (index + 1);
|
|
166
|
+
|
|
167
|
+
if (!metric.key) {
|
|
168
|
+
|
|
169
|
+
issues.push({ code: "missing_key", message: rowLabel + ": cheia registrului este obligatorie." });
|
|
170
|
+
|
|
171
|
+
} else if (seenKeys.has(metric.key)) {
|
|
172
|
+
|
|
173
|
+
issues.push({ code: "duplicate_key", message: rowLabel + ": cheia \"" + metric.key + "\" este duplicata." });
|
|
174
|
+
|
|
175
|
+
} else {
|
|
176
|
+
|
|
177
|
+
seenKeys.add(metric.key);
|
|
178
|
+
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if (!metric.path) {
|
|
183
|
+
|
|
184
|
+
issues.push({ code: "missing_path", message: rowLabel + ": calea mesajului este obligatorie." });
|
|
185
|
+
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
if (!VALID_TYPES.includes(metric.type)) {
|
|
190
|
+
|
|
191
|
+
issues.push({ code: "invalid_type", message: rowLabel + ": tipul \"" + metric.type + "\" nu este suportat." });
|
|
192
|
+
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
if (!VALID_BYTE_ORDERS.includes(metric.byteOrder)) {
|
|
197
|
+
|
|
198
|
+
issues.push({ code: "invalid_byte_order", message: rowLabel + ": byte order \"" + metric.byteOrder + "\" nu este suportat." });
|
|
199
|
+
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
if (!VALID_WORD_ORDERS.includes(metric.wordOrder)) {
|
|
204
|
+
|
|
205
|
+
issues.push({ code: "invalid_word_order", message: rowLabel + ": word order \"" + metric.wordOrder + "\" nu este suportat." });
|
|
206
|
+
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
if (!Number.isFinite(Number(metric.scale)) || Number(metric.scale) === 0) {
|
|
211
|
+
|
|
212
|
+
issues.push({ code: "invalid_scale", message: rowLabel + ": scale trebuie sa fie un numar diferit de 0." });
|
|
213
|
+
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
if (!Number.isFinite(Number(metric.address)) || Number(metric.address) < 0) {
|
|
218
|
+
|
|
219
|
+
issues.push({ code: "invalid_address", message: rowLabel + ": adresa trebuie sa fie un numar >= 0." });
|
|
220
|
+
return;
|
|
221
|
+
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
const range = metricRegisterRange(metric);
|
|
226
|
+
|
|
227
|
+
if (range.end > MAX_REGISTER_ADDRESS) {
|
|
228
|
+
|
|
229
|
+
issues.push({
|
|
230
|
+
code: "address_out_of_range",
|
|
231
|
+
message: rowLabel + ": registrul depaseste limita Modbus " + MAX_REGISTER_ADDRESS + " (end=" + range.end + ")."
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
ranges.push({
|
|
237
|
+
key: metric.key || ("row_" + index),
|
|
238
|
+
start: range.start,
|
|
239
|
+
end: range.end
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
ranges.sort(function (left, right) {
|
|
246
|
+
|
|
247
|
+
return left.start - right.start;
|
|
248
|
+
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
for (let index = 1; index < ranges.length; index += 1) {
|
|
253
|
+
|
|
254
|
+
const previous = ranges[index - 1];
|
|
255
|
+
const current = ranges[index];
|
|
256
|
+
|
|
257
|
+
if (current.start <= previous.end) {
|
|
258
|
+
|
|
259
|
+
issues.push({
|
|
260
|
+
code: "overlap",
|
|
261
|
+
message: "Registrele \"" + previous.key + "\" si \"" + current.key + "\" se suprapun intre adresele " + current.start + " si " + previous.end + "."
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
return issues;
|
|
270
|
+
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
module.exports = {
|
|
275
|
+
|
|
276
|
+
buildRegisterImage,
|
|
277
|
+
|
|
278
|
+
normalizeMetricValue,
|
|
279
|
+
|
|
280
|
+
normalizeMetricConfigs,
|
|
281
|
+
|
|
282
|
+
registerSpan,
|
|
283
|
+
|
|
284
|
+
validateMetricConfigs,
|
|
285
|
+
|
|
286
|
+
MAX_REGISTER_ADDRESS
|
|
287
|
+
|
|
288
|
+
};
|