@switchbot/homebridge-switchbot 3.5.0 → 3.5.1-beta.1

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 (137) hide show
  1. package/.github/npm-version-script.cjs +81 -0
  2. package/config.schema.json +4 -4
  3. package/dist/device/blindtilt.d.ts.map +1 -1
  4. package/dist/device/blindtilt.js +64 -189
  5. package/dist/device/blindtilt.js.map +1 -1
  6. package/dist/device/bot.d.ts.map +1 -1
  7. package/dist/device/bot.js +34 -68
  8. package/dist/device/bot.js.map +1 -1
  9. package/dist/device/ceilinglight.d.ts +1 -1
  10. package/dist/device/ceilinglight.d.ts.map +1 -1
  11. package/dist/device/ceilinglight.js +65 -158
  12. package/dist/device/ceilinglight.js.map +1 -1
  13. package/dist/device/colorbulb.d.ts +1 -1
  14. package/dist/device/colorbulb.d.ts.map +1 -1
  15. package/dist/device/colorbulb.js +47 -159
  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 +42 -105
  19. package/dist/device/contact.js.map +1 -1
  20. package/dist/device/curtain.d.ts +1 -0
  21. package/dist/device/curtain.d.ts.map +1 -1
  22. package/dist/device/curtain.js +61 -182
  23. package/dist/device/curtain.js.map +1 -1
  24. package/dist/device/device.d.ts +41 -2
  25. package/dist/device/device.d.ts.map +1 -1
  26. package/dist/device/device.js +182 -5
  27. package/dist/device/device.js.map +1 -1
  28. package/dist/device/fan.d.ts.map +1 -1
  29. package/dist/device/fan.js +76 -145
  30. package/dist/device/fan.js.map +1 -1
  31. package/dist/device/hub.d.ts +7 -1
  32. package/dist/device/hub.d.ts.map +1 -1
  33. package/dist/device/hub.js +54 -17
  34. package/dist/device/hub.js.map +1 -1
  35. package/dist/device/humidifier.d.ts.map +1 -1
  36. package/dist/device/humidifier.js +55 -104
  37. package/dist/device/humidifier.js.map +1 -1
  38. package/dist/device/iosensor.d.ts.map +1 -1
  39. package/dist/device/iosensor.js +27 -46
  40. package/dist/device/iosensor.js.map +1 -1
  41. package/dist/device/lightstrip.d.ts +1 -1
  42. package/dist/device/lightstrip.d.ts.map +1 -1
  43. package/dist/device/lightstrip.js +56 -120
  44. package/dist/device/lightstrip.js.map +1 -1
  45. package/dist/device/lock.d.ts +1 -1
  46. package/dist/device/lock.d.ts.map +1 -1
  47. package/dist/device/lock.js +36 -66
  48. package/dist/device/lock.js.map +1 -1
  49. package/dist/device/meter.d.ts.map +1 -1
  50. package/dist/device/meter.js +27 -46
  51. package/dist/device/meter.js.map +1 -1
  52. package/dist/device/meterplus.d.ts.map +1 -1
  53. package/dist/device/meterplus.js +26 -45
  54. package/dist/device/meterplus.js.map +1 -1
  55. package/dist/device/motion.d.ts.map +1 -1
  56. package/dist/device/motion.js +24 -43
  57. package/dist/device/motion.js.map +1 -1
  58. package/dist/device/plug.d.ts.map +1 -1
  59. package/dist/device/plug.js +32 -66
  60. package/dist/device/plug.js.map +1 -1
  61. package/dist/device/robotvacuumcleaner.d.ts +1 -1
  62. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  63. package/dist/device/robotvacuumcleaner.js +43 -88
  64. package/dist/device/robotvacuumcleaner.js.map +1 -1
  65. package/dist/device/waterdetector.d.ts.map +1 -1
  66. package/dist/device/waterdetector.js +23 -43
  67. package/dist/device/waterdetector.js.map +1 -1
  68. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  69. package/dist/irdevice/airconditioner.js +10 -28
  70. package/dist/irdevice/airconditioner.js.map +1 -1
  71. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  72. package/dist/irdevice/airpurifier.js +8 -20
  73. package/dist/irdevice/airpurifier.js.map +1 -1
  74. package/dist/irdevice/camera.d.ts.map +1 -1
  75. package/dist/irdevice/camera.js +8 -20
  76. package/dist/irdevice/camera.js.map +1 -1
  77. package/dist/irdevice/fan.d.ts.map +1 -1
  78. package/dist/irdevice/fan.js +8 -20
  79. package/dist/irdevice/fan.js.map +1 -1
  80. package/dist/irdevice/irdevice.d.ts +7 -0
  81. package/dist/irdevice/irdevice.d.ts.map +1 -1
  82. package/dist/irdevice/irdevice.js +28 -0
  83. package/dist/irdevice/irdevice.js.map +1 -1
  84. package/dist/irdevice/light.d.ts.map +1 -1
  85. package/dist/irdevice/light.js +8 -20
  86. package/dist/irdevice/light.js.map +1 -1
  87. package/dist/irdevice/other.d.ts.map +1 -1
  88. package/dist/irdevice/other.js +8 -20
  89. package/dist/irdevice/other.js.map +1 -1
  90. package/dist/irdevice/tv.d.ts.map +1 -1
  91. package/dist/irdevice/tv.js +8 -20
  92. package/dist/irdevice/tv.js.map +1 -1
  93. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  94. package/dist/irdevice/vacuumcleaner.js +8 -20
  95. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  96. package/dist/irdevice/waterheater.d.ts.map +1 -1
  97. package/dist/irdevice/waterheater.js +8 -20
  98. package/dist/irdevice/waterheater.js.map +1 -1
  99. package/dist/settings.d.ts +4 -2
  100. package/dist/settings.d.ts.map +1 -1
  101. package/dist/settings.js.map +1 -1
  102. package/dist/utils.d.ts +19 -1
  103. package/dist/utils.d.ts.map +1 -1
  104. package/dist/utils.js +20 -1
  105. package/dist/utils.js.map +1 -1
  106. package/package.json +8 -8
  107. package/src/device/blindtilt.ts +71 -186
  108. package/src/device/bot.ts +32 -68
  109. package/src/device/ceilinglight.ts +67 -153
  110. package/src/device/colorbulb.ts +51 -155
  111. package/src/device/contact.ts +49 -104
  112. package/src/device/curtain.ts +70 -177
  113. package/src/device/device.ts +207 -8
  114. package/src/device/fan.ts +75 -147
  115. package/src/device/hub.ts +55 -19
  116. package/src/device/humidifier.ts +52 -104
  117. package/src/device/iosensor.ts +25 -46
  118. package/src/device/lightstrip.ts +54 -121
  119. package/src/device/lock.ts +35 -67
  120. package/src/device/meter.ts +25 -46
  121. package/src/device/meterplus.ts +24 -45
  122. package/src/device/motion.ts +22 -43
  123. package/src/device/plug.ts +30 -66
  124. package/src/device/robotvacuumcleaner.ts +40 -89
  125. package/src/device/waterdetector.ts +22 -43
  126. package/src/irdevice/airconditioner.ts +10 -26
  127. package/src/irdevice/airpurifier.ts +8 -20
  128. package/src/irdevice/camera.ts +8 -20
  129. package/src/irdevice/fan.ts +8 -20
  130. package/src/irdevice/irdevice.ts +29 -0
  131. package/src/irdevice/light.ts +8 -20
  132. package/src/irdevice/other.ts +8 -20
  133. package/src/irdevice/tv.ts +8 -20
  134. package/src/irdevice/vacuumcleaner.ts +8 -20
  135. package/src/irdevice/waterheater.ts +8 -20
  136. package/src/settings.ts +4 -2
  137. package/src/utils.ts +20 -1
