@switchbot/homebridge-switchbot 1.3.1-beta.6 → 1.4.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 (88) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/config.schema.json +9 -22
  3. package/dist/devices/bots.d.ts +2 -0
  4. package/dist/devices/bots.d.ts.map +1 -1
  5. package/dist/devices/bots.js +109 -84
  6. package/dist/devices/bots.js.map +1 -1
  7. package/dist/devices/colorbulb.d.ts +1 -0
  8. package/dist/devices/colorbulb.d.ts.map +1 -1
  9. package/dist/devices/colorbulb.js +18 -4
  10. package/dist/devices/colorbulb.js.map +1 -1
  11. package/dist/devices/contact.js +1 -1
  12. package/dist/devices/contact.js.map +1 -1
  13. package/dist/devices/humidifiers.d.ts +1 -0
  14. package/dist/devices/humidifiers.d.ts.map +1 -1
  15. package/dist/devices/humidifiers.js +9 -1
  16. package/dist/devices/humidifiers.js.map +1 -1
  17. package/dist/devices/indoorcam.d.ts.map +1 -1
  18. package/dist/devices/indoorcam.js +6 -0
  19. package/dist/devices/indoorcam.js.map +1 -1
  20. package/dist/devices/meters.d.ts +5 -11
  21. package/dist/devices/meters.d.ts.map +1 -1
  22. package/dist/devices/meters.js +49 -47
  23. package/dist/devices/meters.js.map +1 -1
  24. package/dist/devices/plugs.d.ts +2 -0
  25. package/dist/devices/plugs.d.ts.map +1 -1
  26. package/dist/devices/plugs.js +35 -16
  27. package/dist/devices/plugs.js.map +1 -1
  28. package/dist/irdevices/airconditioners.d.ts +2 -0
  29. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  30. package/dist/irdevices/airconditioners.js +17 -1
  31. package/dist/irdevices/airconditioners.js.map +1 -1
  32. package/dist/irdevices/airpurifiers.d.ts +2 -0
  33. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  34. package/dist/irdevices/airpurifiers.js +17 -0
  35. package/dist/irdevices/airpurifiers.js.map +1 -1
  36. package/dist/irdevices/cameras.d.ts +1 -0
  37. package/dist/irdevices/cameras.d.ts.map +1 -1
  38. package/dist/irdevices/cameras.js +9 -0
  39. package/dist/irdevices/cameras.js.map +1 -1
  40. package/dist/irdevices/fans.d.ts +1 -0
  41. package/dist/irdevices/fans.d.ts.map +1 -1
  42. package/dist/irdevices/fans.js +9 -0
  43. package/dist/irdevices/fans.js.map +1 -1
  44. package/dist/irdevices/lights.d.ts +1 -0
  45. package/dist/irdevices/lights.d.ts.map +1 -1
  46. package/dist/irdevices/lights.js +9 -0
  47. package/dist/irdevices/lights.js.map +1 -1
  48. package/dist/irdevices/others.d.ts +1 -0
  49. package/dist/irdevices/others.d.ts.map +1 -1
  50. package/dist/irdevices/others.js +9 -0
  51. package/dist/irdevices/others.js.map +1 -1
  52. package/dist/irdevices/tvs.d.ts +1 -0
  53. package/dist/irdevices/tvs.d.ts.map +1 -1
  54. package/dist/irdevices/tvs.js +9 -0
  55. package/dist/irdevices/tvs.js.map +1 -1
  56. package/dist/irdevices/vacuumcleaners.d.ts +1 -0
  57. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  58. package/dist/irdevices/vacuumcleaners.js +9 -0
  59. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  60. package/dist/irdevices/waterheaters.d.ts +1 -0
  61. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  62. package/dist/irdevices/waterheaters.js +9 -0
  63. package/dist/irdevices/waterheaters.js.map +1 -1
  64. package/dist/platform.d.ts.map +1 -1
  65. package/dist/platform.js +46 -2
  66. package/dist/platform.js.map +1 -1
  67. package/dist/settings.d.ts +6 -5
  68. package/dist/settings.d.ts.map +1 -1
  69. package/dist/settings.js.map +1 -1
  70. package/package.json +66 -66
  71. package/src/devices/bots.ts +88 -63
  72. package/src/devices/colorbulb.ts +18 -4
  73. package/src/devices/contact.ts +1 -1
  74. package/src/devices/humidifiers.ts +10 -1
  75. package/src/devices/indoorcam.ts +6 -0
  76. package/src/devices/meters.ts +50 -48
  77. package/src/devices/plugs.ts +38 -17
  78. package/src/irdevices/airconditioners.ts +17 -1
  79. package/src/irdevices/airpurifiers.ts +18 -0
  80. package/src/irdevices/cameras.ts +10 -0
  81. package/src/irdevices/fans.ts +10 -0
  82. package/src/irdevices/lights.ts +10 -0
  83. package/src/irdevices/others.ts +10 -0
  84. package/src/irdevices/tvs.ts +10 -0
  85. package/src/irdevices/vacuumcleaners.ts +10 -0
  86. package/src/irdevices/waterheaters.ts +10 -0
  87. package/src/platform.ts +37 -2
  88. package/src/settings.ts +7 -5
