@switchbot/homebridge-switchbot 1.7.1-beta.1 → 1.7.1-beta.10

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 (97) hide show
  1. package/CHANGELOG.md +7 -2
  2. package/config.schema.json +46 -33
  3. package/dist/devices/bots.d.ts +4 -2
  4. package/dist/devices/bots.d.ts.map +1 -1
  5. package/dist/devices/bots.js +40 -40
  6. package/dist/devices/bots.js.map +1 -1
  7. package/dist/devices/colorbulb.d.ts +6 -1
  8. package/dist/devices/colorbulb.d.ts.map +1 -1
  9. package/dist/devices/colorbulb.js +18 -11
  10. package/dist/devices/colorbulb.js.map +1 -1
  11. package/dist/devices/contact.d.ts +6 -7
  12. package/dist/devices/contact.d.ts.map +1 -1
  13. package/dist/devices/contact.js +69 -107
  14. package/dist/devices/contact.js.map +1 -1
  15. package/dist/devices/curtains.d.ts +10 -3
  16. package/dist/devices/curtains.d.ts.map +1 -1
  17. package/dist/devices/curtains.js +52 -34
  18. package/dist/devices/curtains.js.map +1 -1
  19. package/dist/devices/humidifiers.d.ts +8 -2
  20. package/dist/devices/humidifiers.d.ts.map +1 -1
  21. package/dist/devices/humidifiers.js +28 -35
  22. package/dist/devices/humidifiers.js.map +1 -1
  23. package/dist/devices/meters.d.ts +14 -12
  24. package/dist/devices/meters.d.ts.map +1 -1
  25. package/dist/devices/meters.js +63 -103
  26. package/dist/devices/meters.js.map +1 -1
  27. package/dist/devices/motion.d.ts +5 -6
  28. package/dist/devices/motion.d.ts.map +1 -1
  29. package/dist/devices/motion.js +61 -90
  30. package/dist/devices/motion.js.map +1 -1
  31. package/dist/devices/plugs.d.ts +3 -1
  32. package/dist/devices/plugs.d.ts.map +1 -1
  33. package/dist/devices/plugs.js +8 -1
  34. package/dist/devices/plugs.js.map +1 -1
  35. package/dist/irdevices/airconditioners.d.ts +1 -0
  36. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  37. package/dist/irdevices/airconditioners.js +6 -0
  38. package/dist/irdevices/airconditioners.js.map +1 -1
  39. package/dist/irdevices/airpurifiers.d.ts +1 -0
  40. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  41. package/dist/irdevices/airpurifiers.js +6 -0
  42. package/dist/irdevices/airpurifiers.js.map +1 -1
  43. package/dist/irdevices/cameras.d.ts +1 -0
  44. package/dist/irdevices/cameras.d.ts.map +1 -1
  45. package/dist/irdevices/cameras.js +6 -0
  46. package/dist/irdevices/cameras.js.map +1 -1
  47. package/dist/irdevices/fans.d.ts +1 -0
  48. package/dist/irdevices/fans.d.ts.map +1 -1
  49. package/dist/irdevices/fans.js +6 -0
  50. package/dist/irdevices/fans.js.map +1 -1
  51. package/dist/irdevices/lights.d.ts +1 -0
  52. package/dist/irdevices/lights.d.ts.map +1 -1
  53. package/dist/irdevices/lights.js +6 -0
  54. package/dist/irdevices/lights.js.map +1 -1
  55. package/dist/irdevices/others.d.ts +1 -0
  56. package/dist/irdevices/others.d.ts.map +1 -1
  57. package/dist/irdevices/others.js +6 -0
  58. package/dist/irdevices/others.js.map +1 -1
  59. package/dist/irdevices/tvs.d.ts +1 -0
  60. package/dist/irdevices/tvs.d.ts.map +1 -1
  61. package/dist/irdevices/tvs.js +6 -0
  62. package/dist/irdevices/tvs.js.map +1 -1
  63. package/dist/irdevices/vacuumcleaners.d.ts +1 -0
  64. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  65. package/dist/irdevices/vacuumcleaners.js +6 -0
  66. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  67. package/dist/irdevices/waterheaters.d.ts +1 -0
  68. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  69. package/dist/irdevices/waterheaters.js +6 -0
  70. package/dist/irdevices/waterheaters.js.map +1 -1
  71. package/dist/platform.d.ts +2 -1
  72. package/dist/platform.d.ts.map +1 -1
  73. package/dist/platform.js +14 -1
  74. package/dist/platform.js.map +1 -1
  75. package/dist/settings.d.ts +6 -0
  76. package/dist/settings.d.ts.map +1 -1
  77. package/dist/settings.js.map +1 -1
  78. package/package.json +5 -5
  79. package/src/devices/bots.ts +43 -44
  80. package/src/devices/colorbulb.ts +24 -14
  81. package/src/devices/contact.ts +72 -108
  82. package/src/devices/curtains.ts +60 -36
  83. package/src/devices/humidifiers.ts +36 -36
  84. package/src/devices/meters.ts +79 -113
  85. package/src/devices/motion.ts +66 -91
  86. package/src/devices/plugs.ts +11 -2
  87. package/src/irdevices/airconditioners.ts +7 -0
  88. package/src/irdevices/airpurifiers.ts +7 -0
  89. package/src/irdevices/cameras.ts +7 -0
  90. package/src/irdevices/fans.ts +7 -0
  91. package/src/irdevices/lights.ts +7 -0
  92. package/src/irdevices/others.ts +7 -0
  93. package/src/irdevices/tvs.ts +7 -0
  94. package/src/irdevices/vacuumcleaners.ts +7 -0
  95. package/src/irdevices/waterheaters.ts +7 -0
  96. package/src/platform.ts +14 -1
  97. package/src/settings.ts +6 -0
