@switchbot/homebridge-switchbot 1.3.1-beta.9 → 1.4.1-beta.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.
Files changed (103) hide show
  1. package/CHANGELOG.md +18 -2
  2. package/config.schema.json +82 -32
  3. package/dist/devices/bots.d.ts +15 -3
  4. package/dist/devices/bots.d.ts.map +1 -1
  5. package/dist/devices/bots.js +227 -165
  6. package/dist/devices/bots.js.map +1 -1
  7. package/dist/devices/colorbulb.d.ts +14 -3
  8. package/dist/devices/colorbulb.d.ts.map +1 -1
  9. package/dist/devices/colorbulb.js +163 -105
  10. package/dist/devices/colorbulb.js.map +1 -1
  11. package/dist/devices/contact.d.ts +13 -3
  12. package/dist/devices/contact.d.ts.map +1 -1
  13. package/dist/devices/contact.js +102 -63
  14. package/dist/devices/contact.js.map +1 -1
  15. package/dist/devices/curtains.d.ts +14 -5
  16. package/dist/devices/curtains.d.ts.map +1 -1
  17. package/dist/devices/curtains.js +180 -140
  18. package/dist/devices/curtains.js.map +1 -1
  19. package/dist/devices/humidifiers.d.ts +14 -3
  20. package/dist/devices/humidifiers.d.ts.map +1 -1
  21. package/dist/devices/humidifiers.js +173 -133
  22. package/dist/devices/humidifiers.js.map +1 -1
  23. package/dist/devices/meters.d.ts +17 -13
  24. package/dist/devices/meters.d.ts.map +1 -1
  25. package/dist/devices/meters.js +150 -105
  26. package/dist/devices/meters.js.map +1 -1
  27. package/dist/devices/motion.d.ts +13 -3
  28. package/dist/devices/motion.d.ts.map +1 -1
  29. package/dist/devices/motion.js +89 -45
  30. package/dist/devices/motion.js.map +1 -1
  31. package/dist/devices/plugs.d.ts +15 -3
  32. package/dist/devices/plugs.d.ts.map +1 -1
  33. package/dist/devices/plugs.js +115 -53
  34. package/dist/devices/plugs.js.map +1 -1
  35. package/dist/irdevices/airconditioners.d.ts +13 -3
  36. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  37. package/dist/irdevices/airconditioners.js +97 -46
  38. package/dist/irdevices/airconditioners.js.map +1 -1
  39. package/dist/irdevices/airpurifiers.d.ts +13 -3
  40. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  41. package/dist/irdevices/airpurifiers.js +85 -31
  42. package/dist/irdevices/airpurifiers.js.map +1 -1
  43. package/dist/irdevices/cameras.d.ts +12 -3
  44. package/dist/irdevices/cameras.d.ts.map +1 -1
  45. package/dist/irdevices/cameras.js +73 -24
  46. package/dist/irdevices/cameras.js.map +1 -1
  47. package/dist/irdevices/fans.d.ts +12 -3
  48. package/dist/irdevices/fans.d.ts.map +1 -1
  49. package/dist/irdevices/fans.js +83 -35
  50. package/dist/irdevices/fans.js.map +1 -1
  51. package/dist/irdevices/lights.d.ts +12 -3
  52. package/dist/irdevices/lights.d.ts.map +1 -1
  53. package/dist/irdevices/lights.js +74 -25
  54. package/dist/irdevices/lights.js.map +1 -1
  55. package/dist/irdevices/others.d.ts +12 -3
  56. package/dist/irdevices/others.d.ts.map +1 -1
  57. package/dist/irdevices/others.js +80 -31
  58. package/dist/irdevices/others.js.map +1 -1
  59. package/dist/irdevices/tvs.d.ts +12 -3
  60. package/dist/irdevices/tvs.d.ts.map +1 -1
  61. package/dist/irdevices/tvs.js +90 -42
  62. package/dist/irdevices/tvs.js.map +1 -1
  63. package/dist/irdevices/vacuumcleaners.d.ts +12 -3
  64. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  65. package/dist/irdevices/vacuumcleaners.js +73 -24
  66. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  67. package/dist/irdevices/waterheaters.d.ts +12 -3
  68. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  69. package/dist/irdevices/waterheaters.js +73 -24
  70. package/dist/irdevices/waterheaters.js.map +1 -1
  71. package/dist/platform.d.ts +10 -10
  72. package/dist/platform.d.ts.map +1 -1
  73. package/dist/platform.js +290 -307
  74. package/dist/platform.js.map +1 -1
  75. package/dist/settings.d.ts +9 -6
  76. package/dist/settings.d.ts.map +1 -1
  77. package/dist/settings.js.map +1 -1
  78. package/nodemon.json +1 -1
  79. package/package.json +6 -6
  80. package/src/devices/bots.ts +221 -152
  81. package/src/devices/colorbulb.ts +172 -108
  82. package/src/devices/contact.ts +109 -64
  83. package/src/devices/curtains.ts +190 -146
  84. package/src/devices/humidifiers.ts +181 -135
  85. package/src/devices/meters.ts +156 -105
  86. package/src/devices/motion.ts +95 -45
  87. package/src/devices/plugs.ts +121 -53
  88. package/src/irdevices/airconditioners.ts +102 -46
  89. package/src/irdevices/airpurifiers.ts +91 -31
  90. package/src/irdevices/cameras.ts +79 -24
  91. package/src/irdevices/fans.ts +89 -36
  92. package/src/irdevices/lights.ts +80 -25
  93. package/src/irdevices/others.ts +86 -31
  94. package/src/irdevices/tvs.ts +96 -42
  95. package/src/irdevices/vacuumcleaners.ts +79 -24
  96. package/src/irdevices/waterheaters.ts +79 -24
  97. package/src/platform.ts +285 -302
  98. package/src/settings.ts +10 -6
  99. package/dist/devices/indoorcam.d.ts +0 -64
  100. package/dist/devices/indoorcam.d.ts.map +0 -1
  101. package/dist/devices/indoorcam.js +0 -249
  102. package/dist/devices/indoorcam.js.map +0 -1
  103. package/src/devices/indoorcam.ts +0 -309
