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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) 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 +32 -63
  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 +31 -63
  8. package/dist/device/bot.js.map +1 -1
  9. package/dist/device/ceilinglight.d.ts.map +1 -1
  10. package/dist/device/ceilinglight.js +51 -111
  11. package/dist/device/ceilinglight.js.map +1 -1
  12. package/dist/device/colorbulb.d.ts +1 -1
  13. package/dist/device/colorbulb.d.ts.map +1 -1
  14. package/dist/device/colorbulb.js +38 -113
  15. package/dist/device/colorbulb.js.map +1 -1
  16. package/dist/device/contact.d.ts.map +1 -1
  17. package/dist/device/contact.js +22 -49
  18. package/dist/device/contact.js.map +1 -1
  19. package/dist/device/curtain.d.ts.map +1 -1
  20. package/dist/device/curtain.js +53 -61
  21. package/dist/device/curtain.js.map +1 -1
  22. package/dist/device/device.d.ts +17 -1
  23. package/dist/device/device.d.ts.map +1 -1
  24. package/dist/device/device.js +112 -5
  25. package/dist/device/device.js.map +1 -1
  26. package/dist/device/fan.d.ts.map +1 -1
  27. package/dist/device/fan.js +42 -95
  28. package/dist/device/fan.js.map +1 -1
  29. package/dist/device/hub.d.ts +7 -1
  30. package/dist/device/hub.d.ts.map +1 -1
  31. package/dist/device/hub.js +52 -14
  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 +52 -99
  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 +25 -43
  38. package/dist/device/iosensor.js.map +1 -1
  39. package/dist/device/lightstrip.d.ts +1 -1
  40. package/dist/device/lightstrip.d.ts.map +1 -1
  41. package/dist/device/lightstrip.js +53 -115
  42. package/dist/device/lightstrip.js.map +1 -1
  43. package/dist/device/lock.d.ts +1 -1
  44. package/dist/device/lock.d.ts.map +1 -1
  45. package/dist/device/lock.js +33 -61
  46. package/dist/device/lock.js.map +1 -1
  47. package/dist/device/meter.d.ts.map +1 -1
  48. package/dist/device/meter.js +25 -43
  49. package/dist/device/meter.js.map +1 -1
  50. package/dist/device/meterplus.d.ts.map +1 -1
  51. package/dist/device/meterplus.js +24 -42
  52. package/dist/device/meterplus.js.map +1 -1
  53. package/dist/device/motion.d.ts.map +1 -1
  54. package/dist/device/motion.js +22 -40
  55. package/dist/device/motion.js.map +1 -1
  56. package/dist/device/plug.d.ts.map +1 -1
  57. package/dist/device/plug.js +29 -61
  58. package/dist/device/plug.js.map +1 -1
  59. package/dist/device/robotvacuumcleaner.d.ts +1 -1
  60. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  61. package/dist/device/robotvacuumcleaner.js +36 -77
  62. package/dist/device/robotvacuumcleaner.js.map +1 -1
  63. package/dist/device/waterdetector.d.ts.map +1 -1
  64. package/dist/device/waterdetector.js +21 -40
  65. package/dist/device/waterdetector.js.map +1 -1
  66. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  67. package/dist/irdevice/airconditioner.js +8 -25
  68. package/dist/irdevice/airconditioner.js.map +1 -1
  69. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  70. package/dist/irdevice/airpurifier.js +6 -17
  71. package/dist/irdevice/airpurifier.js.map +1 -1
  72. package/dist/irdevice/camera.d.ts.map +1 -1
  73. package/dist/irdevice/camera.js +6 -17
  74. package/dist/irdevice/camera.js.map +1 -1
  75. package/dist/irdevice/fan.d.ts.map +1 -1
  76. package/dist/irdevice/fan.js +6 -17
  77. package/dist/irdevice/fan.js.map +1 -1
  78. package/dist/irdevice/irdevice.d.ts +6 -0
  79. package/dist/irdevice/irdevice.d.ts.map +1 -1
  80. package/dist/irdevice/irdevice.js +24 -0
  81. package/dist/irdevice/irdevice.js.map +1 -1
  82. package/dist/irdevice/light.d.ts.map +1 -1
  83. package/dist/irdevice/light.js +6 -17
  84. package/dist/irdevice/light.js.map +1 -1
  85. package/dist/irdevice/other.d.ts.map +1 -1
  86. package/dist/irdevice/other.js +6 -17
  87. package/dist/irdevice/other.js.map +1 -1
  88. package/dist/irdevice/tv.d.ts.map +1 -1
  89. package/dist/irdevice/tv.js +6 -17
  90. package/dist/irdevice/tv.js.map +1 -1
  91. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  92. package/dist/irdevice/vacuumcleaner.js +6 -17
  93. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  94. package/dist/irdevice/waterheater.d.ts.map +1 -1
  95. package/dist/irdevice/waterheater.js +6 -17
  96. package/dist/irdevice/waterheater.js.map +1 -1
  97. package/dist/settings.d.ts +2 -1
  98. package/dist/settings.d.ts.map +1 -1
  99. package/dist/utils.d.ts +19 -1
  100. package/dist/utils.d.ts.map +1 -1
  101. package/dist/utils.js +20 -1
  102. package/dist/utils.js.map +1 -1
  103. package/package.json +8 -8
  104. package/src/device/blindtilt.ts +30 -63
  105. package/src/device/bot.ts +29 -63
  106. package/src/device/ceilinglight.ts +48 -111
  107. package/src/device/colorbulb.ts +37 -114
  108. package/src/device/contact.ts +20 -49
  109. package/src/device/curtain.ts +52 -62
  110. package/src/device/device.ts +124 -7
  111. package/src/device/fan.ts +40 -97
  112. package/src/device/hub.ts +53 -16
  113. package/src/device/humidifier.ts +49 -99
  114. package/src/device/iosensor.ts +23 -43
  115. package/src/device/lightstrip.ts +51 -116
  116. package/src/device/lock.ts +32 -62
  117. package/src/device/meter.ts +23 -43
  118. package/src/device/meterplus.ts +22 -42
  119. package/src/device/motion.ts +20 -40
  120. package/src/device/plug.ts +27 -61
  121. package/src/device/robotvacuumcleaner.ts +33 -78
  122. package/src/device/waterdetector.ts +20 -40
  123. package/src/irdevice/airconditioner.ts +8 -23
  124. package/src/irdevice/airpurifier.ts +6 -17
  125. package/src/irdevice/camera.ts +6 -17
  126. package/src/irdevice/fan.ts +6 -17
  127. package/src/irdevice/irdevice.ts +24 -0
  128. package/src/irdevice/light.ts +6 -17
  129. package/src/irdevice/other.ts +6 -17
  130. package/src/irdevice/tv.ts +6 -17
  131. package/src/irdevice/vacuumcleaner.ts +6 -17
  132. package/src/irdevice/waterheater.ts +6 -17
  133. package/src/settings.ts +2 -1
  134. 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,58 +260,39 @@ 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);
