@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
@@ -3,7 +3,7 @@ import Switchbot from 'node-switchbot';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform';
5
5
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
+ import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
7
7
  import { DeviceURL, device, devicesConfig, serviceData, ad, deviceStatusResponse, payload } from '../settings';
8
8
 
9
9
  /**
@@ -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
@@ -184,7 +184,7 @@ export class Humidifier {
184
184
  this.platform.log.error(`Humidifier: ${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.humidifierUpdateInProgress = false;
190
190
  });
@@ -354,7 +354,7 @@ export class Humidifier {
354
354
  this.platform.log.warn(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
355
355
  await this.openAPIRefreshStatus();
356
356
  }
357
- this.apiError(e);
357
+ this.apiError();
358
358
  });
359
359
  }
360
360
 
@@ -380,7 +380,7 @@ export class Humidifier {
380
380
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
381
381
  + ` Error: ${JSON.stringify(e)}`);
382
382
  }
383
- this.apiError(e);
383
+ this.apiError();
384
384
  }
385
385
  }
386
386
  }
@@ -424,7 +424,7 @@ export class Humidifier {
424
424
  this.platform.log.warn(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
425
425
  await this.OpenAPIpushChanges();
426
426
  }
427
- this.apiError(e);
427
+ this.apiError();
428
428
  });
429
429
  }
430
430
 
@@ -461,7 +461,7 @@ export class Humidifier {
461
461
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
462
462
  + ` Error: ${JSON.stringify(e)}`);
463
463
  }
464
- this.apiError(e);
464
+ this.apiError();
465
465
  }
466
466
  } else if (
467
467
  this.TargetHumidifierDehumidifierState ===
@@ -510,7 +510,7 @@ export class Humidifier {
510
510
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushAutoChanges with OpenAPI Connection,`
511
511
  + ` Error: ${JSON.stringify(e)}`);
512
512
  }
513
- this.apiError(e);
513
+ this.apiError();
514
514
  }
515
515
  }
516
516
 
@@ -545,7 +545,7 @@ export class Humidifier {
545
545
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushActiveChanges with OpenAPI Connection,`
546
546
  + ` Error: ${JSON.stringify(e)}`);
547
547
  }
548
- this.apiError(e);
548
+ this.apiError();
549
549
  }
550
550
  }
551
551
 
@@ -606,18 +606,8 @@ export class Humidifier {
606
606
  }
607
607
  }
608
608
 
609
- public apiError(e: any) {
610
- this.service.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
611
- if (!this.device.ble) {
612
- this.service.updateCharacteristic(this.platform.Characteristic.WaterLevel, e);
613
- }
614
- this.service.updateCharacteristic(this.platform.Characteristic.CurrentHumidifierDehumidifierState, e);
615
- this.service.updateCharacteristic(this.platform.Characteristic.TargetHumidifierDehumidifierState, e);
616
- this.service.updateCharacteristic(this.platform.Characteristic.Active, e);
617
- this.service.updateCharacteristic(this.platform.Characteristic.RelativeHumidityHumidifierThreshold, e);
618
- if (!this.device.humidifier?.hide_temperature && !this.device.ble) {
619
- this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
620
- }
609
+ public apiError() {
610
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
621
611
  }
622
612
 
623
613
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
@@ -633,9 +623,11 @@ export class Humidifier {
633
623
  break;
634
624
  case 161:
635
625
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device is offline.`);
626
+ this.offlineOff();
636
627
  break;
637
628
  case 171:
638
629
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
630
+ this.offlineOff();
639
631
  break;
640
632
  case 190:
641
633
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -649,6 +641,13 @@ export class Humidifier {
649
641
  }
650
642
  }
651
643
 
644
+ private offlineOff() {
645
+ if (this.device.offline) {
646
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
647
+ this.service.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.Active);
648
+ }
649
+ }
650
+
652
651
  /**
653
652
  * Handle requests to set the "Target Humidifier Dehumidifier State" characteristic
654
653
  */
@@ -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, take, tap } from 'rxjs/operators';
5
- import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
5
+ import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
6
6
  import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
