homebridge-smartsystem 6.3.2 → 6.3.4
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 +3 -2
- package/config.json +137 -108
- package/package.json +3 -2
- package/server/powerbase.js +31 -12
- package/server/powerbase.ts +46 -19
- package/server/smappee.js +8 -3
- package/server/smappee.ts +7 -3
package/README.md
CHANGED
|
@@ -277,9 +277,10 @@ Homebridge UI version
|
|
|
277
277
|
- 6: power: 5% instead of 10% for power rules
|
|
278
278
|
|
|
279
279
|
### v6.3.x - 23-09-2022 - Shelly PM release
|
|
280
|
-
- 1: first test
|
|
280
|
+
- 1: first test Shelly PM - allow address or addresses, example: "192.168.0.95,102.168.0.96"
|
|
281
281
|
- 2: logging now more according to debug true/false in the config file
|
|
282
|
-
|
|
282
|
+
- 3: power bindings now when: 5% change < 1000W, 2% change > 1000W
|
|
283
|
+
- 4: added if in set-plug if smappee not (yet) connected.
|
|
283
284
|
|
|
284
285
|
## Hardware
|
|
285
286
|
A Raspberry Pi that connects to a Duotecno IP Node
|
package/config.json
CHANGED
|
@@ -8,138 +8,104 @@
|
|
|
8
8
|
"type": "sun",
|
|
9
9
|
"channel": "0",
|
|
10
10
|
"low": 30,
|
|
11
|
-
"high":
|
|
11
|
+
"high": 3000,
|
|
12
12
|
"actions": [
|
|
13
13
|
{
|
|
14
|
-
"name": "
|
|
14
|
+
"name": "Lamp-Bottom",
|
|
15
15
|
"value": false,
|
|
16
16
|
"masterAddress": "192.168.0.97",
|
|
17
17
|
"masterPort": 5001,
|
|
18
|
-
"logicalAddress":
|
|
19
|
-
"logicalNodeAddress":
|
|
18
|
+
"logicalAddress": 34,
|
|
19
|
+
"logicalNodeAddress": 3
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
"name": "
|
|
23
|
-
"value":
|
|
22
|
+
"name": "Lamp-Bottom",
|
|
23
|
+
"value": false,
|
|
24
24
|
"masterAddress": "192.168.0.97",
|
|
25
25
|
"masterPort": 5001,
|
|
26
|
-
"logicalAddress":
|
|
27
|
-
"logicalNodeAddress":
|
|
26
|
+
"logicalAddress": 34,
|
|
27
|
+
"logicalNodeAddress": 3
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
|
-
"name": "
|
|
30
|
+
"name": "Lamp-Bottom",
|
|
31
31
|
"value": true,
|
|
32
32
|
"masterAddress": "192.168.0.97",
|
|
33
33
|
"masterPort": 5001,
|
|
34
|
-
"logicalAddress":
|
|
35
|
-
"logicalNodeAddress":
|
|
34
|
+
"logicalAddress": 34,
|
|
35
|
+
"logicalNodeAddress": 3
|
|
36
36
|
}
|
|
37
37
|
],
|
|
38
|
-
"power":
|
|
39
|
-
"current":
|
|
38
|
+
"power": 146,
|
|
39
|
+
"current": 1
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"type": "power",
|
|
43
|
-
"channel": "
|
|
44
|
-
"low":
|
|
45
|
-
"high":
|
|
43
|
+
"channel": "7+8+9",
|
|
44
|
+
"low": 100,
|
|
45
|
+
"high": 10000,
|
|
46
46
|
"actions": [
|
|
47
47
|
{
|
|
48
|
-
"name": "
|
|
48
|
+
"name": "",
|
|
49
49
|
"value": false,
|
|
50
50
|
"masterAddress": "192.168.0.97",
|
|
51
51
|
"masterPort": 5001,
|
|
52
|
-
"logicalAddress":
|
|
53
|
-
"logicalNodeAddress":
|
|
52
|
+
"logicalAddress": 30,
|
|
53
|
+
"logicalNodeAddress": 3
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
|
-
"name": "
|
|
57
|
-
"value":
|
|
56
|
+
"name": "",
|
|
57
|
+
"value": true,
|
|
58
58
|
"masterAddress": "192.168.0.97",
|
|
59
59
|
"masterPort": 5001,
|
|
60
|
-
"logicalAddress":
|
|
61
|
-
"logicalNodeAddress":
|
|
60
|
+
"logicalAddress": 30,
|
|
61
|
+
"logicalNodeAddress": 3
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
|
-
"name": "
|
|
64
|
+
"name": "0;0",
|
|
65
65
|
"value": true,
|
|
66
66
|
"masterAddress": "192.168.0.97",
|
|
67
67
|
"masterPort": 5001,
|
|
68
|
-
"logicalAddress":
|
|
69
|
-
"logicalNodeAddress":
|
|
68
|
+
"logicalAddress": 0,
|
|
69
|
+
"logicalNodeAddress": 0
|
|
70
70
|
}
|
|
71
71
|
],
|
|
72
|
-
"power":
|
|
73
|
-
"current":
|
|
72
|
+
"power": 446,
|
|
73
|
+
"current": 1
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
"type": "power",
|
|
77
77
|
"channel": "7+8+9",
|
|
78
|
-
"low":
|
|
78
|
+
"low": 400,
|
|
79
79
|
"high": 900,
|
|
80
80
|
"actions": [
|
|
81
81
|
{
|
|
82
|
-
"name": "",
|
|
83
|
-
"value":
|
|
84
|
-
"masterAddress": "192.168.0.97",
|
|
85
|
-
"masterPort": 5001,
|
|
86
|
-
"logicalAddress": 4,
|
|
87
|
-
"logicalNodeAddress": 3
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
"name": "",
|
|
91
|
-
"value": -1,
|
|
82
|
+
"name": "Lamp-Top",
|
|
83
|
+
"value": false,
|
|
92
84
|
"masterAddress": "192.168.0.97",
|
|
93
85
|
"masterPort": 5001,
|
|
94
|
-
"logicalAddress":
|
|
86
|
+
"logicalAddress": 33,
|
|
95
87
|
"logicalNodeAddress": 3
|
|
96
88
|
},
|
|
97
89
|
{
|
|
98
|
-
"name": "",
|
|
99
|
-
"value":
|
|
90
|
+
"name": "Lamp-Top",
|
|
91
|
+
"value": true,
|
|
100
92
|
"masterAddress": "192.168.0.97",
|
|
101
93
|
"masterPort": 5001,
|
|
102
|
-
"logicalAddress":
|
|
94
|
+
"logicalAddress": 33,
|
|
103
95
|
"logicalNodeAddress": 3
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
"type": "sun",
|
|
109
|
-
"channel": "7",
|
|
110
|
-
"low": 0,
|
|
111
|
-
"high": 0,
|
|
112
|
-
"actions": [
|
|
113
|
-
{
|
|
114
|
-
"name": "Mood C",
|
|
115
|
-
"value": false,
|
|
116
|
-
"masterAddress": "192.168.0.97",
|
|
117
|
-
"masterPort": 5001,
|
|
118
|
-
"logicalAddress": 12,
|
|
119
|
-
"logicalNodeAddress": 252
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
"name": "Mood C",
|
|
123
|
-
"value": 50,
|
|
124
|
-
"masterAddress": "192.168.0.97",
|
|
125
|
-
"masterPort": 5001,
|
|
126
|
-
"logicalAddress": 12,
|
|
127
|
-
"logicalNodeAddress": 252
|
|
128
96
|
},
|
|
129
97
|
{
|
|
130
|
-
"name": "
|
|
98
|
+
"name": "--",
|
|
131
99
|
"value": true,
|
|
132
100
|
"masterAddress": "192.168.0.97",
|
|
133
101
|
"masterPort": 5001,
|
|
134
|
-
"logicalAddress":
|
|
135
|
-
"logicalNodeAddress":
|
|
102
|
+
"logicalAddress": 0,
|
|
103
|
+
"logicalNodeAddress": 0
|
|
136
104
|
}
|
|
137
|
-
]
|
|
138
|
-
"power": 3263,
|
|
139
|
-
"current": 2
|
|
105
|
+
]
|
|
140
106
|
}
|
|
141
107
|
],
|
|
142
|
-
"address": "192.168.0.
|
|
108
|
+
"address": "192.168.0.184",
|
|
143
109
|
"uid": "57e3e0d8-bb05-4b04-8662-1a9871998f3f",
|
|
144
110
|
"bindings": [
|
|
145
111
|
{
|
|
@@ -190,40 +156,7 @@
|
|
|
190
156
|
},
|
|
191
157
|
"p1": {
|
|
192
158
|
"debug": false,
|
|
193
|
-
"rules": [
|
|
194
|
-
{
|
|
195
|
-
"type": "power",
|
|
196
|
-
"channel": "3+4+5",
|
|
197
|
-
"low": 30,
|
|
198
|
-
"high": 1500,
|
|
199
|
-
"actions": [
|
|
200
|
-
{
|
|
201
|
-
"name": "--",
|
|
202
|
-
"value": false,
|
|
203
|
-
"masterAddress": "192.168.0.97",
|
|
204
|
-
"masterPort": 5001,
|
|
205
|
-
"logicalAddress": 0,
|
|
206
|
-
"logicalNodeAddress": 0
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
"name": "--",
|
|
210
|
-
"value": 50,
|
|
211
|
-
"masterAddress": "192.168.0.97",
|
|
212
|
-
"masterPort": 5001,
|
|
213
|
-
"logicalAddress": 0,
|
|
214
|
-
"logicalNodeAddress": 0
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
"name": "Alles aan",
|
|
218
|
-
"value": true,
|
|
219
|
-
"masterAddress": "192.168.0.97",
|
|
220
|
-
"masterPort": 5001,
|
|
221
|
-
"logicalAddress": 5,
|
|
222
|
-
"logicalNodeAddress": 3
|
|
223
|
-
}
|
|
224
|
-
]
|
|
225
|
-
}
|
|
226
|
-
],
|
|
159
|
+
"rules": [],
|
|
227
160
|
"bindings": [
|
|
228
161
|
{
|
|
229
162
|
"logicalNodeAddress": 252,
|
|
@@ -380,6 +313,102 @@
|
|
|
380
313
|
}
|
|
381
314
|
],
|
|
382
315
|
"cunits": [
|
|
316
|
+
{
|
|
317
|
+
"logicalNodeAddress": 252,
|
|
318
|
+
"logicalAddress": 102,
|
|
319
|
+
"masterAddress": "192.168.0.97",
|
|
320
|
+
"masterPort": 5001,
|
|
321
|
+
"name": "<Solar Panels",
|
|
322
|
+
"displayName": "<Solar Panels",
|
|
323
|
+
"extendedType": 0,
|
|
324
|
+
"active": "N",
|
|
325
|
+
"used": "Y",
|
|
326
|
+
"group": 0
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"logicalNodeAddress": 252,
|
|
330
|
+
"logicalAddress": 103,
|
|
331
|
+
"masterAddress": "192.168.0.97",
|
|
332
|
+
"masterPort": 5001,
|
|
333
|
+
"name": ">Cars",
|
|
334
|
+
"displayName": ">Cars",
|
|
335
|
+
"extendedType": 0,
|
|
336
|
+
"active": "N",
|
|
337
|
+
"used": "Y",
|
|
338
|
+
"group": 0
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
"logicalNodeAddress": 252,
|
|
342
|
+
"logicalAddress": 100,
|
|
343
|
+
"masterAddress": "192.168.0.97",
|
|
344
|
+
"masterPort": 5001,
|
|
345
|
+
"name": ">Grid",
|
|
346
|
+
"displayName": ">Grid",
|
|
347
|
+
"extendedType": 0,
|
|
348
|
+
"active": "N",
|
|
349
|
+
"used": "Y",
|
|
350
|
+
"group": 0
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"logicalNodeAddress": 252,
|
|
354
|
+
"logicalAddress": 101,
|
|
355
|
+
"masterAddress": "192.168.0.97",
|
|
356
|
+
"masterPort": 5001,
|
|
357
|
+
"name": ">Swimmingpool",
|
|
358
|
+
"displayName": ">Swimmingpool",
|
|
359
|
+
"extendedType": 0,
|
|
360
|
+
"active": "N",
|
|
361
|
+
"used": "Y",
|
|
362
|
+
"group": 0
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"logicalNodeAddress": 252,
|
|
366
|
+
"logicalAddress": 7,
|
|
367
|
+
"masterAddress": "192.168.0.97",
|
|
368
|
+
"masterPort": 5001,
|
|
369
|
+
"name": "Bottom-Left",
|
|
370
|
+
"displayName": "Bottom-Left",
|
|
371
|
+
"extendedType": 102,
|
|
372
|
+
"active": "Y",
|
|
373
|
+
"used": "Y",
|
|
374
|
+
"group": 0
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"logicalNodeAddress": 3,
|
|
378
|
+
"logicalAddress": 30,
|
|
379
|
+
"masterAddress": "192.168.0.97",
|
|
380
|
+
"masterPort": 5001,
|
|
381
|
+
"name": "Blue LED",
|
|
382
|
+
"displayName": "Blue LED",
|
|
383
|
+
"extendedType": 1,
|
|
384
|
+
"active": "N",
|
|
385
|
+
"used": "Y",
|
|
386
|
+
"group": 0
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
"logicalNodeAddress": 3,
|
|
390
|
+
"logicalAddress": 34,
|
|
391
|
+
"masterAddress": "192.168.0.97",
|
|
392
|
+
"masterPort": 5001,
|
|
393
|
+
"name": "Lamp-Bottom",
|
|
394
|
+
"displayName": "Lamp-Bottom",
|
|
395
|
+
"extendedType": 2,
|
|
396
|
+
"active": "N",
|
|
397
|
+
"used": "Y",
|
|
398
|
+
"group": 0
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
"logicalNodeAddress": 3,
|
|
402
|
+
"logicalAddress": 33,
|
|
403
|
+
"masterAddress": "192.168.0.97",
|
|
404
|
+
"masterPort": 5001,
|
|
405
|
+
"name": "Lamp-Top",
|
|
406
|
+
"displayName": "Lamp-Top",
|
|
407
|
+
"extendedType": 2,
|
|
408
|
+
"active": "N",
|
|
409
|
+
"used": "Y",
|
|
410
|
+
"group": 0
|
|
411
|
+
},
|
|
383
412
|
{
|
|
384
413
|
"logicalNodeAddress": 3,
|
|
385
414
|
"logicalAddress": 4,
|
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.4",
|
|
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",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"license": "ISC",
|
|
10
10
|
"scripts": {
|
|
11
11
|
"start": "DEBUG=* homebridge -D -P '/Users/johan/Development/duotecno/smartsocket'",
|
|
12
|
-
"watch": "npx tsc --build . --watch"
|
|
12
|
+
"watch": "npx tsc --build . --watch",
|
|
13
|
+
"publish": "npx tsc --build && npm i && npm publish"
|
|
13
14
|
},
|
|
14
15
|
"engines": {
|
|
15
16
|
"node": ">=14.18.1",
|
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
126
|
.catch((e) => (0, logger_1.err)(this.type, e.message || e));
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
}
|
|
@@ -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
|
@@ -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
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
|
|
|
@@ -151,8 +176,8 @@ export class PowerBase extends Base {
|
|
|
151
176
|
applyRules() {
|
|
152
177
|
if (this.realtimeCounter % 60 === 0) {
|
|
153
178
|
log("power", this.type + " > RealTime totals: Power = " + this.realtime.totalPower +
|
|
154
|
-
|
|
155
|
-
|
|
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/smappee.js
CHANGED
|
@@ -280,9 +280,14 @@ class Smappee extends powerbase_1.PowerBase {
|
|
|
280
280
|
if ((typeof currState === "boolean") && (state != currState)) {
|
|
281
281
|
// do we need to do this? do we get an mqtt status message ??
|
|
282
282
|
this.plugs[plugNr].value = currState;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
if (this.client) {
|
|
284
|
+
const topic = 'servicelocation/' + this.config.uid + '/plug/' + plugNr + '/setstate';
|
|
285
|
+
const payload = '{"value": "' + ((state) ? "ON" : "OFF") + '", "since": "' + (new Date().getTime()) + '"}';
|
|
286
|
+
this.client.publish(topic, payload);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
(0, logger_1.err)("smappee", "no open connection (yet?) to " + this.config.uid + " on " + this.config.address);
|
|
290
|
+
}
|
|
286
291
|
}
|
|
287
292
|
}
|
|
288
293
|
}
|
package/server/smappee.ts
CHANGED
|
@@ -296,9 +296,13 @@ export class Smappee extends PowerBase {
|
|
|
296
296
|
// do we need to do this? do we get an mqtt status message ??
|
|
297
297
|
this.plugs[plugNr].value = currState;
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
if (this.client) {
|
|
300
|
+
const topic = 'servicelocation/' + this.config.uid + '/plug/' + plugNr + '/setstate';
|
|
301
|
+
const payload = '{"value": "' + ((state) ? "ON" : "OFF") + '", "since": "' + (new Date().getTime()) + '"}';
|
|
302
|
+
this.client.publish(topic, payload);
|
|
303
|
+
} else {
|
|
304
|
+
err("smappee", "no open connection (yet?) to " + this.config.uid + " on " + this.config.address);
|
|
305
|
+
}
|
|
302
306
|
}
|
|
303
307
|
}
|
|
304
308
|
|