@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.
Files changed (107) hide show
  1. package/NOTICE +56 -0
  2. package/PROPRIETARY-LICENSE.txt +157 -0
  3. package/README.md +105 -0
  4. package/TERMS-AND-CONDITIONS.md +311 -0
  5. package/advantech-read/advantech-read.html +775 -0
  6. package/advantech-read/advantech-read.js +449 -0
  7. package/advantech-write/advantech-write.html +413 -0
  8. package/advantech-write/advantech-write.js +338 -0
  9. package/bess-control/bess-control.html +569 -0
  10. package/bess-control/bess-control.js +541 -0
  11. package/bess-control/lib/allocation.js +149 -0
  12. package/bess-control/lib/batteries.js +86 -0
  13. package/bess-control/lib/helpers.js +157 -0
  14. package/bess-control/lib/messages.js +131 -0
  15. package/bess-control/lib/runtime.js +156 -0
  16. package/carlo-gavazzi/carlo-gavazzi.html +4327 -0
  17. package/carlo-gavazzi/carlo-gavazzi.js +3081 -0
  18. package/control-export/control-export.html +3644 -0
  19. package/control-export/control-export.js +2192 -0
  20. package/control-reactive/control-reactive.html +3136 -0
  21. package/control-reactive/control-reactive.js +2124 -0
  22. package/fronius-emulator/README.md +258 -0
  23. package/fronius-emulator/fronius-emulator.html +170 -0
  24. package/fronius-emulator/fronius-emulator.js +520 -0
  25. package/fronius-emulator/lib/binary-codec.js +65 -0
  26. package/fronius-emulator/lib/fronius-register-map.js +185 -0
  27. package/fronius-emulator/lib/modbus-parser.js +61 -0
  28. package/fronius-emulator/lib/modbus-tcp-server.js +224 -0
  29. package/fronius-emulator/lib/validation.js +206 -0
  30. package/fronius-emulator/lib/virtual-meter.js +132 -0
  31. package/fronius-read/fronius-read.html +3944 -0
  32. package/fronius-read/fronius-read.js +1466 -0
  33. package/fronius-read/lib/inverter-profiles.js +711 -0
  34. package/fronius-read/lib/sunspec-core.js +303 -0
  35. package/fronius-read/lib/sunspec-model-parsers.js +845 -0
  36. package/fronius-write/fronius-write.html +1789 -0
  37. package/fronius-write/fronius-write.js +2531 -0
  38. package/influxdb/influxdb.html +1077 -0
  39. package/influxdb/influxdb.js +1487 -0
  40. package/janitza/janitza.html +2562 -0
  41. package/janitza/janitza.js +1500 -0
  42. package/janitza/lib/janitza-profiles.js +371 -0
  43. package/lib/a3-test-server.js +199 -0
  44. package/lib/adam-6000-profiles.js +173 -0
  45. package/lib/licensing/constants.js +103 -0
  46. package/lib/licensing/device-id.js +251 -0
  47. package/lib/licensing/errors.js +21 -0
  48. package/lib/licensing/license-client.js +377 -0
  49. package/lib/licensing/license-state.js +50 -0
  50. package/lib/licensing/node-guard.js +150 -0
  51. package/lib/licensing/package-integrity.js +167 -0
  52. package/lib/licensing/package-integrity.json +513 -0
  53. package/lib/licensing/public-key.pem +3 -0
  54. package/lib/licensing/public-key.pem.example +2 -0
  55. package/lib/licensing/public-keys.js +18 -0
  56. package/lib/licensing/storage.js +63 -0
  57. package/lib/licensing/token-verifier.js +84 -0
  58. package/lib/numbers.js +26 -0
  59. package/license/atelier-license.html +88 -0
  60. package/license/atelier-license.js +170 -0
  61. package/modbus-tcp-discover/modbus-tcp-discover.html +190 -0
  62. package/modbus-tcp-discover/modbus-tcp-discover.js +706 -0
  63. package/multi-battery/multi-battery.html +649 -0
  64. package/multi-battery/multi-battery.js +668 -0
  65. package/multi-grid/multi-grid.html +745 -0
  66. package/multi-grid/multi-grid.js +1392 -0
  67. package/multi-inverter/lib/engine-core.js +237 -0
  68. package/multi-inverter/multi-inverter.html +2674 -0
  69. package/multi-inverter/multi-inverter.js +1393 -0
  70. package/package.json +109 -0
  71. package/phoenix-contact/lib/eem-ma370-advanced.js +175 -0
  72. package/phoenix-contact/lib/eem-ma370.js +138 -0
  73. package/phoenix-contact/lib/integrations.js +149 -0
  74. package/phoenix-contact/lib/phoenix-contact-profile.js +35030 -0
  75. package/phoenix-contact/phoenix-contact.html +840 -0
  76. package/phoenix-contact/phoenix-contact.js +679 -0
  77. package/pv-generator/pv-generator.html +284 -0
  78. package/pv-generator/pv-generator.js +387 -0
  79. package/pylontech-read/pylontech-read.html +763 -0
  80. package/pylontech-read/pylontech-read.js +518 -0
  81. package/pylontech-write/pylontech-write.html +405 -0
  82. package/pylontech-write/pylontech-write.js +546 -0
  83. package/scada-aggregator/lib/aggregate.js +72 -0
  84. package/scada-aggregator/lib/groups.js +39 -0
  85. package/scada-aggregator/scada-aggregator.html +108 -0
  86. package/scada-aggregator/scada-aggregator.js +117 -0
  87. package/scada-server/lib/aggregator-map.js +58 -0
  88. package/scada-server/lib/encoding.js +235 -0
  89. package/scada-server/lib/modbus-server.js +492 -0
  90. package/scada-server/lib/object-path.js +18 -0
  91. package/scada-server/lib/register-map.js +288 -0
  92. package/scada-server/scada-server.html +1419 -0
  93. package/scada-server/scada-server.js +704 -0
  94. package/scripts/check-syntax.js +66 -0
  95. package/scripts/package-integrity.js +46 -0
  96. package/scripts/package-release.js +116 -0
  97. package/scripts/run-tests.js +2178 -0
  98. package/scripts/tgz-integrity.js +74 -0
  99. package/sma-read/lib/sunspec-core.js +83 -0
  100. package/sma-read/lib/sunspec-model-parsers.js +853 -0
  101. package/sma-read/sma-read.html +659 -0
  102. package/sma-read/sma-read.js +458 -0
  103. package/sma-write/sma-write.html +105 -0
  104. package/sma-write/sma-write.js +270 -0
  105. package/victron-read/lib/mqtt-state.js +176 -0
  106. package/victron-read/victron-read.html +1074 -0
  107. package/victron-read/victron-read.js +1222 -0
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+
3
+
4
+ function normalizeBatteries(batteries, batteryCount) {
5
+
6
+ const list = Array.isArray(batteries) ? batteries : [];
7
+
8
+ const count = Math.max(1, Number(batteryCount || list.length || 1));
9
+
10
+ const defaultShare = 100 / count;
11
+
12
+ const normalized = [];
13
+
14
+
15
+ for (let index = 0; index < count; index += 1) {
16
+
17
+ const battery = list[index] || {};
18
+
19
+ const socMin = Number.isFinite(Number(battery.socMin)) ? Number(battery.socMin) : 30;
20
+ const rawSocHyst = Number.isFinite(Number(battery.socHystPct))
21
+ ? Number(battery.socHystPct)
22
+ : (Number.isFinite(Number(battery.socHyst)) ? Number(battery.socHyst) : 5);
23
+ const socHyst = Math.max(0, rawSocHyst > socMin ? (rawSocHyst - socMin) : rawSocHyst);
24
+
25
+ normalized.push({
26
+
27
+ index: index,
28
+
29
+ id: String(battery.id || ("bat" + (index + 1))).trim(),
30
+
31
+ shareChargePct: Number.isFinite(Number(battery.shareChargePct)) ? Number(battery.shareChargePct) : defaultShare,
32
+
33
+ shareDischargePct: Number.isFinite(Number(battery.shareDischargePct)) ? Number(battery.shareDischargePct) : defaultShare,
34
+
35
+ maxChargeW: Math.max(0, Number(battery.maxChargeW || 150000)),
36
+
37
+ maxDischargeW: Math.max(0, Number(battery.maxDischargeW || 150000)),
38
+
39
+ socMin: socMin,
40
+
41
+ socHyst: socHyst,
42
+
43
+ rampUpW: Math.max(0, Number(battery.rampUpW || 1000)),
44
+
45
+ rampDownW: Math.max(0, Number(battery.rampDownW || 25000)),
46
+
47
+ priorityWeight: Number.isFinite(Number(battery.priorityWeight)) ? Math.max(0, Number(battery.priorityWeight)) : 1
48
+
49
+ });
50
+
51
+ }
52
+
53
+
54
+ return normalized;
55
+
56
+ }
57
+
58
+
59
+ function distributionIsValid(batteries) {
60
+
61
+ const chargeTotal = (Array.isArray(batteries) ? batteries : []).reduce(function (sum, battery) {
62
+
63
+ return sum + Number((battery && battery.shareChargePct) || 0);
64
+
65
+ }, 0);
66
+
67
+
68
+ const dischargeTotal = (Array.isArray(batteries) ? batteries : []).reduce(function (sum, battery) {
69
+
70
+ return sum + Number((battery && battery.shareDischargePct) || 0);
71
+
72
+ }, 0);
73
+
74
+
75
+ return Math.abs(chargeTotal - 100) <= 0.01 && Math.abs(dischargeTotal - 100) <= 0.01;
76
+
77
+ }
78
+
79
+
80
+ module.exports = {
81
+
82
+ distributionIsValid,
83
+
84
+ normalizeBatteries
85
+
86
+ };
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+
3
+
4
+ function firstFinite() {
5
+
6
+ for (let i = 0; i < arguments.length; i += 1) {
7
+
8
+ const value = Number(arguments[i]);
9
+
10
+ if (Number.isFinite(value)) {
11
+
12
+ return value;
13
+
14
+ }
15
+
16
+ }
17
+
18
+ return null;
19
+
20
+ }
21
+
22
+
23
+ function getByPath(source, path) {
24
+
25
+ if (!source || !path) return undefined;
26
+
27
+
28
+ return String(path).split(".").reduce(function (acc, key) {
29
+
30
+ return acc != null ? acc[key] : undefined;
31
+
32
+ }, source);
33
+
34
+ }
35
+
36
+
37
+ function clamp(value, min, max) {
38
+
39
+ return Math.min(Math.max(value, min), max);
40
+
41
+ }
42
+
43
+
44
+ function normalizeByConvention(value, signConvention) {
45
+
46
+ return Number.isFinite(value)
47
+
48
+ ? (signConvention === "positive_export" ? -value : value)
49
+
50
+ : value;
51
+
52
+ }
53
+
54
+
55
+ function denormalizeByConvention(value, signConvention) {
56
+
57
+ return Number.isFinite(value)
58
+
59
+ ? (signConvention === "positive_export" ? -value : value)
60
+
61
+ : value;
62
+
63
+ }
64
+
65
+
66
+ function parseBooleanLike(value) {
67
+
68
+ if (typeof value === "boolean") return value;
69
+
70
+
71
+ if (typeof value === "number") {
72
+
73
+ if (value === 85 || value === 1) return true;
74
+
75
+ if (value === 170 || value === 0) return false;
76
+
77
+ }
78
+
79
+
80
+ if (typeof value === "string") {
81
+
82
+ const normalized = value.trim().toLowerCase();
83
+
84
+
85
+ if (["1", "true", "on", "enable", "enabled", "activ", "active", "auto"].includes(normalized)) {
86
+
87
+ return true;
88
+
89
+ }
90
+
91
+
92
+ if (["0", "false", "off", "disable", "disabled", "dezactiv", "inactive", "manual"].includes(normalized)) {
93
+
94
+ return false;
95
+
96
+ }
97
+
98
+
99
+ if (normalized === "85") return true;
100
+
101
+ if (normalized === "170") return false;
102
+
103
+ }
104
+
105
+
106
+ return null;
107
+
108
+ }
109
+
110
+
111
+ function extractTimestampMs(msg) {
112
+
113
+ const ts = firstFinite(
114
+
115
+ msg && msg.timestamp_ms,
116
+
117
+ msg && msg.timestamp,
118
+
119
+ msg && msg.ts,
120
+
121
+ msg && msg.time,
122
+
123
+ msg && msg.payload && msg.payload.timestamp_ms,
124
+
125
+ msg && msg.payload && msg.payload.timestamp,
126
+
127
+ msg && msg.payload && msg.payload.ts,
128
+
129
+ msg && msg.payload && msg.payload.time
130
+
131
+ );
132
+
133
+
134
+ if (ts === null) return Date.now();
135
+
136
+ return ts < 1e11 ? Math.round(ts * 1000) : Math.round(ts);
137
+
138
+ }
139
+
140
+
141
+ module.exports = {
142
+
143
+ clamp,
144
+
145
+ denormalizeByConvention,
146
+
147
+ extractTimestampMs,
148
+
149
+ firstFinite,
150
+
151
+ getByPath,
152
+
153
+ normalizeByConvention,
154
+
155
+ parseBooleanLike
156
+
157
+ };
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+
3
+
4
+ function isFeedbackMessage(msg) {
5
+
6
+ const status = msg && msg.payload && typeof msg.payload === "object" ? msg.payload.status : null;
7
+
8
+ return Boolean(status && (msg.topic === "pylontech/write" || msg.topic === "pylontech/error"));
9
+
10
+ }
11
+
12
+
13
+ function extractGridReference(msg, options) {
14
+
15
+ if (typeof msg.payload === "number") {
16
+
17
+ return Number(msg.payload);
18
+
19
+ }
20
+
21
+
22
+ if (typeof msg.payload === "string" && msg.payload.trim() !== "") {
23
+
24
+ const direct = Number(msg.payload);
25
+
26
+ if (Number.isFinite(direct)) return direct;
27
+
28
+ }
29
+
30
+
31
+ const payload = msg.payload;
32
+
33
+ if (!payload || typeof payload !== "object") {
34
+
35
+ return null;
36
+
37
+ }
38
+
39
+
40
+ const byPath = Number(options.getByPath(msg, options.gridPowerPath));
41
+
42
+ if (Number.isFinite(byPath)) {
43
+
44
+ return byPath;
45
+
46
+ }
47
+
48
+
49
+ return options.firstFinite(
50
+
51
+ payload.grid_reference_w,
52
+
53
+ payload.power_w,
54
+
55
+ payload.pcc_power,
56
+
57
+ payload.grid_power,
58
+
59
+ payload.power,
60
+
61
+ payload.value
62
+
63
+ );
64
+
65
+ }
66
+
67
+
68
+ function extractBatteryId(msg) {
69
+
70
+ return String(
71
+
72
+ msg.batteryId !== undefined
73
+
74
+ ? msg.batteryId
75
+
76
+ : (msg.payload && (msg.payload.batteryId !== undefined ? msg.payload.batteryId : msg.payload.battery_id)) || ""
77
+
78
+ ).trim();
79
+
80
+ }
81
+
82
+
83
+ function extractBatteryTelemetry(msg, options) {
84
+
85
+ const soc = Number(options.getByPath(msg, options.batterySocPath));
86
+
87
+ const externalControlStatus = options.parseBooleanLike(options.getByPath(msg, options.externalControlStatusPath));
88
+
89
+ const alarmLevel = options.getByPath(msg, options.alarmLevelPath);
90
+
91
+ const operatingStatus = options.getByPath(msg, options.operatingStatusPath);
92
+
93
+ const deratingReason = options.getByPath(msg, options.deratingReasonPath);
94
+
95
+ const availableChargeW = options.availableChargePath ? Number(options.getByPath(msg, options.availableChargePath)) : null;
96
+
97
+ const availableDischargeW = options.availableDischargePath ? Number(options.getByPath(msg, options.availableDischargePath)) : null;
98
+
99
+
100
+ return {
101
+
102
+ soc: Number.isFinite(soc) ? soc : null,
103
+
104
+ externalControlStatus: externalControlStatus,
105
+
106
+ alarmLevel: alarmLevel,
107
+
108
+ operatingStatus: operatingStatus,
109
+
110
+ deratingReason: deratingReason,
111
+
112
+ availableChargeW: Number.isFinite(availableChargeW) ? availableChargeW : null,
113
+
114
+ availableDischargeW: Number.isFinite(availableDischargeW) ? availableDischargeW : null
115
+
116
+ };
117
+
118
+ }
119
+
120
+
121
+ module.exports = {
122
+
123
+ extractBatteryId,
124
+
125
+ extractBatteryTelemetry,
126
+
127
+ extractGridReference,
128
+
129
+ isFeedbackMessage
130
+
131
+ };
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+
3
+
4
+ function healthFactor(alarmLevel, operatingStatus, deratingReason) {
5
+
6
+ let factor = 1;
7
+
8
+ const alarm = Number(alarmLevel);
9
+
10
+
11
+ if (Number.isFinite(alarm) && alarm > 0) {
12
+
13
+ factor *= Math.max(0.1, 1 - (alarm * 0.2));
14
+
15
+ }
16
+
17
+
18
+ if (deratingReason !== undefined && deratingReason !== null && String(deratingReason).trim() !== "" && String(deratingReason) !== "0") {
19
+
20
+ factor *= 0.5;
21
+
22
+ }
23
+
24
+
25
+ if (
26
+
27
+ operatingStatus !== undefined &&
28
+
29
+ operatingStatus !== null &&
30
+
31
+ ["fault", "error", "offline", "off", "disabled"].includes(String(operatingStatus).trim().toLowerCase())
32
+
33
+ ) {
34
+
35
+ factor = 0;
36
+
37
+ }
38
+
39
+
40
+ return factor;
41
+
42
+ }
43
+
44
+
45
+ function isStale(timestampMs, now, timeoutMs) {
46
+
47
+ const timeout = Number(timeoutMs || 0);
48
+
49
+ return Boolean(timeout) && (!Number.isFinite(timestampMs) || (now - timestampMs) > timeout);
50
+
51
+ }
52
+
53
+
54
+ function evaluateRuntimeBatteries(batteries, batteryState, options, now) {
55
+
56
+ return batteries.map(function (battery) {
57
+
58
+ const state = batteryState[battery.id] || {};
59
+
60
+ const telemetryStale = isStale(state.ts, now, options.staleTimeoutMs);
61
+
62
+ const feedbackStale = !state.writeFeedback || isStale(state.writeFeedback.ts, now, options.feedbackTimeoutMs);
63
+
64
+ const writeError = Boolean(state.writeFeedback && state.writeFeedback.status === "error" && !feedbackStale);
65
+
66
+ const health = healthFactor(state.alarmLevel, state.operatingStatus, state.deratingReason);
67
+
68
+
69
+ let dischargeAllowed = true;
70
+
71
+ if (Number.isFinite(state.soc)) {
72
+
73
+ const resumeSoc = Number(battery.socMin || 0) + Math.max(0, Number(battery.socHyst || 0));
74
+
75
+ if (state.soc <= battery.socMin) {
76
+
77
+ dischargeAllowed = false;
78
+
79
+ } else if (state.soc >= resumeSoc) {
80
+
81
+ dischargeAllowed = true;
82
+
83
+ } else if (state.dischargeAllowed !== undefined) {
84
+
85
+ dischargeAllowed = Boolean(state.dischargeAllowed);
86
+
87
+ }
88
+
89
+ state.dischargeAllowed = dischargeAllowed;
90
+
91
+ }
92
+
93
+
94
+ const excludedReasons = [];
95
+
96
+ if (!Number.isFinite(state.soc)) excludedReasons.push("missing_soc");
97
+
98
+ if (telemetryStale) excludedReasons.push("stale");
99
+
100
+ if (writeError) excludedReasons.push("write_error");
101
+
102
+ if (health <= 0) excludedReasons.push("health_block");
103
+
104
+
105
+ return {
106
+
107
+ config: battery,
108
+
109
+ state: state,
110
+
111
+ telemetryStale: telemetryStale,
112
+
113
+ feedbackStale: feedbackStale,
114
+
115
+ writeError: writeError,
116
+
117
+ healthFactor: health,
118
+
119
+ dischargeAllowed: dischargeAllowed,
120
+
121
+ availableChargeW: Math.min(
122
+
123
+ battery.maxChargeW,
124
+
125
+ Number.isFinite(state.availableChargeW) ? Math.max(0, state.availableChargeW) : battery.maxChargeW
126
+
127
+ ),
128
+
129
+ availableDischargeW: Math.min(
130
+
131
+ battery.maxDischargeW,
132
+
133
+ Number.isFinite(state.availableDischargeW) ? Math.max(0, state.availableDischargeW) : battery.maxDischargeW
134
+
135
+ ),
136
+
137
+ excluded: excludedReasons.length > 0,
138
+
139
+ excludedReasons: excludedReasons
140
+
141
+ };
142
+
143
+ });
144
+
145
+ }
146
+
147
+
148
+ module.exports = {
149
+
150
+ evaluateRuntimeBatteries,
151
+
152
+ healthFactor,
153
+
154
+ isStale
155
+
156
+ };