@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
package/src/device/fan.ts CHANGED
@@ -2,9 +2,7 @@
2
2
  *
3
3
  * plug.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
- import { request } from 'undici';
6
5
  import { deviceBase } from './device.js';
7
- import { Devices } from '../settings.js';
8
6
  import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
9
7
 
10
8
  import type { SwitchBotPlatform } from '../platform.js';
@@ -243,8 +241,6 @@ export class Fan extends deviceBase {
243
241
  }
244
242
  }
245
243
 
246
-
247
-
248
244
  /**
249
245
  * Asks the SwitchBot API for the latest device information
250
246
  */
@@ -264,63 +260,43 @@ export class Fan extends deviceBase {
264
260
 
265
261
  async BLERefreshStatus(): Promise<void> {
266
262
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
267
- const switchbot = await this.platform.connectBLE();
268
- // Convert to BLE Address
269
- this.device.bleMac = this.device
270
- .deviceId!.match(/.{1,2}/g)!
271
- .join(':')
272
- .toLowerCase();
273
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
274
- this.getCustomBLEAddress(switchbot);
275
- // Start to monitor advertisement packets
276
- (async () => {
263
+ const switchbot = await this.switchbotBLE();
264
+
265
+ if (switchbot === undefined) {
266
+ await this.BLERefreshConnection(switchbot);
267
+ } else {
277
268
  // Start to monitor advertisement packets
278
- await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
279
- // Set an event handler
280
- switchbot.onadvertisement = (ad: any) => {
281
- if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
282
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
283
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
284
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
269
+ (async () => {
270
+ // Start to monitor advertisement packets
271
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
272
+ // Update HomeKit
273
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
274
+ await this.BLEparseStatus(serviceData);
275
+ await this.updateHomeKitCharacteristics();
285
276
  } else {
286
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
277
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
278
+ await this.BLERefreshConnection(switchbot);
287
279
  }
288
- };
289
- // Wait 10 seconds
290
- await switchbot.wait(this.scanDuration * 1000);
291
- // Stop to monitor
292
- await switchbot.stopScan();
293
- // Update HomeKit
294
- await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
295
- await this.updateHomeKitCharacteristics();
296
- })();
297
- if (switchbot === undefined) {
298
- await this.BLERefreshConnection(switchbot);
280
+ })();
299
281
  }
300
282
  }
301
283
 
302
284
  async openAPIRefreshStatus(): Promise<void> {
303
285
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
304
286
  try {
305
- const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
306
- `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
307
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
287
+ const { body, statusCode } = await this.deviceRefreshStatus();
308
288
  const deviceStatus: any = await body.json();
309
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
310
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
289
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
311
290
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
312
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
313
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
314
- this.openAPIparseStatus(deviceStatus);
315
- this.updateHomeKitCharacteristics();
291
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
292
+ await this.openAPIparseStatus(deviceStatus);
293
+ await this.updateHomeKitCharacteristics();
316
294
  } else {
317
- this.statusCode(statusCode);
318
- this.statusCode(deviceStatus.statusCode);
295
+ await this.statusCodes(statusCode, deviceStatus);
319
296
  }
320
297
  } catch (e: any) {
321
- this.apiError(e);
322
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
323
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
298
+ await this.apiError(e);
299
+ await this.openAPIRefreshError(e);
324
300
  }
325
301
  }
326
302
 
@@ -393,8 +369,7 @@ export class Fan extends deviceBase {
393
369
  await this.openAPIpushChanges();
394
370
  } else {
395
371
  await this.offlineOff();
396
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
397
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
372
+ await this.pushChangeDisabled();
398
373
  }
399
374
  // Refresh the status from the API
400
375
  interval(15000)
@@ -412,16 +387,9 @@ export class Fan extends deviceBase {
412
387
  + ` On: ${this.Fan.Active} OnCached: ${this.accessory.context.Active}`);
413
388
  const switchbot = await this.platform.connectBLE();
414
389
  // Convert to BLE Address
415
- this.device.bleMac = this.device
416
- .deviceId!.match(/.{1,2}/g)!
417
- .join(':')
418
- .toLowerCase();
419
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
390
+ await this.convertBLEAddress();
420
391
  switchbot
421
- .discover({
422
- model: this.device.bleModel,
423
- id: this.device.bleMac,
424
- })
392
+ .discover({ model: this.device.bleModel, id: this.device.bleMac })
425
393
  .then(async (device_list: any) => {
426
394
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Fan.Active}`);
427
395
  return await this.retryBLE({
@@ -435,16 +403,13 @@ export class Fan extends deviceBase {
435
403
  },
436
404
  });
437
405
  })
