@switchbot/homebridge-switchbot 3.6.1-beta.1 → 3.6.1-beta.11

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 (136) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/device/blindtilt.d.ts.map +1 -1
  3. package/dist/device/blindtilt.js +44 -17
  4. package/dist/device/blindtilt.js.map +1 -1
  5. package/dist/device/bot.d.ts +1 -2
  6. package/dist/device/bot.d.ts.map +1 -1
  7. package/dist/device/bot.js +220 -397
  8. package/dist/device/bot.js.map +1 -1
  9. package/dist/device/ceilinglight.d.ts +3 -2
  10. package/dist/device/ceilinglight.d.ts.map +1 -1
  11. package/dist/device/ceilinglight.js +59 -31
  12. package/dist/device/ceilinglight.js.map +1 -1
  13. package/dist/device/colorbulb.d.ts +3 -2
  14. package/dist/device/colorbulb.d.ts.map +1 -1
  15. package/dist/device/colorbulb.js +57 -29
  16. package/dist/device/colorbulb.js.map +1 -1
  17. package/dist/device/contact.d.ts.map +1 -1
  18. package/dist/device/contact.js +47 -18
  19. package/dist/device/contact.js.map +1 -1
  20. package/dist/device/curtain.d.ts.map +1 -1
  21. package/dist/device/curtain.js +16 -5
  22. package/dist/device/curtain.js.map +1 -1
  23. package/dist/device/device.d.ts +9 -0
  24. package/dist/device/device.d.ts.map +1 -1
  25. package/dist/device/device.js +30 -3
  26. package/dist/device/device.js.map +1 -1
  27. package/dist/device/fan.d.ts.map +1 -1
  28. package/dist/device/fan.js +44 -18
  29. package/dist/device/fan.js.map +1 -1
  30. package/dist/device/hub.d.ts.map +1 -1
  31. package/dist/device/hub.js +46 -18
  32. package/dist/device/hub.js.map +1 -1
  33. package/dist/device/humidifier.d.ts.map +1 -1
  34. package/dist/device/humidifier.js +45 -20
  35. package/dist/device/humidifier.js.map +1 -1
  36. package/dist/device/iosensor.d.ts.map +1 -1
  37. package/dist/device/iosensor.js +46 -18
  38. package/dist/device/iosensor.js.map +1 -1
  39. package/dist/device/lightstrip.d.ts +4 -3
  40. package/dist/device/lightstrip.d.ts.map +1 -1
  41. package/dist/device/lightstrip.js +60 -31
  42. package/dist/device/lightstrip.js.map +1 -1
  43. package/dist/device/lock.d.ts.map +1 -1
  44. package/dist/device/lock.js +48 -17
  45. package/dist/device/lock.js.map +1 -1
  46. package/dist/device/meter.d.ts.map +1 -1
  47. package/dist/device/meter.js +46 -18
  48. package/dist/device/meter.js.map +1 -1
  49. package/dist/device/meterplus.d.ts.map +1 -1
  50. package/dist/device/meterplus.js +46 -18
  51. package/dist/device/meterplus.js.map +1 -1
  52. package/dist/device/motion.d.ts.map +1 -1
  53. package/dist/device/motion.js +45 -17
  54. package/dist/device/motion.js.map +1 -1
  55. package/dist/device/plug.d.ts.map +1 -1
  56. package/dist/device/plug.js +40 -18
  57. package/dist/device/plug.js.map +1 -1
  58. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  59. package/dist/device/robotvacuumcleaner.js +42 -17
  60. package/dist/device/robotvacuumcleaner.js.map +1 -1
  61. package/dist/device/waterdetector.d.ts.map +1 -1
  62. package/dist/device/waterdetector.js +41 -16
  63. package/dist/device/waterdetector.js.map +1 -1
  64. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  65. package/dist/irdevice/airconditioner.js +8 -1
  66. package/dist/irdevice/airconditioner.js.map +1 -1
  67. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  68. package/dist/irdevice/airpurifier.js +6 -0
  69. package/dist/irdevice/airpurifier.js.map +1 -1
  70. package/dist/irdevice/camera.d.ts.map +1 -1
  71. package/dist/irdevice/camera.js +3 -0
  72. package/dist/irdevice/camera.js.map +1 -1
  73. package/dist/irdevice/fan.d.ts.map +1 -1
  74. package/dist/irdevice/fan.js +3 -0
  75. package/dist/irdevice/fan.js.map +1 -1
  76. package/dist/irdevice/irdevice.d.ts +9 -0
  77. package/dist/irdevice/irdevice.d.ts.map +1 -1
  78. package/dist/irdevice/irdevice.js +29 -2
  79. package/dist/irdevice/irdevice.js.map +1 -1
  80. package/dist/irdevice/light.d.ts.map +1 -1
  81. package/dist/irdevice/light.js +9 -0
  82. package/dist/irdevice/light.js.map +1 -1
  83. package/dist/irdevice/other.d.ts +1 -0
  84. package/dist/irdevice/other.d.ts.map +1 -1
  85. package/dist/irdevice/other.js +216 -228
  86. package/dist/irdevice/other.js.map +1 -1
  87. package/dist/irdevice/tv.d.ts.map +1 -1
  88. package/dist/irdevice/tv.js +9 -0
  89. package/dist/irdevice/tv.js.map +1 -1
  90. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  91. package/dist/irdevice/vacuumcleaner.js +3 -0
  92. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  93. package/dist/irdevice/waterheater.js +1 -1
  94. package/dist/irdevice/waterheater.js.map +1 -1
  95. package/dist/platform.d.ts.map +1 -1
  96. package/dist/platform.js +11 -2
  97. package/dist/platform.js.map +1 -1
  98. package/dist/types/bledevicestatus.d.ts +1 -0
  99. package/dist/types/bledevicestatus.d.ts.map +1 -1
  100. package/dist/utils.d.ts +8 -0
  101. package/dist/utils.d.ts.map +1 -1
  102. package/dist/utils.js +16 -0
  103. package/dist/utils.js.map +1 -1
  104. package/package.json +6 -6
  105. package/src/device/blindtilt.ts +44 -17
  106. package/src/device/bot.ts +224 -407
  107. package/src/device/ceilinglight.ts +57 -33
  108. package/src/device/colorbulb.ts +55 -31
  109. package/src/device/contact.ts +48 -19
  110. package/src/device/curtain.ts +19 -6
  111. package/src/device/device.ts +36 -3
  112. package/src/device/fan.ts +44 -19
  113. package/src/device/hub.ts +46 -18
  114. package/src/device/humidifier.ts +44 -20
  115. package/src/device/iosensor.ts +46 -18
  116. package/src/device/lightstrip.ts +60 -33
  117. package/src/device/lock.ts +49 -17
  118. package/src/device/meter.ts +46 -18
  119. package/src/device/meterplus.ts +46 -18
  120. package/src/device/motion.ts +46 -18
  121. package/src/device/plug.ts +38 -18
  122. package/src/device/robotvacuumcleaner.ts +41 -17
  123. package/src/device/waterdetector.ts +40 -16
  124. package/src/irdevice/airconditioner.ts +11 -2
  125. package/src/irdevice/airpurifier.ts +8 -0
  126. package/src/irdevice/camera.ts +4 -0
  127. package/src/irdevice/fan.ts +4 -0
  128. package/src/irdevice/irdevice.ts +35 -2
  129. package/src/irdevice/light.ts +12 -0
  130. package/src/irdevice/other.ts +254 -283
  131. package/src/irdevice/tv.ts +12 -0
  132. package/src/irdevice/vacuumcleaner.ts +4 -0
  133. package/src/irdevice/waterheater.ts +1 -1
  134. package/src/platform.ts +11 -2
  135. package/src/types/bledevicestatus.ts +1 -0
  136. package/src/utils.ts +15 -0