@@ -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
 
@@ -122,7 +127,6 @@ export class Bot {
122
127
  }
123
128
 
124
129
  // Retrieve initial values and updateHomekit
125
- this.parseStatus();
126
130
  this.updateHomeKitCharacteristics();
127
131
 
128
132
  // Start an update interval
@@ -341,14 +345,38 @@ export class Bot {
341
345
  }
342
346
 
343
347
  private async BLEpushChanges() {
344
- this.platform.debug(`Bot: ${this.accessory.displayName} BLE pushChanges`);
345
- const switchbot = this.connectBLE();
346
- if (this.device.bot?.mode === 'press') {
347
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
348
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac })
349
- .then((device_list: { press: (arg0: { id: string | undefined; }) => any; }[]) => {
350
- this.platform.log.info(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
351
- 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(e);
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);
352
380
  }).then(() => {
353
381
  this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
354
382
  }).catch(async (e: any) => {
@@ -367,32 +395,12 @@ export class Bot {
367
395
  }
368
396
  this.apiError(e);
369
397
  });
370
- } else if (this.device.bot?.mode === 'switch') {
371
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
372
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
373
- this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.On}`);
374
- return this.turnOnOff(device_list);
375
- }).then(() => {
376
- this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
377
- }).catch(async (e: any) => {
378
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
379
- if (this.deviceDebug) {
380
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
381
- + ` Error Message: ${JSON.stringify(e.message)}`);
382
- }
383
- if (this.debugDebug) {
384
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
385
- + ` Error: ${JSON.stringify(e)}`);
386
- }
387
- if (this.platform.config.credentials?.openToken) {
388
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
389
- await this.openAPIpushChanges();
390
- }
391
- this.apiError(e);
392
- });
393
- } else {
394
- 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
+ }
395
401
  }
402
+ this.OnCached = this.On;
403
+ this.accessory.context.On = this.OnCached;
396
404
  }
397
405
 
398
406
  private turnOnOff(device_list: any) {
@@ -406,35 +414,39 @@ export class Bot {
406
414
  private async openAPIpushChanges() {
407
415
  if (this.platform.config.credentials?.openToken) {
408
416
  try {
409
- this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
410
- const payload = {
411
- commandType: 'command',
412
- parameter: 'default',
413
- } as payload;
414
-
415
- if (this.device.bot?.mode === 'switch' && this.On) {
416
- payload.command = 'turnOn';
417
- this.On = true;
418
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
419
- } else if (this.device.bot?.mode === 'switch' && !this.On) {
420
- payload.command = 'turnOff';
421
- this.On = false;
422
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
423
- } else if (this.device.bot?.mode === 'press') {
424
- payload.command = 'press';
425
- this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
426
- this.On = false;
427
- } else {
428
- throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
429
- }
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
+ }
430
439
 
431
- this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
432
- + ` 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}`);
433
442
 
434
- // Make the API request
435
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
436
- this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
437
- 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
+ }
438
450
  } catch (e: any) {
439
451
  this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
440
452
  if (this.deviceDebug) {
@@ -505,9 +517,11 @@ export class Bot {
505
517
  break;
506
518
  case 161:
507
519
  this.platform.log.error(`Bot: ${this.accessory.displayName} Device is offline.`);
520
+ this.offlineOff();
508
521
  break;
509
522
  case 171:
510
523
  this.platform.log.error(`Bot: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