@@ -1,7 +1,9 @@
1
- import { request } from 'undici';
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * humidifier.ts: @switchbot/homebridge-switchbot.
4
+ */
2
5
  import { deviceBase } from './device.js';
3
6
  import { interval, Subject } from 'rxjs';
4
- import { Devices } from '../settings.js';
5
7
  import { convertUnits } from '../utils.js';
6
8
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
7
9
 
@@ -277,63 +279,43 @@ export class Humidifier extends deviceBase {
277
279
 
278
280
  async BLERefreshStatus(): Promise<void> {
279
281
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
280
- const switchbot = await this.platform.connectBLE();
281
- // Convert to BLE Address
282
- this.device.bleMac = this.device
283
- .deviceId!.match(/.{1,2}/g)!
284
- .join(':')
285
- .toLowerCase();
286
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
287
- this.getCustomBLEAddress(switchbot);
282
+ const switchbot = await this.switchbotBLE();
283
+
284
+ if (switchbot === undefined) {
285
+ await this.BLERefreshConnection(switchbot);
286
+ } else {
288
287
  // Start to monitor advertisement packets
289
- (async () => {
288
+ (async () => {
290
289
  // Start to monitor advertisement packets
291
- await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
292
- // Set an event handler
293
- switchbot.onadvertisement = (ad: any) => {
294
- if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
295
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
296
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
297
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
290
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
291
+ // Update HomeKit
292
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
293
+ await this.BLEparseStatus(serviceData);
294
+ await this.updateHomeKitCharacteristics();
298
295
  } else {
299
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
296
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
297
+ await this.BLERefreshConnection(switchbot);
300
298
  }
301
- };
302
- // Wait 10 seconds
303
- await switchbot.wait(this.scanDuration * 1000);
304
- // Stop to monitor
305
- await switchbot.stopScan();
306
- // Update HomeKit
307
- await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
308
- await this.updateHomeKitCharacteristics();
309
- })();
310
- if (switchbot === undefined) {
311
- await this.BLERefreshConnection(switchbot);
299
+ })();
312
300
  }
313
301
  }
314
302
 
315
303
  async openAPIRefreshStatus(): Promise<void> {
316
304
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
317
305
  try {
318
- const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
319
- `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
320
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
306
+ const { body, statusCode } = await this.deviceRefreshStatus();
321
307
  const deviceStatus: any = await body.json();
322
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
323
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
308
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
324
309
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
325
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
326
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
327
- this.openAPIparseStatus(deviceStatus);
328
- this.updateHomeKitCharacteristics();
310
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
311
+ await this.openAPIparseStatus(deviceStatus);
312
+ await this.updateHomeKitCharacteristics();
329
313
  } else {
330
- this.statusCode(statusCode);
331
- this.statusCode(deviceStatus.statusCode);
314
+ await this.statusCodes(statusCode, deviceStatus);
332
315
  }
333
316
  } catch (e: any) {
334
- this.apiError(e);
335
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
336
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
317
+ await this.apiError(e);
318
+ await this.openAPIRefreshError(e);
337
319
  }
338
320
  }
339
321
 
@@ -367,16 +349,17 @@ export class Humidifier extends deviceBase {
367
349
  async pushChanges(): Promise<void> {
368
350
  if (!this.device.enableCloudService && this.OpenAPI) {
369
351
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
370
- /*} else if (this.BLE) {
371
- await this.BLEpushChanges();*/
352
+ } else if (this.BLE) {
353
+ await this.BLEpushChanges();
372
354
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
373
355
  await this.openAPIpushChanges();
374
356
  } else {
375
357
  await this.offlineOff();
376
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
377
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
358
+ await this.pushChangeDisabled();
378
359
  }
379
- interval(5000)
360
+ // Refresh the status from the API
361
+ interval(15000)
362
+ .pipe(skipWhile(() => this.humidifierUpdateInProgress))
380
363
  .pipe(take(1))
381
364
  .subscribe(async () => {
382
365
  await this.refreshStatus();
@@ -387,17 +370,9 @@ export class Humidifier extends deviceBase {
387
370
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
388
371
  const switchbot = await this.platform.connectBLE();
389
372
  // Convert to BLE Address
390
- this.device.bleMac = this.device
391
- .deviceId!.match(/.{1,2}/g)!
392
- .join(':')
393
- .toLowerCase();
394
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
373
+ await this.convertBLEAddress();
395
374
  switchbot
396
- .discover({
397
- model: 'e',
398
- quick: true,
399
- id: this.device.bleMac,
400
- })
375
+ .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
401
376
  .then(async (device_list: any) => {
402
377
  this.infoLog(`${this.accessory.displayName} Active: ${this.HumidifierDehumidifier.Active}`);
403
378
  return await device_list[0].percentage(this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold);
@@ -430,24 +405,15 @@ export class Humidifier extends deviceBase {
430
405
  });
431
406
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
432
407
  try {
433
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
434
- body: bodyChange,
435
- method: 'POST',
436
- headers: this.platform.generateHeaders(),
437
- });
438
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
408
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
439
409
  const deviceStatus: any = await body.json();
440
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
441
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
442
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
410
+ await this.pushStatusCodes(statusCode, deviceStatus);
443
411
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
444
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
445
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
446
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
447
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
412
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
413
+ await this.updateHomeKitCharacteristics();
448
414
  } else {
449
- this.statusCode(statusCode);
450
- this.statusCode(deviceStatus.statusCode);
415
+ await this.statusCode(statusCode);
416
+ await this.statusCode(deviceStatus.statusCode);
451
417
  }
452
418
  } catch (e: any) {
453
419
  this.apiError(e);
@@ -483,24 +449,15 @@ export class Humidifier extends deviceBase {
483
449
  });
484
450
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
485
451
  try {
486
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
487
- body: bodyChange,
488
- method: 'POST',
489
- headers: this.platform.generateHeaders(),
490
- });
491
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
452
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
492
453
  const deviceStatus: any = await body.json();
493
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
494
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
495
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
454
+ await this.pushStatusCodes(statusCode, deviceStatus);
496
455
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
497
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
498
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
499
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
500
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
456
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
457
+ await this.updateHomeKitCharacteristics();
501
458
  } else {
502
- this.statusCode(statusCode);
503
- this.statusCode(deviceStatus.statusCode);
459
+ await this.statusCode(statusCode);
460
+ await this.statusCode(deviceStatus.statusCode);
504
461
  }
505
462
  } catch (e: any) {
506
463
  this.apiError(e);
@@ -527,24 +484,15 @@ export class Humidifier extends deviceBase {
527
484
  });
528
485
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
529
486
  try {
530
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
531
- body: bodyChange,
532
- method: 'POST',
533
- headers: this.platform.generateHeaders(),
534
- });
535
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
487
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
536
488
  const deviceStatus: any = await body.json();
537
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
538
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
539
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
489
+ await this.pushStatusCodes(statusCode, deviceStatus);
540
490
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
541
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
542
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
543
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
544
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
491
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
492
+ await this.updateHomeKitCharacteristics();
545
493
  } else {
546
- this.statusCode(statusCode);
547
- this.statusCode(deviceStatus.statusCode);
494
+ await this.statusCode(statusCode);
495
+ await this.statusCode(deviceStatus.statusCode);
548
496
  }
549
497
  } catch (e: any) {
550
498
  this.apiError(e);
@@ -4,7 +4,6 @@
4
4
  */
5
5
  import { Units } from 'homebridge';
6
6
  import { deviceBase } from './device.js';
7
- import { Devices } from '../settings.js';
8
7
  import { convertUnits } from '../utils.js';
9
8
  import { Subject, interval, skipWhile } from 'rxjs';
10
9
 
@@ -174,9 +173,9 @@ export class IOSensor extends deviceBase {
174
173
  }
175
174
 
176
175
  // Current Temperature
177
- if (!this.device.iosensor?.hide_temperature) {
178
- serviceData.temperature!.c < 0 ? 0 : serviceData.temperature!.c > 100 ? 100 : serviceData.temperature!.c;
179
- this.TemperatureSensor!.CurrentTemperature = serviceData.temperature!.c;
176
+ if (!this.device.meter?.hide_temperature) {
177
+ const celcius = serviceData.temperature!.c < 0 ? 0 : serviceData.temperature!.c > 100 ? 100 : serviceData.temperature!.c;
178
+ this.TemperatureSensor!.CurrentTemperature = celcius;
180
179
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.TemperatureSensor!.CurrentTemperature}°c`);
181
180
  }
182
181
  }