package/src/device/hub.ts CHANGED
@@ -4,8 +4,8 @@
4
4
  */
5
5
  import { Units } from 'homebridge';
6
6
  import { deviceBase } from './device.js';
7
- import { convertUnits } from '../utils.js';
8
7
  import { Subject, interval, skipWhile} from 'rxjs';
8
+ import { validHumidity, convertUnits } from '../utils.js';
9
9
  import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot';
10
10
 
11
11
  import type { devicesConfig } from '../settings.js';
@@ -71,6 +71,10 @@ export class Hub extends deviceBase {
71
71
  }
72
72
  } else {
73
73
  accessory.context.TemperatureSensor = accessory.context.TemperatureSensor ?? {};
74
+ if (accessory.context.TemperatureSensor.Name) {
75
+ accessory.context.TemperatureSensor.Name = this.validateAndCleanString(accessory.context.TemperatureSensor.Name,
76
+ 'TemperatureSensor Name', accessory.context.TemperatureSensor.Name);
77
+ }
74
78
  this.TemperatureSensor = {
75
79
  Name: accessory.context.TemperatureSensor.Name ?? `${accessory.displayName} Temperature Sensor`,
76
80
  Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? this.accessory.addService(this.hap.Service.TemperatureSensor) as Service,
@@ -103,6 +107,10 @@ export class Hub extends deviceBase {
103
107
  }
104
108
  } else {
105
109
  accessory.context.HumiditySensor = accessory.context.HumiditySensor ?? {};
110
+ if (accessory.context.HumiditySensor.Name) {
111
+ accessory.context.HumiditySensor.Name = this.validateAndCleanString(accessory.context.HumiditySensor.Name,
112
+ 'HumiditySensor Name', accessory.context.HumiditySensor.Name);
113
+ }
106
114
  this.HumiditySensor = {
107
115
  Name: accessory.context.HumiditySensor.Name ?? `${accessory.displayName} Humidity Sensor`,
108
116
  Service: accessory.getService(this.hap.Service.HumiditySensor) ?? this.accessory.addService(this.hap.Service.HumiditySensor) as Service,
@@ -131,6 +139,10 @@ export class Hub extends deviceBase {
131
139
  }
132
140
  } else {
133
141
  accessory.context.LightSensor = accessory.context.LightSensor ?? {};
142
+ if (accessory.context.LightSensor.Name) {
143
+ accessory.context.LightSensor.Name = this.validateAndCleanString(accessory.context.LightSensor.Name,
144
+ 'LightSensor Name', accessory.context.LightSensor.Name);
145
+ }
134
146
  this.LightSensor = {
135
147
  Name: accessory.context.LightSensor.Name ?? `${accessory.displayName} Light Sensor`,
136
148
  Service: accessory.getService(this.hap.Service.LightSensor) ?? this.accessory.addService(this.hap.Service.LightSensor) as Service,
@@ -181,7 +193,7 @@ export class Hub extends deviceBase {
181
193
 
182
194
  // CurrentRelativeHumidity
183
195
  if (!this.device.hub?.hide_humidity && this.HumiditySensor?.Service) {
184
- this.HumiditySensor!.CurrentRelativeHumidity = this.serviceData.humidity;
196
+ this.HumiditySensor!.CurrentRelativeHumidity = validHumidity(this.serviceData.humidity, 0, 100);
185
197
  await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`);
186
198
  }
187
199
 
@@ -290,25 +302,41 @@ export class Hub extends deviceBase {
290
302
 
291
303
  async BLERefreshStatus(): Promise<void> {
292
304
  await this.debugLog('BLERefreshStatus');
293
- const switchbot = await this.switchbotBLE();
294
-
295
- if (switchbot === undefined) {
296
- await this.BLERefreshConnection(switchbot);
297
- } else {
298
- // Start to monitor advertisement packets
299
- (async () => {
300
- // Start to monitor advertisement packets
301
- const serviceData = await this.monitorAdvertisementPackets(switchbot) as hub2ServiceData;
302
- // Update HomeKit
303
- if (serviceData.model === SwitchBotBLEModel.Hub2 && serviceData.modelName === SwitchBotBLEModelName.Hub2) {
304
- this.serviceData = serviceData;
305
+ if (this.config.options?.BLE) {
306
+ await this.debugLog('is listening to Platform BLE.');
307
+ this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
308
+ await this.debugLog(`bleMac: ${this.device.bleMac}`);
309
+ this.platform.bleEventHandler[this.device.bleMac] = async (context: hub2ServiceData) => {
310
+ try {
311
+ await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
312
+ this.serviceData = context;
305
313
  await this.BLEparseStatus();
306
314
  await this.updateHomeKitCharacteristics();
307
- } else {
308
- await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
309
- await this.BLERefreshConnection(switchbot);
315
+ } catch (e: any) {
316
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
310
317
  }
311
- })();
318
+ };
319
+ } else {
320
+ await this.debugLog('is using Device BLE Scanning.');
321
+ const switchbot = await this.switchbotBLE();
322
+ if (switchbot === undefined) {
323
+ await this.BLERefreshConnection(switchbot);
324
+ } else {
325
+ // Start to monitor advertisement packets
326
+ (async () => {
327
+ // Start to monitor advertisement packets
328
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as hub2ServiceData;
329
+ // Update HomeKit
330
+ if (serviceData.model === SwitchBotBLEModel.Hub2 && serviceData.modelName === SwitchBotBLEModelName.Hub2) {
331
+ this.serviceData = serviceData;
332
+ await this.BLEparseStatus();
333
+ await this.updateHomeKitCharacteristics();
334
+ } else {
335
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
336
+ await this.BLERefreshConnection(switchbot);
337
+ }
338
+ })();
339
+ }
312
340
  }
313
341
  }
314
342
 
@@ -3,7 +3,7 @@
3
3
  * humidifier.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
5
  import { deviceBase } from './device.js';
6
- import { convertUnits } from '../utils.js';
6
+ import { convertUnits, validHumidity } from '../utils.js';
7
7
  import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot';
8
8
  import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
9
9
 
@@ -67,6 +67,10 @@ export class Humidifier extends deviceBase {
67
67
 
68
68
  // Initialize the HumidifierDehumidifier Service
69
69
  accessory.context.HumidifierDehumidifier = accessory.context.HumidifierDehumidifier ?? {};
70
+ if (accessory.context.HumidifierDehumidifier.Name) {
71
+ accessory.context.HumidifierDehumidifier.Name = this.validateAndCleanString(accessory.context.HumidifierDehumidifier.Name,
72
+ 'HumidifierDehumidifier Name', accessory.context.HumidifierDehumidifier.Name);
73
+ }
70
74
  this.HumidifierDehumidifier = {
71
75
  Name: accessory.context.HumidifierDehumidifier.Name ?? accessory.displayName,
72
76
  Service: accessory.getService(this.hap.Service.HumidifierDehumidifier)
@@ -128,6 +132,10 @@ export class Humidifier extends deviceBase {
128
132
  }
129
133
  } else {
130
134
  accessory.context.TemperatureSensor = accessory.context.TemperatureSensor ?? {};
135
+ if (accessory.context.TemperatureSensor.Name) {
136
+ accessory.context.TemperatureSensor.Name = this.validateAndCleanString(accessory.context.TemperatureSensor.Name,
137
+ 'TemperatureSensor Name', accessory.context.TemperatureSensor.Name);
138
+ }
131
139
  this.TemperatureSensor = {
132
140
  Name: accessory.context.TemperatureSensor.Name ?? `${accessory.displayName} Temperature Sensor`,
133
141
  Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? this.accessory.addService(this.hap.Service.TemperatureSensor) as Service,
@@ -197,7 +205,7 @@ export class Humidifier extends deviceBase {
197
205
  await this.debugLog(`Active: ${this.HumidifierDehumidifier.Active}`);
198
206
 
199
207
  // Current Relative Humidity
200
- this.HumidifierDehumidifier.CurrentRelativeHumidity = this.serviceData.percentage;
208
+ this.HumidifierDehumidifier.CurrentRelativeHumidity = validHumidity(this.serviceData.humidity);
201
209
  await this.debugLog(`CurrentRelativeHumidity: ${this.HumidifierDehumidifier.CurrentRelativeHumidity}`);
202
210
 
203
211
  // Target Humidifier Dehumidifier State
@@ -238,7 +246,7 @@ export class Humidifier extends deviceBase {
238
246
  await this.debugLog(`Active: ${this.HumidifierDehumidifier.Active}`);
239
247
 
240
248
  // Current Relative Humidity
241
- this.HumidifierDehumidifier.CurrentRelativeHumidity = this.deviceStatus.temperature!;
249
+ this.HumidifierDehumidifier.CurrentRelativeHumidity = validHumidity(this.deviceStatus.humidity);
242
250
  await this.debugLog(`CurrentRelativeHumidity: ${this.HumidifierDehumidifier.CurrentRelativeHumidity}`);
243
251
 
244
252
  // Current Temperature
@@ -301,7 +309,7 @@ export class Humidifier extends deviceBase {
301
309
  + ` ${this.HumidifierDehumidifier.CurrentRelativeHumidity})`);
302
310
 
303
311
  // CurrentRelativeHumidity
304
- this.HumidifierDehumidifier.CurrentRelativeHumidity = this.webhookContext.humidity;
312
+ this.HumidifierDehumidifier.CurrentRelativeHumidity = validHumidity(this.webhookContext.humidity);
305
313
  await this.debugLog(`CurrentRelativeHumidity: ${this.HumidifierDehumidifier.CurrentRelativeHumidity}`);
306
314
 
307
315
  // CurrentTemperature
@@ -330,25 +338,41 @@ export class Humidifier extends deviceBase {
330
338
 
331
339
  async BLERefreshStatus(): Promise<void> {
332
340
  await this.debugLog('BLERefreshStatus');
333
- const switchbot = await this.switchbotBLE();
334
-
335
- if (switchbot === undefined) {
336
- await this.BLERefreshConnection(switchbot);
337
- } else {
338
- // Start to monitor advertisement packets
339
- (async () => {
340
- // Start to monitor advertisement packets
341
- const serviceData = await this.monitorAdvertisementPackets(switchbot) as humidifierServiceData;
342
- // Update HomeKit
343
- if (serviceData.model === SwitchBotBLEModel.Humidifier && serviceData.modelName === SwitchBotBLEModelName.Humidifier) {
344
- this.serviceData = serviceData;
341
+ if (this.config.options?.BLE) {
342
+ await this.debugLog('is listening to Platform BLE.');
343
+ this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
344
+ await this.debugLog(`bleMac: ${this.device.bleMac}`);
345
+ this.platform.bleEventHandler[this.device.bleMac] = async (context: humidifierServiceData) => {
346
+ try {
347
+ await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
348
+ this.serviceData = context;
345
349
  await this.BLEparseStatus();
346
350
  await this.updateHomeKitCharacteristics();
347
- } else {
348
- await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
349
- await this.BLERefreshConnection(switchbot);
351
+ } catch (e: any) {
352
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
350
353
  }
351
- })();
354
+ };
355
+ } else {
356
+ await this.debugLog('is using Device BLE Scanning.');
357
+ const switchbot = await this.switchbotBLE();
358
+ if (switchbot === undefined) {
359
+ await this.BLERefreshConnection(switchbot);
360
+ } else {
361
+ // Start to monitor advertisement packets
362
+ (async () => {
363
+ // Start to monitor advertisement packets
364
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as humidifierServiceData;
365
+ // Update HomeKit
366
+ if (serviceData.model === SwitchBotBLEModel.Humidifier && serviceData.modelName === SwitchBotBLEModelName.Humidifier) {
367
+ this.serviceData = serviceData;
368
+ await this.BLEparseStatus();
369
+ await this.updateHomeKitCharacteristics();
370
+ } else {
371
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
372
+ await this.BLERefreshConnection(switchbot);
373
+ }
374
+ })();
375
+ }
352
376
  }
353
377
  }
354
378
 
@@ -4,8 +4,8 @@
4
4
  */
5
5
  import { Units } from 'homebridge';
6
6
  import { deviceBase } from './device.js';
7
- import { convertUnits } from '../utils.js';
8
7
  import { Subject, interval, skipWhile } from 'rxjs';
8
+ import { convertUnits, validHumidity } from '../utils.js';
9
9
  import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot';
10
10
 
11
11
  import type { devicesConfig } from '../settings.js';
@@ -70,6 +70,10 @@ export class IOSensor extends deviceBase {
70
70
 
71
71
  // Initialize Battery Service
72
72
  accessory.context.Battery = accessory.context.Battery ?? {};
73
+ if (accessory.context.Battery.Name) {
74
+ accessory.context.Battery.Name = this.validateAndCleanString(accessory.context.Battery.Name,
75
+ 'Battery Name', accessory.context.Battery.Name);
76
+ }
73
77
  this.Battery = {
74
78
  Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
75
79
  Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
@@ -103,6 +107,10 @@ export class IOSensor extends deviceBase {
103
107
  }
104
108
  } else {
105
109
  accessory.context.TemperatureSensor = accessory.context.TemperatureSensor ?? {};
110
+ if (accessory.context.TemperatureSensor.Name) {
111
+ accessory.context.TemperatureSensor.Name = this.validateAndCleanString(accessory.context.TemperatureSensor.Name,
112
+ 'TemperatureSensor Name', accessory.context.TemperatureSensor.Name);
113
+ }
106
114
  this.TemperatureSensor = {
107
115
  Name: accessory.context.TemperatureSensor.Name ?? `${accessory.displayName} Temperature Sensor`,
108
116
  Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? this.accessory.addService(this.hap.Service.TemperatureSensor) as Service,
@@ -135,6 +143,10 @@ export class IOSensor extends deviceBase {
135
143
  }
136
144
  } else {
137
145
  accessory.context.HumiditySensor = accessory.context.HumiditySensor ?? {};
146
+ if (accessory.context.HumiditySensor.Name) {
147
+ accessory.context.HumiditySensor.Name = this.validateAndCleanString(accessory.context.HumiditySensor.Name,
148
+ 'HumiditySensor Name', accessory.context.HumiditySensor.Name);
149
+ }
138
150
  this.HumiditySensor = {
139
151
  Name: accessory.context.HumiditySensor.Name ?? `${accessory.displayName} Humidity Sensor`,
140
152
  Service: accessory.getService(this.hap.Service.HumiditySensor) ?? this.accessory.addService(this.hap.Service.HumiditySensor) as Service,
@@ -187,7 +199,7 @@ export class IOSensor extends deviceBase {
187
199
 
188
200
  // CurrentRelativeHumidity
189
201
  if (!this.device.iosensor?.hide_humidity && this.HumiditySensor?.Service) {
190
- this.HumiditySensor.CurrentRelativeHumidity = this.serviceData.humidity;
202
+ this.HumiditySensor.CurrentRelativeHumidity = validHumidity(this.serviceData.humidity, 0, 100);
191
203
  await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`);
192
204
  }
193
205
 
@@ -283,25 +295,41 @@ export class IOSensor extends deviceBase {
283
295
 
284
296
  async BLERefreshStatus(): Promise<void> {
285
297
  await this.debugLog('BLERefreshStatus');
286
- const switchbot = await this.switchbotBLE();
287
-
288
- if (switchbot === undefined) {
289
- await this.BLERefreshConnection(switchbot);
290
- } else {
291
- // Start to monitor advertisement packets
292
- (async () => {
293
- // Start to monitor advertisement packets
294
- const serviceData = await this.monitorAdvertisementPackets(switchbot) as outdoorMeterServiceData;
295
- // Update HomeKit
296
- if (serviceData.model === SwitchBotBLEModel.OutdoorMeter && serviceData.modelName === SwitchBotBLEModelName.OutdoorMeter) {
297
- this.serviceData = serviceData;
298
+ if (this.config.options?.BLE) {
299
+ await this.debugLog('is listening to Platform BLE.');
300
+ this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
301
+ await this.debugLog(`bleMac: ${this.device.bleMac}`);
302
+ this.platform.bleEventHandler[this.device.bleMac] = async (context: outdoorMeterServiceData) => {
303
+ try {
304
+ await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
305
+ this.serviceData = context;
298
306
  await this.BLEparseStatus();
299
307
  await this.updateHomeKitCharacteristics();
300
- } else {
301
- await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
302
- await this.BLERefreshConnection(switchbot);
308
+ } catch (e: any) {
309
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
303
310
  }
304
- })();
311
+ };
312
+ } else {
313
+ await this.debugLog('is using Device BLE Scanning.');
314
+ const switchbot = await this.switchbotBLE();
315
+ if (switchbot === undefined) {
316
+ await this.BLERefreshConnection(switchbot);
317
+ } else {
318
+ // Start to monitor advertisement packets
319
+ (async () => {
320
+ // Start to monitor advertisement packets
321
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as outdoorMeterServiceData;
322
+ // Update HomeKit
323
+ if (serviceData.model === SwitchBotBLEModel.OutdoorMeter && serviceData.modelName === SwitchBotBLEModelName.OutdoorMeter) {
324
+ this.serviceData = serviceData;
325
+ await this.BLEparseStatus();
326
+ await this.updateHomeKitCharacteristics();
327
+ } else {
328
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
329
+ await this.BLERefreshConnection(switchbot);
330
+ }
331
+ })();
332
+ }
305
333
  }
306
334
  }
307
335
 
@@ -10,8 +10,8 @@ import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
10
10
  import type { devicesConfig } from '../settings.js';
11
11
  import type { device } from '../types/devicelist.js';
12
12
  import type { SwitchBotPlatform } from '../platform.js';
13
- import type { stripLightServiceData } from '../types/bledevicestatus.js';
14
13
  import type { stripLightStatus } from '../types/devicestatus.js';
14
+ import type { stripLightServiceData } from '../types/bledevicestatus.js';
15
15
  import type { stripLightWebhookContext } from '../types/devicewebhookstatus.js';
16
16
  import type { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
17
17
 
@@ -42,8 +42,9 @@ export class StripLight extends deviceBase {
42
42
  serviceData!: stripLightServiceData;
43
43
 
44
44
  // Adaptive Lighting
45
+ adaptiveLighting!: boolean;
46
+ adaptiveLightingShift!: number;
45
47
  AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
46
- adaptiveLightingShift?: number;
47
48
 
48
49
  // Updates
49
50
  stripLightUpdateInProgress!: boolean;
@@ -59,13 +60,18 @@ export class StripLight extends deviceBase {
59
60
  accessory.category = this.hap.Categories.LIGHTBULB;
60
61
 
61
62
  // Adaptive Lighting
62
- this.adaptiveLighting(device);
63
+ this.getAdaptiveLightingSettings(accessory, device);
64
+
63
65
  // this is subject we use to track when we need to POST changes to the SwitchBot API
64
66
  this.doStripLightUpdate = new Subject();
65
67
  this.stripLightUpdateInProgress = false;
66
68
 
67
69
  // Initialize the LightBulb Service
68
70
  accessory.context.LightBulb = accessory.context.LightBulb ?? {};
71
+ if (accessory.context.LightBulb.Name) {
72
+ accessory.context.LightBulb.Name = this.validateAndCleanString(accessory.context.LightBulb.Name,
73
+ 'LightBulb Name', accessory.context.LightBulb.Name);
74
+ }
69
75
  this.LightBulb = {
70
76
  Name: accessory.context.LightBulb.Name ?? accessory.displayName,
71
77
  Service: accessory.getService(this.hap.Service.Lightbulb) ?? accessory.addService(this.hap.Service.Lightbulb) as Service,
@@ -77,23 +83,24 @@ export class StripLight extends deviceBase {
77
83
  };
78
84
  accessory.context.LightBulb = this.LightBulb as object;
79
85
 
80
- // Adaptive Lighting
81
- if (this.adaptiveLightingShift === -1 && this.accessory.context.adaptiveLighting) {
82
- this.accessory.removeService(this.LightBulb.Service);
83
- this.LightBulb.Service = this.accessory.addService(this.hap.Service.Lightbulb);
84
- this.accessory.context.adaptiveLighting = false;
85
- this.debugLog(`adaptiveLighting: ${this.accessory.context.adaptiveLighting}`);
86
- }
87
- if (this.adaptiveLightingShift !== -1) {
86
+ if (this.adaptiveLighting && this.adaptiveLightingShift === -1 && this.LightBulb) {
87
+ accessory.removeService(this.LightBulb.Service);
88
+ this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb);
89
+ accessory.context.adaptiveLighting = false;
90
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
91
+ } else if (this.adaptiveLighting && this.adaptiveLightingShift >= 0 && this.LightBulb) {
88
92
  this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
93
+ controllerMode: this.hap.AdaptiveLightingControllerMode.AUTOMATIC,
89
94
  customTemperatureAdjustment: this.adaptiveLightingShift,
90
95
  });
91
- this.accessory.configureController(this.AdaptiveLightingController);
92
- this.accessory.context.adaptiveLighting = true;
93
- this.debugLog(`adaptiveLighting: ${this.accessory.context.adaptiveLighting},`
94
- + ` adaptiveLightingShift: ${this.adaptiveLightingShift}`);
96
+ accessory.configureController(this.AdaptiveLightingController);
97
+ accessory.context.adaptiveLighting = true;
98
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}, adaptiveLightingShift: ${this.adaptiveLightingShift}`,
99
+ );
100
+ } else {
101
+ accessory.context.adaptiveLighting = false;
102
+ this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`);
95
103
  }
96
- this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
97
104
 
98
105
  // Initialize LightBulb Characteristics
99
106
  this.LightBulb.Service
@@ -313,25 +320,41 @@ export class StripLight extends deviceBase {
313
320
 
314
321
  async BLERefreshStatus(): Promise<void> {
315
322
  await this.debugLog('BLERefreshStatus');
316
- const switchbot = await this.switchbotBLE();
317
-
318
- if (switchbot === undefined) {
319
- await this.BLERefreshConnection(switchbot);
320
- } else {
321
- // Start to monitor advertisement packets
322
- (async () => {
323
- // Start to monitor advertisement packets
324
- const serviceData = await this.monitorAdvertisementPackets(switchbot) as stripLightServiceData;
325
- // Update HomeKit
326
- if (serviceData.model === SwitchBotBLEModel.StripLight && serviceData.modelName === SwitchBotBLEModelName.StripLight) {
327
- this.serviceData = serviceData;
323
+ if (this.config.options?.BLE) {
324
+ await this.debugLog('is listening to Platform BLE.');
325
+ this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
326
+ await this.debugLog(`bleMac: ${this.device.bleMac}`);
327
+ this.platform.bleEventHandler[this.device.bleMac] = async (context: stripLightServiceData) => {
328
+ try {
329
+ await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
330
+ this.serviceData = context;
328
331
  await this.BLEparseStatus();
329
332
  await this.updateHomeKitCharacteristics();
330
- } else {
331
- await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
332
- await this.BLERefreshConnection(switchbot);
333
+ } catch (e: any) {
334
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
333
335
  }
334
- })();
336
+ };
337
+ } else {
338
+ await this.debugLog('is using Device BLE Scanning.');
339
+ const switchbot = await this.switchbotBLE();
340
+ if (switchbot === undefined) {
341
+ await this.BLERefreshConnection(switchbot);
342
+ } else {
343
+ // Start to monitor advertisement packets
344
+ (async () => {
345
+ // Start to monitor advertisement packets
346
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as stripLightServiceData;
347
+ // Update HomeKit
348
+ if (serviceData.model === SwitchBotBLEModel.StripLight && serviceData.modelName === SwitchBotBLEModelName.StripLight) {
349
+ this.serviceData = serviceData;
350
+ await this.BLEparseStatus();
351
+ await this.updateHomeKitCharacteristics();
352
+ } else {
353
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
354
+ await this.BLERefreshConnection(switchbot);
355
+ }
356
+ })();
357
+ }
335
358
  }
336
359
  }
337
360
 
@@ -757,7 +780,11 @@ export class StripLight extends deviceBase {
757
780
  this.LightBulb.Saturation, 'Saturation');
758
781
  }
759
782
 
760
- async adaptiveLighting(device: device & devicesConfig): Promise<void> {
783
+ async getAdaptiveLightingSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
784
+ // Adaptive Lighting
785
+ this.adaptiveLighting = accessory.context.adaptiveLighting ?? true;
786
+ await this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
787
+ // Adaptive Lighting Shift
761
788
  if (device.striplight?.adaptiveLightingShift) {
762
789
  this.adaptiveLightingShift = device.striplight.adaptiveLightingShift;
763
790
  this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
@@ -70,6 +70,10 @@ export class Lock extends deviceBase {
70
70
 
71
71
  // Initialize LockMechanism Service
72
72
  accessory.context.LockMechanism = accessory.context.LockMechanism ?? {};
73
+ if (accessory.context.LockMechanism.Name) {
74
+ accessory.context.LockMechanism.Name = this.validateAndCleanString(accessory.context.LockMechanism.Name,
75
+ 'LockMechanism Name', accessory.context.LockMechanism.Name);
76
+ }
73
77
  this.LockMechanism = {
74
78
  Name: accessory.context.LockMechanism.Name ?? accessory.displayName,
75
79
  Service: accessory.getService(this.hap.Service.LockMechanism) ?? accessory.addService(this.hap.Service.LockMechanism) as Service,
@@ -89,6 +93,10 @@ export class Lock extends deviceBase {
89
93
 
90
94
  // Initialize Battery property
91
95
  accessory.context.Battery = accessory.context.Battery ?? {};
96
+ if (accessory.context.Battery.Name) {
97
+ accessory.context.Battery.Name = this.validateAndCleanString(accessory.context.Battery.Name,
98
+ 'Battery Name', accessory.context.Battery.Name);
99
+ }
92
100
  this.Battery = {
93
101
  Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
94
102
  Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
@@ -121,6 +129,10 @@ export class Lock extends deviceBase {
121
129
  }
122
130
  } else {
123
131
  accessory.context.ContactSensor = accessory.context.ContactSensor ?? {};
132
+ if (accessory.context.ContactSensor.Name) {
133
+ accessory.context.ContactSensor.Name = this.validateAndCleanString(accessory.context.ContactSensor.Name,
134
+ 'ContactSensor Name', accessory.context.ContactSensor.Name);
135
+ }
124
136
  this.ContactSensor = {
125
137
  Name: accessory.context.ContactSensor.Name ?? `${accessory.displayName} Contact Sensor`,
126
138
  Service: accessory.getService(this.hap.Service.ContactSensor) ?? this.accessory.addService(this.hap.Service.ContactSensor) as Service,
@@ -147,6 +159,10 @@ export class Lock extends deviceBase {
147
159
  }
148
160
  } else {
149
161
  accessory.context.Switch = accessory.context.Switch ?? {};
162
+ if (accessory.context.Switch.Name) {
163
+ accessory.context.Switch.Name = this.validateAndCleanString(accessory.context.Switch.Name,
164
+ 'Switch Name', accessory.context.Switch.Name);
165
+ }
150
166
  this.Switch = {
151
167
  Name: accessory.context.Switch.Name ?? `${accessory.displayName} Latch`,
152
168
  Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch) as Service,
@@ -309,26 +325,42 @@ export class Lock extends deviceBase {
309
325
 
310
326
  async BLERefreshStatus(): Promise<void> {
311
327
  await this.debugLog('BLERefreshStatus');
312
- const switchbot = await this.switchbotBLE();
313
-
314
- if (switchbot === undefined) {
315
- await this.BLERefreshConnection(switchbot);
316
- } else {
317
- // Start to monitor advertisement packets
318
- (async () => {
319
- // Start to monitor advertisement packets
320
- const serviceData = await this.monitorAdvertisementPackets(switchbot) as lockServiceData | lockProServiceData;
321
- // Update HomeKit
322
- if ((serviceData.model === SwitchBotBLEModel.Lock || SwitchBotBLEModel.LockPro)
323
- && (serviceData.modelName === SwitchBotBLEModelName.Lock || SwitchBotBLEModelName.LockPro)) {
324
- this.serviceData = serviceData;
328
+ if (this.config.options?.BLE) {
329
+ await this.debugLog('is listening to Platform BLE.');
330
+ this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
331
+ await this.debugLog(`bleMac: ${this.device.bleMac}`);
332
+ this.platform.bleEventHandler[this.device.bleMac] = async (context: lockServiceData | lockProServiceData) => {
333
+ try {
334
+ await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
335
+ this.serviceData = context;
325
336
  await this.BLEparseStatus();
326
337
  await this.updateHomeKitCharacteristics();
327
- } else {
328
- await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
329
- await this.BLERefreshConnection(switchbot);
338
+ } catch (e: any) {
339
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
330
340
  }
331
- })();
341
+ };
342
+ } else {
343
+ await this.debugLog('is using Device BLE Scanning.');
344
+ const switchbot = await this.switchbotBLE();
345
+ if (switchbot === undefined) {
346
+ await this.BLERefreshConnection(switchbot);
347
+ } else {
348
+ // Start to monitor advertisement packets
349
+ (async () => {
350
+ // Start to monitor advertisement packets
351
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as lockServiceData | lockProServiceData;
352
+ // Update HomeKit
353
+ if ((serviceData.model === SwitchBotBLEModel.Lock || SwitchBotBLEModel.LockPro)
354
+ && (serviceData.modelName === SwitchBotBLEModelName.Lock || SwitchBotBLEModelName.LockPro)) {
355
+ this.serviceData = serviceData;
356
+ await this.BLEparseStatus();
357
+ await this.updateHomeKitCharacteristics();
358
+ } else {
359
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
360
+ await this.BLERefreshConnection(switchbot);
361
+ }
362
+ })();
363
+ }
332
364
  }
333
365
  }
334
366