@@ -2,7 +2,7 @@ import { interval, Subject } from 'rxjs';
2
2
  import { skipWhile } from 'rxjs/operators';
3
3
  import { SwitchBotPlatform } from '../platform';
4
4
  import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
5
- import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, temperature } from '../settings';
5
+ import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, temperature, deviceStatus } from '../settings';
6
6
 
7
7
  /**
8
8
  * Platform Accessory
@@ -11,28 +11,30 @@ import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceSta
11
11
  */
12
12
  export class Meter {
13
13
  // Services
14
- private service: Service;
15
- temperatureservice?: Service;
16
- humidityservice?: Service;
14
+ private batteryService?: Service;
15
+ private temperatureservice?: Service;
16
+ private humidityservice?: Service;
17
17
 
18
18
  // Characteristic Values
19
19
  CurrentRelativeHumidity!: CharacteristicValue;
20
20
  CurrentRelativeHumidityCached!: CharacteristicValue;
21
- CurrentTemperature!: CharacteristicValue;
22
- CurrentTemperatureCached!: CharacteristicValue;
23
- BatteryLevel!: CharacteristicValue;
24
- BatteryLevelCached!: CharacteristicValue;
25
- ChargingState!: CharacteristicValue;
26
- StatusLowBattery!: CharacteristicValue;
21
+ CurrentTemperature?: CharacteristicValue;
22
+ CurrentTemperatureCached?: CharacteristicValue;
23
+ BatteryLevel?: CharacteristicValue;
24
+ ChargingState?: CharacteristicValue;
25
+ StatusLowBattery?: CharacteristicValue;
27
26
  Active!: CharacteristicValue;
28
27
  WaterLevel!: CharacteristicValue;
29
28
 
30
29
  // OpenAPI Others
30
+ Temperature: deviceStatus['temperature'];
31
+ Humidity: deviceStatus['humidity'];
31
32
  deviceStatus!: deviceStatusResponse;
32
33
 
33
34
  // BLE Others
34
35
  connected?: boolean;
35
36
  switchbot!: switchbot;
37
+ SwitchToOpenAPI?: boolean;
36
38
  serviceData!: serviceData;
37
39
  temperature!: temperature['c'];
38
40
  battery!: serviceData['battery'];
@@ -56,17 +58,7 @@ export class Meter {
56
58
  this.logs();
57
59
  this.scan();
58
60
  this.refreshRate();
59
- if (this.BatteryLevel === undefined) {
60
- this.BatteryLevel = 100;
61
- } else {
62
- this.BatteryLevel = this.accessory.context.BatteryLevel;
63
- }
64
- if (this.BatteryLevel < 15) {
65
- this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
66
- } else {
67
- this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
68
- }
69
- this.ChargingState = this.platform.Characteristic.ChargingState.NOT_CHARGEABLE;
61
+ this.config(device);
70
62
  if (this.CurrentRelativeHumidity === undefined) {
71
63
  this.CurrentRelativeHumidity = 0;
72
64
  } else {
@@ -96,26 +88,6 @@ export class Meter {
96
88
  .setCharacteristic(this.platform.Characteristic.Model, 'SWITCHBOT-METERTH-S1')
97
89
  .setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
98
90
 
99
- // get the Battery service if it exists, otherwise create a new Battery service
100
- // you can create multiple services for each accessory
101
- (this.service =
102
- accessory.getService(this.platform.Service.Battery) ||
103
- accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
104
-
105
- // To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
106
- // when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
107
- // accessory.getService('NAME') ?? accessory.addService(this.platform.Service.Battery, 'NAME', 'USER_DEFINED_SUBTYPE');
108
-
109
- // set the service name, this is what is displayed as the default name on the Home app
110
- // in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
111
- this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
112
-
113
- // each service must implement at-minimum the "required characteristics" for the given service type
114
- // see https://developers.homebridge.io/#/service/Battery
115
-
116
- // create handlers for required characteristics
117
- this.service.setCharacteristic(this.platform.Characteristic.ChargingState, 2);
118
-
119
91
  // Temperature Sensor Service
120
92
  if (device.meter?.hide_temperature) {
121
93
  this.debugLog(`Meter: ${accessory.displayName} Removing Temperature Sensor Service`);
@@ -127,7 +99,7 @@ export class Meter {
127
99
  this.accessory.getService(this.platform.Service.TemperatureSensor) ||
128
100
  this.accessory.addService(this.platform.Service.TemperatureSensor)), `${accessory.displayName} Temperature Sensor`;
129
101
 
130
- this.service.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Temperature Sensor`);
102
+ this.temperatureservice.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Temperature Sensor`);
131
103
 
132
104
  this.temperatureservice
133
105
  .getCharacteristic(this.platform.Characteristic.CurrentTemperature)
@@ -139,7 +111,7 @@ export class Meter {
139
111
  minStep: 0.1,
140
112
  })
141
113
  .onGet(() => {
142
- return this.CurrentTemperature;
114
+ return this.CurrentTemperature!;
143
115
  });
144
116
  } else {
145
117
  this.debugLog(`Meter: ${accessory.displayName} Temperature Sensor Service Not Added`);
@@ -156,7 +128,7 @@ export class Meter {
156
128
  this.accessory.getService(this.platform.Service.HumiditySensor) ||
157
129
  this.accessory.addService(this.platform.Service.HumiditySensor)), `${accessory.displayName} Humidity Sensor`;
158
130
 
159
- this.service.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Humidity Sensor`);
131
+ this.humidityservice.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Humidity Sensor`);
160
132
 
161
133
  this.humidityservice
162
134
  .getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)
@@ -170,6 +142,27 @@ export class Meter {
170
142
  this.debugLog(`Meter: ${accessory.displayName} Humidity Sensor Service Not Added`);
171
143
  }
172
144
 
145
+ // Battery Service
146
+ if (!device.ble) {
147
+ this.debugLog(`Meter: ${accessory.displayName} Removing Battery Service`);
148
+ this.batteryService = this.accessory.getService(this.platform.Service.Battery);
149
+ accessory.removeService(this.batteryService!);
150
+ } else if (device.ble && !this.batteryService) {
151
+ this.debugLog(`Meter: ${accessory.displayName} Add Battery Service`);
152
+ (this.batteryService =
153
+ this.accessory.getService(this.platform.Service.Battery) ||
154
+ this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
155
+
156
+ this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
157
+
158
+ this.batteryService.setCharacteristic(this.platform.Characteristic.ChargingState, this.platform.Characteristic.ChargingState.NOT_CHARGEABLE);
159
+
160
+ } else {
161
+ this.debugLog(`Meter: ${accessory.displayName} Battery Service Not Added`);
162
+ }
163
+
164
+
165
+
173
166
  // Retrieve initial values and updateHomekit
174
167
  this.updateHomeKitCharacteristics();
175
168
 
@@ -181,6 +174,12 @@ export class Meter {
181
174
  });
182
175
  }
183
176
 
177
+ config(device: device & devicesConfig) {
178
+ if (device.meter !== undefined || device.ble !== undefined) {
179
+ this.warnLog(`Meter: ${this.accessory.displayName} Config: ${JSON.stringify(device.meter)}, BLE: ${device.ble}`);
180
+ }
181
+ }
182
+
184
183
  refreshRate() {
185
184
  if (this.device.refreshRate) {
186
185
  this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
@@ -232,10 +231,10 @@ export class Meter {
232
231
  * Parse the device status from the SwitchBot api
233
232
  */
234
233
  async parseStatus() {
235
- if (this.device.ble) {
236
- await this.BLEparseStatus();
237
- } else {
234
+ if (this.SwitchToOpenAPI || !this.device.ble) {
238
235
  await this.openAPIparseStatus();
236
+ } else {
237
+ await this.BLEparseStatus();
239
238
  }
240
239
  }
241
240
 
@@ -251,9 +250,9 @@ export class Meter {
251
250
  }
252
251
  this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
253
252
 
253
+ // Humidity
254
254
  if (!this.device.meter?.hide_humidity) {
255
- // Humidity
256
- this.CurrentRelativeHumidity = Number(this.humidity);
255
+ this.CurrentRelativeHumidity = this.humidity!;
257
256
  this.debugLog(`Meter: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
258
257
  }
259
258
 
@@ -266,27 +265,20 @@ export class Meter {
266
265
  }
267
266
 
268
267
  private async openAPIparseStatus() {
268
+ if (this.device.ble) {
269
+ this.SwitchToOpenAPI = false;
270
+ }
269
271
  if (this.platform.config.credentials?.openToken) {
270
272
  this.debugLog(`Meter: ${this.accessory.displayName} OpenAPI parseStatus`);
271
- if (this.deviceStatus.body) {
272
- this.BatteryLevel = 100;
273
- } else {
274
- this.BatteryLevel = 10;
275
- }
276
- if (this.BatteryLevel < 15) {
277
- this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
278
- } else {
279
- this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
280
- }
281
273
  // Current Relative Humidity
282
274
  if (!this.device.meter?.hide_humidity) {
283
- this.CurrentRelativeHumidity = this.deviceStatus.body.humidity!;
275
+ this.CurrentRelativeHumidity = this.Humidity!;
284
276
  this.debugLog(`Meter: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
285
277
  }
286
278
 
287
279
  // Current Temperature
288
280
  if (!this.device.meter?.hide_temperature) {
289
- this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
281
+ this.CurrentTemperature = this.Temperature!;
290
282
  this.debugLog(`Meter: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
291
283
  }
292
284
  }
@@ -303,34 +295,12 @@ export class Meter {
303
295
  }
304
296
  }
305
297
 
306
- private async connectBLE() {
307
- let switchbot: any;
308
- try {
309
- // eslint-disable-next-line @typescript-eslint/no-var-requires
310
- const Switchbot = require('node-switchbot');
311
- switchbot = new Switchbot();
312
- // Convert to BLE Address
313
- this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
314
- this.debugLog(`Meter: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
315
- } catch (e: any) {
316
- switchbot = false;
317
- this.errorLog(`Meter: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot}`);
318
- if (this.deviceLogging === 'debug') {
319
- this.errorLog(`Meter: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
320
- + ` Error Message: ${JSON.stringify(e.message)}`);
321
- }
322
- if (this.platform.debugMode) {
323
- this.errorLog(`Meter: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
324
- + ` Error: ${JSON.stringify(e)}`);
325
- }
326
- }
327
- return switchbot;
328
- }
329
-
330
298
  private async BLErefreshStatus() {
331
299
  this.debugLog(`Meter: ${this.accessory.displayName} BLE RefreshStatus`);
332
- // eslint-disable-next-line @typescript-eslint/no-var-requires
333
- const switchbot = await this.connectBLE();
300
+ const switchbot = await this.platform.connectBLE();
301
+ // Convert to BLE Address
302
+ this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
303
+ this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
334
304
  // Start to monitor advertisement packets
335
305
  if (switchbot !== false) {
336
306
  switchbot.startScan({
@@ -362,12 +332,6 @@ export class Meter {
362
332
  // Stop to monitor
363
333
  switchbot.stopScan();
364
334
  if (this.connected) {
365
- this.CurrentTemperatureCached = this.temperature;
366
- this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
367
- this.CurrentRelativeHumidityCached = this.humidity!;
368
- this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
369
- this.BatteryLevelCached = this.battery!;
370
- this.accessory.context.BatteryLevel = this.BatteryLevelCached;
371
335
  this.parseStatus();
372
336
  this.updateHomeKitCharacteristics();
373
337
  } else {
@@ -385,6 +349,7 @@ export class Meter {
385
349
  }
386
350
  if (this.platform.config.credentials?.openToken) {
387
351
  this.warnLog(`Meter: ${this.accessory.displayName} Using OpenAPI Connection`);
352
+ this.SwitchToOpenAPI = true;
388
353
  this.openAPIRefreshStatus();
389
354
  }
390
355
  this.apiError(e);
@@ -398,6 +363,7 @@ export class Meter {
398
363
  this.errorLog(`Meter: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
399
364
  if (this.platform.config.credentials?.openToken) {
400
365
  this.warnLog(`Meter: ${this.accessory.displayName} Using OpenAPI Connection`);
366
+ this.SwitchToOpenAPI = true;
401
367
  await this.openAPIRefreshStatus();
402
368
  }
403
369
  }
@@ -408,12 +374,8 @@ export class Meter {
408
374
  try {
409
375
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
410
376
  this.debugLog(`Meter: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
411
- this.CurrentTemperatureCached = this.deviceStatus.body.humidity!;
412
- this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
413
- this.CurrentRelativeHumidityCached = this.deviceStatus.body.humidity!;
414
- this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
415
- this.BatteryLevelCached = 100;
416
- this.accessory.context.BatteryLevel = this.BatteryLevelCached;
377
+ this.Humidity = this.deviceStatus.body.humidity!;
378
+ this.Temperature = this.deviceStatus.body.temperature!;
417
379
  this.parseStatus();
418
380
  this.updateHomeKitCharacteristics();
419
381
  } catch (e: any) {
@@ -435,18 +397,6 @@ export class Meter {
435
397
  * Updates the status for each of the HomeKit Characteristics
436
398
  */
437
399
  updateHomeKitCharacteristics() {
438
- if (this.StatusLowBattery === undefined) {
439
- this.debugLog(`Meter: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
440
- } else {
441
- this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
442
- this.debugLog(`Meter: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
443
- }
444
- if (this.BatteryLevel === undefined) {
445
- this.debugLog(`Meter: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
446
- } else {
447
- this.service.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
448
- this.debugLog(`Meter: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
449
- }
450
400
  if (!this.device.meter?.hide_humidity) {
451
401
  if (this.CurrentRelativeHumidity === undefined) {
452
402
  this.debugLog(`Meter: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
@@ -463,17 +413,33 @@ export class Meter {
463
413
  this.debugLog(`Meter: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
464
414
  }
465
415
  }
416
+ if (this.device.ble) {
417
+ if (this.BatteryLevel === undefined) {
418
+ this.debugLog(`Bot: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
419
+ } else {
420
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
421
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
422
+ }
423
+ if (this.StatusLowBattery === undefined) {
424
+ this.debugLog(`Bot: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
425
+ } else {
426
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
427
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
428
+ }
429
+ }
466
430
  }
467
431
 
468
432
  public apiError(e: any) {
469
- this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
470
- this.service.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
471
433
  if (!this.device.meter?.hide_humidity) {
472
434
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
473
435
  }
474
436
  if (!this.device.meter?.hide_temperature) {
475
437
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
476
438
  }
439
+ if (this.device.ble) {
440
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
441
+ this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
442
+ }
477
443
  //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
478
444
  }
479
445
 
@@ -2,7 +2,7 @@ import { interval, Subject } from 'rxjs';
2
2
  import { skipWhile } from 'rxjs/operators';
3
3
  import { SwitchBotPlatform } from '../platform';
4
4
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
5
- import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse } from '../settings';
5
+ import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, deviceStatus } from '../settings';
6
6
 
7
7
  /**
8
8
  * Platform Accessory
@@ -23,10 +23,13 @@ export class Motion {
23
23
 
24
24
  // OpenAPI Others
25
25
  deviceStatus!: deviceStatusResponse;
26
+ moveDetected: deviceStatus['moveDetected'];
27
+ brightness: deviceStatus['brightness'];
26
28
 
27
29
  // BLE Others
28
30
  connected?: boolean;
29
31
  switchbot!: switchbot;
32
+ SwitchToOpenAPI?: boolean;
30
33
  serviceData!: serviceData;
31
34
  battery!: serviceData['battery'];
32
35
  movement!: serviceData['movement'];
@@ -52,6 +55,7 @@ export class Motion {
52
55
  this.logs();
53
56
  this.scan();
54
57
  this.refreshRate();
58
+ this.config(device);
55
59
  this.MotionDetected = false;
56
60
 
57
61
  // Motion Config
@@ -108,12 +112,20 @@ export class Motion {
108
112
  }
109
113
 
110
114
  // Battery Service
111
- if (device.ble) {
115
+ if (!device.ble) {
116
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Removing Battery Service`);
117
+ this.batteryService = this.accessory.getService(this.platform.Service.Battery);
118
+ accessory.removeService(this.batteryService!);
119
+ } else if (device.ble && !this.batteryService) {
120
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Add Battery Service`);
112
121
  (this.batteryService =
113
- accessory.getService(this.platform.Service.Battery) ||
114
- accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
122
+ this.accessory.getService(this.platform.Service.Battery) ||
123
+ this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
115
124
 
116
125
  this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
126
+
127
+ } else {
128
+ this.debugLog(`Motion Sensor: ${accessory.displayName} Battery Service Not Added`);
117
129
  }
118
130
 
119
131
  // Retrieve initial values and updateHomekit
@@ -127,6 +139,12 @@ export class Motion {
127
139
  });
128
140
  }
129
141
 
142
+ config(device: device & devicesConfig) {
143
+ if (device.motion !== undefined) {
144
+ this.warnLog(`Motion Sensor: ${this.accessory.displayName} Config: ${JSON.stringify(device.motion)}`);
145
+ }
146
+ }
147
+
130
148
  refreshRate() {
131
149
  if (this.device.refreshRate) {
132
150
  this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
@@ -196,42 +214,38 @@ export class Motion {
196
214
  * Parse the device status from the SwitchBot api
197
215
  */
198
216
  async parseStatus() {
199
- if (this.device.ble) {
200
- await this.BLEparseStatus();
201
- } else {
217
+ if (this.SwitchToOpenAPI || !this.device.ble) {
202
218
  await this.openAPIparseStatus();
219
+ } else {
220
+ await this.BLEparseStatus();
203
221
  }
204
222
  }
205
223
 
206
224
  private async BLEparseStatus() {
207
225
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE parseStatus`);
208
226
  // Movement
209
- if (this.movement === undefined && this.platform.config.credentials?.openToken) {
210
- this.openAPImotion();
211
- } else if (this.movement === undefined) {
212
- this.movement = false;
213
- this.BLEmotion();
214
- } else {
215
- this.BLEmotion();
216
- }
227
+ this.MotionDetected = this.movement!;
228
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
217
229
  // Light Level
218
230
  if (!this.device.motion?.hide_lightsensor) {
219
231
  this.set_minLux = this.minLux();
220
232
  this.set_maxLux = this.maxLux();
221
- if (this.lightLevel === undefined && this.platform.config.credentials?.openToken) {
222
- this.openAPIlux();
223
- } else if (this.lightLevel === undefined) {
224
- this.lightLevel = 100;
225
- this.BLElux();
226
- } else {
227
- this.BLElux();
233
+ switch (this.lightLevel) {
234
+ case 'dark':
235
+ case 1:
236
+ this.CurrentAmbientLightLevel = this.set_minLux;
237
+ break;
238
+ default:
239
+ this.CurrentAmbientLightLevel = this.set_maxLux;
228
240
  }
241
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
242
+ + ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
229
243
  }
230
244
  // Battery
231
245
  if (this.battery === undefined) {
232
246
  this.battery = 100;
233
247
  }
234
- this.BatteryLevel = Number(this.battery);
248
+ this.BatteryLevel = this.battery!;
235
249
  if (this.BatteryLevel < 10) {
236
250
  this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
237
251
  } else {
@@ -240,55 +254,31 @@ export class Motion {
240
254
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
241
255
  }
242
256
 
243
- private BLEmotion() {
244
- this.MotionDetected = Boolean(this.movement);
245
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
246
- }
247
-
248
- private BLElux() {
249
- switch (this.lightLevel) {
250
- case 'dark':
251
- case 1:
252
- this.CurrentAmbientLightLevel = this.set_minLux;
253
- break;
254
- default:
255
- this.CurrentAmbientLightLevel = this.set_maxLux;
256
- }
257
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
258
- + ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
259
- }
260
-
261
257
  private async openAPIparseStatus() {
258
+ if (this.device.ble) {
259
+ this.SwitchToOpenAPI = false;
260
+ }
262
261
  if (this.platform.config.credentials?.openToken) {
263
262
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
264
263
  // Motion State
265
- this.openAPImotion();
264
+ this.MotionDetected = this.moveDetected!;
265
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
266
266
  // Light Level
267
267
  if (!this.device.motion?.hide_lightsensor) {
268
- this.openAPIlux();
269
- }
270
- }
271
- }
272
-
273
- private openAPImotion() {
274
- if (typeof this.deviceStatus.body.moveDetected === 'boolean') {
275
- this.MotionDetected = this.deviceStatus.body.moveDetected;
276
- }
277
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
278
- }
268
+ this.set_minLux = this.minLux();
269
+ this.set_maxLux = this.maxLux();
270
+ switch (this.brightness) {
271
+ case 'dim':
272
+ this.CurrentAmbientLightLevel = this.set_minLux;
273
+ break;
274
+ case 'bright':
275
+ default:
276
+ this.CurrentAmbientLightLevel = this.set_maxLux;
277
+ }
278
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
279
279
 
280
- private openAPIlux() {
281
- this.set_minLux = this.minLux();
282
- this.set_maxLux = this.maxLux();
283
- switch (this.deviceStatus.body.brightness) {
284
- case 'dim':
285
- this.CurrentAmbientLightLevel = this.set_minLux;
286
- break;
287
- case 'bright':
288
- default:
289
- this.CurrentAmbientLightLevel = this.set_maxLux;
280
+ }
290
281
  }
291
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
292
282
  }
293
283
 
294
284
  /**
@@ -302,38 +292,16 @@ export class Motion {
302
292
  }
303
293
  }
304
294
 
305
- public async connectBLE() {
306
- let switchbot: any;
307
- try {
308
- // eslint-disable-next-line @typescript-eslint/no-var-requires
309
- const Switchbot = require('node-switchbot');
310
- switchbot = new Switchbot();
311
- // Convert to BLE Address
312
- this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
313
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
314
- } catch (e: any) {
315
- switchbot = false;
316
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot}`);
317
- if (this.deviceLogging === 'debug') {
318
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
319
- + ` Error Message: ${JSON.stringify(e.message)}`);
320
- }
321
- if (this.platform.debugMode) {
322
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
323
- + ` Error: ${JSON.stringify(e)}`);
324
- }
325
- }
326
- return switchbot;
327
- }
328
-
329
295
  private async BLERefreshStatus() {
330
296
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE RefreshStatus`);
331
- // eslint-disable-next-line @typescript-eslint/no-var-requires
332
- const switchbot = await this.connectBLE();
297
+ const switchbot = await this.platform.connectBLE();
298
+ // Convert to BLE Address
299
+ this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
300
+ this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
333
301
  // Start to monitor advertisement packets
334
302
  if (switchbot !== false) {
335
303
  switchbot.startScan({
336
- //model: 's',
304
+ model: 's',
337
305
  id: this.device.bleMac,
338
306
  }).then(() => {
339
307
  // Set an event hander
@@ -377,6 +345,7 @@ export class Motion {
377
345
  }
378
346
  if (this.platform.config.credentials?.openToken) {
379
347
  this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
348
+ this.SwitchToOpenAPI = true;
380
349
  await this.openAPIRefreshStatus();
381
350
  }
382
351
  this.apiError(e);
@@ -390,6 +359,7 @@ export class Motion {
390
359
  this.errorLog(`Motion Sensor: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
391
360
  if (this.platform.config.credentials?.openToken) {
392
361
  this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
362
+ this.SwitchToOpenAPI = true;
393
363
  await this.openAPIRefreshStatus();
394
364
  }
395
365
  }
@@ -400,6 +370,11 @@ export class Motion {
400
370
  try {
401
371
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
402
372
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
373
+ if (this.deviceStatus.body.moveDetected === undefined) {
374
+ this.errorLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
375
+ }
376
+ this.moveDetected = this.deviceStatus.body.moveDetected;
377
+ this.brightness = this.deviceStatus.body.brightness;
403
378
  this.parseStatus();
404
379
  this.updateHomeKitCharacteristics();
405
380
  } catch (e: any) {
@@ -4,7 +4,7 @@ import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform';
5
5
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
6
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
7
- import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
7
+ import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload, deviceStatus } from '../settings';
8
8
 
9
9
  export class Plug {
10
10
  // Services
@@ -15,6 +15,7 @@ export class Plug {
15
15
  OnCached!: CharacteristicValue;
16
16
 
17
17
  // OpenAPI Others
18
+ power: deviceStatus['power'];
18
19
  deviceStatus!: deviceStatusResponse;
19
20
 
20
21
  // Config
@@ -35,6 +36,7 @@ export class Plug {
35
36
  this.logs();
36
37
  this.scan();
37
38
  this.refreshRate();
39
+ this.config(device);
38
40
  if (this.On === undefined) {
39
41
  this.On = false;
40
42
  } else {
@@ -116,6 +118,12 @@ export class Plug {
116
118
  });
117
119
  }
118
120
 
121
+ config(device: device & devicesConfig) {
122
+ if (device.plug !== undefined) {
123
+ this.warnLog(`Plug: ${this.accessory.displayName} Config: ${JSON.stringify(device.plug)}`);
124
+ }
125
+ }
126
+
119
127
  refreshRate() {
120
128
  if (this.device.refreshRate) {
121
129
  this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
@@ -164,7 +172,7 @@ export class Plug {
164
172
  }
165
173
 
166
174
  parseStatus() {
167
- switch (this.deviceStatus.body.power) {
175
+ switch (this.power) {
168
176
  case 'on':
169
177
  this.On = true;
170
178
  break;
@@ -178,6 +186,7 @@ export class Plug {
178
186
  try {
179
187
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
180
188
  this.debugLog(`Plug: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
189
+ this.power = this.deviceStatus.body.power;
181
190
  this.parseStatus();
182
191
  this.updateHomeKitCharacteristics();
183
192
  } catch (e: any) {