@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,2562 @@
1
+ <style>
2
+
3
+ .janitza-editor {
4
+
5
+ --pr-border: #d7dde5;
6
+
7
+ --pr-muted: #667085;
8
+
9
+ --pr-surface: #f8fafc;
10
+
11
+ }
12
+
13
+
14
+ .janitza-editor .pr-section {
15
+
16
+ margin: 0 0 18px;
17
+
18
+ padding: 14px 16px 16px;
19
+
20
+ border: 1px solid var(--pr-border);
21
+
22
+ border-radius: 8px;
23
+
24
+ background: var(--pr-surface);
25
+
26
+ }
27
+
28
+
29
+ .janitza-editor .pr-section-title {
30
+
31
+ display: flex;
32
+
33
+ align-items: center;
34
+
35
+ gap: 8px;
36
+
37
+ margin: 0 0 4px;
38
+
39
+ font-size: 15px;
40
+
41
+ font-weight: 600;
42
+
43
+ color: #243447;
44
+
45
+ }
46
+
47
+
48
+ .janitza-editor .pr-section-note {
49
+
50
+ margin: 0 0 14px;
51
+
52
+ color: var(--pr-muted);
53
+
54
+ font-size: 12px;
55
+
56
+ line-height: 1.45;
57
+
58
+ }
59
+
60
+
61
+ .janitza-editor .pr-grid {
62
+
63
+ display: grid;
64
+
65
+ grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
66
+
67
+ gap: 12px 16px;
68
+
69
+ }
70
+
71
+
72
+ .janitza-editor .form-row {
73
+
74
+ margin-bottom: 12px;
75
+
76
+ }
77
+
78
+
79
+ .janitza-editor .pr-grid .form-row,
80
+
81
+ .janitza-editor .form-row:last-child {
82
+
83
+ margin-bottom: 0;
84
+
85
+ }
86
+
87
+
88
+ .janitza-editor .form-row > label {
89
+
90
+ width: 150px;
91
+
92
+ font-weight: 600;
93
+
94
+ }
95
+
96
+
97
+ .janitza-editor .form-row > input[type="text"],
98
+
99
+ .janitza-editor .form-row > input[type="number"],
100
+
101
+ .janitza-editor .form-row > select {
102
+
103
+ width: calc(100% - 160px);
104
+
105
+ }
106
+
107
+
108
+ .janitza-editor .pr-checkbox-row > input[type="checkbox"] {
109
+
110
+ display: inline-block;
111
+
112
+ width: auto;
113
+
114
+ vertical-align: top;
115
+
116
+ }
117
+
118
+
119
+ .janitza-editor .pr-checkbox-row > label {
120
+
121
+ width: 180px;
122
+
123
+ white-space: nowrap;
124
+
125
+ }
126
+
127
+
128
+ .janitza-editor .pr-inline-note {
129
+
130
+ margin-left: 8px;
131
+
132
+ color: var(--pr-muted);
133
+
134
+ line-height: 1.4;
135
+
136
+ }
137
+
138
+
139
+ .janitza-editor .pr-field-list {
140
+
141
+ max-height: 320px;
142
+
143
+ overflow: auto;
144
+
145
+ padding: 12px;
146
+
147
+ border: 1px solid var(--pr-border);
148
+
149
+ border-radius: 8px;
150
+
151
+ background: #fff;
152
+
153
+ }
154
+
155
+
156
+ .janitza-editor .pr-field-group {
157
+
158
+ margin-bottom: 14px;
159
+
160
+ }
161
+
162
+
163
+ .janitza-editor .pr-field-group:last-child {
164
+
165
+ margin-bottom: 0;
166
+
167
+ }
168
+
169
+
170
+ .janitza-editor .pr-field-group-title {
171
+
172
+ margin: 0 0 8px;
173
+
174
+ font-size: 12px;
175
+
176
+ font-weight: 700;
177
+
178
+ text-transform: uppercase;
179
+
180
+ letter-spacing: 0.03em;
181
+
182
+ color: #344054;
183
+
184
+ }
185
+
186
+
187
+ .janitza-editor .pr-field-group-grid {
188
+
189
+ display: grid;
190
+
191
+ grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
192
+
193
+ gap: 8px 16px;
194
+
195
+ }
196
+
197
+
198
+ .janitza-editor .pr-field-item {
199
+
200
+ display: flex;
201
+
202
+ align-items: center;
203
+
204
+ min-height: 28px;
205
+
206
+ margin: 0;
207
+
208
+ color: #243447;
209
+
210
+ font-size: 13px;
211
+
212
+ }
213
+
214
+
215
+ .janitza-editor .pr-field-item input {
216
+
217
+ margin: 0 8px 0 0;
218
+
219
+ }
220
+
221
+
222
+ .janitza-editor .pr-actions {
223
+
224
+ display: flex;
225
+
226
+ flex-wrap: wrap;
227
+
228
+ gap: 8px;
229
+
230
+ margin-bottom: 10px;
231
+
232
+ }
233
+
234
+
235
+ .janitza-editor .pr-actions button {
236
+
237
+ min-width: 110px;
238
+
239
+ }
240
+
241
+ </style>
242
+
243
+
244
+ <script type="text/javascript">
245
+
246
+ (function () {
247
+
248
+ const FIELD_GROUPS = [
249
+
250
+ {
251
+
252
+ label: "General",
253
+
254
+ fields: [
255
+
256
+ "summary.power.total_w",
257
+
258
+ "summary.frequency_hz",
259
+
260
+ "summary.phase_sequence"
261
+
262
+ ]
263
+
264
+ },
265
+
266
+ {
267
+
268
+ label: "Voltage",
269
+
270
+ fields: [
271
+
272
+ "summary.voltage.l1_n_v",
273
+
274
+ "summary.voltage.l2_n_v",
275
+
276
+ "summary.voltage.l3_n_v",
277
+
278
+ "summary.voltage.l1_l2_v",
279
+
280
+ "summary.voltage.l2_l3_v",
281
+
282
+ "summary.voltage.l3_l1_v"
283
+
284
+ ]
285
+
286
+ },
287
+
288
+ {
289
+
290
+ label: "Current",
291
+
292
+ fields: [
293
+
294
+ "summary.current.l1_a",
295
+
296
+ "summary.current.l2_a",
297
+
298
+ "summary.current.l3_a",
299
+
300
+ "summary.current.neutral_a"
301
+
302
+ ]
303
+
304
+ },
305
+
306
+ {
307
+
308
+ label: "Active Power",
309
+
310
+ fields: [
311
+
312
+ "summary.power.l1_w",
313
+
314
+ "summary.power.l2_w",
315
+
316
+ "summary.power.l3_w"
317
+
318
+ ]
319
+
320
+ },
321
+
322
+ {
323
+
324
+ label: "Apparent Power",
325
+
326
+ fields: [
327
+
328
+ "summary.apparent.l1_va",
329
+
330
+ "summary.apparent.l2_va",
331
+
332
+ "summary.apparent.l3_va",
333
+
334
+ "summary.apparent.total_va"
335
+
336
+ ]
337
+
338
+ },
339
+
340
+ {
341
+
342
+ label: "Reactive Power",
343
+
344
+ fields: [
345
+
346
+ "summary.reactive.l1_var",
347
+
348
+ "summary.reactive.l2_var",
349
+
350
+ "summary.reactive.l3_var",
351
+
352
+ "summary.reactive.total_var"
353
+
354
+ ]
355
+
356
+ },
357
+
358
+ {
359
+
360
+ label: "Power Factor",
361
+
362
+ fields: [
363
+
364
+ "summary.power_factor.l1",
365
+
366
+ "summary.power_factor.l2",
367
+
368
+ "summary.power_factor.l3"
369
+
370
+ ]
371
+
372
+ },
373
+
374
+ {
375
+
376
+ label: "Energy",
377
+
378
+ fields: [
379
+
380
+ "summary.energy.import_kwh",
381
+
382
+ "summary.energy.export_kwh",
383
+
384
+ "summary.energy.l1_kwh",
385
+
386
+ "summary.energy.l2_kwh",
387
+
388
+ "summary.energy.l3_kwh",
389
+
390
+ "summary.energy.apparent_kvah",
391
+
392
+ "summary.energy.reactive_import_kvarh",
393
+
394
+ "summary.energy.reactive_inductive_kvarh",
395
+
396
+ "summary.energy.reactive_capacitive_kvarh"
397
+
398
+ ]
399
+
400
+ },
401
+
402
+ {
403
+
404
+ label: "Harmonics",
405
+
406
+ fields: [
407
+
408
+ "summary.thd.voltage.l1_pct",
409
+
410
+ "summary.thd.voltage.l2_pct",
411
+
412
+ "summary.thd.voltage.l3_pct",
413
+
414
+ "summary.thd.current.l1_pct",
415
+
416
+ "summary.thd.current.l2_pct",
417
+
418
+ "summary.thd.current.l3_pct"
419
+
420
+ ]
421
+
422
+ }
423
+
424
+ ];
425
+
426
+ const EXTENDED_FIELD_GROUPS = [
427
+
428
+ {
429
+
430
+ label: "Extended L4 / Totals",
431
+
432
+ fields: [
433
+
434
+ "summary.extended.voltage.l4_n_v",
435
+
436
+ "summary.extended.current.l4_a",
437
+
438
+ "summary.extended.power.l4_w",
439
+
440
+ "summary.extended.reactive.l4_var",
441
+
442
+ "summary.extended.apparent.l4_va",
443
+
444
+ "summary.extended.current.sum_l1_l4_a",
445
+
446
+ "summary.extended.power.total_l1_l4_w",
447
+
448
+ "summary.extended.reactive.total_l1_l4_var",
449
+
450
+ "summary.extended.apparent.total_l1_l4_va",
451
+
452
+ "summary.extended.power_factor.total_l1_l4"
453
+
454
+ ]
455
+
456
+ },
457
+
458
+ {
459
+
460
+ label: "Power Quality",
461
+
462
+ fields: [
463
+
464
+ "summary.power_quality.voltage.avg_l_n_v",
465
+
466
+ "summary.power_quality.voltage.avg_l_l_v",
467
+
468
+ "summary.power_quality.current.avg_a",
469
+
470
+ "summary.power_quality.power_factor.avg",
471
+
472
+ "summary.power_quality.current.tdd_l1_pct",
473
+
474
+ "summary.power_quality.current.tdd_l2_pct",
475
+
476
+ "summary.power_quality.current.tdd_l3_pct",
477
+
478
+ "summary.power_quality.current.unsymmetry_pct",
479
+
480
+ "summary.power_quality.crest_factor.voltage_l1",
481
+
482
+ "summary.power_quality.crest_factor.current_l1",
483
+
484
+ "summary.power_quality.distortion_reactive.l1_var",
485
+
486
+ "summary.power_quality.k_factor.l1",
487
+
488
+ "summary.power_quality.k_factor.l2",
489
+
490
+ "summary.power_quality.k_factor.l3"
491
+
492
+ ]
493
+
494
+ },
495
+
496
+ {
497
+
498
+ label: "Maximum Values",
499
+
500
+ fields: [
501
+
502
+ "summary.max.voltage.l1_n_v",
503
+
504
+ "summary.max.voltage.l2_n_v",
505
+
506
+ "summary.max.voltage.l3_n_v",
507
+
508
+ "summary.max.current.l1_a",
509
+
510
+ "summary.max.current.l2_a",
511
+
512
+ "summary.max.current.l3_a",
513
+
514
+ "summary.max.power.total_w",
515
+
516
+ "summary.max.reactive.total_var",
517
+
518
+ "summary.max.frequency_hz"
519
+
520
+ ]
521
+
522
+ },
523
+
524
+ {
525
+
526
+ label: "Detailed Energy / Inputs",
527
+
528
+ fields: [
529
+
530
+ "summary.energy.tariff.active",
531
+
532
+ "summary.energy.tariff.reactive",
533
+
534
+ "summary.energy.detail.active_total_kwh",
535
+
536
+ "summary.energy.detail.consumed_total_kwh",
537
+
538
+ "summary.energy.detail.supplied_total_kwh",
539
+
540
+ "summary.energy.detail.reactive_inductive_total_kvarh",
541
+
542
+ "summary.energy.detail.reactive_capacitive_total_kvarh",
543
+
544
+ "summary.digital_inputs.pulse_counter_1",
545
+
546
+ "summary.digital_inputs.pulse_counter_2"
547
+
548
+ ]
549
+
550
+ },
551
+
552
+ {
553
+
554
+ label: "Device / Events",
555
+
556
+ fields: [
557
+
558
+ "summary.device.serial_number",
559
+
560
+ "summary.device.production_number",
561
+
562
+ "summary.device.modbus_address",
563
+
564
+ "summary.device.ip_address",
565
+
566
+ "summary.device.ip_mask",
567
+
568
+ "summary.device.ip_gateway",
569
+
570
+ "summary.device.current_transformer.primary_l1_a",
571
+
572
+ "summary.device.voltage_transformer.primary_l1_v",
573
+
574
+ "summary.events.current_threshold_l1_pct",
575
+
576
+ "summary.events.voltage_max_l1_pct",
577
+
578
+ "summary.events.voltage_min_l1_pct",
579
+
580
+ "summary.temperature.offset_c"
581
+
582
+ ]
583
+
584
+ },
585
+
586
+ {
587
+
588
+ label: "Quick 200 ms",
589
+
590
+ fields: [
591
+
592
+ "summary.quick.frequency_hz",
593
+
594
+ "summary.quick.voltage.l1_n_v",
595
+
596
+ "summary.quick.voltage.l2_n_v",
597
+
598
+ "summary.quick.voltage.l3_n_v",
599
+
600
+ "summary.quick.current.l1_a",
601
+
602
+ "summary.quick.current.l2_a",
603
+
604
+ "summary.quick.current.l3_a",
605
+
606
+ "summary.quick.power.l1_w",
607
+
608
+ "summary.quick.power.l2_w",
609
+
610
+ "summary.quick.power.l3_w",
611
+
612
+ "summary.quick.reactive.l1_var",
613
+
614
+ "summary.quick.reactive.l2_var",
615
+
616
+ "summary.quick.reactive.l3_var"
617
+
618
+ ]
619
+
620
+ }
621
+
622
+ ];
623
+
624
+
625
+ const MULTI_GRID_DEFAULT_FIELDS = [
626
+
627
+ "summary.power.total_w",
628
+
629
+ "summary.power.l1_w",
630
+
631
+ "summary.power.l2_w",
632
+
633
+ "summary.power.l3_w"
634
+
635
+ ];
636
+
637
+ const BESS_CONTROL_DEFAULT_FIELDS = MULTI_GRID_DEFAULT_FIELDS.slice();
638
+
639
+ const CONTROL_EXPORT_REACTIVE_DEFAULT_FIELDS = [
640
+
641
+ "summary.power.total_w",
642
+
643
+ "summary.power.l1_w",
644
+
645
+ "summary.power.l2_w",
646
+
647
+ "summary.power.l3_w",
648
+
649
+ "summary.reactive.total_var",
650
+
651
+ "summary.reactive.l1_var",
652
+
653
+ "summary.reactive.l2_var",
654
+
655
+ "summary.reactive.l3_var"
656
+
657
+ ];
658
+
659
+ const SCADA_DEFAULT_FIELDS = [
660
+
661
+ "summary.power.total_w",
662
+
663
+ "summary.reactive.total_var",
664
+
665
+ "summary.frequency_hz",
666
+
667
+ "summary.voltage.l1_l2_v",
668
+
669
+ "summary.voltage.l2_l3_v",
670
+
671
+ "summary.voltage.l3_l1_v"
672
+
673
+ ];
674
+
675
+
676
+ let payloadSelectionState = ["full"];
677
+
678
+ let customModeSelections = {
679
+
680
+ multiGrid: [],
681
+
682
+ bessControl: [],
683
+
684
+ controlExportReactive: [],
685
+
686
+ scadaServer: [],
687
+
688
+ influxDb: []
689
+
690
+ };
691
+
692
+ let customModeEnabledState = {
693
+
694
+ multiGrid: false,
695
+
696
+ bessControl: false,
697
+
698
+ controlExportReactive: false,
699
+
700
+ scadaServer: false,
701
+
702
+ influxDb: false
703
+
704
+ };
705
+
706
+ let specialExpertUnlockedState = {
707
+
708
+ multiGrid: false,
709
+
710
+ bessControl: false,
711
+
712
+ controlExportReactive: false,
713
+
714
+ scadaServer: false,
715
+
716
+ influxDb: false
717
+
718
+ };
719
+
720
+ let specialLongPressTimer = null;
721
+
722
+ let specialLongPressTriggeredMode = "";
723
+
724
+ let specialLongPressStartChecked = false;
725
+
726
+ let specialLongPressActivationMode = "";
727
+
728
+ let extendedFieldsUnlocked = false;
729
+
730
+ let selectAllLongPressTimer = null;
731
+
732
+ let selectAllLongPressTriggered = false;
733
+
734
+ const SPECIAL_EXPERT_LONG_PRESS_MS = 5000;
735
+
736
+
737
+ function getVisibleFieldGroups() {
738
+
739
+ return extendedFieldsUnlocked ? FIELD_GROUPS.concat(EXTENDED_FIELD_GROUPS) : FIELD_GROUPS;
740
+
741
+ }
742
+
743
+
744
+ function mergeHiddenExtendedSelections(visibleFields) {
745
+
746
+ if (extendedFieldsUnlocked) {
747
+
748
+ return visibleFields;
749
+
750
+ }
751
+
752
+
753
+ const visible = new Set(getAllSelectableFields());
754
+
755
+ const hiddenSelected = normalizePayloadFields(payloadSelectionState, true).filter(function (field) {
756
+
757
+ return field !== "full" && !visible.has(field);
758
+
759
+ });
760
+
761
+
762
+ return Array.from(new Set(hiddenSelected.concat(visibleFields)));
763
+
764
+ }
765
+
766
+
767
+ function getAllSelectableFields() {
768
+
769
+ return getVisibleFieldGroups().reduce(function (acc, group) {
770
+
771
+ return acc.concat(group.fields);
772
+
773
+ }, []);
774
+
775
+ }
776
+
777
+
778
+ function normalizePayloadFields(fields, allowEmpty) {
779
+
780
+ const keepEmpty = !!allowEmpty;
781
+
782
+
783
+ if (Array.isArray(fields) && fields.length) {
784
+
785
+ const normalized = Array.from(new Set(fields.map(function (field) {
786
+
787
+ return String(field || "").trim();
788
+
789
+ }).filter(Boolean)));
790
+
791
+
792
+ if (!normalized.length) {
793
+
794
+ return keepEmpty ? [] : ["full"];
795
+
796
+ }
797
+
798
+ if (normalized.includes("full")) {
799
+
800
+ return ["full"];
801
+
802
+ }
803
+
804
+ return normalized;
805
+
806
+ }
807
+
808
+
809
+ if (typeof fields === "string" && fields.trim()) {
810
+
811
+ const trimmed = fields.trim();
812
+
813
+ if (trimmed[0] === "[") {
814
+
815
+ try {
816
+
817
+ const parsed = JSON.parse(trimmed);
818
+
819
+ if (Array.isArray(parsed)) {
820
+
821
+ return normalizePayloadFields(parsed, keepEmpty);
822
+
823
+ }
824
+
825
+ } catch (e) {
826
+
827
+ // ignore invalid old editor state
828
+
829
+ }
830
+
831
+ }
832
+
833
+ return [trimmed];
834
+
835
+ }
836
+
837
+
838
+ return keepEmpty ? [] : ["full"];
839
+
840
+ }
841
+
842
+
843
+ function arraysEqual(a, b) {
844
+
845
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
846
+
847
+ return false;
848
+
849
+ }
850
+
851
+ for (let i = 0; i < a.length; i += 1) {
852
+
853
+ if (a[i] !== b[i]) {
854
+
855
+ return false;
856
+
857
+ }
858
+
859
+ }
860
+
861
+ return true;
862
+
863
+ }
864
+
865
+
866
+ function sanitizeCustomModeSelection(values) {
867
+
868
+ return normalizePayloadFields(values, true).filter(function (value) {
869
+
870
+ return value !== "full";
871
+
872
+ });
873
+
874
+ }
875
+
876
+
877
+ function getActiveSpecialMode(multiGrid, bessControl, controlExportReactive, scadaServer, influxDb) {
878
+
879
+ if (multiGrid) {
880
+
881
+ return "multiGrid";
882
+
883
+ }
884
+
885
+ if (bessControl) {
886
+
887
+ return "bessControl";
888
+
889
+ }
890
+
891
+ if (controlExportReactive) {
892
+
893
+ return "controlExportReactive";
894
+
895
+ }
896
+
897
+ if (scadaServer) {
898
+
899
+ return "scadaServer";
900
+
901
+ }
902
+
903
+ if (influxDb) {
904
+
905
+ return "influxDb";
906
+
907
+ }
908
+
909
+ return "";
910
+
911
+ }
912
+
913
+
914
+ function getDefaultFieldsForMode(mode) {
915
+
916
+ if (mode === "multiGrid") {
917
+
918
+ return MULTI_GRID_DEFAULT_FIELDS.slice();
919
+
920
+ }
921
+
922
+ if (mode === "bessControl") {
923
+
924
+ return BESS_CONTROL_DEFAULT_FIELDS.slice();
925
+
926
+ }
927
+
928
+ if (mode === "controlExportReactive") {
929
+
930
+ return CONTROL_EXPORT_REACTIVE_DEFAULT_FIELDS.slice();
931
+
932
+ }
933
+
934
+ if (mode === "scadaServer") {
935
+
936
+ return SCADA_DEFAULT_FIELDS.slice();
937
+
938
+ }
939
+
940
+ if (mode === "influxDb") {
941
+
942
+ return getAllSelectableFields();
943
+
944
+ }
945
+
946
+ return ["full"];
947
+
948
+ }
949
+
950
+
951
+ function isSpecialModeEnabled(mode) {
952
+
953
+ return mode === "multiGrid" || mode === "bessControl" || mode === "controlExportReactive" || mode === "scadaServer" || mode === "influxDb";
954
+
955
+ }
956
+
957
+
958
+ function getModeCheckbox(mode) {
959
+
960
+ if (mode === "multiGrid") {
961
+
962
+ return $("#node-input-multiGrid");
963
+
964
+ }
965
+
966
+ if (mode === "bessControl") {
967
+
968
+ return $("#node-input-bessControl");
969
+
970
+ }
971
+
972
+ if (mode === "controlExportReactive") {
973
+
974
+ return $("#node-input-controlExportReactive");
975
+
976
+ }
977
+
978
+ if (mode === "scadaServer") {
979
+
980
+ return $("#node-input-scadaServer");
981
+
982
+ }
983
+
984
+ if (mode === "influxDb") {
985
+
986
+ return $("#node-input-influxDb");
987
+
988
+ }
989
+
990
+ return $();
991
+
992
+ }
993
+
994
+
995
+ function sanitizeForMode(values, multiGrid, bessControl, controlExportReactive, scadaServer, influxDb, options) {
996
+
997
+ const mode = getActiveSpecialMode(multiGrid, bessControl, controlExportReactive, scadaServer, influxDb);
998
+
999
+ const allowEmptySpecial = !!(options && options.allowEmptySpecial && mode);
1000
+
1001
+ const normalized = normalizePayloadFields(values, allowEmptySpecial);
1002
+
1003
+
1004
+ if (mode && normalized.includes("full")) {
1005
+
1006
+ return getDefaultFieldsForMode(mode);
1007
+
1008
+ }
1009
+
1010
+ return normalized;
1011
+
1012
+ }
1013
+
1014
+
1015
+ function getPayloadLabel(path) {
1016
+
1017
+ const labels = {
1018
+
1019
+ "full": "Toate valorile",
1020
+
1021
+ "summary.voltage.l1_n_v": "Tensiune L1-N",
1022
+
1023
+ "summary.voltage.l2_n_v": "Tensiune L2-N",
1024
+
1025
+ "summary.voltage.l3_n_v": "Tensiune L3-N",
1026
+
1027
+ "summary.voltage.l1_l2_v": "Tensiune L1-L2",
1028
+
1029
+ "summary.voltage.l2_l3_v": "Tensiune L2-L3",
1030
+
1031
+ "summary.voltage.l3_l1_v": "Tensiune L3-L1",
1032
+
1033
+ "summary.current.l1_a": "Curent L1",
1034
+
1035
+ "summary.current.l2_a": "Curent L2",
1036
+
1037
+ "summary.current.l3_a": "Curent L3",
1038
+
1039
+ "summary.current.neutral_a": "Curent neutral",
1040
+
1041
+ "summary.power.l1_w": "Putere L1",
1042
+
1043
+ "summary.power.l2_w": "Putere L2",
1044
+
1045
+ "summary.power.l3_w": "Putere L3",
1046
+
1047
+ "summary.power.total_w": "Putere totala",
1048
+
1049
+ "summary.apparent.l1_va": "Putere aparenta L1",
1050
+
1051
+ "summary.apparent.l2_va": "Putere aparenta L2",
1052
+
1053
+ "summary.apparent.l3_va": "Putere aparenta L3",
1054
+
1055
+ "summary.apparent.total_va": "Putere aparenta totala",
1056
+
1057
+ "summary.reactive.l1_var": "Putere reactiva L1",
1058
+
1059
+ "summary.reactive.l2_var": "Putere reactiva L2",
1060
+
1061
+ "summary.reactive.l3_var": "Putere reactiva L3",
1062
+
1063
+ "summary.reactive.total_var": "Putere reactiva totala",
1064
+
1065
+ "summary.power_factor.l1": "Cos phi L1",
1066
+
1067
+ "summary.power_factor.l2": "Cos phi L2",
1068
+
1069
+ "summary.power_factor.l3": "Cos phi L3",
1070
+
1071
+ "summary.frequency_hz": "Frecventa",
1072
+
1073
+ "summary.phase_sequence": "Ordine faze",
1074
+
1075
+ "summary.energy.import_kwh": "Energie importata",
1076
+
1077
+ "summary.energy.export_kwh": "Energie exportata",
1078
+
1079
+ "summary.energy.l1_kwh": "Energie L1",
1080
+
1081
+ "summary.energy.l2_kwh": "Energie L2",
1082
+
1083
+ "summary.energy.l3_kwh": "Energie L3",
1084
+
1085
+ "summary.energy.apparent_kvah": "Energie aparenta",
1086
+
1087
+ "summary.energy.reactive_import_kvarh": "Energie reactiva",
1088
+
1089
+ "summary.energy.reactive_inductive_kvarh": "Energie reactiva inductiva",
1090
+
1091
+ "summary.energy.reactive_capacitive_kvarh": "Energie reactiva capacitiva",
1092
+
1093
+ "summary.thd.voltage.l1_pct": "THD tensiune L1",
1094
+
1095
+ "summary.thd.voltage.l2_pct": "THD tensiune L2",
1096
+
1097
+ "summary.thd.voltage.l3_pct": "THD tensiune L3",
1098
+
1099
+ "summary.thd.current.l1_pct": "THD curent L1",
1100
+
1101
+ "summary.thd.current.l2_pct": "THD curent L2",
1102
+
1103
+ "summary.thd.current.l3_pct": "THD curent L3",
1104
+
1105
+ "summary.extended.voltage.l4_n_v": "Tensiune L4-N",
1106
+
1107
+ "summary.extended.current.l4_a": "Curent L4",
1108
+
1109
+ "summary.extended.power.l4_w": "Putere L4",
1110
+
1111
+ "summary.extended.reactive.l4_var": "Putere reactiva L4",
1112
+
1113
+ "summary.extended.apparent.l4_va": "Putere aparenta L4",
1114
+
1115
+ "summary.extended.current.sum_l1_l4_a": "Curent suma L1-L4",
1116
+
1117
+ "summary.extended.power.total_l1_l4_w": "Putere totala L1-L4",
1118
+
1119
+ "summary.extended.reactive.total_l1_l4_var": "Putere reactiva L1-L4",
1120
+
1121
+ "summary.extended.apparent.total_l1_l4_va": "Putere aparenta L1-L4",
1122
+
1123
+ "summary.extended.power_factor.total_l1_l4": "Factor putere L1-L4",
1124
+
1125
+ "summary.power_quality.voltage.avg_l_n_v": "Tensiune medie L-N",
1126
+
1127
+ "summary.power_quality.voltage.avg_l_l_v": "Tensiune medie L-L",
1128
+
1129
+ "summary.power_quality.current.avg_a": "Curent mediu",
1130
+
1131
+ "summary.power_quality.power_factor.avg": "Factor putere mediu",
1132
+
1133
+ "summary.power_quality.current.tdd_l1_pct": "TDD curent L1",
1134
+
1135
+ "summary.power_quality.current.tdd_l2_pct": "TDD curent L2",
1136
+
1137
+ "summary.power_quality.current.tdd_l3_pct": "TDD curent L3",
1138
+
1139
+ "summary.power_quality.current.unsymmetry_pct": "Dezechilibru curent",
1140
+
1141
+ "summary.power_quality.crest_factor.voltage_l1": "Crest factor tensiune L1",
1142
+
1143
+ "summary.power_quality.crest_factor.current_l1": "Crest factor curent L1",
1144
+
1145
+ "summary.power_quality.distortion_reactive.l1_var": "Putere reactiva distorsiune L1",
1146
+
1147
+ "summary.power_quality.k_factor.l1": "K-factor L1",
1148
+
1149
+ "summary.power_quality.k_factor.l2": "K-factor L2",
1150
+
1151
+ "summary.power_quality.k_factor.l3": "K-factor L3",
1152
+
1153
+ "summary.max.voltage.l1_n_v": "Max tensiune L1-N",
1154
+
1155
+ "summary.max.voltage.l2_n_v": "Max tensiune L2-N",
1156
+
1157
+ "summary.max.voltage.l3_n_v": "Max tensiune L3-N",
1158
+
1159
+ "summary.max.current.l1_a": "Max curent L1",
1160
+
1161
+ "summary.max.current.l2_a": "Max curent L2",
1162
+
1163
+ "summary.max.current.l3_a": "Max curent L3",
1164
+
1165
+ "summary.max.power.total_w": "Max putere totala",
1166
+
1167
+ "summary.max.reactive.total_var": "Max putere reactiva",
1168
+
1169
+ "summary.max.frequency_hz": "Max frecventa",
1170
+
1171
+ "summary.energy.tariff.active": "Tarif energie activa",
1172
+
1173
+ "summary.energy.tariff.reactive": "Tarif energie reactiva",
1174
+
1175
+ "summary.energy.detail.active_total_kwh": "Energie activa totala",
1176
+
1177
+ "summary.energy.detail.consumed_total_kwh": "Energie consumata total",
1178
+
1179
+ "summary.energy.detail.supplied_total_kwh": "Energie livrata total",
1180
+
1181
+ "summary.energy.detail.reactive_inductive_total_kvarh": "Energie reactiva inductiva total",
1182
+
1183
+ "summary.energy.detail.reactive_capacitive_total_kvarh": "Energie reactiva capacitiva total",
1184
+
1185
+ "summary.digital_inputs.pulse_counter_1": "Contor impuls intrare 1",
1186
+
1187
+ "summary.digital_inputs.pulse_counter_2": "Contor impuls intrare 2",
1188
+
1189
+ "summary.device.serial_number": "Serial number",
1190
+
1191
+ "summary.device.production_number": "Production number",
1192
+
1193
+ "summary.device.modbus_address": "Adresa Modbus",
1194
+
1195
+ "summary.device.ip_address": "IP device",
1196
+
1197
+ "summary.device.ip_mask": "Masca IP",
1198
+
1199
+ "summary.device.ip_gateway": "Gateway IP",
1200
+
1201
+ "summary.device.current_transformer.primary_l1_a": "TC primar L1",
1202
+
1203
+ "summary.device.voltage_transformer.primary_l1_v": "TT primar L1",
1204
+
1205
+ "summary.events.current_threshold_l1_pct": "Prag eveniment curent L1",
1206
+
1207
+ "summary.events.voltage_max_l1_pct": "Prag tensiune maxima L1",
1208
+
1209
+ "summary.events.voltage_min_l1_pct": "Prag tensiune minima L1",
1210
+
1211
+ "summary.temperature.offset_c": "Offset temperatura",
1212
+
1213
+ "summary.quick.frequency_hz": "Frecventa quick",
1214
+
1215
+ "summary.quick.voltage.l1_n_v": "Tensiune quick L1-N",
1216
+
1217
+ "summary.quick.voltage.l2_n_v": "Tensiune quick L2-N",
1218
+
1219
+ "summary.quick.voltage.l3_n_v": "Tensiune quick L3-N",
1220
+
1221
+ "summary.quick.current.l1_a": "Curent quick L1",
1222
+
1223
+ "summary.quick.current.l2_a": "Curent quick L2",
1224
+
1225
+ "summary.quick.current.l3_a": "Curent quick L3",
1226
+
1227
+ "summary.quick.power.l1_w": "Putere quick L1",
1228
+
1229
+ "summary.quick.power.l2_w": "Putere quick L2",
1230
+
1231
+ "summary.quick.power.l3_w": "Putere quick L3",
1232
+
1233
+ "summary.quick.reactive.l1_var": "Reactiva quick L1",
1234
+
1235
+ "summary.quick.reactive.l2_var": "Reactiva quick L2",
1236
+
1237
+ "summary.quick.reactive.l3_var": "Reactiva quick L3"
1238
+
1239
+ };
1240
+
1241
+ return labels[path] || path;
1242
+
1243
+ }
1244
+
1245
+
1246
+ function persistPayloadSelection(fields, options) {
1247
+
1248
+ const multiGrid = $("#node-input-multiGrid").is(":checked");
1249
+
1250
+ const bessControl = $("#node-input-bessControl").is(":checked");
1251
+
1252
+ const controlExportReactive = $("#node-input-controlExportReactive").is(":checked");
1253
+
1254
+ const scadaServer = $("#node-input-scadaServer").is(":checked");
1255
+ const influxDb = $("#node-input-influxDb").is(":checked");
1256
+
1257
+ const mode = getActiveSpecialMode(multiGrid, bessControl, controlExportReactive, scadaServer, influxDb);
1258
+
1259
+ const expertMode = $("#node-input-expertMode").is(":checked");
1260
+
1261
+ const modeCustomEnabled = !!(mode && customModeEnabledState[mode]);
1262
+
1263
+ const allowEmptySpecial = !!(options && options.allowEmptySpecial && mode && (expertMode || modeCustomEnabled));
1264
+
1265
+
1266
+ payloadSelectionState = sanitizeForMode(
1267
+
1268
+ fields,
1269
+
1270
+ multiGrid,
1271
+
1272
+ bessControl,
1273
+
1274
+ controlExportReactive,
1275
+
1276
+ scadaServer,
1277
+
1278
+ influxDb,
1279
+
1280
+ { allowEmptySpecial: allowEmptySpecial }
1281
+
1282
+ );
1283
+
1284
+ $("#node-input-payloadFields").val(JSON.stringify(payloadSelectionState));
1285
+
1286
+
1287
+ if (mode && (expertMode || modeCustomEnabled)) {
1288
+
1289
+ customModeSelections[mode] = sanitizeCustomModeSelection(payloadSelectionState);
1290
+
1291
+ }
1292
+
1293
+
1294
+ updateOutputs();
1295
+
1296
+ }
1297
+
1298
+
1299
+ function renderFieldSelection(currentFields) {
1300
+
1301
+ const selected = new Set(currentFields || []);
1302
+
1303
+ const $container = $("#node-janitza-field-list").empty();
1304
+
1305
+
1306
+ getVisibleFieldGroups().forEach(function (group) {
1307
+
1308
+ const $group = $('<div class="pr-field-group"></div>');
1309
+
1310
+ const $grid = $('<div class="pr-field-group-grid"></div>');
1311
+
1312
+
1313
+ $group.append($('<p class="pr-field-group-title"></p>').text(group.label));
1314
+
1315
+
1316
+ group.fields.forEach(function (field) {
1317
+
1318
+ const $checkbox = $('<input type="checkbox">')
1319
+
1320
+ .attr("data-field", field)
1321
+
1322
+ .prop("checked", selected.has(field));
1323
+
1324
+
1325
+ const $label = $('<label class="pr-field-item"></label>')
1326
+
1327
+ .append($checkbox)
1328
+
1329
+ .append($('<span></span>').text(getPayloadLabel(field)));
1330
+
1331
+
1332
+ $grid.append($label);
1333
+
1334
+ });
1335
+
1336
+
1337
+ $group.append($grid);
1338
+
1339
+ $container.append($group);
1340
+
1341
+ });
1342
+
1343
+
1344
+ $container.find("input[type=checkbox]").on("change", function () {
1345
+
1346
+ const fields = [];
1347
+
1348
+ $container.find("input[type=checkbox]:checked").each(function () {
1349
+
1350
+ fields.push($(this).attr("data-field"));
1351
+
1352
+ });
1353
+
1354
+ persistPayloadSelection(mergeHiddenExtendedSelections(fields), { allowEmptySpecial: true });
1355
+
1356
+ });
1357
+
1358
+ }
1359
+
1360
+
1361
+ function syncPayloadModeUi() {
1362
+
1363
+ const multiGrid = $("#node-input-multiGrid").is(":checked");
1364
+
1365
+ const bessControl = $("#node-input-bessControl").is(":checked");
1366
+
1367
+ const controlExportReactive = $("#node-input-controlExportReactive").is(":checked");
1368
+
1369
+ const scadaServer = $("#node-input-scadaServer").is(":checked");
1370
+ const influxDb = $("#node-input-influxDb").is(":checked");
1371
+
1372
+ const specialMode = getActiveSpecialMode(
1373
+
1374
+ multiGrid,
1375
+
1376
+ bessControl,
1377
+
1378
+ controlExportReactive,
1379
+
1380
+ scadaServer,
1381
+
1382
+ influxDb
1383
+
1384
+ );
1385
+
1386
+ if (!specialMode) {
1387
+
1388
+ $("#node-input-expertMode").prop("checked", false);
1389
+
1390
+ }
1391
+
1392
+
1393
+ const expertMode = $("#node-input-expertMode").is(":checked");
1394
+
1395
+ const specialModeCustomEnabled = !!(specialMode && customModeEnabledState[specialMode]);
1396
+
1397
+ const selectedMode = specialMode ? "selected" : ($("#node-input-payloadMode").val() || "full");
1398
+
1399
+ const showSelectedFields = selectedMode === "selected" && (!specialMode || expertMode);
1400
+
1401
+ const showDefaultButton = showSelectedFields && !!specialMode;
1402
+
1403
+
1404
+ $("#node-input-payloadMode").val(selectedMode);
1405
+
1406
+ $("#node-janitza-field-tools").toggle(showSelectedFields);
1407
+
1408
+ $("#node-janitza-field-list").toggle(showSelectedFields);
1409
+
1410
+ $("#node-janitza-default-values").toggle(showDefaultButton);
1411
+
1412
+ $("#row-expert-mode").toggle(!!specialMode && !!specialExpertUnlockedState[specialMode]);
1413
+
1414
+ $("#row-meter-id").toggle(!!specialMode);
1415
+ $("#row-influx-measurement,#row-influx-node").toggle(!!influxDb);
1416
+
1417
+
1418
+ if (specialMode && !expertMode) {
1419
+
1420
+ payloadSelectionState = (specialModeCustomEnabled ? customModeSelections[specialMode] : getDefaultFieldsForMode(specialMode)).slice();
1421
+
1422
+ $("#node-input-payloadFields").val(JSON.stringify(payloadSelectionState));
1423
+
1424
+ $("#node-input-outputs").val(1);
1425
+
1426
+ } else if (!showSelectedFields) {
1427
+
1428
+ persistPayloadSelection(["full"]);
1429
+
1430
+ } else if (specialMode && expertMode) {
1431
+
1432
+ if (payloadSelectionState.includes("full")) {
1433
+
1434
+ payloadSelectionState = customModeSelections[specialMode].slice();
1435
+
1436
+ }
1437
+
1438
+ persistPayloadSelection(payloadSelectionState, { allowEmptySpecial: true });
1439
+
1440
+ } else if (payloadSelectionState.includes("full")) {
1441
+
1442
+ persistPayloadSelection([]);
1443
+
1444
+ }
1445
+
1446
+
1447
+ renderFieldSelection(payloadSelectionState);
1448
+
1449
+ updateOutputs();
1450
+
1451
+ }
1452
+
1453
+
1454
+ function clearSpecialLongPressTimer() {
1455
+
1456
+ if (specialLongPressTimer) {
1457
+
1458
+ clearTimeout(specialLongPressTimer);
1459
+
1460
+ specialLongPressTimer = null;
1461
+
1462
+ }
1463
+
1464
+ }
1465
+
1466
+
1467
+ function unlockSpecialExpertMode(mode) {
1468
+
1469
+ if (!isSpecialModeEnabled(mode)) {
1470
+
1471
+ return;
1472
+
1473
+ }
1474
+
1475
+
1476
+ specialExpertUnlockedState[mode] = true;
1477
+
1478
+ $("#node-input-expertMode").prop("checked", true).trigger("change");
1479
+
1480
+ syncPayloadModeUi();
1481
+
1482
+
1483
+ if (RED && RED.notify) {
1484
+
1485
+ RED.notify("Selectia custom a fost activata.", "success");
1486
+
1487
+ }
1488
+
1489
+ }
1490
+
1491
+
1492
+ function setupSpecialModeLongPress() {
1493
+
1494
+ function startLongPress(mode) {
1495
+
1496
+ const $checkbox = getModeCheckbox(mode);
1497
+
1498
+ if (!$checkbox.length || specialExpertUnlockedState[mode]) {
1499
+
1500
+ return;
1501
+
1502
+ }
1503
+
1504
+
1505
+ specialLongPressTriggeredMode = "";
1506
+
1507
+ specialLongPressStartChecked = $checkbox.is(":checked");
1508
+
1509
+ clearSpecialLongPressTimer();
1510
+
1511
+
1512
+ specialLongPressTimer = setTimeout(function () {
1513
+
1514
+ if (specialLongPressStartChecked && $checkbox.is(":checked")) {
1515
+
1516
+ specialLongPressTriggeredMode = mode;
1517
+
1518
+ unlockSpecialExpertMode(mode);
1519
+
1520
+ }
1521
+
1522
+ }, SPECIAL_EXPERT_LONG_PRESS_MS);
1523
+
1524
+ }
1525
+
1526
+
1527
+ ["multiGrid", "bessControl", "controlExportReactive", "scadaServer", "influxDb"].forEach(function (mode) {
1528
+
1529
+ const $checkbox = getModeCheckbox(mode);
1530
+
1531
+ $checkbox
1532
+
1533
+ .off(".janitzaSpecialLongPress")
1534
+
1535
+ .on("mousedown.janitzaSpecialLongPress touchstart.janitzaSpecialLongPress", function () {
1536
+
1537
+ startLongPress(mode);
1538
+
1539
+ })
1540
+
1541
+ .on("mouseup.janitzaSpecialLongPress mouseleave.janitzaSpecialLongPress touchend.janitzaSpecialLongPress touchcancel.janitzaSpecialLongPress", function () {
1542
+
1543
+ clearSpecialLongPressTimer();
1544
+
1545
+ })
1546
+
1547
+ .on("click.janitzaSpecialLongPress", function (evt) {
1548
+
1549
+ if (specialLongPressTriggeredMode !== mode) {
1550
+
1551
+ return;
1552
+
1553
+ }
1554
+
1555
+ evt.preventDefault();
1556
+
1557
+ evt.stopImmediatePropagation();
1558
+
1559
+ specialLongPressActivationMode = mode;
1560
+
1561
+ $checkbox.prop("checked", true).trigger("change");
1562
+
1563
+ specialLongPressTriggeredMode = "";
1564
+
1565
+ });
1566
+
1567
+ });
1568
+
1569
+ }
1570
+
1571
+
1572
+ function clearSelectAllLongPressTimer() {
1573
+
1574
+ if (selectAllLongPressTimer) {
1575
+
1576
+ clearTimeout(selectAllLongPressTimer);
1577
+
1578
+ selectAllLongPressTimer = null;
1579
+
1580
+ }
1581
+
1582
+ }
1583
+
1584
+
1585
+ function setupSelectAllLongPress() {
1586
+
1587
+ $("#node-janitza-select-all")
1588
+
1589
+ .off(".janitzaExtendedLongPress")
1590
+
1591
+ .on("mousedown.janitzaExtendedLongPress touchstart.janitzaExtendedLongPress", function () {
1592
+
1593
+ if ($("#node-input-payloadMode").val() !== "selected") {
1594
+
1595
+ return;
1596
+
1597
+ }
1598
+
1599
+
1600
+ selectAllLongPressTriggered = false;
1601
+
1602
+ clearSelectAllLongPressTimer();
1603
+
1604
+ selectAllLongPressTimer = setTimeout(function () {
1605
+
1606
+ extendedFieldsUnlocked = true;
1607
+
1608
+ selectAllLongPressTriggered = true;
1609
+
1610
+ renderFieldSelection(payloadSelectionState);
1611
+
1612
+ if (RED && RED.notify) {
1613
+
1614
+ RED.notify("Valorile extinse Janitza au fost afisate.", "success");
1615
+
1616
+ }
1617
+
1618
+ }, SPECIAL_EXPERT_LONG_PRESS_MS);
1619
+
1620
+ })
1621
+
1622
+ .on("mouseup.janitzaExtendedLongPress mouseleave.janitzaExtendedLongPress touchend.janitzaExtendedLongPress touchcancel.janitzaExtendedLongPress", function () {
1623
+
1624
+ clearSelectAllLongPressTimer();
1625
+
1626
+ });
1627
+
1628
+ }
1629
+
1630
+
1631
+ function updateSpecialModes(changedId) {
1632
+
1633
+ const ids = ["multiGrid", "bessControl", "controlExportReactive", "scadaServer", "influxDb"];
1634
+
1635
+ const activatedByLongPress = specialLongPressActivationMode === changedId;
1636
+
1637
+ const previousState = {};
1638
+
1639
+ ids.forEach(function (id) {
1640
+
1641
+ previousState[id] = $("#node-input-" + id).is(":checked");
1642
+
1643
+ });
1644
+
1645
+ previousState[changedId] = !previousState[changedId];
1646
+
1647
+ const previousMode = getActiveSpecialMode(previousState.multiGrid, previousState.bessControl, previousState.controlExportReactive, previousState.scadaServer, previousState.influxDb);
1648
+
1649
+
1650
+ if (previousMode && ($("#node-input-expertMode").is(":checked") || customModeEnabledState[previousMode])) {
1651
+
1652
+ customModeSelections[previousMode] = sanitizeCustomModeSelection(payloadSelectionState);
1653
+
1654
+ }
1655
+
1656
+
1657
+ if ($("#node-input-" + changedId).is(":checked")) {
1658
+
1659
+ ids.forEach(function (id) {
1660
+
1661
+ const keepInfluxPair = changedId === "influxDb" ? id !== "influxDb" : id === "influxDb";
1662
+ if (id !== changedId && !keepInfluxPair) {
1663
+
1664
+ $("#node-input-" + id).prop("checked", false);
1665
+
1666
+ }
1667
+
1668
+ });
1669
+
1670
+ }
1671
+
1672
+
1673
+ const specialMode = getActiveSpecialMode(
1674
+
1675
+ $("#node-input-multiGrid").is(":checked"),
1676
+
1677
+ $("#node-input-bessControl").is(":checked"),
1678
+
1679
+ $("#node-input-controlExportReactive").is(":checked"),
1680
+
1681
+ $("#node-input-scadaServer").is(":checked"),
1682
+
1683
+ $("#node-input-influxDb").is(":checked")
1684
+
1685
+ );
1686
+
1687
+
1688
+ $("#node-input-payloadMode").prop("disabled", !!specialMode);
1689
+
1690
+ if (specialMode) {
1691
+
1692
+ $("#node-input-payloadMode").val("selected");
1693
+
1694
+ if (!activatedByLongPress) {
1695
+
1696
+ $("#node-input-expertMode").prop("checked", false);
1697
+
1698
+ ids.forEach(function (id) {
1699
+
1700
+ specialExpertUnlockedState[id] = false;
1701
+
1702
+ });
1703
+
1704
+ } else {
1705
+
1706
+ specialExpertUnlockedState[changedId] = true;
1707
+
1708
+ }
1709
+
1710
+ } else if (changedId) {
1711
+
1712
+ specialExpertUnlockedState[changedId] = false;
1713
+
1714
+ }
1715
+
1716
+ specialLongPressActivationMode = "";
1717
+
1718
+ syncPayloadModeUi();
1719
+
1720
+ persistPayloadSelection(payloadSelectionState, { allowEmptySpecial: true });
1721
+
1722
+ }
1723
+
1724
+
1725
+ function updateOutputs() {
1726
+
1727
+ const specialMode = getActiveSpecialMode(
1728
+
1729
+ $("#node-input-multiGrid").is(":checked"),
1730
+
1731
+ $("#node-input-bessControl").is(":checked"),
1732
+
1733
+ $("#node-input-controlExportReactive").is(":checked"),
1734
+
1735
+ $("#node-input-scadaServer").is(":checked"),
1736
+
1737
+ $("#node-input-influxDb").is(":checked")
1738
+
1739
+ );
1740
+
1741
+ const payloadMode = $("#node-input-payloadMode").val();
1742
+
1743
+ const outputs = specialMode || payloadMode === "full" ? 1 : Math.max(1, payloadSelectionState.length);
1744
+
1745
+ $("#node-input-outputs").val(outputs);
1746
+
1747
+ }
1748
+
1749
+
1750
+ RED.nodes.registerType("janitza", {
1751
+
1752
+ category: "Atelierul de Tehnologii",
1753
+
1754
+ color: "#c7e9c0",
1755
+
1756
+ defaults: {
1757
+ license: { value: "", type: "atelier-license", required: true },
1758
+
1759
+ name: { value: "" },
1760
+
1761
+ model: { value: "umg604pro", required: true },
1762
+
1763
+ host: { value: "", required: true },
1764
+
1765
+ port: { value: 502, required: true, validate: RED.validators.number() },
1766
+
1767
+ unitId: { value: 1, required: true, validate: RED.validators.number() },
1768
+
1769
+ timestep: {
1770
+ value: 1000,
1771
+ required: true,
1772
+ validate: function (v) {
1773
+ const text = String(v || "").trim().toLowerCase();
1774
+ const n = Number(text);
1775
+ return text === "off" || (Number.isFinite(n) && n >= 0);
1776
+ }
1777
+ },
1778
+
1779
+ payloadFields: { value: ["full"] },
1780
+
1781
+ payloadMode: { value: "full" },
1782
+
1783
+ multiGrid: { value: false },
1784
+
1785
+ bessControl: { value: false },
1786
+
1787
+ controlExportReactive: { value: false },
1788
+
1789
+ scadaServer: { value: false },
1790
+
1791
+ influxDb: { value: false },
1792
+
1793
+ influxMeasurement: {
1794
+
1795
+ value: "",
1796
+
1797
+ validate: function (v) {
1798
+
1799
+ const influxChecked = $("#node-input-influxDb").length
1800
+ ? $("#node-input-influxDb").is(":checked")
1801
+ : !!this.influxDb;
1802
+
1803
+ return !influxChecked || !!String(v || "").trim();
1804
+ }
1805
+
1806
+ },
1807
+
1808
+ influxNode: { value: "" },
1809
+ expertMode: { value: false },
1810
+
1811
+ multiGridCustomFields: { value: [] },
1812
+
1813
+ bessControlCustomFields: { value: [] },
1814
+
1815
+ controlExportReactiveCustomFields: { value: [] },
1816
+
1817
+ scadaServerCustomFields: { value: [] },
1818
+
1819
+ influxDbCustomFields: { value: [] },
1820
+
1821
+ multiGridUseSelectedFields: { value: false },
1822
+
1823
+ bessControlUseSelectedFields: { value: false },
1824
+
1825
+ controlExportReactiveUseSelectedFields: { value: false },
1826
+
1827
+ scadaServerUseSelectedFields: { value: false },
1828
+
1829
+ influxDbUseSelectedFields: { value: false },
1830
+
1831
+ meterId: {
1832
+
1833
+ value: "",
1834
+
1835
+ validate: function (v) {
1836
+
1837
+ const isSpecial = (
1838
+
1839
+ $("#node-input-multiGrid").is(":checked") ||
1840
+
1841
+ $("#node-input-bessControl").is(":checked") ||
1842
+
1843
+ $("#node-input-controlExportReactive").is(":checked") ||
1844
+
1845
+ $("#node-input-scadaServer").is(":checked") ||
1846
+
1847
+ $("#node-input-influxDb").is(":checked")
1848
+
1849
+ );
1850
+
1851
+ return !isSpecial || !!String(v || "").trim();
1852
+
1853
+ }
1854
+
1855
+ },
1856
+
1857
+ outputs: { value: 1 }
1858
+
1859
+ },
1860
+
1861
+ inputs: 0,
1862
+
1863
+ outputs: 1,
1864
+
1865
+ icon: "bridge.svg",
1866
+
1867
+ label: function () {
1868
+
1869
+ if (this.name && String(this.name).trim()) {
1870
+
1871
+ return this.name;
1872
+
1873
+ }
1874
+
1875
+ if (this.host && String(this.host).trim()) {
1876
+
1877
+ return String(this.host).trim();
1878
+
1879
+ }
1880
+
1881
+ return "janitza";
1882
+
1883
+ },
1884
+
1885
+ oneditprepare: function () {
1886
+ const node = this;
1887
+ const influxSelect = $("#node-input-influxNode").empty().append($("<option></option>").val("").text("Selecteaza adt-influxdb"));
1888
+ RED.nodes.eachNode(function (candidate) {
1889
+ if (candidate.type === "adt-influxdb") influxSelect.append($("<option></option>").val(candidate.id).text(candidate.name || "adt-influxdb"));
1890
+ });
1891
+ influxSelect.val(node.influxNode || "");
1892
+
1893
+ function syncInputs() {
1894
+ const text = String($("#node-input-timestep").val() || "").trim().toLowerCase();
1895
+ node.inputs = text === "off" || text === "0" ? 1 : 0;
1896
+ }
1897
+
1898
+ $("#node-input-timestep").off(".janitzaPoll").on("keyup.janitzaPoll change.janitzaPoll", syncInputs);
1899
+ syncInputs();
1900
+
1901
+ const $dialog = $("#dialog-form").closest(".ui-dialog");
1902
+
1903
+ if ($dialog.length) {
1904
+
1905
+ $("#dialog-form").dialog("option", "width", 700);
1906
+
1907
+ }
1908
+
1909
+
1910
+ let nameManuallyEdited = !!(this.name && this.name.trim());
1911
+
1912
+ const specialMode = getActiveSpecialMode(!!this.multiGrid, !!this.bessControl, !!this.controlExportReactive, !!this.scadaServer, !!this.influxDb);
1913
+
1914
+
1915
+ customModeSelections = {
1916
+
1917
+ multiGrid: sanitizeCustomModeSelection(this.multiGridCustomFields),
1918
+
1919
+ bessControl: sanitizeCustomModeSelection(this.bessControlCustomFields),
1920
+
1921
+ controlExportReactive: sanitizeCustomModeSelection(this.controlExportReactiveCustomFields),
1922
+
1923
+ scadaServer: sanitizeCustomModeSelection(this.scadaServerCustomFields),
1924
+
1925
+ influxDb: sanitizeCustomModeSelection(this.influxDbCustomFields)
1926
+
1927
+ };
1928
+
1929
+ customModeEnabledState = {
1930
+
1931
+ multiGrid: !!this.multiGridUseSelectedFields,
1932
+
1933
+ bessControl: !!this.bessControlUseSelectedFields,
1934
+
1935
+ controlExportReactive: !!this.controlExportReactiveUseSelectedFields,
1936
+
1937
+ scadaServer: !!this.scadaServerUseSelectedFields,
1938
+
1939
+ influxDb: !!this.influxDbUseSelectedFields
1940
+
1941
+ };
1942
+
1943
+ if (specialMode && this.expertMode) {
1944
+
1945
+ customModeEnabledState[specialMode] = true;
1946
+
1947
+ }
1948
+
1949
+ specialExpertUnlockedState = {
1950
+
1951
+ multiGrid: false,
1952
+
1953
+ bessControl: false,
1954
+
1955
+ controlExportReactive: false,
1956
+
1957
+ scadaServer: false,
1958
+
1959
+ influxDb: false
1960
+
1961
+ };
1962
+
1963
+
1964
+ if (!this.name && this.host) {
1965
+
1966
+ $("#node-input-name").val(this.host);
1967
+
1968
+ }
1969
+
1970
+
1971
+ payloadSelectionState = sanitizeForMode(
1972
+
1973
+ this.payloadFields || ["full"],
1974
+
1975
+ !!this.multiGrid,
1976
+
1977
+ !!this.bessControl,
1978
+
1979
+ !!this.controlExportReactive,
1980
+
1981
+ !!this.scadaServer,
1982
+
1983
+ !!this.influxDb,
1984
+
1985
+ { allowEmptySpecial: !!(specialMode && (this.expertMode || customModeEnabledState[specialMode])) }
1986
+
1987
+ );
1988
+
1989
+ extendedFieldsUnlocked = false;
1990
+
1991
+
1992
+ $("#node-input-payloadMode").val(specialMode ? "selected" : (payloadSelectionState.includes("full") ? "full" : (this.payloadMode || "selected")));
1993
+
1994
+ $("#node-input-payloadFields").val(JSON.stringify(payloadSelectionState));
1995
+
1996
+ $("#node-input-expertMode").prop("checked", false);
1997
+
1998
+ renderFieldSelection(payloadSelectionState);
1999
+
2000
+
2001
+ $("#node-input-name").on("input.janitzaName", function () {
2002
+
2003
+ nameManuallyEdited = true;
2004
+
2005
+ });
2006
+
2007
+
2008
+ $("#node-input-host").on("input.janitzaHostSync change.janitzaHostSync", function () {
2009
+
2010
+ const newHost = String($(this).val() || "").trim();
2011
+
2012
+ if (newHost || !$("#node-input-name").val().trim()) {
2013
+
2014
+ $("#node-input-name").val(newHost);
2015
+
2016
+ }
2017
+
2018
+ });
2019
+
2020
+
2021
+ $("#node-input-payloadMode").on("change.janitzaPayloadMode", syncPayloadModeUi);
2022
+
2023
+ $("#node-input-expertMode").on("change.janitzaExpert", function () {
2024
+
2025
+ const special = getActiveSpecialMode(
2026
+
2027
+ $("#node-input-multiGrid").is(":checked"),
2028
+
2029
+ $("#node-input-bessControl").is(":checked"),
2030
+
2031
+ $("#node-input-controlExportReactive").is(":checked"),
2032
+
2033
+ $("#node-input-scadaServer").is(":checked"),
2034
+
2035
+ $("#node-input-influxDb").is(":checked")
2036
+
2037
+ );
2038
+
2039
+ if (special && !$(this).is(":checked")) {
2040
+
2041
+ persistPayloadSelection(getDefaultFieldsForMode(special), { allowEmptySpecial: true });
2042
+
2043
+ renderFieldSelection(payloadSelectionState);
2044
+
2045
+ }
2046
+
2047
+ syncPayloadModeUi();
2048
+
2049
+ });
2050
+
2051
+
2052
+ $("#node-janitza-select-all").on("click.janitzaToolbar", function (evt) {
2053
+
2054
+ evt.preventDefault();
2055
+
2056
+ if (selectAllLongPressTriggered) {
2057
+
2058
+ selectAllLongPressTriggered = false;
2059
+
2060
+ return;
2061
+
2062
+ }
2063
+
2064
+ persistPayloadSelection(mergeHiddenExtendedSelections(getAllSelectableFields()), { allowEmptySpecial: true });
2065
+
2066
+ renderFieldSelection(payloadSelectionState);
2067
+
2068
+ });
2069
+
2070
+
2071
+ $("#node-janitza-clear-all").on("click.janitzaToolbar", function (evt) {
2072
+
2073
+ evt.preventDefault();
2074
+
2075
+ persistPayloadSelection(mergeHiddenExtendedSelections([]), { allowEmptySpecial: true });
2076
+
2077
+ renderFieldSelection(payloadSelectionState);
2078
+
2079
+ });
2080
+
2081
+
2082
+ $("#node-janitza-default-values").on("click.janitzaToolbar", function (evt) {
2083
+
2084
+ evt.preventDefault();
2085
+
2086
+ const special = getActiveSpecialMode(
2087
+
2088
+ $("#node-input-multiGrid").is(":checked"),
2089
+
2090
+ $("#node-input-bessControl").is(":checked"),
2091
+
2092
+ $("#node-input-controlExportReactive").is(":checked"),
2093
+
2094
+ $("#node-input-scadaServer").is(":checked"),
2095
+
2096
+ $("#node-input-influxDb").is(":checked")
2097
+
2098
+ );
2099
+
2100
+ persistPayloadSelection(special ? getDefaultFieldsForMode(special) : ["full"], { allowEmptySpecial: true });
2101
+
2102
+ if (!special) {
2103
+
2104
+ $("#node-input-payloadMode").val("full");
2105
+
2106
+ }
2107
+
2108
+ renderFieldSelection(payloadSelectionState);
2109
+
2110
+ syncPayloadModeUi();
2111
+
2112
+ });
2113
+
2114
+
2115
+ ["multiGrid", "bessControl", "controlExportReactive", "scadaServer", "influxDb"].forEach(function (id) {
2116
+
2117
+ $("#node-input-" + id).on("change.janitzaSpecial", function () {
2118
+
2119
+ updateSpecialModes(id);
2120
+
2121
+ });
2122
+
2123
+ });
2124
+
2125
+
2126
+ setupSpecialModeLongPress();
2127
+
2128
+ setupSelectAllLongPress();
2129
+
2130
+ updateSpecialModes(specialMode || "");
2131
+
2132
+ syncPayloadModeUi();
2133
+
2134
+ },
2135
+
2136
+ oneditsave: function () {
2137
+
2138
+ const multiGrid = $("#node-input-multiGrid").is(":checked");
2139
+
2140
+ const bessControl = $("#node-input-bessControl").is(":checked");
2141
+
2142
+ const controlExportReactive = $("#node-input-controlExportReactive").is(":checked");
2143
+
2144
+ const scadaServer = $("#node-input-scadaServer").is(":checked");
2145
+ const influxDb = $("#node-input-influxDb").is(":checked");
2146
+
2147
+ const expertMode = $("#node-input-expertMode").is(":checked");
2148
+
2149
+ const specialMode = getActiveSpecialMode(multiGrid, bessControl, controlExportReactive, scadaServer, influxDb);
2150
+
2151
+ const modeCustomEnabled = !!(specialMode && (customModeEnabledState[specialMode] || expertMode));
2152
+
2153
+ let selected = sanitizeForMode(
2154
+
2155
+ payloadSelectionState,
2156
+
2157
+ multiGrid,
2158
+
2159
+ bessControl,
2160
+
2161
+ controlExportReactive,
2162
+
2163
+ scadaServer,
2164
+
2165
+ influxDb,
2166
+
2167
+ { allowEmptySpecial: !!(specialMode && modeCustomEnabled) }
2168
+
2169
+ );
2170
+
2171
+
2172
+ if (specialMode && expertMode) {
2173
+
2174
+ customModeEnabledState[specialMode] = true;
2175
+
2176
+ customModeSelections[specialMode] = sanitizeCustomModeSelection(selected);
2177
+
2178
+ }
2179
+
2180
+
2181
+ if (specialMode && customModeEnabledState[specialMode]) {
2182
+
2183
+ this.payloadFields = selected.slice();
2184
+
2185
+ } else if (specialMode) {
2186
+
2187
+ this.payloadFields = getDefaultFieldsForMode(specialMode);
2188
+
2189
+ } else if (selected.includes("full")) {
2190
+
2191
+ this.payloadFields = ["full"];
2192
+
2193
+ }
2194
+
2195
+ else {
2196
+
2197
+ this.payloadFields = selected.slice();
2198
+
2199
+ }
2200
+
2201
+
2202
+ this.payloadMode = $("#node-input-payloadMode").val();
2203
+
2204
+ this.multiGrid = multiGrid;
2205
+
2206
+ this.bessControl = bessControl;
2207
+
2208
+ this.controlExportReactive = controlExportReactive;
2209
+
2210
+ this.scadaServer = scadaServer;
2211
+
2212
+ this.influxDb = influxDb;
2213
+ this.influxMeasurement = String($("#node-input-influxMeasurement").val() || "").trim();
2214
+
2215
+ this.expertMode = false;
2216
+
2217
+ this.multiGridCustomFields = customModeSelections.multiGrid.slice();
2218
+
2219
+ this.bessControlCustomFields = customModeSelections.bessControl.slice();
2220
+
2221
+ this.controlExportReactiveCustomFields = customModeSelections.controlExportReactive.slice();
2222
+
2223
+ this.scadaServerCustomFields = customModeSelections.scadaServer.slice();
2224
+
2225
+ this.influxDbCustomFields = customModeSelections.influxDb.slice();
2226
+
2227
+ this.multiGridUseSelectedFields = !!customModeEnabledState.multiGrid;
2228
+
2229
+ this.bessControlUseSelectedFields = !!customModeEnabledState.bessControl;
2230
+
2231
+ this.controlExportReactiveUseSelectedFields = !!customModeEnabledState.controlExportReactive;
2232
+
2233
+ this.scadaServerUseSelectedFields = !!customModeEnabledState.scadaServer;
2234
+
2235
+ this.influxDbUseSelectedFields = !!customModeEnabledState.influxDb;
2236
+ const timestepText = String($("#node-input-timestep").val() || "").trim().toLowerCase();
2237
+ this.inputs = timestepText === "off" || timestepText === "0" ? 1 : 0;
2238
+
2239
+ this.outputs = specialMode || this.payloadFields.includes("full") ? 1 : Math.max(1, this.payloadFields.length);
2240
+
2241
+
2242
+ if (!this.name || !String(this.name).trim()) {
2243
+
2244
+ this.name = String($("#node-input-host").val() || "").trim();
2245
+
2246
+ $("#node-input-name").val(this.name);
2247
+
2248
+ }
2249
+
2250
+
2251
+ $("#node-input-payloadFields").val(JSON.stringify(this.payloadFields));
2252
+
2253
+ $("#node-input-outputs").val(this.outputs);
2254
+
2255
+ },
2256
+
2257
+ oneditcancel: function () {
2258
+
2259
+ $("#node-input-name").off(".janitzaName");
2260
+
2261
+ $("#node-input-host").off(".janitzaHostSync");
2262
+
2263
+ $("#node-input-payloadMode").off(".janitzaPayloadMode");
2264
+
2265
+ $("#node-input-expertMode").off(".janitzaExpert");
2266
+ $("#node-input-timestep").off(".janitzaPoll");
2267
+
2268
+ $("#node-janitza-select-all").off(".janitzaToolbar");
2269
+
2270
+ $("#node-janitza-clear-all").off(".janitzaToolbar");
2271
+
2272
+ $("#node-janitza-default-values").off(".janitzaToolbar");
2273
+
2274
+ $("#node-input-multiGrid").off(".janitzaSpecial");
2275
+
2276
+ $("#node-input-bessControl").off(".janitzaSpecial");
2277
+
2278
+ $("#node-input-controlExportReactive").off(".janitzaSpecial");
2279
+
2280
+ $("#node-input-scadaServer").off(".janitzaSpecial");
2281
+
2282
+ $("#node-input-influxDb").off(".janitzaSpecial");
2283
+
2284
+ $("#node-input-multiGrid").off(".janitzaSpecialLongPress");
2285
+
2286
+ $("#node-input-bessControl").off(".janitzaSpecialLongPress");
2287
+
2288
+ $("#node-input-controlExportReactive").off(".janitzaSpecialLongPress");
2289
+
2290
+ $("#node-input-scadaServer").off(".janitzaSpecialLongPress");
2291
+
2292
+ $("#node-input-influxDb").off(".janitzaSpecialLongPress");
2293
+
2294
+ $("#node-janitza-select-all").off(".janitzaExtendedLongPress");
2295
+
2296
+ clearSelectAllLongPressTimer();
2297
+
2298
+ }
2299
+
2300
+ });
2301
+
2302
+ }());
2303
+
2304
+ </script>
2305
+
2306
+
2307
+ <script type="text/html" data-template-name="janitza">
2308
+ <div class="form-row"><label for="node-input-license"><i class="fa fa-key"></i> License</label><input type="text" id="node-input-license"></div>
2309
+
2310
+ <div class="janitza-editor">
2311
+
2312
+ <div class="pr-section">
2313
+
2314
+ <p class="pr-section-title"><i class="fa fa-plug"></i> Janitza</p>
2315
+
2316
+ <p class="pr-section-note">Selecteaza modelul contorului. Pentru moment profilul disponibil este UMG 604 Pro.</p>
2317
+
2318
+ <div class="pr-grid">
2319
+
2320
+ <div class="form-row">
2321
+
2322
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
2323
+
2324
+ <input type="text" id="node-input-name" placeholder="janitza">
2325
+
2326
+ </div>
2327
+
2328
+ <div class="form-row">
2329
+
2330
+ <label for="node-input-model"><i class="fa fa-microchip"></i> Model</label>
2331
+
2332
+ <select id="node-input-model">
2333
+
2334
+ <option value="umg604pro">UMG 604 Pro</option>
2335
+
2336
+ </select>
2337
+
2338
+ </div>
2339
+
2340
+ <div class="form-row" id="row-meter-id" style="display:none;">
2341
+
2342
+ <label for="node-input-meterId"><i class="fa fa-id-badge"></i> Meter ID</label>
2343
+
2344
+ <input type="text" id="node-input-meterId" placeholder="meter1">
2345
+
2346
+ </div>
2347
+
2348
+ <div class="form-row">
2349
+
2350
+ <label for="node-input-host"><i class="fa fa-globe"></i> Host</label>
2351
+
2352
+ <input type="text" id="node-input-host" placeholder="192.168.1.100">
2353
+
2354
+ </div>
2355
+
2356
+ <div class="form-row">
2357
+
2358
+ <label for="node-input-port"><i class="fa fa-ellipsis-h"></i> Port</label>
2359
+
2360
+ <input type="number" id="node-input-port" min="1" max="65535" placeholder="502">
2361
+
2362
+ </div>
2363
+
2364
+ <div class="form-row">
2365
+
2366
+ <label for="node-input-unitId"><i class="fa fa-hashtag"></i> Unit ID</label>
2367
+
2368
+ <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
2369
+
2370
+ </div>
2371
+
2372
+ <div class="form-row">
2373
+
2374
+ <label for="node-input-timestep"><i class="fa fa-refresh"></i> Poll interval</label>
2375
+
2376
+ <input type="text" id="node-input-timestep" placeholder="1000 sau off">
2377
+
2378
+ </div>
2379
+
2380
+ </div>
2381
+
2382
+ </div>
2383
+
2384
+
2385
+ <div class="pr-section">
2386
+
2387
+ <p class="pr-section-title"><i class="fa fa-list"></i> Payload</p>
2388
+
2389
+ <p class="pr-section-note">Selecteaza valorile trimise de nod. In modurile speciale se trimite un singur mesaj agregat.</p>
2390
+
2391
+ <div class="form-row">
2392
+
2393
+ <label for="node-input-payloadMode"><i class="fa fa-list"></i> Payload mode</label>
2394
+
2395
+ <select id="node-input-payloadMode">
2396
+
2397
+ <option value="full">Full object</option>
2398
+
2399
+ <option value="selected">Selected fields</option>
2400
+
2401
+ </select>
2402
+
2403
+ </div>
2404
+
2405
+ <input type="hidden" id="node-input-payloadFields">
2406
+
2407
+ <input type="hidden" id="node-input-outputs">
2408
+
2409
+ <div class="pr-actions" id="node-janitza-field-tools">
2410
+
2411
+ <button type="button" class="red-ui-button" id="node-janitza-select-all"><i class="fa fa-check-square-o"></i> Select all</button>
2412
+
2413
+ <button type="button" class="red-ui-button" id="node-janitza-clear-all"><i class="fa fa-square-o"></i> Clear</button>
2414
+
2415
+ <button type="button" class="red-ui-button" id="node-janitza-default-values"><i class="fa fa-magic"></i> Defaults</button>
2416
+
2417
+ </div>
2418
+
2419
+ <div class="pr-field-list" id="node-janitza-field-list"></div>
2420
+
2421
+ </div>
2422
+
2423
+
2424
+ <div class="pr-section">
2425
+
2426
+ <p class="pr-section-title"><i class="fa fa-share-alt"></i> Integrari</p>
2427
+
2428
+ <p class="pr-section-note">Pastreaza acelasi model de iesire ca nodul Carlo Gavazzi pentru fluxurile existente.</p>
2429
+
2430
+ <div class="form-row pr-checkbox-row">
2431
+
2432
+ <label for="node-input-multiGrid"><i class="fa fa-sitemap"></i> Multi-grid</label>
2433
+
2434
+ <input type="checkbox" id="node-input-multiGrid">
2435
+
2436
+ <span class="pr-inline-note">Trimite puterile active intr-un mesaj agregat.</span>
2437
+
2438
+ </div>
2439
+
2440
+ <div class="form-row pr-checkbox-row">
2441
+
2442
+ <label for="node-input-bessControl"><i class="fa fa-link"></i> BESS control</label>
2443
+
2444
+ <input type="checkbox" id="node-input-bessControl">
2445
+
2446
+ <span class="pr-inline-note">Payload compatibil cu controlul bateriei.</span>
2447
+
2448
+ </div>
2449
+
2450
+ <div class="form-row pr-checkbox-row">
2451
+
2452
+ <label for="node-input-controlExportReactive"><i class="fa fa-bolt"></i> Control export/reactive</label>
2453
+
2454
+ <input type="checkbox" id="node-input-controlExportReactive">
2455
+
2456
+ <span class="pr-inline-note">Include putere activa si reactiva.</span>
2457
+
2458
+ </div>
2459
+
2460
+ <div class="form-row pr-checkbox-row">
2461
+
2462
+ <label for="node-input-scadaServer"><i class="fa fa-server"></i> SCADA server</label>
2463
+
2464
+ <input type="checkbox" id="node-input-scadaServer">
2465
+
2466
+ <span class="pr-inline-note">Mapeaza cheile pentru serverul SCADA.</span>
2467
+
2468
+ </div>
2469
+
2470
+ <div class="form-row pr-checkbox-row">
2471
+
2472
+ <label for="node-input-influxDb"><i class="fa fa-database"></i> InfluxDB</label>
2473
+
2474
+ <input type="checkbox" id="node-input-influxDb">
2475
+
2476
+ <span class="pr-inline-note">Grupeaza valorile in <code>msg.influx</code> pentru nodul <code>adt-influxdb</code>.</span>
2477
+
2478
+ </div>
2479
+
2480
+ <div class="form-row" id="row-influx-measurement" style="display:none;">
2481
+
2482
+ <label for="node-input-influxMeasurement"><i class="fa fa-line-chart"></i> Measurement</label>
2483
+
2484
+ <input type="text" id="node-input-influxMeasurement" placeholder="Grid Meter 1">
2485
+
2486
+ </div>
2487
+ <div class="form-row" id="row-influx-node" style="display:none;">
2488
+ <label for="node-input-influxNode"><i class="fa fa-plug"></i> Nod InfluxDB</label>
2489
+ <select id="node-input-influxNode"></select>
2490
+ </div>
2491
+
2492
+ <div class="form-row pr-checkbox-row" id="row-expert-mode" style="display:none;">
2493
+
2494
+ <label for="node-input-expertMode"><i class="fa fa-wrench"></i> Custom fields</label>
2495
+
2496
+ <input type="checkbox" id="node-input-expertMode">
2497
+
2498
+ <span class="pr-inline-note">Permite selectie manuala si in modurile speciale.</span>
2499
+
2500
+ </div>
2501
+
2502
+ </div>
2503
+
2504
+ </div>
2505
+
2506
+ </script>
2507
+
2508
+
2509
+ <script type="text/html" data-help-name="janitza">
2510
+
2511
+ <p>Citeste valori Modbus TCP dintr-un contor Janitza, in functie de modelul selectat.</p>
2512
+
2513
+ <p>Profilul disponibil acum este <code>UMG 604 Pro</code>, cu functia Modbus 03 pentru registrii <code>19000</code>-<code>19120</code>, format <code>float</code> Big-Endian.</p>
2514
+
2515
+ <p>Energiile raportate in Wh/varh sunt convertite in kWh/kvarh in payload.</p>
2516
+
2517
+ <p>Cand este activ <b>InfluxDB</b>, nodul emite un singur mesaj agregat cu <code>msg.influx.measurement</code>, <code>msg.influx.tags</code>, <code>msg.influx.fields</code> si <code>msg.influx.timestamp</code>, compatibil direct cu nodul <code>adt-influxdb</code>.</p>
2518
+
2519
+ <h3>Referinta completa parametri</h3>
2520
+
2521
+ <ul>
2522
+
2523
+ <li><code>model</code>: profilul Janitza folosit pentru maparea registrelor.</li>
2524
+
2525
+ <li><code>host</code>, <code>port</code>, <code>unitId</code>: conexiunea Modbus TCP.</li>
2526
+
2527
+ <li><code>timestep</code>: intervalul de poll in milisecunde; <code>off</code> sau <code>0</code> opreste poll-ul automat si citeste doar la trigger pe intrare.</li>
2528
+
2529
+ <li><code>meterId</code>: ID emis in <code>msg.topic</code>, <code>msg.meter_id</code> si <code>msg.source_id</code>.</li>
2530
+
2531
+ <li><code>payloadMode</code>: <code>full</code> sau <code>selected</code>.</li>
2532
+
2533
+ <li><code>payloadFields</code>: lista campurilor selectate.</li>
2534
+
2535
+ <li><code>multiGrid</code>, <code>bessControl</code>, <code>controlExportReactive</code>, <code>scadaServer</code>, <code>influxDb</code>: preseturi exclusive pentru integrare.</li>
2536
+
2537
+ <li><code>influxMeasurement</code>: measurement-ul folosit in <code>msg.influx</code>.</li>
2538
+
2539
+ <li><code>multiGridCustomFields</code>, <code>bessControlCustomFields</code>, <code>controlExportReactiveCustomFields</code>, <code>scadaServerCustomFields</code>, <code>influxDbCustomFields</code>: listele custom pentru fiecare preset.</li>
2540
+
2541
+ <li><code>multiGridUseSelectedFields</code>, <code>bessControlUseSelectedFields</code>, <code>controlExportReactiveUseSelectedFields</code>, <code>scadaServerUseSelectedFields</code>, <code>influxDbUseSelectedFields</code>: activeaza listele custom in locul presetului implicit.</li>
2542
+
2543
+ <li><code>outputs</code>: numarul de iesiri calculat de editor.</li>
2544
+
2545
+ </ul>
2546
+
2547
+ <h3>Exemplu control-export/reactive</h3>
2548
+
2549
+ <pre>{
2550
+ "topic": "janitza-main",
2551
+ "payload": {
2552
+ "power_w": -850,
2553
+ "power_l1_w": -200,
2554
+ "power_l2_w": -310,
2555
+ "power_l3_w": -340,
2556
+ "reactive_total_var": 420
2557
+ },
2558
+ "meter_id": "janitza-main"
2559
+ }</pre>
2560
+
2561
+ </script>
2562
+