438
- .then(() => {
439
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
440
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
441
- + `Active: ${this.Fan.Active} sent over BLE, sent successfully`);
442
- this.Fan.Active = false;
406
+ .then(async () => {
407
+ await this.successfulPushChange_BLE('Active', this.Fan.Active, 'BLE API');
408
+ await this.updateHomeKitCharacteristics();
443
409
  })
444
410
  .catch(async (e: any) => {
445
- this.apiError(e);
446
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
447
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
411
+ await this.apiError(e);
412
+ await this.pushChangeError('BLEpushChanges', e);
448
413
  await this.BLEPushConnection();
449
414
  });
450
415
  } else {
@@ -469,29 +434,19 @@ export class Fan extends deviceBase {
469
434
  });
470
435
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
471
436
  try {
472
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
473
- body: bodyChange,
474
- method: 'POST',
475
- headers: this.platform.generateHeaders(),
476
- });
477
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
437
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
478
438
  const deviceStatus: any = await body.json();
479
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
480
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
481
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
439
+ await this.pushStatusCodes(statusCode, deviceStatus);
482
440
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
483
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
484
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
485
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
486
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
441
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
442
+ await this.updateHomeKitCharacteristics();
487
443
  } else {
488
- this.statusCode(statusCode);
489
- this.statusCode(deviceStatus.statusCode);
444
+ await this.statusCode(statusCode);
445
+ await this.statusCode(deviceStatus.statusCode);
490
446
  }
491
447
  } catch (e: any) {
492
448
  this.apiError(e);
493
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
494
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
449
+ await this.pushChangeError('openAPIpushChanges', e);
495
450
  }
496
451
  } else {
497
452
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.`
@@ -508,88 +463,61 @@ export class Fan extends deviceBase {
508
463
  }
509
464
 
510
465
  async pushRotationSpeedChanges(): Promise<void> {
511
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushRotationSpeedChanges`);
466
+ await this.pushChange('pushRotationSpeedChanges');
512
467
  if (this.Fan.SwingMode !== this.accessory.context.SwingMode) {
513
468
  const bodyChange = JSON.stringify({
514
469
  command: 'setWindSpeed',
515
470
  parameter: `${this.Fan.RotationSpeed}`,
516
471
  commandType: 'command',
517
472
  });
518
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
473
+ await this.bodyChange(bodyChange, 'SwitchBot OpenAPI');
519
474
  try {
520
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
521
- body: bodyChange,
522
- method: 'POST',
523
- headers: this.platform.generateHeaders(),
524
- });
525
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
475
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
526
476
  const deviceStatus: any = await body.json();
527
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
528
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
529
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
477
+ await this.pushStatusCodes(statusCode, deviceStatus);
530
478
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
531
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
532
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
533
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
534
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
479
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
480
+ await this.updateHomeKitCharacteristics();
535
481
  } else {
536
- this.statusCode(statusCode);
537
- this.statusCode(deviceStatus.statusCode);
482
+ await this.statusCode(statusCode);
483
+ await this.statusCode(deviceStatus.statusCode);
538
484
  }
539
485
  } catch (e: any) {
540
486
  this.apiError(e);
541
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushRotationSpeedChanges with ${this.device.connectionType}`
542
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
487
+ await this.pushChangeError('pushRotationSpeedChanges', e);
543
488
  }
544
489
  } else {
545
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, pushRotationSpeedChanges: ${this.Fan.RotationSpeed}, `
546
- + `pushRotationSpeedChangesCached: ${this.accessory.context.RotationSpeed}`);
490
+ await this.noChanges('RotationSpeed', this.Fan.RotationSpeed, this.accessory.context.RotationSpeed);
547
491
  }
548
492
  }
549
493
 
