homebridge-smartsystem 6.1.7 → 6.2.2
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 +14 -0
- package/accessories/accessory.js +4 -4
- package/accessories/accessory.ts +1 -2
- package/accessories/dimmer.js +6 -6
- package/accessories/dimmer.ts +1 -1
- package/accessories/door.js +2 -2
- package/accessories/door.ts +1 -1
- package/accessories/garagedoor.js +5 -4
- package/accessories/garagedoor.ts +2 -1
- package/accessories/lock.js +6 -5
- package/accessories/lock.ts +2 -1
- package/accessories/mood.js +2 -1
- package/accessories/mood.ts +2 -1
- package/accessories/temperature.js +2 -2
- package/accessories/temperature.ts +1 -1
- package/accessories/windowcovering.js +8 -7
- package/accessories/windowcovering.ts +2 -1
- package/config.json +169 -228
- package/config.smappee.json +178 -2
- package/config.smartapp.json +63 -0
- package/duotecno/Q.js +8 -8
- package/duotecno/Q.ts +1 -1
- package/duotecno/api.js +3 -3
- package/duotecno/api.ts +2 -2
- package/duotecno/config.js +24 -23
- package/duotecno/config.ts +23 -16
- package/duotecno/logger.js +51 -0
- package/duotecno/logger.ts +41 -0
- package/duotecno/master.js +4 -6
- package/duotecno/master.ts +2 -4
- package/duotecno/protocol.js +10 -9
- package/duotecno/protocol.ts +2 -1
- package/duotecno/system.js +17 -41
- package/duotecno/system.ts +7 -34
- package/duotecno/types.js +58 -131
- package/duotecno/types.ts +65 -125
- package/index.spec.js +22 -36
- package/index.spec.ts +20 -33
- package/package.json +2 -2
- package/server/base.js +10 -38
- package/server/base.ts +9 -42
- package/server/p1.js +9 -8
- package/server/p1.ts +6 -4
- package/server/platform.js +66 -36
- package/server/platform.ts +47 -12
- package/server/powerbase.js +15 -55
- package/server/powerbase.ts +4 -50
- package/server/shelly.js +4 -4
- package/server/shelly.ts +3 -2
- package/server/smappee.js +9 -8
- package/server/smappee.ts +4 -3
- package/server/smartapp.js +94 -39
- package/server/smartapp.ts +73 -20
- package/server/socapp.js +6 -6
- package/server/socapp.ts +2 -1
- package/server/somfy.js +12 -12
- package/server/somfy.ts +1 -1
- package/server/support.js +13 -13
- package/server/support.ts +4 -4
- package/server/views/style.ejs +1 -0
- package/server/views/switch-details.ejs +15 -5
- package/server/webapp.js +45 -47
- package/server/webapp.ts +29 -38
- package/config.groups.json +0 -8
- package/config.p1-dev.json +0 -59
- package/config.scenes.json +0 -15
package/server/powerbase.js
CHANGED
|
@@ -11,15 +11,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.PowerBase = void 0;
|
|
13
13
|
const types_1 = require("../duotecno/types");
|
|
14
|
+
const logger_1 = require("../duotecno/logger");
|
|
14
15
|
const base_1 = require("./base");
|
|
15
|
-
const http = require("http");
|
|
16
16
|
// Power base class
|
|
17
17
|
// used by Smappee, Shelly PM, P1 Meter, ...
|
|
18
18
|
// Johan Coppieters, Jul 2022.
|
|
19
19
|
//
|
|
20
20
|
class PowerBase extends base_1.Base {
|
|
21
|
-
constructor(type, system
|
|
22
|
-
super(type
|
|
21
|
+
constructor(type, system) {
|
|
22
|
+
super(type);
|
|
23
23
|
// called by Base: this.readConfig();
|
|
24
24
|
this.system = system;
|
|
25
25
|
// will grow when we encounter one in the mqtt stream or if we receive a config message
|
|
@@ -31,7 +31,7 @@ class PowerBase extends base_1.Base {
|
|
|
31
31
|
this.rules = (this.config.rules || []).map(rule => types_1.Sanitizers.ruleConfig(rule));
|
|
32
32
|
this.bindings = (this.config.bindings || []).map(binding => types_1.Sanitizers.bindingConfig(binding));
|
|
33
33
|
this.init(true).then(() => {
|
|
34
|
-
(0,
|
|
34
|
+
(0, logger_1.log)("power", "Power[" + type + "] created and started");
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
//
|
|
@@ -76,46 +76,6 @@ class PowerBase extends base_1.Base {
|
|
|
76
76
|
return this.init(false);
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
|
-
//////////////
|
|
80
|
-
// http get //
|
|
81
|
-
//////////////
|
|
82
|
-
get(host, path) {
|
|
83
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
-
let timer;
|
|
85
|
-
let httpReq;
|
|
86
|
-
return new Promise((resolve, reject) => {
|
|
87
|
-
try {
|
|
88
|
-
timer = setTimeout(() => {
|
|
89
|
-
if (httpReq) {
|
|
90
|
-
httpReq.destroy();
|
|
91
|
-
}
|
|
92
|
-
reject("Request to " + host + path + " timed out");
|
|
93
|
-
}, 4000);
|
|
94
|
-
httpReq = http.get({ host, path }, (response) => {
|
|
95
|
-
let str = '';
|
|
96
|
-
// another chunk of data has been received, so append it to `str`
|
|
97
|
-
response.on('data', (chunk) => {
|
|
98
|
-
str += chunk;
|
|
99
|
-
});
|
|
100
|
-
// the whole response has been received,
|
|
101
|
-
// stop the timet and resolve the promise with ithe collected result
|
|
102
|
-
response.on('end', () => {
|
|
103
|
-
if (timer)
|
|
104
|
-
clearTimeout(timer);
|
|
105
|
-
resolve(str);
|
|
106
|
-
});
|
|
107
|
-
}).on('error', (e) => {
|
|
108
|
-
(0, types_1.err)("power", "http.get failed with " + JSON.stringify(e));
|
|
109
|
-
reject(e);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
catch (error) {
|
|
113
|
-
(0, types_1.err)("power", "http.get failed with " + JSON.stringify(error));
|
|
114
|
-
reject(error);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
79
|
evalPower(exp) {
|
|
120
80
|
var _a, _b, _c, _d, _e, _f;
|
|
121
81
|
let parsed = exp.split(/(\+|-)/);
|
|
@@ -126,7 +86,7 @@ class PowerBase extends base_1.Base {
|
|
|
126
86
|
else if (parsed[i] === "+")
|
|
127
87
|
result += (_f = (_e = this.channels[parseInt(parsed[i + 1]) || 0]) === null || _e === void 0 ? void 0 : _e.power) !== null && _f !== void 0 ? _f : 0;
|
|
128
88
|
}
|
|
129
|
-
(0,
|
|
89
|
+
(0, logger_1.debug)("power", "evalPower: " + exp + " -> " + parsed + " = " + result);
|
|
130
90
|
return result;
|
|
131
91
|
}
|
|
132
92
|
//////////////////////////////////////////////
|
|
@@ -138,16 +98,16 @@ class PowerBase extends base_1.Base {
|
|
|
138
98
|
this.bindings.forEach(b => {
|
|
139
99
|
const power = this.evalPower(b.channel);
|
|
140
100
|
if ((!isNaN(power)) && (isNaN(b.power) || (Math.abs(b.power - power) > Math.abs(b.power * 0.1)))) {
|
|
141
|
-
(0,
|
|
101
|
+
(0, logger_1.debug)("power", "APPLY to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name + " (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) + " > threshold: " + Math.abs(b.power * 0.1));
|
|
142
102
|
this.applyBinding(b, power)
|
|
143
103
|
.then(value => {
|
|
144
104
|
b.power = value;
|
|
145
105
|
// debug("homebridge", "set unit " + b.name + " to " + value);
|
|
146
106
|
})
|
|
147
|
-
.catch((e) => (0,
|
|
107
|
+
.catch((e) => (0, logger_1.err)(this.type, e));
|
|
148
108
|
}
|
|
149
109
|
else {
|
|
150
|
-
(0,
|
|
110
|
+
(0, logger_1.debug)("power", "DONT to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name + " (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) + " > threshold: " + Math.abs(b.power * 0.1));
|
|
151
111
|
}
|
|
152
112
|
});
|
|
153
113
|
}
|
|
@@ -170,7 +130,7 @@ class PowerBase extends base_1.Base {
|
|
|
170
130
|
/////////////////////
|
|
171
131
|
applyRules() {
|
|
172
132
|
if (this.realtimeCounter % 30 === 0) {
|
|
173
|
-
(0,
|
|
133
|
+
(0, logger_1.log)("power", this.type + " > processRealTime: totalPower = " + this.realtime.totalPower +
|
|
174
134
|
", export = " + this.realtime.totalExportEnergy +
|
|
175
135
|
", import = " + this.realtime.totalImportEnergy);
|
|
176
136
|
}
|
|
@@ -188,7 +148,7 @@ class PowerBase extends base_1.Base {
|
|
|
188
148
|
// calc fake power usage
|
|
189
149
|
power = this.production - this.consumption;
|
|
190
150
|
}
|
|
191
|
-
(0,
|
|
151
|
+
(0, logger_1.debug)("power", "checking " + rule.type + "-rule with channel = " + rule.channel + " = " + power + "W");
|
|
192
152
|
this.checkPowerRule(power, rule);
|
|
193
153
|
});
|
|
194
154
|
}
|
|
@@ -208,7 +168,7 @@ class PowerBase extends base_1.Base {
|
|
|
208
168
|
}
|
|
209
169
|
rule.power = power;
|
|
210
170
|
if (newCurrent != rule.current) {
|
|
211
|
-
(0,
|
|
171
|
+
(0, logger_1.debug)("power", "triggered rule for channel: " + rule.channel + ", power = " + power +
|
|
212
172
|
", low: " + rule.low + ", high: " + rule.high +
|
|
213
173
|
", current: " + rule.current + " -> new: " + newCurrent);
|
|
214
174
|
// should be done after successful applyCommand...
|
|
@@ -216,13 +176,13 @@ class PowerBase extends base_1.Base {
|
|
|
216
176
|
if (newCurrent < rule.actions.length) {
|
|
217
177
|
this.applyCommand(rule.actions[newCurrent])
|
|
218
178
|
.then((val) => {
|
|
219
|
-
(0,
|
|
179
|
+
(0, logger_1.debug)("power", "## sent command -> " + rule.type +
|
|
220
180
|
", power = " + power + ", channel = " + rule.channel +
|
|
221
181
|
" -> current = " + newCurrent +
|
|
222
182
|
" (unit: " + rule.actions[newCurrent].name + ", value: " + rule.actions[newCurrent].value + ")");
|
|
223
183
|
rule.current = newCurrent;
|
|
224
184
|
})
|
|
225
|
-
.catch((e) => (0,
|
|
185
|
+
.catch((e) => (0, logger_1.err)(this.type, e.message));
|
|
226
186
|
}
|
|
227
187
|
}
|
|
228
188
|
}
|
|
@@ -244,7 +204,7 @@ class PowerBase extends base_1.Base {
|
|
|
244
204
|
// sanitize and copy all rules into the config
|
|
245
205
|
this.config.rules = [];
|
|
246
206
|
this.rules.forEach(r => this.config.rules.push(types_1.Sanitizers.ruleConfig(r)));
|
|
247
|
-
(0,
|
|
207
|
+
(0, logger_1.debug)("power", "config.rules = " + JSON.stringify(this.config.rules));
|
|
248
208
|
this.writeConfig();
|
|
249
209
|
}
|
|
250
210
|
newRule() {
|
|
@@ -272,7 +232,7 @@ class PowerBase extends base_1.Base {
|
|
|
272
232
|
this.bindings.sort((a, b) => parseInt(a.channel) - parseInt(b.channel));
|
|
273
233
|
// sanitize and copy all rules into the config
|
|
274
234
|
this.config.bindings = this.bindings.map(b => types_1.Sanitizers.bindingConfig(b));
|
|
275
|
-
(0,
|
|
235
|
+
(0, logger_1.debug)("power", "config.bindings = " + JSON.stringify(this.config.bindings));
|
|
276
236
|
this.writeConfig();
|
|
277
237
|
}
|
|
278
238
|
newBinding() {
|
package/server/powerbase.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { System } from "../duotecno/system";
|
|
2
|
-
import { PowerBaseConfig, Rule, Binding, Sanitizers, Boundaries, Action, kEmptyBinding, kEmptyRule
|
|
2
|
+
import { PowerBaseConfig, Rule, Binding, Sanitizers, Boundaries, Action, kEmptyBinding, kEmptyRule } from "../duotecno/types";
|
|
3
|
+
import { err, debug, log } from "../duotecno/logger";
|
|
3
4
|
import { Base } from "./base";
|
|
4
5
|
import { Context } from "./webapp";
|
|
5
|
-
import * as http from "http";
|
|
6
|
-
import { captureRejections } from "events";
|
|
7
6
|
|
|
8
7
|
// Power base class
|
|
9
8
|
// used by Smappee, Shelly PM, P1 Meter, ...
|
|
@@ -33,8 +32,8 @@ export class PowerBase extends Base {
|
|
|
33
32
|
|
|
34
33
|
|
|
35
34
|
|
|
36
|
-
constructor(type:
|
|
37
|
-
super(type
|
|
35
|
+
constructor(type: string, system: System) {
|
|
36
|
+
super(type);
|
|
38
37
|
// called by Base: this.readConfig();
|
|
39
38
|
|
|
40
39
|
this.system = system;
|
|
@@ -92,51 +91,6 @@ export class PowerBase extends Base {
|
|
|
92
91
|
return this.init(false);
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
//////////////
|
|
97
|
-
// http get //
|
|
98
|
-
//////////////
|
|
99
|
-
async get(host: string, path: string): Promise<string> {
|
|
100
|
-
let timer;
|
|
101
|
-
let httpReq: http.ClientRequest;
|
|
102
|
-
return new Promise<any>((resolve, reject) => {
|
|
103
|
-
try {
|
|
104
|
-
timer = setTimeout(() => {
|
|
105
|
-
if (httpReq) {
|
|
106
|
-
httpReq.destroy();
|
|
107
|
-
}
|
|
108
|
-
reject("Request to " + host + path + " timed out");
|
|
109
|
-
}, 4000);
|
|
110
|
-
|
|
111
|
-
httpReq = http.get({ host, path }, (response) => {
|
|
112
|
-
let str = '';
|
|
113
|
-
|
|
114
|
-
// another chunk of data has been received, so append it to `str`
|
|
115
|
-
response.on('data', (chunk) => {
|
|
116
|
-
str += chunk;
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// the whole response has been received,
|
|
120
|
-
// stop the timet and resolve the promise with ithe collected result
|
|
121
|
-
response.on('end', () => {
|
|
122
|
-
if (timer)
|
|
123
|
-
clearTimeout(timer);
|
|
124
|
-
resolve(str);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
}).on('error', (e) => {
|
|
128
|
-
err("power", "http.get failed with " + JSON.stringify(e));
|
|
129
|
-
reject(e);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
} catch(error) {
|
|
133
|
-
err("power", "http.get failed with " + JSON.stringify(error));
|
|
134
|
-
reject(error);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
94
|
evalPower(exp: string): number {
|
|
141
95
|
let parsed = exp.split(/(\+|-)/);
|
|
142
96
|
let result = this.channels[parseInt(parsed[0])||0]?.power ?? 0;
|
package/server/shelly.js
CHANGED
|
@@ -13,10 +13,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.Shelly = void 0;
|
|
16
|
-
const
|
|
16
|
+
const logger_1 = require("../duotecno/logger");
|
|
17
17
|
const powerbase_1 = require("./powerbase");
|
|
18
18
|
class Shelly extends powerbase_1.PowerBase {
|
|
19
|
-
constructor(system
|
|
19
|
+
constructor(system) {
|
|
20
20
|
super("p1", system);
|
|
21
21
|
this.timer = null;
|
|
22
22
|
// init is called by super
|
|
@@ -37,12 +37,12 @@ class Shelly extends powerbase_1.PowerBase {
|
|
|
37
37
|
// }
|
|
38
38
|
subscribe() {
|
|
39
39
|
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
-
(0,
|
|
40
|
+
(0, logger_1.log)("shelly", "connecting to Shelly: " + this.config.address);
|
|
41
41
|
if (this.config.address) {
|
|
42
42
|
this.timer = setInterval(() => {
|
|
43
43
|
this.realtimeCounter++;
|
|
44
44
|
// fetch data from API
|
|
45
|
-
(0,
|
|
45
|
+
(0, logger_1.debug)("shelly", "call shelly API");
|
|
46
46
|
// call process/bindings/rules
|
|
47
47
|
this.applyBindings();
|
|
48
48
|
this.applyRules();
|
package/server/shelly.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { System } from "../duotecno/system";
|
|
6
|
-
import {
|
|
6
|
+
import { P1Config } from "../duotecno/types";
|
|
7
|
+
import { debug, log } from "../duotecno/logger";
|
|
7
8
|
import { PowerBase } from "./powerbase";
|
|
8
9
|
|
|
9
10
|
|
|
@@ -13,7 +14,7 @@ export class Shelly extends PowerBase {
|
|
|
13
14
|
timer: NodeJS.Timer;
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
constructor(system: System
|
|
17
|
+
constructor(system: System) {
|
|
17
18
|
super("p1", system);
|
|
18
19
|
|
|
19
20
|
this.timer = null;
|
package/server/smappee.js
CHANGED
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.Smappee = void 0;
|
|
13
13
|
const mqtt = require("mqtt");
|
|
14
14
|
const types_1 = require("../duotecno/types");
|
|
15
|
+
const logger_1 = require("../duotecno/logger");
|
|
15
16
|
const powerbase_1 = require("./powerbase");
|
|
16
17
|
// Smappee MQTT implementation
|
|
17
18
|
// Johan Coppieters, Jan 2019.
|
|
@@ -26,8 +27,8 @@ const powerbase_1 = require("./powerbase");
|
|
|
26
27
|
//
|
|
27
28
|
// see smappee.json for output
|
|
28
29
|
class Smappee extends powerbase_1.PowerBase {
|
|
29
|
-
constructor(system
|
|
30
|
-
super("smappee", system
|
|
30
|
+
constructor(system) {
|
|
31
|
+
super("smappee", system);
|
|
31
32
|
this.client = null;
|
|
32
33
|
// init is called by super
|
|
33
34
|
}
|
|
@@ -80,15 +81,15 @@ class Smappee extends powerbase_1.PowerBase {
|
|
|
80
81
|
try {
|
|
81
82
|
const client = mqtt.connect('mqtt:' + this.config.address);
|
|
82
83
|
this.client = client;
|
|
83
|
-
(0,
|
|
84
|
+
(0, logger_1.log)("smappee", "connecting to " + 'mqtt:' + this.config.address);
|
|
84
85
|
client.on('connect', () => {
|
|
85
86
|
client.subscribe('servicelocation/' + this.config.uid + '/#', (error) => {
|
|
86
87
|
if (error) {
|
|
87
|
-
(0,
|
|
88
|
+
(0, logger_1.err)("smappee", error.message);
|
|
88
89
|
reject();
|
|
89
90
|
}
|
|
90
91
|
else {
|
|
91
|
-
(0,
|
|
92
|
+
(0, logger_1.log)("smappee", "subscribed to " + 'servicelocation/' + this.config.uid + "/# -- all messages");
|
|
92
93
|
resolve();
|
|
93
94
|
}
|
|
94
95
|
});
|
|
@@ -112,7 +113,7 @@ class Smappee extends powerbase_1.PowerBase {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
catch (error) {
|
|
115
|
-
(0,
|
|
116
|
+
(0, logger_1.err)("smappee", "Error converting incoming : " + topic + " -> " + JSON.stringify(error) + " -> " + buffer.toString());
|
|
116
117
|
}
|
|
117
118
|
});
|
|
118
119
|
}
|
|
@@ -147,7 +148,7 @@ class Smappee extends powerbase_1.PowerBase {
|
|
|
147
148
|
return new Promise((resolve, reject) => {
|
|
148
149
|
try {
|
|
149
150
|
this.client.end(true, () => {
|
|
150
|
-
(0,
|
|
151
|
+
(0, logger_1.log)("smappee", "unsubscribed from the MQTT stream");
|
|
151
152
|
resolve();
|
|
152
153
|
});
|
|
153
154
|
}
|
|
@@ -265,7 +266,7 @@ class Smappee extends powerbase_1.PowerBase {
|
|
|
265
266
|
if (!this.plugs[plugNr])
|
|
266
267
|
this.plugs[plugNr] = this.emptyPlug(plugNr);
|
|
267
268
|
if (this.plugs[plugNr].value != newState) {
|
|
268
|
-
(0,
|
|
269
|
+
(0, logger_1.debug)("smappee", "doPlug, plugNr = " + plugNr + ", received: " + message.value + ", current: " + this.plugs[plugNr].value);
|
|
269
270
|
this.plugs[plugNr].value = newState;
|
|
270
271
|
// send status change to system
|
|
271
272
|
this.system.emitter.emit('plug', types_1.SwitchType.kSmappee, plugNr, newState);
|
package/server/smappee.ts
CHANGED
|
@@ -2,7 +2,8 @@ import * as mqtt from "mqtt";
|
|
|
2
2
|
import { MqttClient } from "mqtt";
|
|
3
3
|
|
|
4
4
|
import { System } from "../duotecno/system";
|
|
5
|
-
import {
|
|
5
|
+
import { SmappeeConfig, SwitchType } from "../duotecno/types";
|
|
6
|
+
import { debug, err, log } from "../duotecno/logger";
|
|
6
7
|
import { PowerBase } from "./powerbase";
|
|
7
8
|
import { Context } from "./webapp";
|
|
8
9
|
|
|
@@ -27,8 +28,8 @@ export class Smappee extends PowerBase {
|
|
|
27
28
|
plugs: { [nodeId: number]: { value: boolean, name: string } };
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
constructor(system: System
|
|
31
|
-
super("smappee", system
|
|
31
|
+
constructor(system: System) {
|
|
32
|
+
super("smappee", system);
|
|
32
33
|
|
|
33
34
|
this.client = null;
|
|
34
35
|
// init is called by super
|