@switchbot/homebridge-switchbot 1.3.1-beta.7 → 1.4.1-beta.0

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 (101) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/config.schema.json +9 -22
  3. package/dist/devices/bots.d.ts +3 -1
  4. package/dist/devices/bots.d.ts.map +1 -1
  5. package/dist/devices/bots.js +114 -97
  6. package/dist/devices/bots.js.map +1 -1
  7. package/dist/devices/colorbulb.d.ts +2 -1
  8. package/dist/devices/colorbulb.d.ts.map +1 -1
  9. package/dist/devices/colorbulb.js +26 -16
  10. package/dist/devices/colorbulb.js.map +1 -1
  11. package/dist/devices/contact.d.ts +1 -1
  12. package/dist/devices/contact.d.ts.map +1 -1
  13. package/dist/devices/contact.js +5 -15
  14. package/dist/devices/contact.js.map +1 -1
  15. package/dist/devices/curtains.d.ts +1 -1
  16. package/dist/devices/curtains.d.ts.map +1 -1
  17. package/dist/devices/curtains.js +7 -16
  18. package/dist/devices/curtains.js.map +1 -1
  19. package/dist/devices/humidifiers.d.ts +2 -1
  20. package/dist/devices/humidifiers.d.ts.map +1 -1
  21. package/dist/devices/humidifiers.js +18 -20
  22. package/dist/devices/humidifiers.js.map +1 -1
  23. package/dist/devices/indoorcam.d.ts +1 -1
  24. package/dist/devices/indoorcam.d.ts.map +1 -1
  25. package/dist/devices/indoorcam.js +11 -5
  26. package/dist/devices/indoorcam.js.map +1 -1
  27. package/dist/devices/meters.d.ts +6 -12
  28. package/dist/devices/meters.d.ts.map +1 -1
  29. package/dist/devices/meters.js +58 -62
  30. package/dist/devices/meters.js.map +1 -1
  31. package/dist/devices/motion.d.ts +1 -1
  32. package/dist/devices/motion.d.ts.map +1 -1
  33. package/dist/devices/motion.js +4 -9
  34. package/dist/devices/motion.js.map +1 -1
  35. package/dist/devices/plugs.d.ts +3 -1
  36. package/dist/devices/plugs.d.ts.map +1 -1
  37. package/dist/devices/plugs.js +39 -20
  38. package/dist/devices/plugs.js.map +1 -1
  39. package/dist/irdevices/airconditioners.d.ts +3 -1
  40. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  41. package/dist/irdevices/airconditioners.js +20 -9
  42. package/dist/irdevices/airconditioners.js.map +1 -1
  43. package/dist/irdevices/airpurifiers.d.ts +3 -1
  44. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  45. package/dist/irdevices/airpurifiers.js +20 -6
  46. package/dist/irdevices/airpurifiers.js.map +1 -1
  47. package/dist/irdevices/cameras.d.ts +2 -1
  48. package/dist/irdevices/cameras.d.ts.map +1 -1
  49. package/dist/irdevices/cameras.js +12 -3
  50. package/dist/irdevices/cameras.js.map +1 -1
  51. package/dist/irdevices/fans.d.ts +2 -1
  52. package/dist/irdevices/fans.d.ts.map +1 -1
  53. package/dist/irdevices/fans.js +12 -5
  54. package/dist/irdevices/fans.js.map +1 -1
  55. package/dist/irdevices/lights.d.ts +2 -1
  56. package/dist/irdevices/lights.d.ts.map +1 -1
  57. package/dist/irdevices/lights.js +12 -3
  58. package/dist/irdevices/lights.js.map +1 -1
  59. package/dist/irdevices/others.d.ts +2 -1
  60. package/dist/irdevices/others.d.ts.map +1 -1
  61. package/dist/irdevices/others.js +12 -3
  62. package/dist/irdevices/others.js.map +1 -1
  63. package/dist/irdevices/tvs.d.ts +2 -1
  64. package/dist/irdevices/tvs.d.ts.map +1 -1
  65. package/dist/irdevices/tvs.js +12 -4
  66. package/dist/irdevices/tvs.js.map +1 -1
  67. package/dist/irdevices/vacuumcleaners.d.ts +2 -1
  68. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  69. package/dist/irdevices/vacuumcleaners.js +12 -3
  70. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  71. package/dist/irdevices/waterheaters.d.ts +2 -1
  72. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  73. package/dist/irdevices/waterheaters.js +12 -3
  74. package/dist/irdevices/waterheaters.js.map +1 -1
  75. package/dist/platform.d.ts.map +1 -1
  76. package/dist/platform.js +46 -2
  77. package/dist/platform.js.map +1 -1
  78. package/dist/settings.d.ts +6 -5
  79. package/dist/settings.d.ts.map +1 -1
  80. package/dist/settings.js.map +1 -1
  81. package/package.json +7 -7
  82. package/src/devices/bots.ts +95 -77
  83. package/src/devices/colorbulb.ts +27 -17
  84. package/src/devices/contact.ts +6 -16
  85. package/src/devices/curtains.ts +8 -17
  86. package/src/devices/humidifiers.ts +20 -21
  87. package/src/devices/indoorcam.ts +12 -6
  88. package/src/devices/meters.ts +60 -64
  89. package/src/devices/motion.ts +5 -10
  90. package/src/devices/plugs.ts +43 -22
  91. package/src/irdevices/airconditioners.ts +21 -10
  92. package/src/irdevices/airpurifiers.ts +22 -7
  93. package/src/irdevices/cameras.ts +14 -4
  94. package/src/irdevices/fans.ts +14 -6
  95. package/src/irdevices/lights.ts +14 -4
  96. package/src/irdevices/others.ts +14 -4
  97. package/src/irdevices/tvs.ts +14 -5
  98. package/src/irdevices/vacuumcleaners.ts +14 -4
  99. package/src/irdevices/waterheaters.ts +14 -4
  100. package/src/platform.ts +37 -2
  101. package/src/settings.ts +7 -5
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Homebridge SwitchBot",
3
3
  "name": "@switchbot/homebridge-switchbot",