@@ -244,63 +243,43 @@ export class IOSensor extends deviceBase {
244
243
 
245
244
  async BLERefreshStatus(): Promise<void> {
246
245
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
247
- const switchbot = await this.platform.connectBLE();
248
- // Convert to BLE Address
249
- this.device.bleMac = this.device
250
- .deviceId!.match(/.{1,2}/g)!
251
- .join(':')
252
- .toLowerCase();
253
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
254
- this.getCustomBLEAddress(switchbot);
246
+ const switchbot = await this.switchbotBLE();
247
+
248
+ if (switchbot === undefined) {
249
+ await this.BLERefreshConnection(switchbot);
250
+ } else {
255
251
  // Start to monitor advertisement packets
256
- (async () => {
252
+ (async () => {
257
253
  // Start to monitor advertisement packets
258
- await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
259
- // Set an event handler
260
- switchbot.onadvertisement = (ad: any) => {
261
- if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
262
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
263
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
264
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
254
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
255
+ // Update HomeKit
256
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
257
+ await this.BLEparseStatus(serviceData);
258
+ await this.updateHomeKitCharacteristics();
265
259
  } else {
266
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
260
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
261
+ await this.BLERefreshConnection(switchbot);
267
262
  }
268
- };
269
- // Wait 10 seconds
270
- await switchbot.wait(this.scanDuration * 1000);
271
- // Stop to monitor
272
- await switchbot.stopScan();
273
- // Update HomeKit
274
- await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
275
- await this.updateHomeKitCharacteristics();
276
- })();
277
- if (switchbot === undefined) {
278
- await this.BLERefreshConnection(switchbot);
263
+ })();
279
264
  }
280
265
  }
281
266
 
282
267
  async openAPIRefreshStatus(): Promise<void> {
283
268
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
284
269
  try {
285
- const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
286
- `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
287
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
270
+ const { body, statusCode } = await this.deviceRefreshStatus();
288
271
  const deviceStatus: any = await body.json();
289
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
290
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
272
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
291
273
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
292
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
293
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
294
- this.openAPIparseStatus(deviceStatus);
295
- this.updateHomeKitCharacteristics();
274
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
275
+ await this.openAPIparseStatus(deviceStatus);
276
+ await this.updateHomeKitCharacteristics();
296
277
  } else {
297
- this.statusCode(statusCode);
298
- this.statusCode(deviceStatus.statusCode);
278
+ await this.statusCodes(statusCode, deviceStatus);
299
279
  }
300
280
  } catch (e: any) {
301
- this.apiError(e);
302
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
303
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
281
+ await this.apiError(e);
282
+ await this.openAPIRefreshError(e);
304
283
  }
305
284
  }
306
285
 
@@ -1,12 +1,14 @@
1
- import { request } from 'undici';
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * lightstrip.ts: @switchbot/homebridge-switchbot.
4
+ */
2
5
  import { deviceBase } from './device.js';
3
- import { Devices } from '../settings.js';
4
6
  import { hs2rgb, rgb2hs, m2hs } from '../utils.js';
5
7
  import { interval, skipWhile, Subject } from 'rxjs';
6
8
  import { debounceTime, take, tap } from 'rxjs/operators';
7
9
 
8
10
  import type { SwitchBotPlatform } from '../platform.js';
9
- import type { device, devicesConfig, deviceStatus, serviceData } from '../settings.js';
11
+ import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
10
12
  import type { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
11
13
 
12
14
  /**
@@ -290,63 +292,43 @@ export class StripLight extends deviceBase {
290
292
 
291
293
  async BLERefreshStatus(): Promise<void> {
292
294
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
293
- const switchbot = await this.platform.connectBLE();
294
- // Convert to BLE Address
295
- this.device.bleMac = this.device
296
- .deviceId!.match(/.{1,2}/g)!
297
- .join(':')
298
- .toLowerCase();
299
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
300
- this.getCustomBLEAddress(switchbot);
295
+ const switchbot = await this.switchbotBLE();
296
+
297
+ if (switchbot === undefined) {
298
+ await this.BLERefreshConnection(switchbot);
299
+ } else {
301
300
  // Start to monitor advertisement packets
302
- (async () => {
301
+ (async () => {
303
302
  // Start to monitor advertisement packets
304
- await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
305
- // Set an event handler
306
- switchbot.onadvertisement = (ad: any) => {
307
- if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
308
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
309
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
310
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
303
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
304
+ // Update HomeKit
305
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
306
+ await this.BLEparseStatus(serviceData);
307
+ await this.updateHomeKitCharacteristics();
311
308
  } else {
312
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
309
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
310
+ await this.BLERefreshConnection(switchbot);
313
311
  }
314
- };
315
- // Wait 10 seconds
316
- await switchbot.wait(this.scanDuration * 1000);
317
- // Stop to monitor
318
- await switchbot.stopScan();
319
- // Update HomeKit
320
- await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
321
- await this.updateHomeKitCharacteristics();
322
- })();
323
- if (switchbot === undefined) {
324
- await this.BLERefreshConnection(switchbot);
312
+ })();
325
313
  }
326
314
  }
327
315
 
328
316
  async openAPIRefreshStatus(): Promise<void> {
329
317
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
330
318
  try {
331
- const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
332
- `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
333
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
319
+ const { body, statusCode } = await this.deviceRefreshStatus();
334
320
  const deviceStatus: any = await body.json();
335
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
336
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
321
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
337
322
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
338
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
339
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
340
- this.openAPIparseStatus(deviceStatus);
341
- this.updateHomeKitCharacteristics();
323
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
324
+ await this.openAPIparseStatus(deviceStatus);
325
+ await this.updateHomeKitCharacteristics();
342
326
  } else {
343
- this.statusCode(statusCode);
344
- this.statusCode(deviceStatus.statusCode);
327
+ await this.statusCodes(statusCode, deviceStatus);
345
328
  }
346
329
  } catch (e: any) {
347
- this.apiError(e);
348
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
349
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
330
+ await this.apiError(e);
331
+ await this.openAPIRefreshError(e);
350
332
  }
351
333
  }