524
+ this.offlineOff();
511
525
  break;
512
526
  case 190:
513
527
  this.platform.log.error(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -521,6 +535,17 @@ export class Bot {
521
535
  }
522
536
  }
523
537
 
538
+ private offlineOff() {
539
+ if (this.device.offline) {
540
+ this.On = false;
541
+ if (this.device.bot?.deviceType === 'switch') {
542
+ this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
543
+ } else {
544
+ this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
545
+ }
546
+ }
547
+ }
548
+
524
549
  /**
525
550
  * Handle requests to set the "On" characteristic
526
551
  */
@@ -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();
@@ -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) {
@@ -498,9 +503,11 @@ export class ColorBulb {
498
503
  break;
499
504
  case 161:
500
505
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device is offline.`);
506
+ this.offlineOff();
501
507
  break;
502
508
  case 171:
503
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
509
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
510
+ this.offlineOff();
504
511
  break;
505
512
  case 190:
506
513
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -514,6 +521,13 @@ export class ColorBulb {
514
521
  }
515
522
  }
516
523
 
524
+ private offlineOff() {
525
+ if (this.device.offline) {
526
+ this.On = false;
527
+ this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
528
+ }
529
+ }
530
+
517
531
  /**
518
532
  * Handle requests to set the value of the "On" characteristic
519
533
  */
@@ -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
 
@@ -50,7 +50,7 @@ export class Humidifier {
50
50
  public device: device & devicesConfig,
51
51
  ) {
52
52
  // Humidifiers Config
53
- this.platform.device(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, hide_temperature: `
53
+ this.platform.device(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, hide_temperature: `
54
54
  + `${device.humidifier?.hide_temperature}, set_minStep: ${device.humidifier?.set_minStep})`);
55
55
 
56
56
  // default placeholders
@@ -633,9 +633,11 @@ export class Humidifier {
633
633
  break;
634
634
  case 161:
635
635
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device is offline.`);
636
+ this.offlineOff();
636
637
  break;
637
638
  case 171:
638
639
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
640
+ this.offlineOff();
639
641
  break;
640
642
  case 190:
641
643
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -649,6 +651,13 @@ export class Humidifier {
649
651
  }
650
652
  }
651
653
 
654
+ private offlineOff() {
655
+ if (this.device.offline) {
656
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
657
+ this.service.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.Active);
658
+ }
659
+ }
660
+
652
661
  /**
653
662
  * Handle requests to set the "Target Humidifier Dehumidifier State" characteristic
654
663
  */
