homebridge-smartsystem 6.2.6 → 6.3.1

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/README.md CHANGED
@@ -275,6 +275,9 @@ Homebridge UI version
275
275
  - 4: fixed empty name bug in unit-def / new accessory()
276
276
  - 5: fixed bad displayNames in published units
277
277
  - 6: power: 5% instead of 10% for power rules
278
+
279
+ ### v6.3.x - 23-09-2022 - Shelly PM release
280
+ - 1: first test 1 PM
278
281
 
279
282
 
280
283
  ## Hardware
package/config.json CHANGED
@@ -247,9 +247,14 @@
247
247
  "power": null
248
248
  }
249
249
  ],
250
- "address": "192.168.0.214"
250
+ "address": "192.168.0.207"
251
+ },
252
+ "shelly": {
253
+ "address": "192.168.0.95",
254
+ "addresses": "192.168.0.95,192.168.0.95",
255
+ "rules": [],
256
+ "bindings": []
251
257
  },
252
- "shelly": false,
253
258
  "smartapp": {
254
259
  "apiPort": 8581,
255
260
  "apiHost": "192.168.0.99",
@@ -373,184 +378,16 @@
373
378
  }
374
379
  ],
375
380
  "cunits": [
376
- {
377
- "logicalNodeAddress": 252,
378
- "logicalAddress": 102,
379
- "masterAddress": "192.168.0.97",
380
- "masterPort": 5001,
381
- "name": "unit 252:102",
382
- "displayName": "unit 252:102",
383
- "extendedType": 0,
384
- "active": "N",
385
- "used": "N",
386
- "group": 0
387
- },
388
- {
389
- "logicalNodeAddress": 252,
390
- "logicalAddress": 103,
391
- "masterAddress": "192.168.0.97",
392
- "masterPort": 5001,
393
- "name": "unit 252:103",
394
- "displayName": "unit 252:103",
395
- "extendedType": 0,
396
- "active": "N",
397
- "used": "N",
398
- "group": 0
399
- },
400
- {
401
- "logicalNodeAddress": 252,
402
- "logicalAddress": 100,
403
- "masterAddress": "192.168.0.97",
404
- "masterPort": 5001,
405
- "name": "unit 252:100",
406
- "displayName": "unit 252:100",
407
- "extendedType": 0,
408
- "active": "N",
409
- "used": "N",
410
- "group": 0
411
- },
412
- {
413
- "logicalNodeAddress": 252,
414
- "logicalAddress": 101,
415
- "masterAddress": "192.168.0.97",
416
- "masterPort": 5001,
417
- "name": "unit 252:101",
418
- "displayName": "unit 252:101",
419
- "extendedType": 0,
420
- "active": "N",
421
- "used": "N",
422
- "group": 0
423
- },
424
- {
425
- "logicalNodeAddress": 252,
426
- "logicalAddress": 105,
427
- "masterAddress": "192.168.0.97",
428
- "masterPort": 5001,
429
- "name": "unit 252:105",
430
- "displayName": "unit 252:105",
431
- "extendedType": 0,
432
- "active": "N",
433
- "used": "N",
434
- "group": 0
435
- },
436
- {
437
- "logicalNodeAddress": 252,
438
- "logicalAddress": 104,
439
- "masterAddress": "192.168.0.97",
440
- "masterPort": 5001,
441
- "name": "unit 252:104",
442
- "displayName": "unit 252:104",
443
- "extendedType": 0,
444
- "active": "N",
445
- "used": "N",
446
- "group": 0
447
- },
448
- {
449
- "logicalNodeAddress": 252,
450
- "logicalAddress": 106,
451
- "masterAddress": "192.168.0.97",
452
- "masterPort": 5001,
453
- "name": "unit 252:106",
454
- "displayName": "unit 252:106",
455
- "extendedType": 0,
456
- "active": "N",
457
- "used": "N",
458
- "group": 0
459
- },
460
381
  {
461
382
  "logicalNodeAddress": 3,
462
- "logicalAddress": 1,
463
- "masterAddress": "192.168.0.97",
464
- "masterPort": 5001,
465
- "name": "unit 3:1",
466
- "displayName": "unit 3:1",
467
- "extendedType": 0,
468
- "active": "N",
469
- "used": "N",
470
- "group": 0
471
- },
472
- {
473
- "logicalNodeAddress": 3,
474
- "logicalAddress": 0,
475
- "masterAddress": "192.168.0.97",
476
- "masterPort": 5001,
477
- "name": "unit 3:0",
478
- "displayName": "unit 3:0",
479
- "extendedType": 0,
480
- "active": "N",
481
- "used": "N",
482
- "group": 0
483
- },
484
- {
485
- "logicalNodeAddress": 3,
486
- "logicalAddress": 30,
487
- "masterAddress": "192.168.0.97",
488
- "masterPort": 5001,
489
- "name": "unit 3:30",
490
- "displayName": "unit 3:30",
491
- "extendedType": 0,
492
- "active": "N",
493
- "used": "N",
494
- "group": 0
495
- },
496
- {
497
- "logicalNodeAddress": 3,
498
- "logicalAddress": 29,
499
- "masterAddress": "192.168.0.97",
500
- "masterPort": 5001,
501
- "name": "unit 3:29",
502
- "displayName": "unit 3:29",
503
- "extendedType": 0,
504
- "active": "N",
505
- "used": "N",
506
- "group": 0
507
- },
508
- {
509
- "logicalNodeAddress": 3,
510
- "logicalAddress": 35,
511
- "masterAddress": "192.168.0.97",
512
- "masterPort": 5001,
513
- "name": "unit 3:35",
514
- "displayName": "unit 3:35",
515
- "extendedType": 0,
516
- "active": "N",
517
- "used": "N",
518
- "group": 0
519
- },
520
- {
521
- "logicalNodeAddress": 3,
522
- "logicalAddress": 34,
523
- "masterAddress": "192.168.0.97",
524
- "masterPort": 5001,
525
- "name": "unit 3:34",
526
- "displayName": "unit 3:34",
527
- "extendedType": 0,
528
- "active": "N",
529
- "used": "N",
530
- "group": 0
531
- },
532
- {
533
- "logicalNodeAddress": 3,
534
- "logicalAddress": 33,
535
- "masterAddress": "192.168.0.97",
536
- "masterPort": 5001,
537
- "name": "unit 3:33",
538
- "displayName": "unit 3:33",
539
- "extendedType": 0,
540
- "active": "N",
541
- "used": "N",
542
- "group": 0
543
- },
544
- {
545
- "logicalNodeAddress": 3,
546
- "logicalAddress": 36,
383
+ "logicalAddress": 4,
547
384
  "masterAddress": "192.168.0.97",
548
385
  "masterPort": 5001,
549
- "name": "unit 3:36",
550
- "displayName": "unit 3:36",
551
- "extendedType": 0,
552
- "active": "N",
553
- "used": "N",
386
+ "name": "All off",
387
+ "displayName": "Alles uitje",
388
+ "extendedType": 7,
389
+ "active": "Y",
390
+ "used": "Y",
554
391
  "group": 0
555
392
  },
556
393
  {
@@ -558,23 +395,11 @@
558
395
  "logicalAddress": 5,
559
396
  "masterAddress": "192.168.0.97",
560
397
  "masterPort": 5001,
561
- "name": "unit 3:5",
562
- "displayName": "unit 3:5",
563
- "extendedType": 0,
564
- "active": "N",
565
- "used": "N",
566
- "group": 0
567
- },
568
- {
569
- "logicalNodeAddress": 3,
570
- "logicalAddress": 4,
571
- "masterAddress": "192.168.0.97",
572
- "masterPort": 5001,
573
- "name": "unit 3:4",
574
- "displayName": "unit 3:4",
575
- "extendedType": 0,
576
- "active": "N",
577
- "used": "N",
398
+ "name": "All on",
399
+ "displayName": "Alles aantje",
400
+ "extendedType": 7,
401
+ "active": "Y",
402
+ "used": "Y",
578
403
  "group": 0
579
404
  }
580
405
  ]
@@ -18,6 +18,7 @@ exports.logSettings = {
18
18
  "protocol": LogLevel.noLog,
19
19
  "webapp": LogLevel.log,
20
20
  "p1": LogLevel.log,
21
+ "shelly": LogLevel.debug,
21
22
  "power": LogLevel.log,
22
23
  "smartapp": LogLevel.log
23
24
  };
@@ -13,6 +13,7 @@ export const logSettings = {
13
13
  "protocol": LogLevel.noLog,
14
14
  "webapp": LogLevel.log,
15
15
  "p1": LogLevel.log,
16
+ "shelly": LogLevel.debug,
16
17
  "power": LogLevel.log,
17
18
  "smartapp": LogLevel.log
18
19
  };
@@ -466,6 +466,7 @@ class Master extends base_1.Base {
466
466
  receiveUnitInfo(message) {
467
467
  const unitInfo = protocol_1.Protocol.makeUnitInfo(message);
468
468
  let unit = this.findUnit(unitInfo.logicalNodeAddress, unitInfo.logicalAddress);
469
+ this.info("> received unit info: " + unitInfo.name + " (" + unitInfo.logicalNodeAddress + "," + unitInfo.logicalAddress + ") for unit: " + (unit === null || unit === void 0 ? void 0 : unit.name));
469
470
  if (!unit) {
470
471
  // find if in config
471
472
  const cunit = this.system.config.cunits.find(u => ((u.logicalNodeAddress == unitInfo.logicalNodeAddress) && (u.logicalAddress == unitInfo.logicalAddress)));
@@ -473,7 +474,6 @@ class Master extends base_1.Base {
473
474
  unitInfo.extendedType = cunit.extendedType;
474
475
  const node = this.findNode(unitInfo.logicalNodeAddress);
475
476
  if (node) {
476
- this.info("> received unit info: " + unitInfo.name + " (" + unitInfo.logicalNodeAddress + "," + unitInfo.logicalAddress + ")");
477
477
  unit = new protocol_1.Unit(node, unitInfo, this.system.config.mood);
478
478
  node.units.push(unit);
479
479
  }
@@ -520,6 +520,8 @@ export class Master extends Base {
520
520
 
521
521
  let unit = this.findUnit(unitInfo.logicalNodeAddress, unitInfo.logicalAddress);
522
522
 
523
+ this.info("> received unit info: " + unitInfo.name + " ("+unitInfo.logicalNodeAddress+","+unitInfo.logicalAddress+") for unit: " + unit?.name);
524
+
523
525
  if (!unit) {
524
526
  // find if in config
525
527
  const cunit = this.system.config.cunits.find(u => ((u.logicalNodeAddress == unitInfo.logicalNodeAddress) && (u.logicalAddress == unitInfo.logicalAddress)));
@@ -527,7 +529,6 @@ export class Master extends Base {
527
529
 
528
530
  const node = this.findNode(unitInfo.logicalNodeAddress);
529
531
  if (node) {
530
- this.info("> received unit info: " + unitInfo.name + " ("+unitInfo.logicalNodeAddress+","+unitInfo.logicalAddress+")");
531
532
  unit = new Unit(node, unitInfo, this.system.config.mood);
532
533
  node.units.push(unit);
533
534
  } else {
@@ -159,28 +159,33 @@ class System extends base_1.Base {
159
159
  this.writeConfig();
160
160
  }
161
161
  setActiveState(item) {
162
+ // for nodes
162
163
  if (item instanceof protocol_1.Node) {
163
164
  const masterAddress = item.master.getAddress();
164
165
  const masterPort = item.master.getPort();
166
+ // check if at least 1 unit is used
165
167
  const unitConfig = this.config.cunits.find((cu) => (cu.logicalNodeAddress === item.logicalAddress) &&
166
168
  (cu.masterAddress === masterAddress) &&
167
169
  (cu.masterPort == masterPort));
168
- // there exists an active unit of this node
170
+ // if there is: set active to true of this node
169
171
  item.active = !!unitConfig;
170
172
  }
173
+ // for units
171
174
  if (item instanceof protocol_1.Unit) {
172
175
  const masterAddress = item.node.master.getAddress();
173
176
  const masterPort = item.node.master.getPort();
177
+ // see if there is a config record for this unit
174
178
  const unitConfig = this.config.cunits.find((cu) => (cu.logicalAddress === item.logicalAddress) &&
175
179
  (cu.logicalNodeAddress === item.logicalNodeAddress) &&
176
180
  (cu.masterAddress === masterAddress) &&
177
181
  (cu.masterPort == masterPort));
178
- ;
182
+ // if there is: copy active, used, displayName and group
179
183
  if (unitConfig) {
180
184
  item.active = (unitConfig.active === "Y");
181
185
  item.used = (unitConfig.used === "Y");
182
186
  item.displayName = unitConfig.displayName || unitConfig.name;
183
187
  item.group = unitConfig.group;
188
+ (0, logger_1.log)("system", "System.setActiveState(unit) -> config name: " + unitConfig.name + ", item name: " + item.name);
184
189
  }
185
190
  else {
186
191
  item.active = false;
@@ -166,31 +166,40 @@ export class System extends Base {
166
166
  }
167
167
 
168
168
  setActiveState(item: Node | Unit) {
169
+ // for nodes
169
170
  if (item instanceof Node) {
170
171
  const masterAddress = item.master.getAddress();
171
172
  const masterPort = item.master.getPort();
173
+
174
+ // check if at least 1 unit is used
172
175
  const unitConfig = this.config.cunits.find((cu: UnitConfig) =>
173
176
  (cu.logicalNodeAddress === item.logicalAddress) &&
174
177
  (cu.masterAddress === masterAddress) &&
175
178
  (cu.masterPort == masterPort));
176
179
 
177
- // there exists an active unit of this node
180
+ // if there is: set active to true of this node
178
181
  item.active = !! unitConfig;
179
182
  }
183
+
184
+ // for units
180
185
  if (item instanceof Unit) {
181
186
  const masterAddress = item.node.master.getAddress();
182
187
  const masterPort = item.node.master.getPort();
188
+
189
+ // see if there is a config record for this unit
183
190
  const unitConfig = this.config.cunits.find((cu: UnitConfig) =>
184
191
  (cu.logicalAddress === item.logicalAddress) &&
185
192
  (cu.logicalNodeAddress === item.logicalNodeAddress) &&
186
193
  (cu.masterAddress === masterAddress) &&
187
194
  (cu.masterPort == masterPort));
188
- ;
195
+
196
+ // if there is: copy active, used, displayName and group
189
197
  if (unitConfig) {
190
198
  item.active = (unitConfig.active === "Y");
191
199
  item.used = (unitConfig.used === "Y");
192
200
  item.displayName = unitConfig.displayName || unitConfig.name;
193
201
  item.group = unitConfig.group;
202
+ log("system", "System.setActiveState(unit) -> config name: " + unitConfig.name + ", item name: " + item.name);
194
203
  } else {
195
204
  item.active = false;
196
205
  }
package/duotecno/types.js CHANGED
@@ -273,8 +273,9 @@ exports.Sanitizers = {
273
273
  return config;
274
274
  },
275
275
  shelly: function (config) {
276
- config = exports.Sanitizers.powerbase(config);
277
- return config;
276
+ const cfg = exports.Sanitizers.powerbase(config);
277
+ cfg.addresses = (config === null || config === void 0 ? void 0 : config.addresses) || "";
278
+ return cfg;
278
279
  },
279
280
  switchConfig: function (aSwitch) {
280
281
  const sw = exports.Sanitizers.unitDef(aSwitch);
package/duotecno/types.ts CHANGED
@@ -273,6 +273,7 @@ export interface SmappeeConfig extends PowerBaseConfig {
273
273
  export interface P1Config extends PowerBaseConfig {
274
274
  }
275
275
  export interface ShellyConfig extends PowerBaseConfig {
276
+ addresses: string;
276
277
  }
277
278
 
278
279
  ////////////////
@@ -453,9 +454,9 @@ export const Sanitizers = {
453
454
  return config;
454
455
  },
455
456
  shelly: function(config: ShellyConfig): ShellyConfig {
456
- config = Sanitizers.powerbase(config);
457
-
458
- return config;
457
+ const cfg = <ShellyConfig> Sanitizers.powerbase(config);
458
+ cfg.addresses = config?.addresses || "";
459
+ return cfg;
459
460
  },
460
461
 
461
462
  switchConfig: function(aSwitch): Switch {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-smartsystem",
3
3
  "displayname": "Duotecno Bridge",
4
- "version": "6.2.6",
4
+ "version": "6.3.1",
5
5
  "description": "SmartServer (Proxy Websockets to TCP sockets, Smappee MQTT, Duotecno IP Nodes, Homekit interface)",
6
6
  "main": "index.js",
7
7
  "author": "Johan Coppieters",
package/server/p1.js CHANGED
@@ -92,48 +92,48 @@ class P1 extends powerbase_1.PowerBase {
92
92
  });
93
93
  }
94
94
  consume(data) {
95
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
95
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
96
96
  if (!data['32.7.0'])
97
97
  return;
98
- this.voltages = [(_a = data['32.7.0']) === null || _a === void 0 ? void 0 : _a.value, (_b = data['52.7.0']) === null || _b === void 0 ? void 0 : _b.value, (_c = data['72.7.0']) === null || _c === void 0 ? void 0 : _c.value];
99
- this.realtime = { totalPower: ((_d = data['1.7.0']) === null || _d === void 0 ? void 0 : _d.value) * 1000,
100
- totalReactivePower: ((_e = data['2.7.0']) === null || _e === void 0 ? void 0 : _e.value) * 1000,
101
- totalExportEnergy: ((_f = data['2.8.1']) === null || _f === void 0 ? void 0 : _f.value) + ((_g = data['2.8.2']) === null || _g === void 0 ? void 0 : _g.value),
102
- totalImportEnergy: ((_h = data['1.8.1']) === null || _h === void 0 ? void 0 : _h.value) + ((_j = data['1.8.2']) === null || _j === void 0 ? void 0 : _j.value),
103
- monitorStatus: 0, utcTimeStamp: new Date().getTime() };
104
98
  this.channels = {
105
99
  0: {
106
- name: "Zonnepanelen L1", type: "CT", flow: "PRODUCTION",
107
- power: ((_k = data['22.7.0']) === null || _k === void 0 ? void 0 : _k.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0,
100
+ name: "Zonnepanelen L1", type: "CT", flow: "PRODUCTION", voltage: (_a = data['32.7.0']) === null || _a === void 0 ? void 0 : _a.value,
101
+ power: ((_b = data['22.7.0']) === null || _b === void 0 ? void 0 : _b.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0,
108
102
  current: 0, apparentPower: 0, cosPhi: 0, formula: ""
109
103
  },
110
104
  1: {
111
- name: "Zonnepanelen L2", type: "CT", flow: "PRODUCTION",
112
- power: ((_l = data['42.7.0']) === null || _l === void 0 ? void 0 : _l.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1,
105
+ name: "Zonnepanelen L2", type: "CT", flow: "PRODUCTION", voltage: (_c = data['52.7.0']) === null || _c === void 0 ? void 0 : _c.value,
106
+ power: ((_d = data['42.7.0']) === null || _d === void 0 ? void 0 : _d.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1,
113
107
  current: 0, apparentPower: 0, cosPhi: 0, formula: ""
114
108
  },
115
109
  2: {
116
- name: "Zonnepanelen L3", type: "CT", flow: "PRODUCTION",
117
- power: ((_m = data['62.7.0']) === null || _m === void 0 ? void 0 : _m.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2,
110
+ name: "Zonnepanelen L3", type: "CT", flow: "PRODUCTION", voltage: (_e = data['72.7.0']) === null || _e === void 0 ? void 0 : _e.value,
111
+ power: ((_f = data['62.7.0']) === null || _f === void 0 ? void 0 : _f.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2,
118
112
  current: 0, apparentPower: 0, cosPhi: 0, formula: ""
119
113
  },
120
114
  3: {
121
- name: "Grid L1", type: "CT", flow: "CONSUMPTION",
122
- power: ((_o = data['21.7.0']) === null || _o === void 0 ? void 0 : _o.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0,
123
- current: (_p = data['31.7.0']) === null || _p === void 0 ? void 0 : _p.value, apparentPower: 0, cosPhi: 0, formula: ""
115
+ name: "Grid L1", type: "CT", flow: "CONSUMPTION", voltage: (_g = data['32.7.0']) === null || _g === void 0 ? void 0 : _g.value,
116
+ power: ((_h = data['21.7.0']) === null || _h === void 0 ? void 0 : _h.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0,
117
+ current: (_j = data['31.7.0']) === null || _j === void 0 ? void 0 : _j.value, apparentPower: 0, cosPhi: 0, formula: ""
124
118
  },
125
119
  4: {
126
- name: "Grid L2", type: "CT", flow: "CONSUMPTION",
127
- power: ((_q = data['41.7.0']) === null || _q === void 0 ? void 0 : _q.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1,
128
- current: (_r = data['51.7.0']) === null || _r === void 0 ? void 0 : _r.value, apparentPower: 0, cosPhi: 0, formula: ""
120
+ name: "Grid L2", type: "CT", flow: "CONSUMPTION", voltage: (_k = data['52.7.0']) === null || _k === void 0 ? void 0 : _k.value,
121
+ power: ((_l = data['41.7.0']) === null || _l === void 0 ? void 0 : _l.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1,
122
+ current: (_m = data['51.7.0']) === null || _m === void 0 ? void 0 : _m.value, apparentPower: 0, cosPhi: 0, formula: ""
129
123
  },
130
124
  5: {
131
- name: "Grid L3", type: "CT", flow: "CONSUMPTION",
132
- power: ((_s = data['61.7.0']) === null || _s === void 0 ? void 0 : _s.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2,
133
- current: (_t = data['71.7.0']) === null || _t === void 0 ? void 0 : _t.value, apparentPower: 0, cosPhi: 0, formula: ""
125
+ name: "Grid L3", type: "CT", flow: "CONSUMPTION", voltage: (_o = data['72.7.0']) === null || _o === void 0 ? void 0 : _o.value,
126
+ power: ((_p = data['61.7.0']) === null || _p === void 0 ? void 0 : _p.value) * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2,
127
+ current: (_q = data['71.7.0']) === null || _q === void 0 ? void 0 : _q.value, apparentPower: 0, cosPhi: 0, formula: ""
134
128
  }
135
129
  };
136
130
  // console.log(data);
131
+ this.voltages = [(_r = data['32.7.0']) === null || _r === void 0 ? void 0 : _r.value, (_s = data['52.7.0']) === null || _s === void 0 ? void 0 : _s.value, (_t = data['72.7.0']) === null || _t === void 0 ? void 0 : _t.value];
132
+ this.realtime = { totalPower: ((_u = data['1.7.0']) === null || _u === void 0 ? void 0 : _u.value) * 1000,
133
+ totalReactivePower: ((_v = data['2.7.0']) === null || _v === void 0 ? void 0 : _v.value) * 1000,
134
+ totalExportEnergy: ((_w = data['2.8.1']) === null || _w === void 0 ? void 0 : _w.value) + ((_x = data['2.8.2']) === null || _x === void 0 ? void 0 : _x.value),
135
+ totalImportEnergy: ((_y = data['1.8.1']) === null || _y === void 0 ? void 0 : _y.value) + ((_z = data['1.8.2']) === null || _z === void 0 ? void 0 : _z.value),
136
+ monitorStatus: 0, utcTimeStamp: new Date().getTime() };
137
137
  this.production = this.realtime.totalPower;
138
138
  this.consumption = this.realtime.totalReactivePower;
139
139
  }
package/server/p1.ts CHANGED
@@ -182,43 +182,45 @@ export class P1 extends PowerBase {
182
182
 
183
183
  consume(data: P1Data) {
184
184
  if (! data['32.7.0']) return;
185
-
186
- this.voltages = [data['32.7.0']?.value, data['52.7.0']?.value, data['72.7.0']?.value];
187
- this.realtime = { totalPower: data['1.7.0']?.value * 1000,
188
- totalReactivePower: data['2.7.0']?.value * 1000,
189
- totalExportEnergy: data['2.8.1']?.value + data['2.8.2']?.value,
190
- totalImportEnergy: data['1.8.1']?.value + data['1.8.2']?.value,
191
- monitorStatus: 0, utcTimeStamp: new Date().getTime() };
192
185
 
193
186
  this.channels = {
194
187
  0: {
195
- name: "Zonnepanelen L1", type: "CT", flow: "PRODUCTION",
188
+ name: "Zonnepanelen L1", type: "CT", flow: "PRODUCTION", voltage: data['32.7.0']?.value,
196
189
  power: data['22.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0,
197
190
  current: 0, apparentPower: 0, cosPhi: 0, formula: ""},
198
191
  1: {
199
- name: "Zonnepanelen L2", type: "CT", flow: "PRODUCTION",
192
+ name: "Zonnepanelen L2", type: "CT", flow: "PRODUCTION", voltage: data['52.7.0']?.value,
200
193
  power: data['42.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1,
201
194
  current: 0, apparentPower: 0, cosPhi: 0, formula: ""},
202
195
  2: {
203
- name: "Zonnepanelen L3", type: "CT", flow: "PRODUCTION",
196
+ name: "Zonnepanelen L3", type: "CT", flow: "PRODUCTION", voltage: data['72.7.0']?.value,
204
197
  power: data['62.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2,
205
198
  current: 0, apparentPower: 0, cosPhi: 0, formula: ""},
206
199
  3: {
207
- name: "Grid L1", type: "CT", flow: "CONSUMPTION",
200
+ name: "Grid L1", type: "CT", flow: "CONSUMPTION", voltage: data['32.7.0']?.value,
208
201
  power: data['21.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 0,
209
202
  current: data['31.7.0']?.value, apparentPower: 0, cosPhi: 0, formula: ""},
210
203
  4: {
211
- name: "Grid L2", type: "CT", flow: "CONSUMPTION",
204
+ name: "Grid L2", type: "CT", flow: "CONSUMPTION", voltage: data['52.7.0']?.value,
212
205
  power: data['41.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 1,
213
206
  current: data['51.7.0']?.value, apparentPower: 0, cosPhi: 0, formula: ""},
214
207
  5: {
215
- name: "Grid L3", type: "CT", flow: "CONSUMPTION",
208
+ name: "Grid L3", type: "CT", flow: "CONSUMPTION", voltage: data['72.7.0']?.value,
216
209
  power: data['61.7.0']?.value * 1000, exportEnergy: 0, importEnergy: 0, phaseId: 2,
217
210
  current: data['71.7.0']?.value, apparentPower: 0, cosPhi: 0, formula: ""}
218
211
  };
219
212
  // console.log(data);
220
213
 
214
+ this.voltages = [data['32.7.0']?.value, data['52.7.0']?.value, data['72.7.0']?.value];
215
+ this.realtime = { totalPower: data['1.7.0']?.value * 1000,
216
+ totalReactivePower: data['2.7.0']?.value * 1000,
217
+ totalExportEnergy: data['2.8.1']?.value + data['2.8.2']?.value,
218
+ totalImportEnergy: data['1.8.1']?.value + data['1.8.2']?.value,
219
+ monitorStatus: 0, utcTimeStamp: new Date().getTime() };
220
+
221
221
  this.production = this.realtime.totalPower;
222
222
  this.consumption = this.realtime.totalReactivePower;
223
+
224
+
223
225
  }
224
226
  }
@@ -72,7 +72,8 @@ class PowerBase extends base_1.Base {
72
72
  //
73
73
  updateConfig(config) {
74
74
  return __awaiter(this, void 0, void 0, function* () {
75
- this.config.address = config.address;
75
+ if (config.address)
76
+ this.config.address = config.address;
76
77
  this.writeConfig();
77
78
  return this.init(false);
78
79
  });
@@ -28,7 +28,7 @@ export class PowerBase extends Base {
28
28
  totalExportEnergy: number, totalImportEnergy: number,
29
29
  monitorStatus: number, utcTimeStamp: number }
30
30
  channels: { [publishIndex: number]: {
31
- name: string, type: string, flow: string,
31
+ name: string, type: string, flow: string, voltage: number,
32
32
  power: number, exportEnergy: number, importEnergy: number, phaseId: number,
33
33
  current: number, apparentPower: number, cosPhi: number, formula: string} };
34
34
 
@@ -87,7 +87,9 @@ export class PowerBase extends Base {
87
87
  // config mgt
88
88
  //
89
89
  async updateConfig(config: any) {
90
- this.config.address = config.address;
90
+ if (config.address)
91
+ this.config.address = config.address;
92
+
91
93
  this.writeConfig();
92
94
 
93
95
  return this.init(false);
package/server/shelly.js CHANGED
@@ -15,10 +15,58 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.Shelly = void 0;
16
16
  const logger_1 = require("../duotecno/logger");
17
17
  const powerbase_1 = require("./powerbase");
18
+ const api_1 = require("../duotecno/api");
19
+ const HTTPstatus = {
20
+ "wifi_sta": {
21
+ "connected": true,
22
+ "ssid": "Tele Coppieters",
23
+ "ip": "192.168.0.95",
24
+ "rssi": -73
25
+ },
26
+ "cloud": {
27
+ "enabled": true,
28
+ "connected": true
29
+ },
30
+ "mqtt": {
31
+ "connected": false
32
+ },
33
+ "time": "18:17",
34
+ "unixtime": 1663863464,
35
+ "serial": 7,
36
+ "has_update": true,
37
+ "mac": "C45BBE7928B9",
38
+ "cfg_changed_cnt": 1,
39
+ "actions_stats": { "skipped": 0 },
40
+ "relays": [{ "ison": true, "has_timer": false, "timer_started": 0, "timer_duration": 0, "timer_remaining": 0, "overpower": false, "is_valid": true, "source": "http" }],
41
+ "emeters": [
42
+ { "power": 10.66, "pf": 1.00, "current": 0.08, "voltage": 232.06, "is_valid": true, "total": 5.3, "total_returned": 0.0 },
43
+ { "power": 0.00, "pf": 0.00, "current": 0.01, "voltage": 232.06, "is_valid": true, "total": 0.0, "total_returned": 0.0 },
44
+ { "power": 0.00, "pf": 0.00, "current": 0.01, "voltage": 232.05, "is_valid": true, "total": 0.0, "total_returned": 0.0 }
45
+ ],
46
+ "total_power": 10.66,
47
+ "fs_mounted": true,
48
+ "update": { "status": "pending", "has_update": true, "new_version": "20220830-080542/v1.12-3EM-gcf4f7c2", "old_version": "20220209-094824/v1.11.8-g8c7bb8d" },
49
+ "ram_total": 49440,
50
+ "ram_free": 30960,
51
+ "fs_size": 233681,
52
+ "fs_free": 156875,
53
+ "uptime": 1364
54
+ };
55
+ const HttpEMeter0 = {
56
+ "power": 10.95,
57
+ "pf": 1.00,
58
+ "current": 0.08,
59
+ "voltage": 231.21,
60
+ "is_valid": true,
61
+ "total": 7.2,
62
+ "total_returned": 0.0
63
+ };
18
64
  class Shelly extends powerbase_1.PowerBase {
19
65
  constructor(system) {
20
- super("p1", system);
66
+ super("shelly", system);
21
67
  this.timer = null;
68
+ this.meters = [];
69
+ this.nrPhases = 0;
22
70
  // init is called by super
23
71
  }
24
72
  //
@@ -31,22 +79,43 @@ class Shelly extends powerbase_1.PowerBase {
31
79
  //
32
80
  // config mgt
33
81
  //
34
- // async updateConfig(config: any) {
35
- // // nothing special... for now
36
- // return super.updateConfig(config);
37
- // }
82
+ updateConfig(config) {
83
+ const _super = Object.create(null, {
84
+ updateConfig: { get: () => super.updateConfig }
85
+ });
86
+ return __awaiter(this, void 0, void 0, function* () {
87
+ this.config.addresses = config.addresses;
88
+ return _super.updateConfig.call(this, config);
89
+ });
90
+ }
38
91
  subscribe() {
39
92
  return __awaiter(this, void 0, void 0, function* () {
40
- (0, logger_1.log)("shelly", "connecting to Shelly: " + this.config.address);
93
+ const kInterval = 5;
41
94
  if (this.config.address) {
42
- this.timer = setInterval(() => {
43
- this.realtimeCounter++;
44
- // fetch data from API
45
- (0, logger_1.debug)("shelly", "call shelly API");
95
+ yield this.getDeviceConfig(this.config.address, true);
96
+ }
97
+ if (this.config.addresses) {
98
+ const list = this.config.addresses.split(",");
99
+ for (let inx in list) {
100
+ const phases = (this.config.address) ? false : (inx == "0");
101
+ yield this.getDeviceConfig(list[inx], phases);
102
+ }
103
+ }
104
+ (0, logger_1.debug)("shelly", "meters: " + JSON.stringify(this.meters));
105
+ if (this.meters.length) {
106
+ this.timer = setInterval(() => __awaiter(this, void 0, void 0, function* () {
107
+ this.realtimeCounter += kInterval;
108
+ // fetch data
109
+ const ok = yield this.fetchData();
110
+ if (ok)
111
+ this.consume();
46
112
  // call process/bindings/rules
47
113
  this.applyBindings();
48
114
  this.applyRules();
49
- }, 5000);
115
+ }), kInterval * 1000);
116
+ }
117
+ else {
118
+ (0, logger_1.log)("shelly", "No Shelly PM devices configured");
50
119
  }
51
120
  });
52
121
  }
@@ -58,6 +127,70 @@ class Shelly extends powerbase_1.PowerBase {
58
127
  }
59
128
  });
60
129
  }
130
+ getDeviceConfig(address, phases) {
131
+ return __awaiter(this, void 0, void 0, function* () {
132
+ try {
133
+ // debug("shelly", "fetching from " + address + "/status");
134
+ const res = yield (0, api_1.get)(address, 80, "/status", undefined);
135
+ (0, logger_1.debug)("shelly", "received status from " + address + " -> " + res);
136
+ const status = JSON.parse(res);
137
+ // enrich meter with its address and index + add to the global meter list
138
+ status.emeters.forEach((m, inx) => {
139
+ m.index = inx; // index with this PM device
140
+ m.phase = phases;
141
+ if (phases) {
142
+ m.phaseNr = this.nrPhases;
143
+ this.nrPhases++;
144
+ }
145
+ else {
146
+ m.phaseNr = -1;
147
+ }
148
+ m.address = address;
149
+ this.meters.push(m);
150
+ });
151
+ }
152
+ catch (error) {
153
+ (0, logger_1.err)("shelly", error.message);
154
+ }
155
+ });
156
+ }
157
+ fetchData() {
158
+ return __awaiter(this, void 0, void 0, function* () {
159
+ try {
160
+ for (let meter in this.meters) {
161
+ // debug("shelly", "fetching from " + this.config.address + "/emeter/" + meter);
162
+ const res = yield (0, api_1.get)(this.meters[meter].address, 80, "/emeter/" + this.meters[meter].index, undefined);
163
+ (0, logger_1.debug)("shelly", "received meter: " + meter + " -> " + res);
164
+ this.meters[meter] = Object.assign(Object.assign({}, this.meters[meter]), JSON.parse(res));
165
+ }
166
+ ;
167
+ return true;
168
+ }
169
+ catch (error) {
170
+ (0, logger_1.err)("shelly", error.message);
171
+ return false;
172
+ }
173
+ });
174
+ }
175
+ consume() {
176
+ // copy this.meters into the powerbase structures
177
+ this.meters.forEach((meter, inx) => {
178
+ this.channels[inx] = {
179
+ name: "Meter " + (inx + 1), type: "CT", flow: "PRODUCTION",
180
+ power: meter.power, exportEnergy: meter.total_returned, importEnergy: meter.total, phaseId: meter.phaseNr,
181
+ current: meter.power / meter.voltage, apparentPower: 0, cosPhi: 0, formula: "", voltage: meter.voltage
182
+ };
183
+ });
184
+ this.voltages = [0, 0, 0];
185
+ this.meters.filter(m => m.phase).forEach(m => this.voltages[m.phaseNr] = m.voltage);
186
+ this.realtime = { totalPower: this.meters.reduce((prev, curr) => curr.power + prev, 0),
187
+ totalReactivePower: 0,
188
+ totalExportEnergy: this.meters.reduce((prev, curr) => curr.total_returned + prev, 0),
189
+ totalImportEnergy: this.meters.reduce((prev, curr) => curr.total + prev, 0),
190
+ monitorStatus: 0, utcTimeStamp: new Date().getTime() };
191
+ this.production = this.realtime.totalPower;
192
+ this.consumption = this.realtime.totalReactivePower;
193
+ }
61
194
  }
62
195
  exports.Shelly = Shelly;
63
196
  //# sourceMappingURL=shelly.js.map
package/server/shelly.ts CHANGED
@@ -3,21 +3,86 @@
3
3
  //
4
4
 
5
5
  import { System } from "../duotecno/system";
6
- import { P1Config } from "../duotecno/types";
7
- import { debug, log } from "../duotecno/logger";
6
+ import { ShellyConfig } from "../duotecno/types";
7
+ import { debug, err, log } from "../duotecno/logger";
8
8
  import { PowerBase } from "./powerbase";
9
+ import { get } from "../duotecno/api";
9
10
 
10
11
 
12
+ const HTTPstatus = {
13
+ "wifi_sta": {
14
+ "connected": true,
15
+ "ssid": "Tele Coppieters",
16
+ "ip": "192.168.0.95",
17
+ "rssi": -73
18
+ },
19
+ "cloud": {
20
+ "enabled": true,
21
+ "connected": true
22
+ },
23
+ "mqtt": {
24
+ "connected": false
25
+ },
26
+ "time": "18:17",
27
+ "unixtime": 1663863464,
28
+ "serial": 7,
29
+ "has_update": true,
30
+ "mac": "C45BBE7928B9",
31
+ "cfg_changed_cnt": 1,
32
+ "actions_stats": { "skipped": 0 },
33
+ "relays": [{ "ison": true, "has_timer": false, "timer_started": 0, "timer_duration": 0, "timer_remaining": 0, "overpower": false, "is_valid": true, "source": "http" }],
34
+ "emeters": [
35
+ { "power": 10.66, "pf": 1.00, "current": 0.08, "voltage": 232.06, "is_valid": true, "total": 5.3, "total_returned": 0.0 },
36
+ { "power": 0.00, "pf": 0.00, "current": 0.01, "voltage": 232.06, "is_valid": true, "total": 0.0, "total_returned": 0.0 },
37
+ { "power": 0.00, "pf": 0.00, "current": 0.01, "voltage": 232.05, "is_valid": true, "total": 0.0, "total_returned": 0.0 }
38
+ ],
39
+ "total_power": 10.66,
40
+ "fs_mounted": true,
41
+ "update": { "status": "pending", "has_update": true, "new_version": "20220830-080542/v1.12-3EM-gcf4f7c2", "old_version": "20220209-094824/v1.11.8-g8c7bb8d" },
42
+ "ram_total": 49440,
43
+ "ram_free": 30960,
44
+ "fs_size": 233681,
45
+ "fs_free": 156875,
46
+ "uptime": 1364
47
+ };
48
+
49
+ const HttpEMeter0 = {
50
+ "power":10.95,
51
+ "pf":1.00,
52
+ "current":0.08,
53
+ "voltage":231.21,
54
+ "is_valid":true,
55
+ "total":7.2,
56
+ "total_returned":0.0
57
+ };
58
+
59
+ interface Meter {
60
+ address: string;
61
+ index: number;
62
+ phase: boolean;
63
+ phaseNr: number;
64
+ power: number;
65
+ pf: number;
66
+ current: number;
67
+ voltage: number;
68
+ is_valid: boolean;
69
+ total: number;
70
+ total_returned: number;
71
+ }
11
72
 
12
73
  export class Shelly extends PowerBase {
13
- config: P1Config; // redefine
74
+ config: ShellyConfig; // redefine
14
75
  timer: NodeJS.Timer;
15
76
 
77
+ meters: Array<Meter>;
78
+ nrPhases: number;
16
79
 
17
80
  constructor(system: System) {
18
- super("p1", system);
81
+ super("shelly", system);
19
82
 
20
83
  this.timer = null;
84
+ this.meters = [];
85
+ this.nrPhases = 0;
21
86
  // init is called by super
22
87
  }
23
88
 
@@ -33,26 +98,43 @@ export class Shelly extends PowerBase {
33
98
  //
34
99
  // config mgt
35
100
  //
36
- // async updateConfig(config: any) {
37
- // // nothing special... for now
38
- // return super.updateConfig(config);
39
- // }
101
+ async updateConfig(config: any) {
102
+ this.config.addresses = config.addresses;
103
+ return super.updateConfig(config);
104
+ }
40
105
 
41
106
 
42
107
  async subscribe() {
43
- log("shelly", "connecting to Shelly: " + this.config.address);
44
-
108
+ const kInterval = 5;
109
+
45
110
  if (this.config.address) {
46
- this.timer = setInterval(() => {
47
- this.realtimeCounter++;
111
+ await this.getDeviceConfig(this.config.address, true);
112
+ }
113
+ if (this.config.addresses) {
114
+ const list = this.config.addresses.split(",");
115
+ for (let inx in list) {
116
+ const phases = (this.config.address) ? false : (inx == "0");
117
+ await this.getDeviceConfig(list[inx], phases);
118
+ }
119
+ }
120
+ debug("shelly", "meters: " + JSON.stringify(this.meters));
121
+
122
+ if (this.meters.length) {
123
+ this.timer = setInterval(async () => {
124
+ this.realtimeCounter += kInterval;
48
125
 
49
- // fetch data from API
50
- debug("shelly", "call shelly API");
126
+ // fetch data
127
+ const ok = await this.fetchData();
128
+ if (ok)
129
+ this.consume();
51
130
 
52
131
  // call process/bindings/rules
53
132
  this.applyBindings();
54
133
  this.applyRules();
55
- }, 5000);
134
+ }, kInterval * 1000);
135
+
136
+ } else {
137
+ log("shelly", "No Shelly PM devices configured");
56
138
  }
57
139
  }
58
140
 
@@ -63,4 +145,68 @@ export class Shelly extends PowerBase {
63
145
  }
64
146
  }
65
147
 
148
+ async getDeviceConfig(address: string, phases: boolean) {
149
+ try {
150
+ // debug("shelly", "fetching from " + address + "/status");
151
+ const res = await get(address, 80, "/status", undefined);
152
+ debug("shelly", "received status from " + address + " -> " + res);
153
+ const status = JSON.parse(res);
154
+
155
+ // enrich meter with its address and index + add to the global meter list
156
+ status.emeters.forEach((m, inx) => {
157
+ m.index = inx; // index with this PM device
158
+ m.phase = phases;
159
+ if (phases) {
160
+ m.phaseNr = this.nrPhases;
161
+ this.nrPhases++;
162
+ } else {
163
+ m.phaseNr = -1;
164
+ }
165
+ m.address = address;
166
+ this.meters.push(m);
167
+ });
168
+
169
+ } catch(error) {
170
+ err("shelly", error.message)
171
+ }
172
+ }
173
+
174
+ async fetchData(): Promise<boolean> {
175
+ try {
176
+ for (let meter in this.meters) {
177
+ // debug("shelly", "fetching from " + this.config.address + "/emeter/" + meter);
178
+ const res = await get(this.meters[meter].address, 80, "/emeter/"+this.meters[meter].index, undefined);
179
+ debug("shelly", "received meter: " + meter + " -> " + res);
180
+ this.meters[meter] = {... this.meters[meter], ...JSON.parse(res)};
181
+ };
182
+ return true;
183
+
184
+ } catch(error) {
185
+ err("shelly", error.message);
186
+ return false;
187
+ }
188
+ }
189
+
190
+ consume() {
191
+ // copy this.meters into the powerbase structures
192
+ this.meters.forEach((meter, inx) => {
193
+ this.channels[inx] = {
194
+ name: "Meter " + (inx+1), type: "CT", flow: "PRODUCTION",
195
+ power: meter.power, exportEnergy: meter.total_returned, importEnergy: meter.total, phaseId: meter.phaseNr,
196
+ current: meter.power / meter.voltage, apparentPower: 0, cosPhi: 0, formula: "", voltage: meter.voltage}
197
+ });
198
+
199
+ this.voltages = [0,0,0];
200
+ this.meters.filter(m => m.phase).forEach(m => this.voltages[m.phaseNr] = m.voltage);
201
+
202
+ this.realtime = { totalPower: this.meters.reduce((prev, curr) => curr.power + prev, 0),
203
+ totalReactivePower: 0,
204
+ totalExportEnergy: this.meters.reduce((prev, curr) => curr.total_returned + prev, 0),
205
+ totalImportEnergy: this.meters.reduce((prev, curr) => curr.total + prev, 0),
206
+ monitorStatus: 0, utcTimeStamp: new Date().getTime() };
207
+
208
+ this.production = this.realtime.totalPower;
209
+ this.consumption = this.realtime.totalReactivePower;
210
+ }
211
+
66
212
  }
package/server/smappee.js CHANGED
@@ -213,6 +213,9 @@ class Smappee extends powerbase_1.PowerBase {
213
213
  this.realtime = { totalPower: message.totalPower, totalReactivePower: message.totalReactivePower,
214
214
  totalExportEnergy: message.totalExportEnergy, totalImportEnergy: message.totalImportEnergy,
215
215
  monitorStatus: message.monitorStatus, utcTimeStamp: message.utcTimeStamp };
216
+ message.voltages.forEach(v => {
217
+ this.voltages[v.phaseId] = v.voltage;
218
+ });
216
219
  message.channelPowers.forEach(p => {
217
220
  const inx = p.publishIndex;
218
221
  if (!this.channels[inx]) {
@@ -223,14 +226,12 @@ class Smappee extends powerbase_1.PowerBase {
223
226
  this.channels[inx].exportEnergy = p.exportEnergy;
224
227
  this.channels[inx].importEnergy = p.importEnergy;
225
228
  this.channels[inx].phaseId = p.phaseId;
229
+ this.channels[inx].voltage = this.voltages[p.phaseId] || 0;
226
230
  this.channels[inx].current = p.current;
227
231
  this.channels[inx].apparentPower = p.apparentPower;
228
232
  this.channels[inx].cosPhi = p.cosPhi;
229
233
  this.channels[inx].formula = p.formula;
230
234
  });
231
- message.voltages.forEach(v => {
232
- this.voltages[v.phaseId] = v.voltage;
233
- });
234
235
  this.calcProducAndConsumption(message);
235
236
  }
236
237
  // check rules
package/server/smappee.ts CHANGED
@@ -215,6 +215,10 @@ export class Smappee extends PowerBase {
215
215
  totalExportEnergy: message.totalExportEnergy, totalImportEnergy: message.totalImportEnergy,
216
216
  monitorStatus: message.monitorStatus, utcTimeStamp: message.utcTimeStamp };
217
217
 
218
+ message.voltages.forEach(v => {
219
+ this.voltages[v.phaseId] = v.voltage;
220
+ });
221
+
218
222
  message.channelPowers.forEach(p => {
219
223
  const inx = p.publishIndex;
220
224
  if (! this.channels[inx]) {
@@ -225,14 +229,13 @@ export class Smappee extends PowerBase {
225
229
  this.channels[inx].exportEnergy = p.exportEnergy;
226
230
  this.channels[inx].importEnergy = p.importEnergy;
227
231
  this.channels[inx].phaseId = p.phaseId;
232
+ this.channels[inx].voltage = this.voltages[p.phaseId] || 0;
228
233
  this.channels[inx].current = p.current;
229
234
  this.channels[inx].apparentPower = p.apparentPower;
230
235
  this.channels[inx].cosPhi = p.cosPhi;
231
236
  this.channels[inx].formula = p.formula;
232
237
  });
233
- message.voltages.forEach(v => {
234
- this.voltages[v.phaseId] = v.voltage;
235
- });
238
+
236
239
 
237
240
  this.calcProducAndConsumption(message);
238
241
  }
@@ -30,6 +30,7 @@ const api_1 = require("../duotecno/api");
30
30
  const config_1 = require("../duotecno/config");
31
31
  const kMaster = { name: "master", type: "string", default: "0.0.0.0:5001" };
32
32
  const kAddress = { name: "address", type: "string", default: "0.0.0.0" };
33
+ const kAddresses = { name: "addresses", type: "string", default: "[0.0.0.0]" };
33
34
  const kAddressOld = { name: "addressX", type: "string", default: "0.0.0.0" };
34
35
  const kPort = { name: "port", type: "integer", default: 80 };
35
36
  const kPortOld = { name: "portX", type: "integer", default: 80 };
@@ -328,7 +329,7 @@ class SmartApp extends webapp_1.WebApp {
328
329
  power.updateRule(id, this.scrapeRule(context));
329
330
  }
330
331
  else if (context.action === "save") {
331
- power.updateConfig({ address: context.getParam(kAddress), uid: context.getParam(kUID) });
332
+ power.updateConfig({ address: context.getParam(kAddress), uid: context.getParam(kUID), addresses: context.getParam(kAddresses), });
332
333
  }
333
334
  else if (context.action === "badd") {
334
335
  const binding = power.newBinding();
@@ -818,7 +819,6 @@ class SmartApp extends webapp_1.WebApp {
818
819
  updateNodes(master, nodes, params) {
819
820
  return __awaiter(this, void 0, void 0, function* () {
820
821
  if (nodes) {
821
- // let nodeArr = nodes.split(",").map(s => parseInt(s));
822
822
  let nodeArr = nodes.map(s => parseInt(s));
823
823
  nodeArr.forEach(adr => {
824
824
  let node = this.system.findNode(master, adr);
@@ -875,7 +875,7 @@ class SmartApp extends webapp_1.WebApp {
875
875
  else { // context.action === "node"
876
876
  // reponding to /units/[master ip address:port]/[logical node address]
877
877
  const nodeLogicalAddress = parseInt(context.id);
878
- let response = yield this.getNodeInfo(master, nodeLogicalAddress);
878
+ let response = yield this.getNodeInfo(master, nodeLogicalAddress, true);
879
879
  let N = this.sortCopy(response.node, context);
880
880
  return this.ejs("nodeDetail", context, { message: response.message, node: N });
881
881
  }
@@ -908,7 +908,7 @@ class SmartApp extends webapp_1.WebApp {
908
908
  this.system.updateSystem(true);
909
909
  }
910
910
  }
911
- getNodeInfo(master, nodeLogicalAddress) {
911
+ getNodeInfo(master, nodeLogicalAddress, doFetch = false) {
912
912
  return __awaiter(this, void 0, void 0, function* () {
913
913
  let node = this.system.findNode(master, nodeLogicalAddress);
914
914
  if (!node) {
@@ -916,7 +916,7 @@ class SmartApp extends webapp_1.WebApp {
916
916
  return { node: new protocol_1.Node(this.system.masters[0], { name: "No node" }), message: "Node not found" };
917
917
  }
918
918
  else {
919
- if (node.nrUnits != node.units.length)
919
+ if ((node.nrUnits != node.units.length) || doFetch)
920
920
  yield master.fetchAllUnits(node);
921
921
  yield node.master.requestNodeStatus(node);
922
922
  return { node };
@@ -26,6 +26,7 @@ import { setToken } from "../duotecno/config";
26
26
 
27
27
  const kMaster = {name: "master", type: "string", default: "0.0.0.0:5001"} as const;
28
28
  const kAddress = {name: "address", type: "string", default: "0.0.0.0"} as const;
29
+ const kAddresses = {name: "addresses", type: "string", default: "[0.0.0.0]"} as const;
29
30
  const kAddressOld = {name: "addressX", type: "string", default: "0.0.0.0"} as const;
30
31
  const kPort = {name: "port", type: "integer", default: 80} as const;
31
32
  const kPortOld = {name: "portX", type: "integer", default: 80} as const;
@@ -357,7 +358,7 @@ export class SmartApp extends WebApp {
357
358
  power.updateRule( id, this.scrapeRule(context) );
358
359
 
359
360
  } else if (context.action === "save") {
360
- power.updateConfig({address: context.getParam(kAddress), uid: context.getParam(kUID)});
361
+ power.updateConfig({address: context.getParam(kAddress), uid: context.getParam(kUID), addresses: context.getParam(kAddresses), });
361
362
 
362
363
 
363
364
  } else if (context.action === "badd") {
@@ -879,7 +880,6 @@ export class SmartApp extends WebApp {
879
880
 
880
881
  async updateNodes(master: Master, nodes, params) {
881
882
  if (nodes) {
882
- // let nodeArr = nodes.split(",").map(s => parseInt(s));
883
883
  let nodeArr = nodes.map(s => parseInt(s));
884
884
  nodeArr.forEach(adr => {
885
885
  let node = this.system.findNode(master, adr);
@@ -935,7 +935,7 @@ export class SmartApp extends WebApp {
935
935
  } else { // context.action === "node"
936
936
  // reponding to /units/[master ip address:port]/[logical node address]
937
937
  const nodeLogicalAddress = parseInt(context.id);
938
- let response = await this.getNodeInfo(master, nodeLogicalAddress);
938
+ let response = await this.getNodeInfo(master, nodeLogicalAddress, true);
939
939
  let N = this.sortCopy(response.node, context);
940
940
  return this.ejs("nodeDetail", context, { message: response.message, node: N });
941
941
  }
@@ -970,14 +970,14 @@ export class SmartApp extends WebApp {
970
970
  }
971
971
  }
972
972
 
973
- async getNodeInfo(master: Master, nodeLogicalAddress: number) {
973
+ async getNodeInfo(master: Master, nodeLogicalAddress: number, doFetch = false) {
974
974
  let node = this.system.findNode(master, nodeLogicalAddress);
975
975
  if (! node) {
976
976
  // if no node found, make some dummy node for the display system. (should not occur !)
977
977
  return { node: new Node(this.system.masters[0], {name: "No node"}), message: "Node not found" };
978
978
 
979
979
  } else {
980
- if (node.nrUnits != node.units.length)
980
+ if ((node.nrUnits != node.units.length) || doFetch)
981
981
  await master.fetchAllUnits(node);
982
982
  await node.master.requestNodeStatus(node);
983
983
  return { node };
@@ -38,6 +38,14 @@
38
38
  </div>
39
39
  <% } %>
40
40
 
41
+ <% if (type === "shelly") { %>
42
+ <div class="row">
43
+ <div class="input-field col s12">
44
+ <input placeholder="xx.xx.xx.xx, ..." id="addresses" name="addresses" type="text" value="<%= config.addresses %>">
45
+ <label for="addresses">Addresses (komma separated)</label>
46
+ </div>
47
+ </div>
48
+ <% } %>
41
49
 
42
50
  <h1>Rules
43
51
  <button class="right btn waves-effect waves-light" type="submit" name="action" value="add">Add rule</button>
@@ -91,17 +99,17 @@
91
99
  <h1>Info</h1>
92
100
  <% if (realtime) { %>
93
101
  <table>
94
- <tr><th>totalPower</th><th>totalReactivePower</th>
95
- <th>totalExportEnergy</th><th>totalImportEnergy</th>
96
- <th>monitorStatus</th></tr>
102
+ <tr><th>Total Power</th><th>Total Reactive</th>
103
+ <th>Total Export</th><th>Total Import</th>
104
+ <th>Status</th></tr>
97
105
  <tr><td><%= realtime.totalPower %></td><td><%= realtime.totalReactivePower %></td>
98
106
  <td><%= watt(realtime.totalExportEnergy) %>h</td><td><%= watt(realtime.totalImportEnergy) %>h</td>
99
107
  <td><%= realtime.monitorStatus %></td></tr>
100
- <tr><th>utcTimeStamp</th>
108
+ <tr><th>Time</th>
101
109
  <% for (let inx in voltages) { %>
102
110
  <th>Phase <%= inx %></th>
103
111
  <% } %>
104
- <th>Realtime Counter</th>
112
+ <th>Poll Counter</th>
105
113
  </tr>
106
114
  <tr><td><%= datetime(new Date(realtime.utcTimeStamp)) %></td>
107
115
  <% for (let inx in voltages) { %>
@@ -114,16 +122,17 @@
114
122
 
115
123
  <h1>Channels</h1>
116
124
  <table>
117
- <tr><th>publishIndex</th><th>Name</th>
118
- <th>power</th><th>exportEnergy</th><th>importEnergy</th>
119
- <th>phaseId</th><th>current</th><th>apparentPower</th>
120
- <th>cosPhi</th><th>type</th><th>flow</th><th>formula</th></tr>
125
+ <tr><th>Index</th><th>Name</th>
126
+ <th>Power</th><th>Total Export</th><th>Total Import</th>
127
+ <th>Phase</th><th>Current</th><th>Voltage</th><th>Apparent Power</th>
128
+ <th>cosPhi</th><th>Type</th><th>Flow</th><th>Formula</th></tr>
121
129
  <% for (let inx in channels) { const ch = channels[inx]; %>
122
130
  <tr><td><%= inx %></td>
123
131
  <td><%= ch.name %></td>
124
- <td><%= ch.power %></td>
132
+ <td><%= watt(ch.power) %></td>
125
133
  <td><%= watt(ch.exportEnergy) %></td><td><%= watt(ch.importEnergy) %></td>
126
- <td><%= ch.phaseId %></td><td><%= ch.current %></td>
134
+ <td><%= (ch.phaseId >= 0) ? ch.phaseId : "-" %></td><td><%= Math.round(ch.current*100)/100 %>A</td>
135
+ <td><%= ch.voltage %>V</td>
127
136
  <td><%= ch.apparentPower %></td><td><%= ch.cosPhi %></td>
128
137
  <td><%= ch.type %></td><td><%= ch.flow %></td><td><%= ch.formula %></td>
129
138
  </tr>