263
+ const switchbot = await this.switchbotBLE();
264
+
265
+ if (switchbot === undefined) {
266
+ await this.BLERefreshConnection(switchbot);
267
+ } else {
275
268
  // Start to monitor advertisement packets
276
- (async () => {
269
+ (async () => {
277
270
  // 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)}`);
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
298
  this.apiError(e);
@@ -412,16 +389,9 @@ export class Fan extends deviceBase {
412
389
  + ` On: ${this.Fan.Active} OnCached: ${this.accessory.context.Active}`);
413
390
  const switchbot = await this.platform.connectBLE();
414
391
  // 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}`);
392
+ await this.convertBLEAddress();
420
393
  switchbot
421
- .discover({
422
- model: this.device.bleModel,
423
- id: this.device.bleMac,
424
- })
394
+ .discover({ model: this.device.bleModel, id: this.device.bleMac })
425
395
  .then(async (device_list: any) => {
426
396
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Fan.Active}`);
427
397
  return await this.retryBLE({
@@ -469,24 +439,15 @@ export class Fan extends deviceBase {
469
439
  });
470
440
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
471
441
  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}`);
442
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
478
443
  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}`);
444
+ await this.pushStatusCodes(statusCode, deviceStatus);
482
445
  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`);
446
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
447
+ await this.updateHomeKitCharacteristics();
487
448
  } else {
488
- this.statusCode(statusCode);
489
- this.statusCode(deviceStatus.statusCode);
449
+ await this.statusCode(statusCode);
450
+ await this.statusCode(deviceStatus.statusCode);
490
451
  }
491
452
  } catch (e: any) {
492
453
  this.apiError(e);
@@ -517,24 +478,15 @@ export class Fan extends deviceBase {
517
478
  });
518
479
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
519
480
  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}`);
481
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
526
482
  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}`);
483
+ await this.pushStatusCodes(statusCode, deviceStatus);
530
484
  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`);
485
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
486
+ await this.updateHomeKitCharacteristics();
535
487
  } else {
536
- this.statusCode(statusCode);
537
- this.statusCode(deviceStatus.statusCode);
488
+ await this.statusCode(statusCode);
489
+ await this.statusCode(deviceStatus.statusCode);
538
490
  }
539
491
  } catch (e: any) {
540
492
  this.apiError(e);
@@ -563,24 +515,15 @@ export class Fan extends deviceBase {
563
515
  });
564
516
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
565
517
  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}`);