@@ -215,9 +215,15 @@ export class IndoorCam {
215
215
  break;
216
216
  case 161:
217
217
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device is offline.`);
218
+ if (this.device.offline) {
219
+ this.Active = false;
220
+ }
218
221
  break;
219
222
  case 171:
220
223
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
224
+ if (this.device.offline) {
225
+ this.Active = false;
226
+ }
221
227
  break;
222
228
  case 190:
223
229
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -3,7 +3,7 @@ import { interval, Subject } from 'rxjs';
3
3
  import { skipWhile } from 'rxjs/operators';
4
4
  import { SwitchBotPlatform } from '../platform';
5
5
  import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
6
- import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse } from '../settings';
6
+ import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, temperature } from '../settings';
7
7
 
8
8
  /**
9
9
  * Platform Accessory
@@ -18,8 +18,11 @@ export class Meter {
18
18
 
19
19
  // Characteristic Values
20
20
  CurrentRelativeHumidity!: CharacteristicValue;
21
+ CurrentRelativeHumidityCached!: CharacteristicValue;
21
22
  CurrentTemperature!: CharacteristicValue;
23
+ CurrentTemperatureCached!: CharacteristicValue;
22
24
  BatteryLevel!: CharacteristicValue;
25
+ BatteryLevelCached!: CharacteristicValue;
23
26
  ChargingState!: CharacteristicValue;
24
27
  StatusLowBattery!: CharacteristicValue;
25
28
  Active!: CharacteristicValue;
@@ -32,10 +35,9 @@ export class Meter {
32
35
  connected?: boolean;
33
36
  switchbot!: switchbot;
34
37
  serviceData!: serviceData;
38
+ temperature!: temperature['c'];
35
39
  battery!: serviceData['battery'];
36
40
  humidity!: serviceData['humidity'];
37
- fahrenheit!: serviceData['fahrenheit'];
38
- temperature!: serviceData['temperature'];
39
41
 
40
42
  // Config
41
43
  private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
@@ -51,15 +53,31 @@ export class Meter {
51
53
  public device: device & devicesConfig,
52
54
  ) {
53
55
  // Meter Config
54
- this.platform.device(`Meter: ${this.accessory.displayName} Config: (ble: ${device.ble}, unit: ${device.meter?.unit},`
55
- + ` hide_temperature: ${device.meter?.hide_temperature}, hide_humidity: ${device.meter?.hide_humidity})`);
56
+ this.platform.device(`Meter: ${this.accessory.displayName} Config: (ble: ${device.ble}, hide_temperature: ${device.meter?.hide_temperature},`
57
+ + ` hide_humidity: ${device.meter?.hide_humidity})`);
56
58
 
57
59
  // default placeholders
58
- this.BatteryLevel = 0;
59
- this.ChargingState = 2;
60
- this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
61
- this.CurrentRelativeHumidity = 0;
62
- this.CurrentTemperature = 0;
60
+ if (this.BatteryLevel === undefined) {
61
+ this.BatteryLevel = 100;
62
+ } else {
63
+ this.BatteryLevel = this.accessory.context.BatteryLevel;
64
+ }
65
+ if (this.BatteryLevel < 15) {
66
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
67
+ } else {
68
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
69
+ }
70
+ this.ChargingState = this.platform.Characteristic.ChargingState.NOT_CHARGEABLE;
71
+ if (this.CurrentRelativeHumidity === undefined) {
72
+ this.CurrentRelativeHumidity = 0;
73
+ } else {
74
+ this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
75
+ }
76
+ if (this.CurrentTemperature === undefined) {
77
+ this.CurrentTemperature = 0;
78
+ } else {
79
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
80
+ }
63
81
 
64
82
  // this is subject we use to track when we need to POST changes to the SwitchBot API
65
83
  this.doMeterUpdate = new Subject();
@@ -177,9 +195,9 @@ export class Meter {
177
195
  // Battery
178
196
  this.BatteryLevel = Number(this.battery);
179
197
  if (this.BatteryLevel < 15) {
180
- this.StatusLowBattery = 1;
198
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
181
199
  } else {
182
- this.StatusLowBattery = 0;
200
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
183
201
  }
184
202
  this.platform.debug(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
185
203
 
@@ -191,13 +209,8 @@ export class Meter {
191
209
 
192
210
  // Current Temperature
193
211
  if (!this.device.meter?.hide_temperature) {
194
- if (this.device.meter?.unit === 1) {
195
- this.CurrentTemperature = this.toFahrenheit(this.temperature!.c);
196
- } else if (this.device.meter?.unit === 0) {
197
- this.CurrentTemperature = this.toCelsius(this.temperature!.c);
198
- } else {
199
- this.CurrentTemperature = Number(this.temperature?.c);
200
- }
212
+ this.temperature < 0 ? 0 : this.temperature > 100 ? 100 : this.temperature;
213
+ this.CurrentTemperature = this.temperature;
201
214
  this.platform.debug(`Meter: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
202
215
  }