550
494
  async pushSwingModeChanges(): Promise<void> {
551
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushSwingModeChanges`);
495
+ await this.pushChange('pushSwingModeChanges');
552
496
  if (this.Fan.SwingMode !== this.accessory.context.SwingMode) {
553
- let parameter = '';
554
- if (this.Fan.SwingMode === this.hap.Characteristic.SwingMode.SWING_ENABLED) {
555
- parameter = 'on';
556
- } else {
557
- parameter = 'off';
558
- }
497
+ const parameter = this.Fan.SwingMode === this.hap.Characteristic.SwingMode.SWING_ENABLED ? 'on' : 'off';
559
498
  const bodyChange = JSON.stringify({
560
499
  command: 'setOscillation',
561
500
  parameter: `${parameter}`,
562
501
  commandType: 'command',
563
502
  });
564
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
503
+ await this.bodyChange(bodyChange, 'SwitchBot OpenAPI');
565
504
  try {
566
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
567
- body: bodyChange,
568
- method: 'POST',
569
- headers: this.platform.generateHeaders(),
570
- });
571
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
505
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
572
506
  const deviceStatus: any = await body.json();
573
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
574
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
575
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
507
+ await this.pushStatusCodes(statusCode, deviceStatus);
576
508
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
577
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
578
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
579
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
580
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
509
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
510
+ await this.updateHomeKitCharacteristics();
581
511
  } else {
582
- this.statusCode(statusCode);
583
- this.statusCode(deviceStatus.statusCode);
512
+ await this.statusCode(statusCode);
513
+ await this.statusCode(deviceStatus.statusCode);
584
514
  }
585
515
  } catch (e: any) {
586
516
  this.apiError(e);
587
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushSwingModeChanges with ${this.device.connectionType}`
588
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
517
+ await this.pushChangeError('pushSwingModeChanges', e);
589
518
  }
590
519
  } else {
591
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, SwingMode: ${this.Fan.SwingMode}, `
592
- + `SwingModeCached: ${this.accessory.context.SwingMode}`);
520
+ await this.noChanges('SwingMode', this.Fan.SwingMode, this.accessory.context.SwingMode);
593
521
  }
594
522
  }
595
523
 
@@ -597,10 +525,10 @@ export class Fan extends deviceBase {
597
525
  * Handle requests to set the value of the "On" characteristic
598
526
  */
599
527
  async ActiveSet(value: CharacteristicValue): Promise<void> {
600
- if (this.Fan.Active === this.accessory.context.Active) {
601
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Active: ${value}`);
528
+ if (this.Fan.Active !== this.accessory.context.Active) {
529
+ await this.changeSet(value, 'Active');
602
530
  } else {
603
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Active: ${value}`);
531
+ await this.noChangeSet(value, 'Active');
604
532
  }
605
533
 
606
534
  this.Fan.Active = value;
@@ -611,10 +539,10 @@ export class Fan extends deviceBase {
611
539
  * Handle requests to set the value of the "On" characteristic
612
540
  */
613
541
  async RotationSpeedSet(value: CharacteristicValue): Promise<void> {
614
- if (this.Fan.RotationSpeed === this.accessory.context.RotationSpeed) {
615
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set RotationSpeed: ${value}`);
542
+ if (this.Fan.RotationSpeed !== this.accessory.context.RotationSpeed) {
543
+ await this.changeSet(value, 'RotationSpeed');
616
544
  } else {
617
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set RotationSpeed: ${value}`);
545
+ await this.noChangeSet(value, 'RotationSpeed');
618
546
  }
619
547
 
620
548
  this.Fan.RotationSpeed = value;
@@ -625,10 +553,10 @@ export class Fan extends deviceBase {
625
553
  * Handle requests to set the value of the "On" characteristic
626
554
  */
627
555
  async SwingModeSet(value: CharacteristicValue): Promise<void> {
628
- if (this.Fan.SwingMode === this.accessory.context.SwingMode) {
629
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set SwingMode: ${value}`);
556
+ if (this.Fan.SwingMode !== this.accessory.context.SwingMode) {
557
+ await this.changeSet(value, 'SwingMode');
630
558
  } else {
631
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set SwingMode: ${value}`);
559
+ await this.noChangeSet(value, 'SwingMode');
632
560
  }
633
561
 
634
562
  this.Fan.SwingMode = value;
@@ -639,10 +567,10 @@ export class Fan extends deviceBase {
639
567
  * Handle requests to set the value of the "On" characteristic
640
568
  */
641
569
  async OnSet(value: CharacteristicValue): Promise<void> {
642
- if (this.LightBulb.On === this.accessory.context.On) {
643
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set On: ${value}`);
570
+ if (this.LightBulb.On !== this.accessory.context.On) {
571
+ await this.changeSet(value, 'On');
644
572
  } else {
645
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
573
+ await this.noChangeSet(value, 'On');
646
574
  }
647
575
 
648
576
  this.LightBulb.On = value;