518
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
572
519
  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}`);
520
+ await this.pushStatusCodes(statusCode, deviceStatus);
576
521
  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`);
522
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
523
+ await this.updateHomeKitCharacteristics();
581
524
  } else {
582
- this.statusCode(statusCode);
583
- this.statusCode(deviceStatus.statusCode);
525
+ await this.statusCode(statusCode);
526
+ await this.statusCode(deviceStatus.statusCode);
584
527
  }
585
528
  } catch (e: any) {
586
529
  this.apiError(e);
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,34 +202,58 @@ 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
259
  this.apiError(e);
@@ -350,6 +378,15 @@ export class Hub extends deviceBase {
350
378
  }
351
379
  }
352
380
 
381
+ async BLERefreshConnection(switchbot: any): Promise<void> {
382
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
383
+ + ` ${JSON.stringify(switchbot)}`);
384
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
385
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
386
+ await this.openAPIRefreshStatus();
387
+ }
388
+ }
389
+
353
390
  async offlineOff(): Promise<void> {
354
391
  if (this.device.offline) {
355
392
  if (!this.device.hub?.hide_temperature) {
@@ -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,58 +279,39 @@ 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
317
  this.apiError(e);
@@ -367,8 +350,8 @@ export class Humidifier extends deviceBase {
367
350
  async pushChanges(): Promise<void> {
368
351
  if (!this.device.enableCloudService && this.OpenAPI) {
369
352
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
370
- /*} else if (this.BLE) {
371
- await this.BLEpushChanges();*/
353
+ } else if (this.BLE) {
354
+ await this.BLEpushChanges();
372
355
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
373
356
  await this.openAPIpushChanges();
374
357
  } else {
@@ -376,7 +359,9 @@ export class Humidifier extends deviceBase {
376
359
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
377
360
  + ` ${this.device.connectionType}, pushChanges will not happen.`);
378
361
  }
379
- interval(5000)
362
+ // Refresh the status from the API
363
+ interval(15000)
364
+ .pipe(skipWhile(() => this.humidifierUpdateInProgress))
380
365
  .pipe(take(1))
381
366
  .subscribe(async () => {
382
367
  await this.refreshStatus();
@@ -387,17 +372,9 @@ export class Humidifier extends deviceBase {
387
372
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
388
373
  const switchbot = await this.platform.connectBLE();
389
374
  // 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}`);
375
+ await this.convertBLEAddress();
395
376
  switchbot
396
- .discover({
397
- model: 'e',
398
- quick: true,
399
- id: this.device.bleMac,
400
- })
377
+ .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
401
378
  .then(async (device_list: any) => {
402
379
  this.infoLog(`${this.accessory.displayName} Active: ${this.HumidifierDehumidifier.Active}`);
403
380
  return await device_list[0].percentage(this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold);
@@ -430,24 +407,15 @@ export class Humidifier extends deviceBase {
430
407
  });
431
408
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
432
409
  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}`);
410
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
439
411
  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}`);
412
+ await this.pushStatusCodes(statusCode, deviceStatus);
443
413
  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`);
414
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
415
+ await this.updateHomeKitCharacteristics();
448
416
  } else {
449
- this.statusCode(statusCode);
450
- this.statusCode(deviceStatus.statusCode);
417
+ await this.statusCode(statusCode);
418
+ await this.statusCode(deviceStatus.statusCode);
451
419
  }
452
420
  } catch (e: any) {
453
421
  this.apiError(e);
@@ -483,24 +451,15 @@ export class Humidifier extends deviceBase {
483
451
  });
484
452
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
485
453
  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}`);
454
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
492
455
  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}`);
456
+ await this.pushStatusCodes(statusCode, deviceStatus);
496
457
  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`);
458
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
459
+ await this.updateHomeKitCharacteristics();
501
460
  } else {
502
- this.statusCode(statusCode);
503
- this.statusCode(deviceStatus.statusCode);
461
+ await this.statusCode(statusCode);
462
+ await this.statusCode(deviceStatus.statusCode);
504
463
  }
505
464
  } catch (e: any) {
506
465
  this.apiError(e);
@@ -527,24 +486,15 @@ export class Humidifier extends deviceBase {
527
486
  });
528
487
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
529
488
  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}`);
489
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
536
490
  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}`);
491
+ await this.pushStatusCodes(statusCode, deviceStatus);
540
492
  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`);
493
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
494
+ await this.updateHomeKitCharacteristics();
545
495
  } else {
546
- this.statusCode(statusCode);
547
- this.statusCode(deviceStatus.statusCode);
496
+ await this.statusCode(statusCode);
497
+ await this.statusCode(deviceStatus.statusCode);
548
498
  }
549
499
  } catch (e: any) {
550
500
  this.apiError(e);