4
- "version": "1.3.1-beta.7",
4
+ "version": "1.4.1-beta.0",
5
5
  "description": "The [Homebridge](https://homebridge.io) SwitchBot plugin allows you to access your [SwitchBot](https://www.switch-bot.com) device(s) from HomeKit.",
6
6
  "author": "SwitchBot <support@wondertechlabs.com> (https://github.com/SwitchBot)",
7
7
  "license": "ISC",
@@ -53,16 +53,16 @@
53
53
  "rxjs": "^7.4.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@types/node": "^16.11.11",
57
- "@typescript-eslint/eslint-plugin": "^5.5.0",
58
- "@typescript-eslint/parser": "^5.5.0",
59
- "eslint": "^8.4.0",
56
+ "@types/node": "^17.0.0",
57
+ "@typescript-eslint/eslint-plugin": "^5.7.0",
58
+ "@typescript-eslint/parser": "^5.7.0",
59
+ "eslint": "^8.4.1",
60
60
  "homebridge": "^1.3.8",
61
61
  "nodemon": "^2.0.15",
62
- "npm-check-updates": "^12.0.2",
62
+ "npm-check-updates": "^12.0.5",
63
63
  "rimraf": "^3.0.2",
64
64
  "ts-node": "^10.4.0",
65
- "typescript": "^4.5.2",
65
+ "typescript": "^4.5.4",
66
66
  "typescript-axios-wb": "^1.0.3"
67
67
  }
68
68
  }
@@ -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
 
@@ -48,11 +49,15 @@ export class Bot {
48
49
  public device: device & devicesConfig,
49
50
  ) {
50
51
  // Bot Config
51
- this.platform.device(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, mode: ${device.bot?.mode},`
52
+ this.platform.device(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, mode: ${device.bot?.mode},`
52
53
  + ` deviceType: ${device.bot?.deviceType})`);
53
54
 
54
55
  // default placeholders
55
- this.On = false;
56
+ if (this.On === undefined) {
57
+ this.On = false;
58
+ } else {
59
+ this.On = this.accessory.context.On;
60
+ }
56
61
  this.BatteryLevel = 100;
57
62
  this.StatusLowBattery = 1;
58
63
 
@@ -281,7 +286,7 @@ export class Bot {
281
286
  this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
282
287
  await this.openAPIRefreshStatus();
283
288
  }
284
- this.apiError(e);
289
+ this.apiError();
285
290
  });
286
291
  }
287
292
 
@@ -313,7 +318,7 @@ export class Bot {
313
318
  this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
314
319
  + ` Error: ${JSON.stringify(e)}`);
315
320
  }
316
- this.apiError(e);
321
+ this.apiError();
317
322
  }
318
323
  }
319
324
  }
@@ -340,14 +345,38 @@ export class Bot {
340
345
  }
341
346
 
342
347
  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 });