@@ -653,12 +581,12 @@ export class Fan extends deviceBase {
653
581
  * Handle requests to set the value of the "Brightness" characteristic
654
582
  */
655
583
  async BrightnessSet(value: CharacteristicValue): Promise<void> {
656
- if (this.LightBulb.Brightness === this.accessory.context.Brightness) {
657
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Brightness: ${value}`);
584
+ if (this.LightBulb.Brightness !== this.accessory.context.Brightness) {
585
+ await this.changeSet(value, 'Brightness');
658
586
  } else if (this.LightBulb.On) {
659
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
587
+ await this.changeSet(value, 'Brightness');
660
588
  } else {
661
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
589
+ await this.noChangeSet(value, 'Brightness');
662
590
  }
663
591
 
664
592
  this.LightBulb.Brightness = value;
package/src/device/hub.ts CHANGED
@@ -4,13 +4,12 @@
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
 
11
10
  import type { SwitchBotPlatform } from '../platform.js';
12
- import type { device, deviceStatus, devicesConfig } from '../settings.js';
13
11
  import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
12
+ import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
14
13
 
15
14
  export class Hub extends deviceBase {
16
15
  // Services
@@ -152,6 +151,11 @@ export class Hub extends deviceBase {
152
151
 
153
152
  }
154
153
 
154
+ async BLEparseStatus(serviceData: serviceData): Promise<void> {
155
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
156
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(serviceData)}`);
157
+ }
158
+
155
159
  async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
156
160
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
157
161
  // CurrentRelativeHumidity
@@ -198,39 +202,62 @@ export class Hub extends deviceBase {
198
202
  }
199
203
  }
200
204
 
205
+ /**
206
+ * Asks the SwitchBot API for the latest device information
207
+ */
201
208
  async refreshStatus(): Promise<void> {
202
- if (this.BLE) {
203
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE not supported`);
209
+ if (!this.device.enableCloudService && this.OpenAPI) {
210
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus enableCloudService: ${this.device.enableCloudService}`);
211
+ } else if (this.BLE) {
212
+ await this.BLERefreshStatus();
204
213
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
205
214
  await this.openAPIRefreshStatus();
206
215
  } else {
207
216
  await this.offlineOff();
208
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type: OpenAPI, refreshStatus will not happen.`);
217
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
218
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
219
+ }
220
+ }
221
+
222
+ async BLERefreshStatus(): Promise<void> {
223
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
224
+ const switchbot = await this.switchbotBLE();
225
+
226
+ if (switchbot === undefined) {
227
+ await this.BLERefreshConnection(switchbot);
228
+ } else {
229
+ // Start to monitor advertisement packets
230
+ (async () => {
231
+ // Start to monitor advertisement packets
232
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
233
+ // Update HomeKit
234
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
235
+ await this.BLEparseStatus(serviceData);
236
+ await this.updateHomeKitCharacteristics();
237
+ } else {
238
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
239
+ await this.BLERefreshConnection(switchbot);
240
+ }
241
+ })();
209
242
  }
210
243
  }
211
244
 
212
245
  async openAPIRefreshStatus(): Promise<void> {
213
246
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
214
247
  try {
215
- const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
216
- `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
217
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
248
+ const { body, statusCode } = await this.deviceRefreshStatus();
218
249
  const deviceStatus: any = await body.json();
219
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
220
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
250
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
221
251
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
222
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
223
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
224
- this.openAPIparseStatus(deviceStatus);
225
- this.updateHomeKitCharacteristics();
252
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
253
+ await this.openAPIparseStatus(deviceStatus);
254
+ await this.updateHomeKitCharacteristics();
226
255
  } else {
227
- this.statusCode(statusCode);
228
- this.statusCode(deviceStatus.statusCode);
256
+ await this.statusCodes(statusCode, deviceStatus);
229
257
  }
230
258
  } catch (e: any) {
231
- this.apiError(e);
232
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
233
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
259
+ await this.apiError(e);
260
+ await this.openAPIRefreshError(e);
234
261
  }
235
262
  }
236
263
 
@@ -350,6 +377,15 @@ export class Hub extends deviceBase {
350
377
  }
351
378
  }
352
379
 
380
+ async BLERefreshConnection(switchbot: any): Promise<void> {
381
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
382
+ + ` ${JSON.stringify(switchbot)}`);
383
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
384
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
385
+ await this.openAPIRefreshStatus();
386
+ }
387
+ }
388
+
353
389
  async offlineOff(): Promise<void> {
354
390
  if (this.device.offline) {
355
391
  if (!this.device.hub?.hide_temperature) {