7
7
 
8
8
  export class IndoorCam {
@@ -126,7 +126,7 @@ export class IndoorCam {
126
126
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} failed pushChanges,`
127
127
  + ` Error: ${JSON.stringify(e)}`);
128
128
  }
129
- this.apiError(e);
129
+ this.apiError();
130
130
  }
131
131
  this.cameraUpdateInProgress = false;
132
132
  });
@@ -139,7 +139,7 @@ export class IndoorCam {
139
139
 
140
140
  private async refreshStatus() {
141
141
  try {
142
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
142
+ //this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
143
143
  this.platform.device(`Indoor Cam: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
144
144
  this.parseStatus();
145
145
  this.updateHomeKitCharacteristics();
@@ -153,7 +153,7 @@ export class IndoorCam {
153
153
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
154
154
  + ` Error: ${JSON.stringify(e)}`);
155
155
  }
156
- this.apiError(e);
156
+ this.apiError();
157
157
  }
158
158
  }
159
159
 
@@ -198,8 +198,8 @@ export class IndoorCam {
198
198
  }
199
199
  }
200
200
 
201
- public apiError(e: any) {
202
- this.service.updateCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration, e);
201
+ public apiError() {
202
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
203
203
  }
204
204
 
205
205
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
@@ -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,`
@@ -2,8 +2,8 @@ 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, Units, CharacteristicValue } from 'homebridge';
6
- import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse } from '../settings';
5
+ import { Service, PlatformAccessory, Units, CharacteristicValue, HAPStatus } from 'homebridge';
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
  }
@@ -240,9 +247,9 @@ export class Meter {
240
247
  */
241
248
  async refreshStatus() {
242
249
  if (this.device.ble) {
243
- await this.BLErefreshStatus();
250
+ this.BLErefreshStatus();
244
251
  } else {
245
- await this.openAPIRefreshStatus();
252
+ this.openAPIRefreshStatus();
246
253
  }
247
254
  }
248
255
 
@@ -253,7 +260,7 @@ export class Meter {
253
260
  return switchbot;
254
261
  }
255
262
 
256
- private async BLErefreshStatus() {
263
+ private BLErefreshStatus() {
257
264
  this.platform.debug(`Meter: ${this.accessory.displayName} BLE RefreshStatus`);
258
265
  // eslint-disable-next-line @typescript-eslint/no-var-requires
259
266
  const switchbot = this.connectBLE();
@@ -265,14 +272,13 @@ export class Meter {
265
272
  // Set an event hander
266
273
  switchbot.onadvertisement = (ad: ad) => {
267
274
  this.serviceData = ad.serviceData;
268
- this.temperature = ad.serviceData.temperature;
269
- this.fahrenheit = ad.serviceData.fahrenheit;
275
+ this.temperature = ad.serviceData.temperature!.c;
270
276
  this.humidity = ad.serviceData.humidity;
271
277
  this.battery = ad.serviceData.battery;
272
278
  this.platform.device(`Meter: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
273
279
  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}`);
280
+ + `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, `
281
+ + `battery: ${ad.serviceData.battery}`);
276
282
 
277
283
  if (this.serviceData) {
278
284
  this.connected = true;
@@ -288,13 +294,19 @@ export class Meter {
288
294
  // Stop to monitor
289
295
  switchbot.stopScan();
290
296
  if (this.connected) {
297
+ this.CurrentTemperatureCached = this.temperature;
298
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
299
+ this.CurrentRelativeHumidityCached = this.humidity!;
300
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
301
+ this.BatteryLevelCached = this.battery!;
302
+ this.accessory.context.BatteryLevel = this.BatteryLevelCached;
291
303
  this.parseStatus();
292
304
  this.updateHomeKitCharacteristics();
293
305
  } else {
294
306
  this.platform.log.error(`Meter: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
295
307
  if (this.platform.config.credentials?.openToken) {
296
308
  this.platform.log.warn(`Meter: ${this.accessory.displayName} Using OpenAPI Connection`);
297
- await this.openAPIRefreshStatus();
309
+ this.openAPIRefreshStatus();
298
310
  }
