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 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,
@@ -18,7 +18,7 @@ exports.logSettings = {
18
18
  "protocol": LogLevel.noLog,
19
19
  "webapp": LogLevel.log,
20
20
  "p1": LogLevel.log,
21
- "shelly": LogLevel.debug,
21
+ "shelly": LogLevel.log,
22
22
  "power": LogLevel.log,
23
23
  "smartapp": LogLevel.log
24
24
  };
@@ -13,7 +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
+ "shelly": LogLevel.log,
17
17
  "power": LogLevel.log,
18
18
  "smartapp": LogLevel.log
19
19
  };
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
- config = exports.Sanitizers.powerbase(config);
273
- return config;
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
- export interface BaseConfig {
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 = Sanitizers.powerbase(config);
457
+ if (!config) config = <P1Config>{};
458
+ const cfg = Sanitizers.powerbase(config);
453
459
 
454
- return config;
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.1",
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["system"] = logger_1.LogLevel.debug;
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["system"] = LogLevel.debug;
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
  }
@@ -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 ((!isNaN(power)) && (isNaN(b.power) || (Math.abs(b.power - power) > Math.abs(b.power * kPercentChange)))) {
103
- (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 * kPercentChange));
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("homebridge", "set unit " + b.name + " to " + value);
124
+ // debug("power", "set unit " + b.name + " to " + value);
108
125
  })
109
- .catch((e) => (0, logger_1.err)(this.type, e));
110
- }
111
- else {
112
- (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 * kPercentChange));
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 (" + value + ") " + binding.masterAddress + " - " + binding.logicalNodeAddress + ";" + binding.logicalAddress + " *****");
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 % 30 === 0) {
135
- (0, logger_1.log)("power", this.type + " > processRealTime: totalPower = " + this.realtime.totalPower +
136
- ", export = " + this.realtime.totalExportEnergy +
137
- ", import = " + this.realtime.totalImportEnergy);
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
- else
197
- throw new Error("***** UNIT NOT FOUND for action (" + action.value + ") " + action.masterAddress + " - " + action.logicalNodeAddress + ";" + action.logicalAddress + " *****");
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
  //
@@ -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 ((!isNaN(power)) && (isNaN(b.power) || (Math.abs(b.power - power) > Math.abs(b.power * kPercentChange)))) {
120
- 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 * kPercentChange))
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("homebridge", "set unit " + b.name + " to " + value);
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 + " (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) + " > threshold: " + Math.abs(b.power * kPercentChange))
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), binding.logicalNodeAddress, binding.logicalAddress);
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 (" + value + ") " + binding.masterAddress + " - " + binding.logicalNodeAddress + ";" + binding.logicalAddress + " *****");
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 % 30 === 0) {
153
- log("power", this.type + " > processRealTime: totalPower = " + this.realtime.totalPower +
154
- ", export = " + this.realtime.totalExportEnergy +
155
- ", import = " + this.realtime.totalImportEnergy);
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
- ", power = " + power + ", channel = " + rule.channel +
206
- " -> current = " + newCurrent +
207
- " (unit: " + rule.actions[newCurrent].name + ", value: " + rule.actions[newCurrent].value + ")");
208
- rule.current = newCurrent;})
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
- else
219
- throw new Error("***** UNIT NOT FOUND for action (" + action.value + ") " + action.masterAddress + " - " + action.logicalNodeAddress + ";" + action.logicalAddress + " *****");
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
@@ -167,7 +167,7 @@ class Shelly extends powerbase_1.PowerBase {
167
167
  return true;
168
168
  }
169
169
  catch (error) {
170
- (0, logger_1.err)("shelly", error.message);
170
+ (0, logger_1.err)("shelly", error.message || error);
171
171
  return false;
172
172
  }
173
173
  });
package/server/shelly.ts CHANGED
@@ -182,7 +182,7 @@ export class Shelly extends PowerBase {
182
182
  return true;
183
183
 
184
184
  } catch(error) {
185
- err("shelly", error.message);
185
+ err("shelly", error.message || error);
186
186
  return false;
187
187
  }
188
188
  }