@@ -4,7 +4,7 @@ import Switchbot from 'node-switchbot';
4
4
  import { interval, Subject } from 'rxjs';
5
5
  import { SwitchBotPlatform } from '../platform';
6
6
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
7
- import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
7
+ import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
8
8
  import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, payload } from '../settings';
9
9
 
10
10
  /**
@@ -20,6 +20,7 @@ export class Bot {
20
20
 
21
21
  // Characteristic Values
22
22
  On!: CharacteristicValue;
23
+ OnCached!: CharacteristicValue;
23
24
  BatteryLevel!: CharacteristicValue;
24
25
  StatusLowBattery!: CharacteristicValue;
25
26
 
@@ -35,8 +36,8 @@ export class Bot {
35
36
  battery!: serviceData['battery'];
36
37
 
37
38
  // Config
38
- private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
39
- private readonly debugDebug = this.platform.config.options?.debug === 'debug' || this.platform.debugMode;
39
+ deviceLogging!: string;
40
+ deviceRefreshRate!: number;
40
41
 
41
42
  // Updates
42
43
  botUpdateInProgress!: boolean;
@@ -47,15 +48,21 @@ export class Bot {
47
48
  private accessory: PlatformAccessory,
48
49
  public device: device & devicesConfig,
49
50
  ) {
50
- // Bot Config
51
- this.platform.device(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, mode: ${device.bot?.mode},`
52
- + ` deviceType: ${device.bot?.deviceType})`);
53
-
54
51
  // default placeholders
55
- this.On = false;
52
+ if (this.On === undefined) {
53
+ this.On = false;
54
+ } else {
55
+ this.On = this.accessory.context.On;
56
+ }
57
+ this.refreshRate();
58
+ this.logs();
56
59
  this.BatteryLevel = 100;
57
60
  this.StatusLowBattery = 1;
58
61
 
62
+ // Bot Config
63
+ this.debugLog(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, mode: ${device.bot?.mode},`
64
+ + ` deviceType: ${device.bot?.deviceType})`);
65
+
59
66
  // this is subject we use to track when we need to POST changes to the SwitchBot API
60
67
  this.doBotUpdate = new Subject();
61
68
  this.botUpdateInProgress = false;
@@ -75,7 +82,7 @@ export class Bot {
75
82
  if (device.bot?.deviceType === 'switch') {
76
83
  // If outletService still pressent, then remove first
77
84
  if (this.outletService) {
78
- this.platform.device(`Bot: ${accessory.displayName} Removing Leftover outletService first`);
85
+ this.debugLog(`Bot: ${accessory.displayName} Removing Leftover outletService first`);
79
86
  }
80
87
  this.outletService = this.accessory.getService(this.platform.Service.Outlet);
81
88
  accessory.removeService(this.outletService!);
@@ -84,13 +91,15 @@ export class Bot {
84
91
  (this.switchService =
85
92
  accessory.getService(this.platform.Service.Switch) ||
86
93
  accessory.addService(this.platform.Service.Switch)), `${accessory.displayName} Switch`;
87
- this.platform.log.info(`Bot: ${accessory.displayName} Displaying as Switch`);
94
+ if (this.deviceLogging !== 'none') {
95
+ this.infoLog(`Bot: ${accessory.displayName} Displaying as Switch`);
96
+ }
88
97
 
89
98
  this.switchService?.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
90
99
  } else {
91
100
  // If switchService still pressent, then remove first
92
101
  if (this.switchService) {
93
- this.platform.device(`Bot: ${accessory.displayName} Removing Leftover switchService first`);
102
+ this.debugLog(`Bot: ${accessory.displayName} Removing Leftover switchService first`);
94
103
  }
95
104
  this.switchService = this.accessory.getService(this.platform.Service.Switch);
96
105
  accessory.removeService(this.switchService!);
@@ -99,7 +108,7 @@ export class Bot {
99
108
  (this.outletService =
100
109
  accessory.getService(this.platform.Service.Outlet) ||
101
110
  accessory.addService(this.platform.Service.Outlet)), `${accessory.displayName} Outlet`;
102
- this.platform.log.info(`Bot: ${accessory.displayName} Displaying as Outlet`);
111
+ this.infoLog(`Bot: ${accessory.displayName} Displaying as Outlet`);
103
112
 
104
113
  this.outletService?.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
105
114
  }
@@ -125,7 +134,7 @@ export class Bot {
125
134
  this.updateHomeKitCharacteristics();
126
135
 
127
136
  // Start an update interval
128
- interval(this.platform.config.options!.refreshRate! * 1000)
137
+ interval(this.deviceRefreshRate * 1000)
129
138
  .pipe(skipWhile(() => this.botUpdateInProgress))
130
139
  .subscribe(() => {
131
140
  this.refreshStatus();
@@ -144,13 +153,13 @@ export class Bot {
144
153
  try {
145
154
  await this.pushChanges();
146
155
  } catch (e: any) {
147
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges`);
148
- if (this.deviceDebug) {
149
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges,`
156
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges`);
157
+ if (this.deviceLogging === 'debug') {
158
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges,`
150
159
  + ` Error Message: ${JSON.stringify(e.message)}`);
151
160
  }
152
- if (this.debugDebug) {
153
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges,`
161
+ if (this.platform.debugMode) {
162
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges,`
154
163
  + ` Error: ${JSON.stringify(e)}`);
155
164
  }
156
165
  }
@@ -158,6 +167,24 @@ export class Bot {
158
167
  });
159
168
  }
160
169
 
170
+ refreshRate() {
171
+ if (this.device.refreshRate) {
172
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
173
+ } else if (this.platform.config.options!.refreshRate) {
174
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
175
+ }
176
+ }
177
+
178
+ logs() {
179
+ if (this.device.logging) {
180
+ this.deviceLogging = this.accessory.context.logging = this.device.logging;
181
+ } else if (this.platform.config.options?.logging) {
182
+ this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
183
+ } else {
184
+ this.deviceLogging = this.accessory.context.logging = 'standard';
185
+ }
186
+ }
187
+
161
188
  /**
162
189
  * Parse the device status from the SwitchBot api
163
190
  */
@@ -170,13 +197,13 @@ export class Bot {
170
197
  }
171
198
 
172
199
  private async BLEparseStatus() {
173
- this.platform.debug(`Bot: ${this.accessory.displayName} BLE parseStatus`);
200
+ this.debugLog(`Bot: ${this.accessory.displayName} BLE parseStatus`);
174
201
  // BLEmode (true if Switch Mode) | (false if Press Mode)
175
202
  if (this.mode) {
176
203
  this.On = Boolean(this.state);
177
- this.platform.device(`Bot: ${this.accessory.displayName} Switch Mode, mode: ${JSON.stringify(this.mode)}, On: ${JSON.stringify(this.On)}`);
204
+ this.debugLog(`Bot: ${this.accessory.displayName} Switch Mode, mode: ${JSON.stringify(this.mode)}, On: ${JSON.stringify(this.On)}`);
178
205
  } else {
179
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode, mode: ${JSON.stringify(this.mode)}, On: ${JSON.stringify(this.On)}`);
206
+ this.debugLog(`Bot: ${this.accessory.displayName} Press Mode, mode: ${JSON.stringify(this.mode)}, On: ${JSON.stringify(this.On)}`);
180
207
  }
181
208
 
182
209
  this.BatteryLevel = Number(this.battery);
@@ -188,12 +215,12 @@ export class Bot {
188
215
  if (Number.isNaN(this.BatteryLevel)) {
189
216
  this.BatteryLevel = 100;
190
217
  }
191
- this.platform.debug(`Bot: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
218
+ this.debugLog(`Bot: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
192
219
  }
193
220
 
194
221
  private async openAPIparseStatus() {
195
222
  if (this.platform.config.credentials?.openToken) {
196
- this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI parseStatus`);
223
+ this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI parseStatus`);
197
224
  if (this.device.bot?.mode === 'press') {
198
225
  this.On = false;
199
226
  } else {
@@ -203,7 +230,7 @@ export class Bot {
203
230
  this.On = false;
204
231
  }
205
232
  }
206
- this.platform.debug(`Bot ${this.accessory.displayName} On: ${this.On}`);
233
+ this.debugLog(`Bot ${this.accessory.displayName} On: ${this.On}`);
207
234
  }
208
235
  }
209
236
 
@@ -221,12 +248,12 @@ export class Bot {
221
248
  private connectBLE() {
222
249
  const switchbot = new Switchbot();
223
250
  this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
224
- this.platform.device(`Bot: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
251
+ this.debugLog(`Bot: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
225
252
  return switchbot;
226
253
  }
227
254
 
228
255
  private async BLERefreshStatus() {
229
- this.platform.debug(`Bot: ${this.accessory.displayName} BLE refreshStatus`);
256
+ this.debugLog(`Bot: ${this.accessory.displayName} BLE refreshStatus`);
230
257
  // eslint-disable-next-line @typescript-eslint/no-var-requires
231
258
  const switchbot = this.connectBLE();
232
259
  // Start to monitor advertisement packets
@@ -240,16 +267,16 @@ export class Bot {
240
267
  this.mode = ad.serviceData.mode;
241
268
  this.state = ad.serviceData.state;
242
269
  this.battery = ad.serviceData.battery;
243
- this.platform.device(`Bot: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
244
- this.platform.device(`Bot: ${this.accessory.displayName}, model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName},`
270
+ this.debugLog(`Bot: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
271
+ this.debugLog(`Bot: ${this.accessory.displayName}, model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName},`
245
272
  + ` mode: ${ad.serviceData.mode}, state: ${ad.serviceData.state}, battery: ${ad.serviceData.battery}`);
246
273
 
247
274
  if (this.serviceData) {
248
275
  this.connected = true;
249
- this.platform.device(`Bot: ${this.accessory.displayName} connected: ${this.connected}`);
276
+ this.debugLog(`Bot: ${this.accessory.displayName} connected: ${this.connected}`);
250
277
  } else {
251
278
  this.connected = false;
252
- this.platform.device(`Bot: ${this.accessory.displayName} connected: ${this.connected}`);
279
+ this.debugLog(`Bot: ${this.accessory.displayName} connected: ${this.connected}`);
253
280
  }
254
281
  };
255
282
  // Wait 10 seconds
@@ -261,36 +288,36 @@ export class Bot {
261
288
  this.parseStatus();
262
289
  this.updateHomeKitCharacteristics();
263
290
  } else {
264
- this.platform.log.error(`Bot: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
291
+ this.errorLog(`Bot: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
265
292
  if (this.platform.config.credentials?.openToken) {
266
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
293
+ this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
267
294
  await this.openAPIRefreshStatus();
268
295
  }
269
296
  }
270
297
  }).catch(async (e: any) => {
271
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
272
- if (this.deviceDebug) {
273
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
298
+ this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
299
+ if (this.deviceLogging === 'debug') {
300
+ this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
274
301
  + ` Error Message: ${JSON.stringify(e.message)}`);
275
302
  }
276
- if (this.debugDebug) {
277
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
303
+ if (this.platform.debugMode) {
304
+ this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
278
305
  + ` Error: ${JSON.stringify(e)}`);
279
306
  }
280
307
  if (this.platform.config.credentials?.openToken) {
281
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
308
+ this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
282
309
  await this.openAPIRefreshStatus();
283
310
  }
284
- this.apiError(e);
311
+ this.apiError();
285
312
  });
286
313
  }
287
314
 
288
315
  private async openAPIRefreshStatus() {
289
316
  if (this.platform.config.credentials?.openToken) {
290
- this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI refreshStatus`);
317
+ this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI refreshStatus`);
291
318
  try {
292
319
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
293
- this.platform.device(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
320
+ this.debugLog(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
294
321
  /*this.deviceStatus = {
295
322
  statusCode: 100,
296
323
  body: {
@@ -304,16 +331,16 @@ export class Bot {
304
331
  this.parseStatus();
305
332
  this.updateHomeKitCharacteristics();
306
333
  } catch (e: any) {
307
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
308
- if (this.deviceDebug) {
309
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
334
+ this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
335
+ if (this.deviceLogging === 'debug') {
336
+ this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
310
337
  + ` Error Message: ${JSON.stringify(e.message)}`);
311
338
  }
312
- if (this.debugDebug) {
313
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
339
+ if (this.platform.debugMode) {
340
+ this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
314
341
  + ` Error: ${JSON.stringify(e)}`);
315
342
  }
316
- this.apiError(e);
343
+ this.apiError();
317
344
  }
318
345
  }
319
346
  }
@@ -340,58 +367,62 @@ export class Bot {
340
367
  }
341
368
 
342
369
  private async BLEpushChanges() {
343
- this.platform.debug(`Bot: ${this.accessory.displayName} BLE pushChanges`);
344
- const switchbot = this.connectBLE();
345
- if (this.device.bot?.mode === 'press') {
346
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
347
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac })
348
- .then((device_list: { press: (arg0: { id: string | undefined; }) => any; }[]) => {
349
- this.platform.log.info(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
350
- return device_list[0].press({ id: this.device.bleMac });
370
+ if (this.On !== this.OnCached) {
371
+ this.debugLog(`Bot: ${this.accessory.displayName} BLE pushChanges`);
372
+ const switchbot = this.connectBLE();
373
+ if (this.device.bot?.mode === 'press') {
374
+ this.debugLog(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
375
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac })
376
+ .then((device_list: { press: (arg0: { id: string | undefined; }) => any; }[]) => {
377
+ this.infoLog(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
378
+ return device_list[0].press({ id: this.device.bleMac });
379
+ }).then(() => {
380
+ this.debugLog(`Bot: ${this.accessory.displayName} Done.`);
381
+ }).catch(async (e: any) => {
382
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
383
+ if (this.deviceLogging === 'debug') {
384
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
385
+ + ` Error Message: ${JSON.stringify(e.message)}`);
386
+ }
387
+ if (this.platform.debugMode) {
388
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
389
+ + ` Error: ${JSON.stringify(e)}`);
390
+ }
391
+ if (this.platform.config.credentials?.openToken) {
392
+ this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
393
+ await this.openAPIpushChanges();
394
+ }
395
+ this.apiError();
396
+ });
397
+ } else if (this.device.bot?.mode === 'switch') {
398
+ this.debugLog(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
399
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
400
+ this.infoLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
401
+ return this.turnOnOff(device_list);
351
402
  }).then(() => {
352
- this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
403
+ this.debugLog(`Bot: ${this.accessory.displayName} Done.`);
353
404
  }).catch(async (e: any) => {
354
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
355
- if (this.deviceDebug) {
356
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
405
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
406
+ if (this.deviceLogging === 'debug') {
407
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
357
408
  + ` Error Message: ${JSON.stringify(e.message)}`);
358
409
  }
359
- if (this.debugDebug) {
360
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
410
+ if (this.platform.debugMode) {
411
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
361
412
  + ` Error: ${JSON.stringify(e)}`);
362
413
  }
363
414
  if (this.platform.config.credentials?.openToken) {
364
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
415
+ this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
365
416
  await this.openAPIpushChanges();
366
417
  }
367
- this.apiError(e);
418
+ this.apiError();
368
419
  });
369
- } else if (this.device.bot?.mode === 'switch') {
370
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
371
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
372
- this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.On}`);
373
- return this.turnOnOff(device_list);
374
- }).then(() => {
375
- this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
376
- }).catch(async (e: any) => {
377
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
378
- if (this.deviceDebug) {
379
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
380
- + ` Error Message: ${JSON.stringify(e.message)}`);
381
- }
382
- if (this.debugDebug) {
383
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
384
- + ` Error: ${JSON.stringify(e)}`);
385
- }
386
- if (this.platform.config.credentials?.openToken) {
387
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
388
- await this.openAPIpushChanges();
389
- }
390
- this.apiError(e);
391
- });
392
- } else {
393
- this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
420
+ } else {
421
+ this.errorLog(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
422
+ }
394
423
  }