203
216
  }
@@ -211,9 +224,9 @@ export class Meter {
211
224
  this.BatteryLevel = 10;
212
225
  }
213
226
  if (this.BatteryLevel < 15) {
214
- this.StatusLowBattery = 1;
227
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
215
228
  } else {
216
- this.StatusLowBattery = 0;
229
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
217
230
  }
218
231
  // Current Relative Humidity
219
232
  if (!this.device.meter?.hide_humidity) {
@@ -223,13 +236,7 @@ export class Meter {
223
236
 
224
237
  // Current Temperature
225
238
  if (!this.device.meter?.hide_temperature) {
226
- if (this.device.meter?.unit === 1) {
227
- this.CurrentTemperature = this.toFahrenheit(this.deviceStatus.body.temperature!);
228
- } else if (this.device.meter?.unit === 0) {
229
- this.CurrentTemperature = this.toCelsius(this.deviceStatus.body.temperature!);
230
- } else {
231
- this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
232
- }
239
+ this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
233
240
  this.platform.debug(`Meter: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
234
241
  }
235
242
  }
@@ -259,20 +266,18 @@ export class Meter {
259
266
  const switchbot = this.connectBLE();
260
267
  // Start to monitor advertisement packets
261
268
  switchbot.startScan({
262
- model: 'T',
263
269
  id: this.device.bleMac,
264
270
  }).then(() => {
265
271
  // Set an event hander
266
272
  switchbot.onadvertisement = (ad: ad) => {
267
273
  this.serviceData = ad.serviceData;
268
- this.temperature = ad.serviceData.temperature;
269
- this.fahrenheit = ad.serviceData.fahrenheit;
274
+ this.temperature = ad.serviceData.temperature!.c;
270
275
  this.humidity = ad.serviceData.humidity;
271
276
  this.battery = ad.serviceData.battery;
272
277
  this.platform.device(`Meter: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
273
278
  this.platform.device(`Meter: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, `
274
- + `temperature: ${JSON.stringify(ad.serviceData.temperature)}, fahrenheit: ${ad.serviceData.fahrenheit}, `
275
- + `humidity: ${ad.serviceData.humidity}, battery: ${ad.serviceData.battery}`);
279
+ + `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, `
280
+ + `battery: ${ad.serviceData.battery}`);
276
281
 
277
282
  if (this.serviceData) {
278
283
  this.connected = true;
@@ -288,6 +293,12 @@ export class Meter {
288
293
  // Stop to monitor
289
294
  switchbot.stopScan();
290
295
  if (this.connected) {
296
+ this.CurrentTemperatureCached = this.temperature;
297
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
298
+ this.CurrentRelativeHumidityCached = this.humidity!;
299
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
300
+ this.BatteryLevelCached = this.battery!;
301
+ this.accessory.context.BatteryLevel = this.BatteryLevelCached;
291
302
  this.parseStatus();
292
303
  this.updateHomeKitCharacteristics();
293
304
  } else {
@@ -321,6 +332,12 @@ export class Meter {
321
332
  try {
322
333
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
323
334
  this.platform.debug(`Meter: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
335
+ this.CurrentTemperatureCached = this.deviceStatus.body.humidity!;
336
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
337
+ this.CurrentRelativeHumidityCached = this.deviceStatus.body.humidity!;
338
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
339
+ this.BatteryLevelCached = 100;
340
+ this.accessory.context.BatteryLevel = this.BatteryLevelCached;
324
341
  this.parseStatus();
325
342
  this.updateHomeKitCharacteristics();
326
343
  } catch (e: any) {
@@ -382,19 +399,4 @@ export class Meter {
382
399
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
383
400
  }
384
401
  }
385
-
386
- /**
387
- * Converts the value to celsius if the temperature units are in Fahrenheit
388
- */
389
- toCelsius(value: number) {
390
- // celsius should be to the nearest 0.5 degree
391
- return Math.round((5 / 9) * (value - 32) * 2) / 2;
392
- }
393
-
394
- /**
395
- * Converts the value to fahrenheit if the temperature units are in Fahrenheit
396
- */
397
- toFahrenheit(value: number) {
398
- return Math.round((value * 9) / 5 + 32);
399
- }
400
402
  }
@@ -12,6 +12,7 @@ export class Plug {
12
12
 
13
13
  // Characteristic Values
14
14
  On!: CharacteristicValue;
15
+ OnCached!: CharacteristicValue;
15
16
 
16
17
  // OpenAPI Others
17
18
  deviceStatus!: deviceStatusResponse;
@@ -29,8 +30,15 @@ export class Plug {
29
30
  private accessory: PlatformAccessory,
30
31
  public device: device & devicesConfig,
31
32
  ) {
33
+ // Bot Config
34
+ this.platform.device(`Plug: ${this.accessory.displayName} Config: (offline: ${device.offline})`);
35
+
32
36
  // default placeholders
33
- this.On = false;
37
+ if (this.On === undefined) {
38
+ this.On = false;
39
+ } else {
40
+ this.On = this.accessory.context.On;
41
+ }
34
42
 
35
43
  // this is subject we use to track when we need to POST changes to the SwitchBot API
36
44
  this.doPlugUpdate = new Subject();
@@ -142,24 +150,28 @@ export class Plug {
142
150
  * Plug - "command" "turnOn" "default" = set to ON state
143
151
  */
144
152
  async pushChanges() {
145
- const payload = {
146
- commandType: 'command',
147
- parameter: 'default',
148
- } as payload;
149
-
150
- if (this.On) {
151
- payload.command = 'turnOn';
152
- } else {
153
- payload.command = 'turnOff';
154
- }
153
+ if (this.On !== this.OnCached) {
154
+ const payload = {
155
+ commandType: 'command',
156
+ parameter: 'default',
157
+ } as payload;
158
+
159
+ if (this.On) {
160
+ payload.command = 'turnOn';
161
+ } else {
162
+ payload.command = 'turnOff';
163
+ }
155
164
 
156
- this.platform.log.info(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
157
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
165
+ this.platform.log.info(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
166
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
158
167
 
159
- // Make the API request
160
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
161
- this.platform.debug(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
162
- this.statusCode(push);
168
+ // Make the API request
169
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
170
+ this.platform.debug(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
171
+ this.statusCode(push);
172
+ this.OnCached = this.On;
173
+ this.accessory.context.On = this.OnCached;
174
+ }
163
175
  interval(5000)
164
176
  .pipe(skipWhile(() => this.plugUpdateInProgress))
165
177
  .pipe(take(1))
@@ -194,9 +206,11 @@ export class Plug {
194
206
  break;
195
207
  case 161:
196
208
  this.platform.log.error(`Plug: ${this.accessory.displayName} Device is offline.`);
209
+ this.offlineOff();
197
210
  break;
198
211
  case 171:
199
212
  this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
213
+ this.offlineOff();
200
214
  break;
201
215
  case 190:
202
216
  this.platform.log.error(`Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -210,6 +224,13 @@ export class Plug {
210
224
  }
211
225
  }
212
226
 
227
+ private offlineOff() {
228
+ if (this.device.offline) {
229
+ this.On = false;
230
+ this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
231
+ }
232
+ }
233
+
213
234
  /**
214
235
  * Handle requests to set the value of the "On" characteristic
215
236
  */