348
+ if (this.On !== this.OnCached) {
349
+ this.platform.debug(`Bot: ${this.accessory.displayName} BLE pushChanges`);
350
+ const switchbot = this.connectBLE();
351
+ if (this.device.bot?.mode === 'press') {
352
+ this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
353
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac })
354
+ .then((device_list: { press: (arg0: { id: string | undefined; }) => any; }[]) => {
355
+ this.platform.log.info(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
356
+ return device_list[0].press({ id: this.device.bleMac });
357
+ }).then(() => {
358
+ this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
359
+ }).catch(async (e: any) => {
360
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
361
+ if (this.deviceDebug) {
362
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
363
+ + ` Error Message: ${JSON.stringify(e.message)}`);
364
+ }
365
+ if (this.debugDebug) {
366
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
367
+ + ` Error: ${JSON.stringify(e)}`);
368
+ }
369
+ if (this.platform.config.credentials?.openToken) {
370
+ this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
371
+ await this.openAPIpushChanges();
372
+ }
373
+ this.apiError();
374
+ });
375
+ } else if (this.device.bot?.mode === 'switch') {
376
+ this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
377
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
378
+ this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.On}`);
379
+ return this.turnOnOff(device_list);
351
380
  }).then(() => {
352
381
  this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
353
382
  }).catch(async (e: any) => {
@@ -364,34 +393,14 @@ export class Bot {
364
393
  this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
365
394
  await this.openAPIpushChanges();
366
395
  }
367
- this.apiError(e);
396
+ this.apiError();
368
397
  });
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}`);
398
+ } else {
399
+ this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
400
+ }
394
401
  }
402
+ this.OnCached = this.On;
403
+ this.accessory.context.On = this.OnCached;
395
404
  }
396
405
 
397
406
  private turnOnOff(device_list: any) {
@@ -405,35 +414,39 @@ export class Bot {
405
414
  private async openAPIpushChanges() {
406
415
  if (this.platform.config.credentials?.openToken) {
407
416
  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
- }
417
+ if (this.On !== this.OnCached) {
418
+ this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
419
+ const payload = {
420
+ commandType: 'command',
421
+ parameter: 'default',
422
+ } as payload;
423
+
424
+ if (this.device.bot?.mode === 'switch' && this.On) {
425
+ payload.command = 'turnOn';
426
+ this.On = true;
427
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
428
+ } else if (this.device.bot?.mode === 'switch' && !this.On) {
429
+ payload.command = 'turnOff';
430
+ this.On = false;
431
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
432
+ } else if (this.device.bot?.mode === 'press') {
433
+ payload.command = 'press';
434
+ this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
435
+ this.On = false;
436
+ } else {
437
+ throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
438
+ }
429
439
 
430
- this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
431
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
440
+ this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
441
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
432
442
 
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);
443
+ // Make the API request
444
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
445
+ this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
446
+ this.statusCode(push);
447
+ this.OnCached = this.On;
448
+ this.accessory.context.On = this.OnCached;
449
+ }
437
450
  } catch (e: any) {
438
451
  this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
439
452
  if (this.deviceDebug) {
@@ -444,7 +457,7 @@ export class Bot {
444
457
  this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
445
458
  + ` Error: ${JSON.stringify(e)}`);
446
459
  }
447
- this.apiError(e);
460
+ this.apiError();
448
461
  }
449
462
  }
450
463
  }
@@ -479,16 +492,8 @@ export class Bot {
479
492
  }
480
493
  }
481
494
 
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
- }
495
+ public apiError() {
496
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
492
497
  }
493
498
 