424
+ this.OnCached = this.On;
425
+ this.accessory.context.On = this.OnCached;
395
426
  }
396
427
 
397
428
  private turnOnOff(device_list: any) {
@@ -405,46 +436,50 @@ export class Bot {
405
436
  private async openAPIpushChanges() {
406
437
  if (this.platform.config.credentials?.openToken) {
407
438
  try {
408
- this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
409
- const payload = {
410
- commandType: 'command',
411
- parameter: 'default',
412
- } as payload;
413
-
414
- if (this.device.bot?.mode === 'switch' && this.On) {
415
- payload.command = 'turnOn';
416
- this.On = true;
417
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
418
- } else if (this.device.bot?.mode === 'switch' && !this.On) {
419
- payload.command = 'turnOff';
420
- this.On = false;
421
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
422
- } else if (this.device.bot?.mode === 'press') {
423
- payload.command = 'press';
424
- this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
425
- this.On = false;
426
- } else {
427
- throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
428
- }
439
+ if (this.On !== this.OnCached) {
440
+ this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
441
+ const payload = {
442
+ commandType: 'command',
443
+ parameter: 'default',
444
+ } as payload;
445
+
446
+ if (this.device.bot?.mode === 'switch' && this.On) {
447
+ payload.command = 'turnOn';
448
+ this.On = true;
449
+ this.debugLog(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
450
+ } else if (this.device.bot?.mode === 'switch' && !this.On) {
451
+ payload.command = 'turnOff';
452
+ this.On = false;
453
+ this.debugLog(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
454
+ } else if (this.device.bot?.mode === 'press') {
455
+ payload.command = 'press';
456
+ this.debugLog(`Bot: ${this.accessory.displayName} Press Mode`);
457
+ this.On = false;
458
+ } else {
459
+ throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
460
+ }
429
461
 
430
- this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
431
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
462
+ this.infoLog(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
463
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
432
464
 
433
- // Make the API request
434
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
435
- this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
436
- this.statusCode(push);
465
+ // Make the API request
466
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
467
+ this.debugLog(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
468
+ this.statusCode(push);
469
+ this.OnCached = this.On;
470
+ this.accessory.context.On = this.OnCached;
471
+ }
437
472
  } catch (e: any) {
438
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
439
- if (this.deviceDebug) {
440
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
473
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
474
+ if (this.deviceLogging === 'debug') {
475
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
441
476
  + ` Error Message: ${JSON.stringify(e.message)}`);
442
477
  }
443
- if (this.debugDebug) {
444
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
478
+ if (this.platform.debugMode) {
479
+ this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
445
480
  + ` Error: ${JSON.stringify(e)}`);
446
481
  }
447
- this.apiError(e);
482
+ this.apiError();
448
483
  }
449
484
  }
450
485
  }
@@ -454,75 +489,74 @@ export class Bot {
454
489
  */
455
490
  updateHomeKitCharacteristics() {
456
491
  if (this.On === undefined) {
457
- this.platform.debug(`Bot: ${this.accessory.displayName} On: ${this.On}`);
492
+ this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
458
493
  } else {
459
494
  if (this.device.bot?.deviceType === 'switch') {
460
495
  this.switchService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
461
496
  } else {
462
497
  this.outletService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
463
498
  }
464
- this.platform.device(`Bot: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
499
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
465
500
  }
466
501
  if (this.device.ble) {
467
502
  if (this.BatteryLevel === undefined) {
468
- this.platform.debug(`Bot: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
503
+ this.debugLog(`Bot: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
469
504
  } else {
470
505
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
471
- this.platform.device(`Bot: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
506
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
472
507
  }
473
508
  if (this.StatusLowBattery === undefined) {
474
- this.platform.debug(`Bot: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
509
+ this.debugLog(`Bot: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
475
510
  } else {
476
511
  this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
477
- this.platform.device(`Bot: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
512
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
478
513
  }
479
514
  }
480
515
  }
481
516
 
482
- public apiError(e: any) {
483
- if (this.device.bot?.deviceType === 'switch') {
484
- this.switchService?.updateCharacteristic(this.platform.Characteristic.On, e);
485
- } else {
486
- this.outletService?.updateCharacteristic(this.platform.Characteristic.On, e);
487
- }
488
- if (this.device.ble) {
489
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
490
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
491
- }
517
+ public apiError() {
518
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
492
519
  }
493
520
 
494
521
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
495
522
  switch (push.data.statusCode) {
496
523
  case 151:
497
- this.platform.log.error(`Bot: ${this.accessory.displayName} Command not supported by this device type.`);
524
+ this.errorLog(`Bot: ${this.accessory.displayName} Command not supported by this device type.`);
498
525
  break;
499
526
  case 152:
500
- this.platform.log.error(`Bot: ${this.accessory.displayName} Device not found.`);
527
+ this.errorLog(`Bot: ${this.accessory.displayName} Device not found.`);
501
528
  break;
502
529
  case 160:
503
- this.platform.log.error(`Bot: ${this.accessory.displayName} Command is not supported.`);
530
+ this.errorLog(`Bot: ${this.accessory.displayName} Command is not supported.`);
504
531
  break;
505
532
  case 161:
506
- this.platform.log.error(`Bot: ${this.accessory.displayName} Device is offline.`);
507
- if (this.device.offline) {
508
- this.On = false;
509
- }
533
+ this.errorLog(`Bot: ${this.accessory.displayName} Device is offline.`);
534
+ this.offlineOff();
510
535
  break;
511
536
  case 171:
512
- this.platform.log.error(`Bot: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
513
- if (this.device.offline) {
514
- this.On = false;
515
- }
537
+ this.errorLog(`Bot: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
538
+ this.offlineOff();
516
539
  break;
517
540
  case 190:
518
- this.platform.log.error(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
541
+ this.errorLog(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
519
542
  + ` Or command: ${JSON.stringify(push.data)} format is invalid`);
520
543
  break;
521
544
  case 100:
522
- this.platform.debug(`Bot: ${this.accessory.displayName} Command successfully sent.`);
545
+ this.debugLog(`Bot: ${this.accessory.displayName} Command successfully sent.`);
523
546
  break;
524
547
  default:
525
- this.platform.debug(`Bot: ${this.accessory.displayName} Unknown statusCode.`);
548
+ this.debugLog(`Bot: ${this.accessory.displayName} Unknown statusCode.`);
549
+ }
550
+ }
551
+
552
+ private offlineOff() {
553
+ if (this.device.offline) {
554
+ this.On = false;
555
+ if (this.device.bot?.deviceType === 'switch') {
556
+ this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
557
+ } else {
558
+ this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
559
+ }
526
560
  }
527
561
  }
528
562
 
@@ -530,8 +564,43 @@ export class Bot {
530
564
  * Handle requests to set the "On" characteristic
531
565
  */
532
566
  private handleOnSet(value: CharacteristicValue) {
533
- this.platform.debug(`Bot: ${this.accessory.displayName} On: ${value}`);
567
+ this.debugLog(`Bot: ${this.accessory.displayName} On: ${value}`);
534
568
  this.On = value;
535
569
  this.doBotUpdate.next();
536
570
  }
571
+
572
+ /**
573
+ * Logging for Device
574
+ */
575
+ infoLog(...log: any[]) {
576
+ if (this.enablingDeviceLogging()) {
577
+ this.platform.log.info(String(...log));
578
+ }
579
+ }
580
+
581
+ warnLog(...log: any[]) {
582
+ if (this.enablingDeviceLogging()) {
583
+ this.platform.log.warn(String(...log));
584
+ }
585
+ }
586
+
587
+ errorLog(...log: any[]) {
588
+ if (this.enablingDeviceLogging()) {
589
+ this.platform.log.error(String(...log));
590
+ }
591
+ }
592
+
593
+ debugLog(...log: any[]) {
594
+ if (this.enablingDeviceLogging()) {
595
+ if (this.deviceLogging === 'debug') {
596
+ this.platform.log.info('[DEBUG]', String(...log));
597
+ } else {
598
+ this.platform.log.debug(String(...log));
599
+ }
600
+ }
601
+ }
602
+
603
+ enablingDeviceLogging(): boolean {
604
+ return this.deviceLogging === 'debug' || this.deviceLogging === 'standard';
605
+ }
537
606
  }