352
334
 
@@ -434,14 +416,13 @@ export class StripLight extends deviceBase {
434
416
  async pushChanges(): Promise<void> {
435
417
  if (!this.device.enableCloudService && this.OpenAPI) {
436
418
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
437
- /* }else if (this.BLE) {
438
- await this.BLEpushChanges();*/
419
+ } else if (this.BLE) {
420
+ await this.BLEpushChanges();
439
421
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
440
422
  await this.openAPIpushChanges();
441
423
  } else {
442
424
  await this.offlineOff();
443
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
444
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
425
+ await this.pushChangeDisabled();
445
426
  }
446
427
  // Refresh the status from the API
447
428
  interval(15000)
@@ -459,16 +440,9 @@ export class StripLight extends deviceBase {
459
440
  + ` On: ${this.LightBulb.On} OnCached: ${this.accessory.context.On}`);
460
441
  const switchbot = await this.platform.connectBLE();
461
442
  // Convert to BLE Address
462
- this.device.bleMac = this.device
463
- .deviceId!.match(/.{1,2}/g)!
464
- .join(':')
465
- .toLowerCase();
466
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
443
+ await this.convertBLEAddress();
467
444
  switchbot
468
- .discover({
469
- model: 'r',
470
- id: this.device.bleMac,
471
- })
445
+ .discover({ model: this.device.bleModel, id: this.device.bleMac })
472
446
  .then(async (device_list: any) => {
473
447
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
474
448
  return await this.retryBLE({
@@ -520,16 +494,9 @@ export class StripLight extends deviceBase {
520
494
  if (this.LightBulb.Brightness !== this.accessory.context.Brightness) {
521
495
  const switchbot = await this.platform.connectBLE();
522
496
  // Convert to BLE Address
523
- this.device.bleMac = this.device
524
- .deviceId!.match(/.{1,2}/g)!
525
- .join(':')
526
- .toLowerCase();
527
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
497
+ await this.convertBLEAddress();
528
498
  switchbot
529
- .discover({
530
- model: 'u',
531
- id: this.device.bleMac,
532
- })
499
+ .discover({ model: this.device.bleModel, id: this.device.bleMac })
533
500
  .then(async (device_list: any) => {
534
501
  this.infoLog(`${this.accessory.displayName} Target Brightness: ${this.LightBulb.Brightness}`);
535
502
  return await device_list[0].setBrightness(this.LightBulb.Brightness);
@@ -562,16 +529,9 @@ export class StripLight extends deviceBase {
562
529
 
563
530
  const switchbot = await this.platform.connectBLE();
564
531
  // Convert to BLE Address
565
- this.device.bleMac = this.device
566
- .deviceId!.match(/.{1,2}/g)!
567
- .join(':')
568
- .toLowerCase();
569
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
532
+ await this.convertBLEAddress();
570
533
  switchbot
571
- .discover({
572
- model: 'u',
573
- id: this.device.bleMac,
574
- })
534
+ .discover({ model: this.device.bleModel, id: this.device.bleMac })
575
535
  .then(async (device_list: any) => {
576
536
  this.infoLog(`${this.accessory.displayName} Target RGB: ${(this.LightBulb.Brightness, red, green, blue)}`);
577
537
  return await device_list[0].setRGB(this.LightBulb.Brightness, red, green, blue);
@@ -608,24 +568,15 @@ export class StripLight extends deviceBase {
608
568
  });
609
569
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
610
570
  try {
611
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
612
- body: bodyChange,
613
- method: 'POST',
614
- headers: this.platform.generateHeaders(),
615
- });
616
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
571
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
617
572
  const deviceStatus: any = await body.json();
618
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
619
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
620
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
573
+ await this.pushStatusCodes(statusCode, deviceStatus);
621
574
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
622
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
623
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
624
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
625
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
575
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
576
+ await this.updateHomeKitCharacteristics();
626
577
  } else {
627
- this.statusCode(statusCode);
628
- this.statusCode(deviceStatus.statusCode);
578
+ await this.statusCode(statusCode);
579
+ await this.statusCode(deviceStatus.statusCode);
629
580
  }
630
581
  } catch (e: any) {
631
582
  this.apiError(e);
@@ -662,24 +613,15 @@ export class StripLight extends deviceBase {
662
613
  });
663
614
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
664
615
  try {
665
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
666
- body: bodyChange,
667
- method: 'POST',
668
- headers: this.platform.generateHeaders(),
669
- });
670
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
616
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
671
617
  const deviceStatus: any = await body.json();
672
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
673
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
674
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
618
+ await this.pushStatusCodes(statusCode, deviceStatus);
675
619
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
676
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
677
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
678
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
679
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
620
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
621
+ await this.updateHomeKitCharacteristics();
680
622
  } else {
681
- this.statusCode(statusCode);
682
- this.statusCode(deviceStatus.statusCode);
623
+ await this.statusCode(statusCode);
624
+ await this.statusCode(deviceStatus.statusCode);
683
625
  }
684
626
  } catch (e: any) {
685
627
  this.apiError(e);
@@ -702,24 +644,15 @@ export class StripLight extends deviceBase {
702
644
  });
703
645
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
704
646
  try {
705
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
706
- body: bodyChange,
707
- method: 'POST',
708
- headers: this.platform.generateHeaders(),
709
- });
710
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
647
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
711
648
  const deviceStatus: any = await body.json();
712
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
713
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
714
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
649
+ await this.pushStatusCodes(statusCode, deviceStatus);
715
650
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
716
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
717
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
718
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
719
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
651
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
652
+ await this.updateHomeKitCharacteristics();
720
653
  } else {
721
- this.statusCode(statusCode);
722
- this.statusCode(deviceStatus.statusCode);
654
+ await this.statusCode(statusCode);
655
+ await this.statusCode(deviceStatus.statusCode);
723
656
  }
724
657
  } catch (e: any) {
725
658
  this.apiError(e);