494
499
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
@@ -504,9 +509,11 @@ export class Bot {
504
509
  break;
505
510
  case 161:
506
511
  this.platform.log.error(`Bot: ${this.accessory.displayName} Device is offline.`);
512
+ this.offlineOff();
507
513
  break;
508
514
  case 171:
509
515
  this.platform.log.error(`Bot: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
516
+ this.offlineOff();
510
517
  break;
511
518
  case 190:
512
519
  this.platform.log.error(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -520,6 +527,17 @@ export class Bot {
520
527
  }
521
528
  }
522
529
 
530
+ private offlineOff() {
531
+ if (this.device.offline) {
532
+ this.On = false;
533
+ if (this.device.bot?.deviceType === 'switch') {
534
+ this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
535
+ } else {
536
+ this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
537
+ }
538
+ }
539
+ }
540
+
523
541
  /**
524
542
  * Handle requests to set the "On" characteristic
525
543
  */
@@ -2,7 +2,7 @@ import { AxiosResponse } from 'axios';
2
2
  import { interval, Subject } from 'rxjs';
3
3
  import { SwitchBotPlatform } from '../platform';
4
4
  import { debounceTime, skipWhile, tap } from 'rxjs/operators';
5
- import { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
5
+ import { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap, HAPStatus } from 'homebridge';
6
6
  import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload, hs2rgb, rgb2hs, m2hs } from '../settings';
7
7
 
8
8
  /**
@@ -56,13 +56,17 @@ export class ColorBulb {
56
56
  this.platform.device(`Color Bulb: ${this.accessory.displayName} Config: (ble: ${device.ble}, set_minStep: ${device.colorbulb?.set_minStep}`);
57
57
 
58
58
  // default placeholders
59
- this.minKelvin = 2000;
60
- this.maxKelvin = 9000;
59
+ if (this.On === undefined) {
60
+ this.On = false;
61
+ } else {
62
+ this.On = this.accessory.context.On;
63
+ }
61
64
  this.Hue = 0;
62
- this.On = false;
63
65
  this.Brightness = 0;
64
66
  this.Saturation = 0;
65
67
  this.ColorTemperature = 140;
68
+ this.minKelvin = 2000;
69
+ this.maxKelvin = 9000;
66
70
 
67
71
  // this is subject we use to track when we need to POST changes to the SwitchBot API
68
72
  this.doColorBulbUpdate = new Subject();
@@ -185,7 +189,7 @@ export class ColorBulb {
185
189
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges,`
186
190
  + ` Error: ${JSON.stringify(e)}`);
187
191
  }
188
- this.apiError(e);
192
+ this.apiError();
189
193
  }
190
194
  this.colorBulbUpdateInProgress = false;
191
195
  });
@@ -262,7 +266,7 @@ export class ColorBulb {
262
266
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
263
267
  + ` Error: ${JSON.stringify(e)}`);
264
268
  }
265
- this.apiError(e);
269
+ this.apiError();
266
270
  }
267
271
  }
268
272
 
@@ -299,6 +303,7 @@ export class ColorBulb {
299
303
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
300
304
  this.statusCode(push);
301
305
  this.OnCached = this.On;
306
+ this.accessory.context.On = this.OnCached;
302
307
  }
303
308
  // Push Brightness Update
304
309
  if (this.On) {
@@ -325,7 +330,7 @@ export class ColorBulb {
325
330
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
326
331
  + ` Error: ${JSON.stringify(e)}`);
327
332
  }
328
- this.apiError(e);
333
+ this.apiError();
329
334
  }
330
335
  }
331
336
 
@@ -367,7 +372,7 @@ export class ColorBulb {
367
372
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
368
373
  + ` Error: ${JSON.stringify(e)}`);
369
374
  }
370
- this.apiError(e);
375
+ this.apiError();
371
376
  }
372
377
  }
373
378
 
@@ -405,7 +410,7 @@ export class ColorBulb {
405
410
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
406
411
  + ` Error: ${JSON.stringify(e)}`);
407
412
  }
408
- this.apiError(e);
413
+ this.apiError();
409
414
  }
410
415
  }
411
416
 
@@ -440,7 +445,7 @@ export class ColorBulb {
440
445
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
441
446
  + ` Error: ${JSON.stringify(e)}`);
442
447
  }
443
- this.apiError(e);
448
+ this.apiError();
444
449
  }
445
450
  }
446
451
 
@@ -477,12 +482,8 @@ export class ColorBulb {
477
482
  }
478
483
  }
479
484
 
