homebridge-smartsystem 6.3.1 → 6.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/config.json +51 -1
- package/duotecno/logger.js +1 -1
- package/duotecno/logger.ts +1 -1
- package/duotecno/types.js +10 -2
- package/duotecno/types.ts +17 -6
- package/package.json +1 -1
- package/server/base.js +3 -1
- package/server/base.ts +3 -1
- package/server/powerbase.js +36 -17
- package/server/powerbase.ts +51 -24
- package/server/shelly.js +1 -1
- package/server/shelly.ts +1 -1
package/README.md
CHANGED
|
@@ -278,6 +278,8 @@ Homebridge UI version
|
|
|
278
278
|
|
|
279
279
|
### v6.3.x - 23-09-2022 - Shelly PM release
|
|
280
280
|
- 1: first test 1 PM
|
|
281
|
+
- 2: logging now more according to debug true/false in the config file
|
|
282
|
+
- 3: power bindings now when: 5% change < 1000W, 2% change > 1000W
|
|
281
283
|
|
|
282
284
|
|
|
283
285
|
## Hardware
|
package/config.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"manufacturer": "Duotecno-Coppieterscc",
|
|
3
3
|
"platform": "DuotecnoPlatform",
|
|
4
4
|
"smappee": {
|
|
5
|
+
"debug": false,
|
|
5
6
|
"rules": [
|
|
6
7
|
{
|
|
7
8
|
"type": "sun",
|
|
@@ -140,7 +141,6 @@
|
|
|
140
141
|
],
|
|
141
142
|
"address": "192.168.0.186",
|
|
142
143
|
"uid": "57e3e0d8-bb05-4b04-8662-1a9871998f3f",
|
|
143
|
-
"debug": false,
|
|
144
144
|
"bindings": [
|
|
145
145
|
{
|
|
146
146
|
"logicalNodeAddress": 252,
|
|
@@ -189,6 +189,7 @@
|
|
|
189
189
|
]
|
|
190
190
|
},
|
|
191
191
|
"p1": {
|
|
192
|
+
"debug": false,
|
|
192
193
|
"rules": [
|
|
193
194
|
{
|
|
194
195
|
"type": "power",
|
|
@@ -250,6 +251,7 @@
|
|
|
250
251
|
"address": "192.168.0.207"
|
|
251
252
|
},
|
|
252
253
|
"shelly": {
|
|
254
|
+
"debug": false,
|
|
253
255
|
"address": "192.168.0.95",
|
|
254
256
|
"addresses": "192.168.0.95,192.168.0.95",
|
|
255
257
|
"rules": [],
|
|
@@ -378,6 +380,54 @@
|
|
|
378
380
|
}
|
|
379
381
|
],
|
|
380
382
|
"cunits": [
|
|
383
|
+
{
|
|
384
|
+
"logicalNodeAddress": 252,
|
|
385
|
+
"logicalAddress": 102,
|
|
386
|
+
"masterAddress": "192.168.0.97",
|
|
387
|
+
"masterPort": 5001,
|
|
388
|
+
"name": "<Solar Panels",
|
|
389
|
+
"displayName": "<Solar Panels",
|
|
390
|
+
"extendedType": 0,
|
|
391
|
+
"active": "N",
|
|
392
|
+
"used": "Y",
|
|
393
|
+
"group": 0
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
"logicalNodeAddress": 252,
|
|
397
|
+
"logicalAddress": 103,
|
|
398
|
+
"masterAddress": "192.168.0.97",
|
|
399
|
+
"masterPort": 5001,
|
|
400
|
+
"name": ">Cars",
|
|
401
|
+
"displayName": ">Cars",
|
|
402
|
+
"extendedType": 0,
|
|
403
|
+
"active": "N",
|
|
404
|
+
"used": "Y",
|
|
405
|
+
"group": 0
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"logicalNodeAddress": 252,
|
|
409
|
+
"logicalAddress": 100,
|
|
410
|
+
"masterAddress": "192.168.0.97",
|
|
411
|
+
"masterPort": 5001,
|
|
412
|
+
"name": ">Grid",
|
|
413
|
+
"displayName": ">Grid",
|
|
414
|
+
"extendedType": 0,
|
|
415
|
+
"active": "N",
|
|
416
|
+
"used": "Y",
|
|
417
|
+
"group": 0
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"logicalNodeAddress": 252,
|
|
421
|
+
"logicalAddress": 101,
|
|
422
|
+
"masterAddress": "192.168.0.97",
|
|
423
|
+
"masterPort": 5001,
|
|
424
|
+
"name": ">Swimmingpool",
|
|
425
|
+
"displayName": ">Swimmingpool",
|
|
426
|
+
"extendedType": 0,
|
|
427
|
+
"active": "N",
|
|
428
|
+
"used": "Y",
|
|
429
|
+
"group": 0
|
|
430
|
+
},
|
|
381
431
|
{
|
|
382
432
|
"logicalNodeAddress": 3,
|
|
383
433
|
"logicalAddress": 4,
|
package/duotecno/logger.js
CHANGED
package/duotecno/logger.ts
CHANGED
package/duotecno/types.js
CHANGED
|
@@ -254,6 +254,7 @@ exports.Sanitizers = {
|
|
|
254
254
|
powerbase: function (config) {
|
|
255
255
|
if (!config)
|
|
256
256
|
config = {};
|
|
257
|
+
config.debug = config.debug || false;
|
|
257
258
|
config.rules = config.rules || [];
|
|
258
259
|
config.rules = config.rules.map(sw => exports.Sanitizers.ruleConfig(sw));
|
|
259
260
|
config.bindings = config.bindings || [];
|
|
@@ -269,10 +270,14 @@ exports.Sanitizers = {
|
|
|
269
270
|
return cfg;
|
|
270
271
|
},
|
|
271
272
|
p1: function (config) {
|
|
272
|
-
|
|
273
|
-
|
|
273
|
+
if (!config)
|
|
274
|
+
config = {};
|
|
275
|
+
const cfg = exports.Sanitizers.powerbase(config);
|
|
276
|
+
return cfg;
|
|
274
277
|
},
|
|
275
278
|
shelly: function (config) {
|
|
279
|
+
if (!config)
|
|
280
|
+
config = {};
|
|
276
281
|
const cfg = exports.Sanitizers.powerbase(config);
|
|
277
282
|
cfg.addresses = (config === null || config === void 0 ? void 0 : config.addresses) || "";
|
|
278
283
|
return cfg;
|
|
@@ -325,6 +330,9 @@ exports.Sanitizers = {
|
|
|
325
330
|
b.power = binding.power || NaN;
|
|
326
331
|
return b;
|
|
327
332
|
},
|
|
333
|
+
//////////////
|
|
334
|
+
// Duotecno //
|
|
335
|
+
//////////////
|
|
328
336
|
masterConfig: function (config) {
|
|
329
337
|
config = (config) ? Object.assign({}, config) : {};
|
|
330
338
|
config.name = config.name || "IP Master";
|
package/duotecno/types.ts
CHANGED
|
@@ -259,6 +259,13 @@ export interface SmartAppConfig extends BaseConfig {
|
|
|
259
259
|
switches: Array<Switch>;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
/////////////////////
|
|
263
|
+
// Smartapp config //
|
|
264
|
+
/////////////////////
|
|
265
|
+
export interface BaseConfig {
|
|
266
|
+
debug?: boolean;
|
|
267
|
+
}
|
|
268
|
+
|
|
262
269
|
///////////
|
|
263
270
|
// Power //
|
|
264
271
|
///////////
|
|
@@ -292,9 +299,7 @@ export interface Bridge {
|
|
|
292
299
|
pin: string // "577-02-003"
|
|
293
300
|
};
|
|
294
301
|
|
|
295
|
-
|
|
296
|
-
debug?: boolean;
|
|
297
|
-
}
|
|
302
|
+
|
|
298
303
|
export interface PlatformConfig extends BaseConfig {
|
|
299
304
|
manufacturer: string;
|
|
300
305
|
platform: string;
|
|
@@ -429,6 +434,7 @@ export const Sanitizers = {
|
|
|
429
434
|
|
|
430
435
|
powerbase: function(config: PowerBaseConfig): PowerBaseConfig {
|
|
431
436
|
if (!config) config = <PowerBaseConfig>{};
|
|
437
|
+
config.debug = config.debug || false;
|
|
432
438
|
|
|
433
439
|
config.rules = config.rules || [];
|
|
434
440
|
config.rules = config.rules.map(sw => Sanitizers.ruleConfig(sw));
|
|
@@ -442,19 +448,21 @@ export const Sanitizers = {
|
|
|
442
448
|
|
|
443
449
|
smappee: function(config: SmappeeConfig): SmappeeConfig {
|
|
444
450
|
if (!config) config = <SmappeeConfig>{};
|
|
445
|
-
|
|
446
451
|
const cfg = <SmappeeConfig> Sanitizers.powerbase(config);
|
|
447
452
|
|
|
448
453
|
cfg.uid = config.uid || "--none--";
|
|
449
454
|
return cfg;
|
|
450
455
|
},
|
|
451
456
|
p1: function(config: P1Config): P1Config {
|
|
452
|
-
config =
|
|
457
|
+
if (!config) config = <P1Config>{};
|
|
458
|
+
const cfg = Sanitizers.powerbase(config);
|
|
453
459
|
|
|
454
|
-
return
|
|
460
|
+
return cfg;
|
|
455
461
|
},
|
|
456
462
|
shelly: function(config: ShellyConfig): ShellyConfig {
|
|
463
|
+
if (!config) config = <ShellyConfig>{};
|
|
457
464
|
const cfg = <ShellyConfig> Sanitizers.powerbase(config);
|
|
465
|
+
|
|
458
466
|
cfg.addresses = config?.addresses || "";
|
|
459
467
|
return cfg;
|
|
460
468
|
},
|
|
@@ -511,6 +519,9 @@ export const Sanitizers = {
|
|
|
511
519
|
return b;
|
|
512
520
|
},
|
|
513
521
|
|
|
522
|
+
//////////////
|
|
523
|
+
// Duotecno //
|
|
524
|
+
//////////////
|
|
514
525
|
masterConfig: function(config?: MasterConfig): MasterConfig {
|
|
515
526
|
config = (config) ? {...config} : <MasterConfig>{};
|
|
516
527
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-smartsystem",
|
|
3
3
|
"displayname": "Duotecno Bridge",
|
|
4
|
-
"version": "6.3.
|
|
4
|
+
"version": "6.3.3",
|
|
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/base.js
CHANGED
|
@@ -14,7 +14,9 @@ class Base {
|
|
|
14
14
|
else
|
|
15
15
|
this.readConfig();
|
|
16
16
|
if (this.debug)
|
|
17
|
-
logger_1.logSettings[
|
|
17
|
+
logger_1.logSettings[this.type] = logger_1.LogLevel.debug;
|
|
18
|
+
else if (logger_1.logSettings[this.type] == logger_1.LogLevel.debug)
|
|
19
|
+
logger_1.logSettings[this.type] = logger_1.LogLevel.log;
|
|
18
20
|
(0, logger_1.debug)("system", "==== read config -> " + JSON.stringify(this.config));
|
|
19
21
|
}
|
|
20
22
|
//////////////////
|
package/server/base.ts
CHANGED
|
@@ -21,7 +21,9 @@ export class Base {
|
|
|
21
21
|
this.readConfig();
|
|
22
22
|
|
|
23
23
|
if (this.debug)
|
|
24
|
-
logSettings[
|
|
24
|
+
logSettings[this.type] = LogLevel.debug;
|
|
25
|
+
else if (logSettings[this.type] == LogLevel.debug)
|
|
26
|
+
logSettings[this.type] = LogLevel.log;
|
|
25
27
|
|
|
26
28
|
debug("system", "==== read config -> " + JSON.stringify(this.config))
|
|
27
29
|
}
|
package/server/powerbase.js
CHANGED
|
@@ -94,22 +94,40 @@ class PowerBase extends base_1.Base {
|
|
|
94
94
|
//////////////////////////////////////////////
|
|
95
95
|
// Bindings to Duotecno virtual temp sensor //
|
|
96
96
|
//////////////////////////////////////////////
|
|
97
|
+
significant(current, previous) {
|
|
98
|
+
// no values yet -> don't update
|
|
99
|
+
if (isNaN(current))
|
|
100
|
+
return false;
|
|
101
|
+
// no previous value -> always update
|
|
102
|
+
if (isNaN(previous))
|
|
103
|
+
return true;
|
|
104
|
+
// less than 1000W -> update on: difference > 5% previous
|
|
105
|
+
if (current < 1000)
|
|
106
|
+
return Math.abs(previous - current) > (previous * 0.05);
|
|
107
|
+
// more than 1000W -> update on: difference > 2% previous
|
|
108
|
+
if (current >= 1000)
|
|
109
|
+
return Math.abs(previous - current) > (previous * 0.02);
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
97
112
|
applyBindings() {
|
|
98
113
|
if (this.realtimeCounter % 2 === 0) {
|
|
99
114
|
// for all bindings
|
|
100
115
|
this.bindings.forEach(b => {
|
|
101
116
|
const power = this.evalPower(b.channel);
|
|
102
|
-
if (
|
|
103
|
-
(0, logger_1.debug)("power", "APPLY to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name +
|
|
117
|
+
if (this.significant(power, b.power)) {
|
|
118
|
+
(0, logger_1.debug)("power", "APPLY to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name +
|
|
119
|
+
" (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) +
|
|
120
|
+
" > threshold: 5% =" + Math.abs(b.power * 0.05) + " > threshold: 2% =" + Math.abs(b.power * 0.02));
|
|
104
121
|
this.applyBinding(b, power)
|
|
105
122
|
.then(value => {
|
|
106
123
|
b.power = value;
|
|
107
|
-
// debug("
|
|
124
|
+
// debug("power", "set unit " + b.name + " to " + value);
|
|
108
125
|
})
|
|
109
|
-
.catch((e) => (0, logger_1.err)(this.type, e));
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
.catch((e) => (0, logger_1.err)(this.type, e.message || e));
|
|
127
|
+
// } else {
|
|
128
|
+
// debug("power", "DONT to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name +
|
|
129
|
+
// " (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) +
|
|
130
|
+
// " > threshold: 5% =" + Math.abs(b.power * 0.05) + " > threshold: 2% =" + Math.abs(b.power * 0.02));
|
|
113
131
|
}
|
|
114
132
|
});
|
|
115
133
|
}
|
|
@@ -122,8 +140,8 @@ class PowerBase extends base_1.Base {
|
|
|
122
140
|
yield unit.setSensorValue(Math.abs(value));
|
|
123
141
|
return value;
|
|
124
142
|
}
|
|
125
|
-
else {
|
|
126
|
-
throw new Error("***** UNIT NOT FOUND for binding
|
|
143
|
+
else if ((binding.logicalNodeAddress != 0) || (binding.logicalAddress != 0)) {
|
|
144
|
+
throw new Error("***** UNIT NOT FOUND for binding value " + value + " to " + binding.masterAddress + " - " + binding.logicalNodeAddress + ";" + binding.logicalAddress + " *****");
|
|
127
145
|
}
|
|
128
146
|
});
|
|
129
147
|
}
|
|
@@ -131,10 +149,10 @@ class PowerBase extends base_1.Base {
|
|
|
131
149
|
// Rules execution //
|
|
132
150
|
/////////////////////
|
|
133
151
|
applyRules() {
|
|
134
|
-
if (this.realtimeCounter %
|
|
135
|
-
(0, logger_1.log)("power", this.type + " >
|
|
136
|
-
",
|
|
137
|
-
",
|
|
152
|
+
if (this.realtimeCounter % 60 === 0) {
|
|
153
|
+
(0, logger_1.log)("power", this.type + " > RealTime totals: Power = " + this.realtime.totalPower +
|
|
154
|
+
", Export = " + this.realtime.totalExportEnergy +
|
|
155
|
+
", Import = " + this.realtime.totalImportEnergy);
|
|
138
156
|
}
|
|
139
157
|
if (this.realtimeCounter % 5 === 0) {
|
|
140
158
|
// for all rules
|
|
@@ -144,7 +162,6 @@ class PowerBase extends base_1.Base {
|
|
|
144
162
|
if (rule.type === "power") {
|
|
145
163
|
// add all channels this rule refers to
|
|
146
164
|
power = this.evalPower(rule.channel);
|
|
147
|
-
// power = rule.channel.split("+").reduce((acc, cur) => acc + this.channels[parseInt(cur)]?.power ?? 0, 0);
|
|
148
165
|
}
|
|
149
166
|
else if (rule.type === "sun") {
|
|
150
167
|
// calc fake power usage
|
|
@@ -191,10 +208,12 @@ class PowerBase extends base_1.Base {
|
|
|
191
208
|
applyCommand(action) {
|
|
192
209
|
return __awaiter(this, void 0, void 0, function* () {
|
|
193
210
|
const unit = this.system.findUnit(this.system.findMaster(action.masterAddress, action.masterPort), action.logicalNodeAddress, action.logicalAddress);
|
|
194
|
-
if (unit)
|
|
211
|
+
if (unit) {
|
|
195
212
|
yield unit.setState(action.value);
|
|
196
|
-
|
|
197
|
-
|
|
213
|
+
}
|
|
214
|
+
else if ((action.logicalNodeAddress != 0) || (action.logicalAddress != 0)) {
|
|
215
|
+
throw new Error("***** UNIT NOT FOUND for action for value " + action.value + " to " + action.masterAddress + " - " + action.logicalNodeAddress + ";" + action.logicalAddress + " *****");
|
|
216
|
+
}
|
|
198
217
|
});
|
|
199
218
|
}
|
|
200
219
|
//
|
package/server/powerbase.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { System } from "../duotecno/system";
|
|
2
2
|
import { PowerBaseConfig, Rule, Binding, Sanitizers, Boundaries, Action, kEmptyBinding, kEmptyRule } from "../duotecno/types";
|
|
3
|
-
import { err, debug, log } from "../duotecno/logger";
|
|
3
|
+
import { err, debug, log, logSettings, LogLevel } from "../duotecno/logger";
|
|
4
4
|
import { Base } from "./base";
|
|
5
5
|
import { Context } from "./webapp";
|
|
6
6
|
|
|
@@ -89,7 +89,7 @@ export class PowerBase extends Base {
|
|
|
89
89
|
async updateConfig(config: any) {
|
|
90
90
|
if (config.address)
|
|
91
91
|
this.config.address = config.address;
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
this.writeConfig();
|
|
94
94
|
|
|
95
95
|
return this.init(false);
|
|
@@ -111,36 +111,61 @@ export class PowerBase extends Base {
|
|
|
111
111
|
//////////////////////////////////////////////
|
|
112
112
|
// Bindings to Duotecno virtual temp sensor //
|
|
113
113
|
//////////////////////////////////////////////
|
|
114
|
+
significant(current: number, previous: number): boolean {
|
|
115
|
+
// no values yet -> don't update
|
|
116
|
+
if (isNaN(current))
|
|
117
|
+
return false;
|
|
118
|
+
|
|
119
|
+
// no previous value -> always update
|
|
120
|
+
if (isNaN(previous))
|
|
121
|
+
return true;
|
|
122
|
+
|
|
123
|
+
// less than 1000W -> update on: difference > 5% previous
|
|
124
|
+
if (current < 1000)
|
|
125
|
+
return Math.abs(previous - current) > (previous * 0.05);
|
|
126
|
+
|
|
127
|
+
// more than 1000W -> update on: difference > 2% previous
|
|
128
|
+
if (current >= 1000)
|
|
129
|
+
return Math.abs(previous - current) > (previous * 0.02);
|
|
130
|
+
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
114
134
|
applyBindings() {
|
|
115
135
|
if (this.realtimeCounter % 2 === 0) {
|
|
116
136
|
// for all bindings
|
|
117
137
|
this.bindings.forEach( b => {
|
|
118
138
|
const power = this.evalPower(b.channel);
|
|
119
|
-
if (
|
|
120
|
-
debug("power", "APPLY to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name +
|
|
139
|
+
if (this.significant(power, b.power)) {
|
|
140
|
+
debug("power", "APPLY to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name +
|
|
141
|
+
" (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) +
|
|
142
|
+
" > threshold: 5% =" + Math.abs(b.power * 0.05) + " > threshold: 2% =" + Math.abs(b.power * 0.02));
|
|
121
143
|
this.applyBinding(b, power)
|
|
122
144
|
.then(value => {
|
|
123
145
|
b.power = value;
|
|
124
|
-
// debug("
|
|
146
|
+
// debug("power", "set unit " + b.name + " to " + value);
|
|
125
147
|
})
|
|
126
|
-
.catch((e) => err(this.type, e));
|
|
148
|
+
.catch((e) => err(this.type, e.message || e));
|
|
127
149
|
|
|
128
|
-
} else {
|
|
129
|
-
debug("power", "DONT to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name +
|
|
150
|
+
// } else {
|
|
151
|
+
// debug("power", "DONT to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name +
|
|
152
|
+
// " (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) +
|
|
153
|
+
// " > threshold: 5% =" + Math.abs(b.power * 0.05) + " > threshold: 2% =" + Math.abs(b.power * 0.02));
|
|
130
154
|
}
|
|
131
155
|
});
|
|
132
156
|
}
|
|
133
157
|
}
|
|
134
158
|
|
|
135
159
|
async applyBinding(binding: Binding, value: number): Promise<number> {
|
|
136
|
-
const unit = this.system.findUnit(this.system.findMaster(binding.masterAddress, binding.masterPort),
|
|
160
|
+
const unit = this.system.findUnit(this.system.findMaster(binding.masterAddress, binding.masterPort),
|
|
161
|
+
binding.logicalNodeAddress, binding.logicalAddress);
|
|
137
162
|
if (unit) {
|
|
138
163
|
if (!isNaN(value))
|
|
139
164
|
await unit.setSensorValue(Math.abs(value));
|
|
140
165
|
return value;
|
|
141
166
|
|
|
142
|
-
} else {
|
|
143
|
-
throw new Error("***** UNIT NOT FOUND for binding
|
|
167
|
+
} else if ((binding.logicalNodeAddress != 0) || (binding.logicalAddress != 0)) {
|
|
168
|
+
throw new Error("***** UNIT NOT FOUND for binding value " + value + " to " + binding.masterAddress + " - " + binding.logicalNodeAddress + ";" + binding.logicalAddress + " *****");
|
|
144
169
|
}
|
|
145
170
|
}
|
|
146
171
|
|
|
@@ -149,10 +174,10 @@ export class PowerBase extends Base {
|
|
|
149
174
|
// Rules execution //
|
|
150
175
|
/////////////////////
|
|
151
176
|
applyRules() {
|
|
152
|
-
if (this.realtimeCounter %
|
|
153
|
-
log("power", this.type + " >
|
|
154
|
-
|
|
155
|
-
|
|
177
|
+
if (this.realtimeCounter % 60 === 0) {
|
|
178
|
+
log("power", this.type + " > RealTime totals: Power = " + this.realtime.totalPower +
|
|
179
|
+
", Export = " + this.realtime.totalExportEnergy +
|
|
180
|
+
", Import = " + this.realtime.totalImportEnergy);
|
|
156
181
|
}
|
|
157
182
|
|
|
158
183
|
if (this.realtimeCounter % 5 === 0) {
|
|
@@ -164,7 +189,6 @@ export class PowerBase extends Base {
|
|
|
164
189
|
if (rule.type === "power") {
|
|
165
190
|
// add all channels this rule refers to
|
|
166
191
|
power = this.evalPower(rule.channel);
|
|
167
|
-
// power = rule.channel.split("+").reduce((acc, cur) => acc + this.channels[parseInt(cur)]?.power ?? 0, 0);
|
|
168
192
|
|
|
169
193
|
} else if (rule.type === "sun") {
|
|
170
194
|
// calc fake power usage
|
|
@@ -201,11 +225,12 @@ export class PowerBase extends Base {
|
|
|
201
225
|
rule.current = newCurrent;
|
|
202
226
|
if (newCurrent < rule.actions.length) {
|
|
203
227
|
this.applyCommand(rule.actions[newCurrent])
|
|
204
|
-
.then((val) => {debug("power", "## sent command -> " + rule.type +
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
228
|
+
.then((val) => { debug("power", "## sent command -> " + rule.type +
|
|
229
|
+
", power = " + power + ", channel = " + rule.channel +
|
|
230
|
+
" -> current = " + newCurrent +
|
|
231
|
+
" (unit: " + rule.actions[newCurrent].name + ", value: " + rule.actions[newCurrent].value + ")");
|
|
232
|
+
rule.current = newCurrent;
|
|
233
|
+
})
|
|
209
234
|
.catch((e) => err(this.type, e.message));
|
|
210
235
|
}
|
|
211
236
|
}
|
|
@@ -213,10 +238,12 @@ export class PowerBase extends Base {
|
|
|
213
238
|
|
|
214
239
|
async applyCommand(action: Action) {
|
|
215
240
|
const unit = this.system.findUnit(this.system.findMaster(action.masterAddress, action.masterPort), action.logicalNodeAddress, action.logicalAddress);
|
|
216
|
-
if (unit)
|
|
241
|
+
if (unit) {
|
|
217
242
|
await unit.setState(action.value);
|
|
218
|
-
|
|
219
|
-
|
|
243
|
+
|
|
244
|
+
} else if ((action.logicalNodeAddress != 0) || (action.logicalAddress != 0)) {
|
|
245
|
+
throw new Error("***** UNIT NOT FOUND for action for value " + action.value + " to " + action.masterAddress + " - " + action.logicalNodeAddress + ";" + action.logicalAddress + " *****");
|
|
246
|
+
}
|
|
220
247
|
}
|
|
221
248
|
|
|
222
249
|
//
|
package/server/shelly.js
CHANGED