299
311
  }
300
312
  }).catch(async (e: any) => {
@@ -309,9 +321,9 @@ export class Meter {
309
321
  }
310
322
  if (this.platform.config.credentials?.openToken) {
311
323
  this.platform.log.warn(`Meter: ${this.accessory.displayName} Using OpenAPI Connection`);
312
- await this.openAPIRefreshStatus();
324
+ this.openAPIRefreshStatus();
313
325
  }
314
- this.apiError(e);
326
+ this.apiError();
315
327
  });
316
328
  }
317
329
 
@@ -321,6 +333,12 @@ export class Meter {
321
333
  try {
322
334
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
323
335
  this.platform.debug(`Meter: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
336
+ this.CurrentTemperatureCached = this.deviceStatus.body.humidity!;
337
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
338
+ this.CurrentRelativeHumidityCached = this.deviceStatus.body.humidity!;
339
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
340
+ this.BatteryLevelCached = 100;
341
+ this.accessory.context.BatteryLevel = this.BatteryLevelCached;
324
342
  this.parseStatus();
325
343
  this.updateHomeKitCharacteristics();
326
344
  } catch (e: any) {
@@ -333,7 +351,7 @@ export class Meter {
333
351
  this.platform.log.error(`Meter: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
334
352
  + ` Error: ${JSON.stringify(e)}`);
335
353
  }
336
- this.apiError(e);
354
+ this.apiError();
337
355
  }
338
356
  }
339
357
  }
@@ -372,29 +390,7 @@ export class Meter {
372
390
  }
373
391
  }
374
392
 
375
- public apiError(e: any) {
376
- this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
377
- this.service.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
378
- if (!this.device.meter?.hide_humidity) {
379
- this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
380
- }
381
- if (!this.device.meter?.hide_temperature) {
382
- this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
383
- }
384
- }
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);
393
+ public apiError() {
394
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
399
395
  }
400
396
  }
@@ -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
  /**
@@ -224,7 +224,7 @@ export class Motion {
224
224
  this.platform.log.warn(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
225
225
  await this.openAPIRefreshStatus();
226
226
  }
227
- this.apiError(e);
227
+ this.apiError();
228
228
  });
229
229
  }
230
230
 
@@ -246,7 +246,7 @@ export class Motion {
246
246
  this.platform.log.error(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
247
247
  + ` Error: ${JSON.stringify(e)}`);
248
248
  }
249
- this.apiError(e);
249
+ this.apiError();
250
250
  }
251
251
  }
252
252
  }
@@ -284,12 +284,7 @@ export class Motion {
284
284
  }
285
285
  }
286
286
 
287
- public apiError(e: any) {
288
- this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, e);
289
- if (this.device.ble) {
290
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
291
- this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
292
- this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, e);
293
- }
287
+ public apiError() {
288
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
294
289
  }
295
290
  }
@@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform';
5
5
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
+ import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
7
7
  import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
8
8
 
9
9
  export class Plug {
@@ -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();
@@ -98,7 +106,7 @@ export class Plug {
98
106
  this.platform.log.error(`Plug: ${this.accessory.displayName} failed pushChanges,`
99
107
  + ` Error: ${JSON.stringify(e)}`);
100
108
  }
101
- this.apiError(e);
109
+ this.apiError();
102
110
  }
103
111
  this.plugUpdateInProgress = false;
104
112
  });
@@ -131,7 +139,7 @@ export class Plug {
131
139
  this.platform.log.error(`Plug: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
132
140
  + ` Error: ${JSON.stringify(e)}`);
133
141
  }
134
- this.apiError(e);
142
+ this.apiError();
135
143
  }
136
144
  }
137
145
 
@@ -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))
@@ -177,8 +189,8 @@ export class Plug {
177
189
  }
178
190
  }
179
191
 
180
- public apiError(e: any) {
181
- this.service.updateCharacteristic(this.platform.Characteristic.On, e);
192
+ public apiError() {
193
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
182
194
  }
183
195
 
184
196
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
@@ -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
  */