480
- public apiError(e: any) {
481
- this.service.updateCharacteristic(this.platform.Characteristic.On, e);
482
- this.service.updateCharacteristic(this.platform.Characteristic.Hue, e);
483
- this.service.updateCharacteristic(this.platform.Characteristic.Brightness, e);
484
- this.service.updateCharacteristic(this.platform.Characteristic.Saturation, e);
485
- this.service.updateCharacteristic(this.platform.Characteristic.ColorTemperature, e);
485
+ public apiError() {
486
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
486
487
  }
487
488
 
488
489
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
@@ -498,9 +499,11 @@ export class ColorBulb {
498
499
  break;
499
500
  case 161:
500
501
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device is offline.`);
502
+ this.offlineOff();
501
503
  break;
502
504
  case 171:
503
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
505
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
506
+ this.offlineOff();
504
507
  break;
505
508
  case 190:
506
509
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -514,6 +517,13 @@ export class ColorBulb {
514
517
  }
515
518
  }
516
519
 
520
+ private offlineOff() {
521
+ if (this.device.offline) {
522
+ this.On = false;
523
+ this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
524
+ }
525
+ }
526
+
517
527
  /**
518
528
  * Handle requests to set the value of the "On" characteristic
519
529
  */
@@ -2,7 +2,7 @@ import Switchbot from 'node-switchbot';
2
2
  import { interval, Subject } from 'rxjs';
3
3
  import { skipWhile } from 'rxjs/operators';
4
4
  import { SwitchBotPlatform } from '../platform';
5
- import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
5
+ import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
6
6
  import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse } from '../settings';
7
7
 
8
8
  /**
@@ -50,7 +50,7 @@ export class Contact {
50
50
  public device: device & devicesConfig,
51
51
  ) {
52
52
  // Contact Config
53
- this.platform.device(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble},`
53
+ this.platform.device(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},`
54
54
  + ` hide_lightsensor: ${device.contact?.hide_lightsensor}, hide_motionsensor: ${device.contact?.hide_motionsensor})`);
55
55
 
56
56
 
@@ -287,7 +287,7 @@ export class Contact {
287
287
  this.platform.log.warn(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
288
288
  await this.openAPIRefreshStatus();
289
289
  }
290
- this.apiError(e);
290
+ this.apiError();
291
291
  });
292
292
  }
293
293
 
@@ -309,7 +309,7 @@ export class Contact {
309
309
  this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
310
310
  + ` Error: ${JSON.stringify(e)}`);
311
311
  }
312
- this.apiError(e);
312
+ this.apiError();
313
313
  }
314
314
  }
315
315
  }
@@ -357,17 +357,7 @@ export class Contact {
357
357
  }
358
358
  }
359
359
 
360
- public apiError(e: any) {
361
- this.service.updateCharacteristic(this.platform.Characteristic.ContactSensorState, e);
362
- if (!this.device.contact?.hide_motionsensor) {
363
- this.motionService?.updateCharacteristic(this.platform.Characteristic.MotionDetected, e);
364
- }
365
- if (!this.device.contact?.hide_lightsensor) {
366
- this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
367
- }
368
- if (this.device.ble) {
369
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
370
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
371
- }
360
+ public apiError() {
361
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
372
362
  }
373
363
  }
@@ -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, switchbot, deviceStatusResponse, payload } from '../settings';
9
9
 
10
10
  export class Curtain {
@@ -184,7 +184,7 @@ export class Curtain {
184
184
  this.platform.log.error(`Curtain: ${this.accessory.displayName} failed pushChanges,`
185
185
  + ` Error: ${JSON.stringify(e)}`);
186
186
  }
187
- this.apiError(e);
187
+ this.apiError();
188
188
  }
189
189
  this.curtainUpdateInProgress = false;
190
190
  });
@@ -454,7 +454,7 @@ export class Curtain {
454
454
  this.platform.log.warn(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
455
455
  await this.openAPIRefreshStatus();
456
456
  }
457
- this.apiError(e);
457
+ this.apiError();
458
458
  });
459
459
  }
460
460
 
@@ -476,7 +476,7 @@ export class Curtain {
476
476
  this.platform.log.error(`Curtain: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
477
477
  + ` Error: ${JSON.stringify(e)}`);
478
478
  }
479
- this.apiError(e);
479
+ this.apiError();
480
480
  }
481
481
  }
482
482
  }
@@ -518,7 +518,7 @@ export class Curtain {
518
518
  this.platform.log.warn(`Curtain: ${this.accessory.displayName} Using OpenAPI Connection`);
519
519
  await this.OpenAPIpushChanges();
520
520
  }
521
- this.apiError(e);
521
+ this.apiError();
522
522
  });
523
523
  } else {
524
524
  this.platform.debug(`Curtain: ${this.accessory.displayName} No BLE Changes, CurrentPosition & TargetPosition Are the Same.`
@@ -560,7 +560,7 @@ export class Curtain {
560
560
  this.platform.log.error(`Curtain: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
561
561
  + ` Error: ${JSON.stringify(e)}`);
562
562
  }
563
- this.apiError(e);
563
+ this.apiError();
564
564
  }
565
565
  }
566
566
  }
@@ -609,17 +609,8 @@ export class Curtain {
609
609
  }
610
610
  }
611
611
 
612
- public apiError(e: any) {
613
- this.service.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
614
- this.service.updateCharacteristic(this.platform.Characteristic.PositionState, e);
615
- this.service.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
616
- if (!this.device.curtain?.hide_lightsensor) {
617
- this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
618
- }
619
- if (this.device.ble) {
620
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
621
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
622
- }
612
+ public apiError() {
613
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
623
614
  }
624
615
 
625
616
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {