@switchbot/homebridge-switchbot 3.5.0-beta.2 → 3.5.0-beta.21

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 (151) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/config.schema.json +57 -6
  3. package/dist/device/blindtilt.d.ts +4 -0
  4. package/dist/device/blindtilt.d.ts.map +1 -1
  5. package/dist/device/blindtilt.js +37 -1
  6. package/dist/device/blindtilt.js.map +1 -1
  7. package/dist/device/bot.d.ts +4 -0
  8. package/dist/device/bot.d.ts.map +1 -1
  9. package/dist/device/bot.js +31 -1
  10. package/dist/device/bot.js.map +1 -1
  11. package/dist/device/ceilinglight.d.ts +4 -0
  12. package/dist/device/ceilinglight.d.ts.map +1 -1
  13. package/dist/device/ceilinglight.js +37 -3
  14. package/dist/device/ceilinglight.js.map +1 -1
  15. package/dist/device/colorbulb.d.ts +4 -0
  16. package/dist/device/colorbulb.d.ts.map +1 -1
  17. package/dist/device/colorbulb.js +39 -3
  18. package/dist/device/colorbulb.js.map +1 -1
  19. package/dist/device/contact.d.ts +4 -0
  20. package/dist/device/contact.d.ts.map +1 -1
  21. package/dist/device/contact.js +27 -2
  22. package/dist/device/contact.js.map +1 -1
  23. package/dist/device/curtain.d.ts +4 -0
  24. package/dist/device/curtain.d.ts.map +1 -1
  25. package/dist/device/curtain.js +31 -1
  26. package/dist/device/curtain.js.map +1 -1
  27. package/dist/device/hub.d.ts +4 -0
  28. package/dist/device/hub.d.ts.map +1 -1
  29. package/dist/device/hub.js +27 -2
  30. package/dist/device/hub.js.map +1 -1
  31. package/dist/device/humidifier.d.ts +4 -0
  32. package/dist/device/humidifier.d.ts.map +1 -1
  33. package/dist/device/humidifier.js +36 -2
  34. package/dist/device/humidifier.js.map +1 -1
  35. package/dist/device/iosensor.d.ts +4 -0
  36. package/dist/device/iosensor.d.ts.map +1 -1
  37. package/dist/device/iosensor.js +27 -2
  38. package/dist/device/iosensor.js.map +1 -1
  39. package/dist/device/lightstrip.d.ts +4 -0
  40. package/dist/device/lightstrip.d.ts.map +1 -1
  41. package/dist/device/lightstrip.js +37 -3
  42. package/dist/device/lightstrip.js.map +1 -1
  43. package/dist/device/lock.d.ts +4 -0
  44. package/dist/device/lock.d.ts.map +1 -1
  45. package/dist/device/lock.js +31 -1
  46. package/dist/device/lock.js.map +1 -1
  47. package/dist/device/meter.d.ts +4 -0
  48. package/dist/device/meter.d.ts.map +1 -1
  49. package/dist/device/meter.js +27 -2
  50. package/dist/device/meter.js.map +1 -1
  51. package/dist/device/meterplus.d.ts +4 -0
  52. package/dist/device/meterplus.d.ts.map +1 -1
  53. package/dist/device/meterplus.js +27 -2
  54. package/dist/device/meterplus.js.map +1 -1
  55. package/dist/device/motion.d.ts +4 -0
  56. package/dist/device/motion.d.ts.map +1 -1
  57. package/dist/device/motion.js +27 -2
  58. package/dist/device/motion.js.map +1 -1
  59. package/dist/device/plug.d.ts +4 -0
  60. package/dist/device/plug.d.ts.map +1 -1
  61. package/dist/device/plug.js +31 -1
  62. package/dist/device/plug.js.map +1 -1
  63. package/dist/device/robotvacuumcleaner.d.ts +4 -0
  64. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  65. package/dist/device/robotvacuumcleaner.js +38 -5
  66. package/dist/device/robotvacuumcleaner.js.map +1 -1
  67. package/dist/device/waterdetector.d.ts +7 -11
  68. package/dist/device/waterdetector.d.ts.map +1 -1
  69. package/dist/device/waterdetector.js +54 -224
  70. package/dist/device/waterdetector.js.map +1 -1
  71. package/dist/index.js +1 -1
  72. package/dist/irdevice/airconditioner.d.ts +1 -0
  73. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  74. package/dist/irdevice/airconditioner.js +6 -0
  75. package/dist/irdevice/airconditioner.js.map +1 -1
  76. package/dist/irdevice/airpurifier.d.ts +1 -0
  77. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  78. package/dist/irdevice/airpurifier.js +6 -0
  79. package/dist/irdevice/airpurifier.js.map +1 -1
  80. package/dist/irdevice/camera.d.ts +1 -0
  81. package/dist/irdevice/camera.d.ts.map +1 -1
  82. package/dist/irdevice/camera.js +6 -0
  83. package/dist/irdevice/camera.js.map +1 -1
  84. package/dist/irdevice/fan.d.ts +1 -0
  85. package/dist/irdevice/fan.d.ts.map +1 -1
  86. package/dist/irdevice/fan.js +6 -0
  87. package/dist/irdevice/fan.js.map +1 -1
  88. package/dist/irdevice/light.d.ts +1 -0
  89. package/dist/irdevice/light.d.ts.map +1 -1
  90. package/dist/irdevice/light.js +6 -0
  91. package/dist/irdevice/light.js.map +1 -1
  92. package/dist/irdevice/other.d.ts +1 -0
  93. package/dist/irdevice/other.d.ts.map +1 -1
  94. package/dist/irdevice/other.js +6 -0
  95. package/dist/irdevice/other.js.map +1 -1
  96. package/dist/irdevice/tv.d.ts +1 -0
  97. package/dist/irdevice/tv.d.ts.map +1 -1
  98. package/dist/irdevice/tv.js +6 -0
  99. package/dist/irdevice/tv.js.map +1 -1
  100. package/dist/irdevice/vacuumcleaner.d.ts +1 -0
  101. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  102. package/dist/irdevice/vacuumcleaner.js +6 -0
  103. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  104. package/dist/irdevice/waterheater.d.ts +1 -0
  105. package/dist/irdevice/waterheater.d.ts.map +1 -1
  106. package/dist/irdevice/waterheater.js +6 -0
  107. package/dist/irdevice/waterheater.js.map +1 -1
  108. package/dist/platform.d.ts +12 -0
  109. package/dist/platform.d.ts.map +1 -1
  110. package/dist/platform.js +148 -89
  111. package/dist/platform.js.map +1 -1
  112. package/dist/settings.d.ts +5 -6
  113. package/dist/settings.d.ts.map +1 -1
  114. package/dist/settings.js +0 -552
  115. package/dist/settings.js.map +1 -1
  116. package/dist/utils.d.ts +4 -0
  117. package/dist/utils.d.ts.map +1 -1
  118. package/dist/utils.js +553 -1
  119. package/dist/utils.js.map +1 -1
  120. package/package.json +16 -15
  121. package/src/custom.d.ts +1 -1
  122. package/src/device/blindtilt.ts +49 -12
  123. package/src/device/bot.ts +34 -3
  124. package/src/device/ceilinglight.ts +40 -5
  125. package/src/device/colorbulb.ts +42 -5
  126. package/src/device/contact.ts +30 -4
  127. package/src/device/curtain.ts +34 -3
  128. package/src/device/hub.ts +30 -4
  129. package/src/device/humidifier.ts +39 -4
  130. package/src/device/iosensor.ts +30 -4
  131. package/src/device/lightstrip.ts +40 -5
  132. package/src/device/lock.ts +34 -3
  133. package/src/device/meter.ts +30 -4
  134. package/src/device/meterplus.ts +30 -4
  135. package/src/device/motion.ts +30 -4
  136. package/src/device/plug.ts +34 -3
  137. package/src/device/robotvacuumcleaner.ts +41 -7
  138. package/src/device/waterdetector.ts +60 -229
  139. package/src/index.ts +1 -1
  140. package/src/irdevice/airconditioner.ts +7 -0
  141. package/src/irdevice/airpurifier.ts +7 -0
  142. package/src/irdevice/camera.ts +7 -0
  143. package/src/irdevice/fan.ts +7 -0
  144. package/src/irdevice/light.ts +7 -0
  145. package/src/irdevice/other.ts +7 -0
  146. package/src/irdevice/tv.ts +7 -0
  147. package/src/irdevice/vacuumcleaner.ts +7 -0
  148. package/src/irdevice/waterheater.ts +7 -0
  149. package/src/platform.ts +157 -95
  150. package/src/settings.ts +6 -557
  151. package/src/utils.ts +556 -1
@@ -30,6 +30,8 @@ export class Plug {
30
30
  scanDuration!: number;
31
31
  deviceLogging!: string;
32
32
  deviceRefreshRate!: number;
33
+ maxRetries!: number;
34
+ delayBetweenRetries!: number;
33
35
 
34
36
  // Updates
35
37
  plugUpdateInProgress!: boolean;
@@ -56,6 +58,7 @@ export class Plug {
56
58
  this.scan(device);
57
59
  this.refreshRate(device);
58
60
  this.deviceContext();
61
+ this.deviceRetry(device);
59
62
  this.deviceConfig(device);
60
63
 
61
64
  // this is subject we use to track when we need to POST changes to the SwitchBot API
@@ -297,9 +300,10 @@ export class Plug {
297
300
  async openAPIRefreshStatus() {
298
301
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
299
302
  try {
300
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
301
- headers: this.platform.generateHeaders(),
302
- });
303
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
304
+ `${Devices}/${this.device.deviceId}/status`, {
305
+ headers: this.platform.generateHeaders(),
306
+ });
303
307
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
304
308
  const deviceStatus: any = await body.json();
305
309
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -386,6 +390,8 @@ export class Plug {
386
390
  })
387
391
  .then(() => {
388
392
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
393
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
394
+ + `On: ${this.On} sent over BLE, sent successfully`);
389
395
  this.On = false;
390
396
  })
391
397
  .catch(async (e: any) => {
@@ -432,6 +438,8 @@ export class Plug {
432
438
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
433
439
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
434
440
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
441
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
442
+ + `request to SwitchBot API, body: ${deviceStatus} sent successfully`);
435
443
  } else {
436
444
  this.statusCode(statusCode);
437
445
  this.statusCode(deviceStatus.statusCode);
@@ -687,6 +695,23 @@ export class Plug {
687
695
  }
688
696
  }
689
697
 
698
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
699
+ if (!device.maxRetries) {
700
+ this.maxRetries = 5; // Maximum number of retries
701
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
702
+ } else {
703
+ this.maxRetries = device.maxRetries;
704
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
705
+ }
706
+ if (!device.delayBetweenRetries) {
707
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
708
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
709
+ } else {
710
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
711
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
712
+ }
713
+ }
714
+
690
715
  async deviceConfig(device: device & devicesConfig): Promise<void> {
691
716
  let config = {};
692
717
  if (device.plug) {
@@ -740,6 +765,12 @@ export class Plug {
740
765
  /**
741
766
  * Logging for Device
742
767
  */
768
+ successLog(...log: any[]): void {
769
+ if (this.enablingDeviceLogging()) {
770
+ this.platform.log.success(String(...log));
771
+ }
772
+ }
773
+
743
774
  infoLog(...log: any[]): void {
744
775
  if (this.enablingDeviceLogging()) {
745
776
  this.platform.log.info(String(...log));
@@ -37,6 +37,8 @@ export class RobotVacuumCleaner {
37
37
  scanDuration!: number;
38
38
  deviceLogging!: string;
39
39
  deviceRefreshRate!: number;
40
+ maxRetries!: number;
41
+ delayBetweenRetries!: number;
40
42
 
41
43
  // Updates
42
44
  robotVacuumCleanerUpdateInProgress!: boolean;
@@ -63,6 +65,7 @@ export class RobotVacuumCleaner {
63
65
  this.scan(device);
64
66
  this.refreshRate(device);
65
67
  this.deviceContext();
68
+ this.deviceRetry(device);
66
69
  this.deviceConfig(device);
67
70
 
68
71
  // this is subject we use to track when we need to POST changes to the SwitchBot API
@@ -344,9 +347,10 @@ export class RobotVacuumCleaner {
344
347
  async openAPIRefreshStatus() {
345
348
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
346
349
  try {
347
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
348
- headers: this.platform.generateHeaders(),
349
- });
350
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
351
+ `${Devices}/${this.device.deviceId}/status`, {
352
+ headers: this.platform.generateHeaders(),
353
+ });
350
354
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
351
355
  const deviceStatus: any = await body.json();
352
356
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -434,6 +438,8 @@ export class RobotVacuumCleaner {
434
438
  })
435
439
  .then(() => {
436
440
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
441
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
442
+ + `On: ${this.On} sent over BLE, sent successfully`);
437
443
  this.On = false;
438
444
  })
439
445
  .catch(async (e: any) => {
@@ -480,6 +486,8 @@ export class RobotVacuumCleaner {
480
486
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
481
487
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
482
488
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
489
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
490
+ + `request to SwitchBot API, body: ${bodyChange} sent successfully`);
483
491
  } else {
484
492
  this.statusCode(statusCode);
485
493
  this.statusCode(deviceStatus.statusCode);
@@ -502,10 +510,11 @@ export class RobotVacuumCleaner {
502
510
 
503
511
  async openAPIpushBrightnessChanges() {
504
512
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushBrightnessChanges`);
505
- const body = await this.brightnessCommands();
506
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${body},`);
513
+ const bodyChange = this.brightnessCommands();
514
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
507
515
  try {
508
516
  const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
517
+ body: bodyChange,
509
518
  method: 'POST',
510
519
  headers: this.platform.generateHeaders(),
511
520
  });
@@ -516,6 +525,8 @@ export class RobotVacuumCleaner {
516
525
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
517
526
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
518
527
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
528
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
529
+ + `request to SwitchBot API, body: ${deviceStatus} sent successfully`);
519
530
  } else {
520
531
  this.statusCode(statusCode);
521
532
  this.statusCode(deviceStatus.statusCode);
@@ -566,12 +577,12 @@ export class RobotVacuumCleaner {
566
577
  command = 'dock';
567
578
  parameter = 'default';
568
579
  }
569
- const body = JSON.stringify({
580
+ const bodyChange = JSON.stringify({
570
581
  command: `${command}`,
571
582
  parameter: `${parameter}`,
572
583
  commandType: 'command',
573
584
  });
574
- return body;
585
+ return bodyChange;
575
586
  }
576
587
 
577
588
  /**
@@ -845,6 +856,23 @@ export class RobotVacuumCleaner {
845
856
  }
846
857
  }
847
858
 
859
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
860
+ if (!device.maxRetries) {
861
+ this.maxRetries = 5; // Maximum number of retries
862
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
863
+ } else {
864
+ this.maxRetries = device.maxRetries;
865
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
866
+ }
867
+ if (!device.delayBetweenRetries) {
868
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
869
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
870
+ } else {
871
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
872
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
873
+ }
874
+ }
875
+
848
876
  async deviceConfig(device: device & devicesConfig): Promise<void> {
849
877
  let config = {};
850
878
  if (device.plug) {
@@ -898,6 +926,12 @@ export class RobotVacuumCleaner {
898
926
  /**
899
927
  * Logging for Device
900
928
  */
929
+ successLog(...log: any[]): void {
930
+ if (this.enablingDeviceLogging()) {
931
+ this.platform.log.success(String(...log));
932
+ }
933
+ }
934
+
901
935
  infoLog(...log: any[]): void {
902
936
  if (this.enablingDeviceLogging()) {
903
937
  this.platform.log.info(String(...log));
@@ -1,13 +1,12 @@
1
1
  import { hostname } from 'os';
2
- import { request } from 'undici';
3
2
  import { sleep } from '../utils.js';
4
3
  import { MqttClient } from 'mqtt';
5
4
  import asyncmqtt from 'async-mqtt';
6
5
  import { interval, Subject } from 'rxjs';
7
6
  import { skipWhile } from 'rxjs/operators';
8
7
  import { SwitchBotPlatform } from '../platform.js';
9
- import { Service, PlatformAccessory, Units, CharacteristicValue, API, Logging, HAP } from 'homebridge';
10
- import { device, devicesConfig, serviceData, temperature, deviceStatus, Devices, SwitchBotPlatformConfig } from '../settings.js';
8
+ import { Service, PlatformAccessory, CharacteristicValue, API, Logging, HAP } from 'homebridge';
9
+ import { device, devicesConfig, serviceData, deviceStatus, Devices, SwitchBotPlatformConfig } from '../settings.js';
11
10
 
12
11
  /**
13
12
  * Platform Accessory
@@ -22,8 +21,6 @@ export class WaterDetector {
22
21
  // Services
23
22
  leakService?: Service;
24
23
  batteryService: Service;
25
- humidityservice?: Service;
26
- temperatureservice?: Service;
27
24
 
28
25
  // Characteristic Values
29
26
  StatusActive!: CharacteristicValue;
@@ -32,21 +29,15 @@ export class WaterDetector {
32
29
  ChargingState!: CharacteristicValue;
33
30
  StatusLowBattery!: CharacteristicValue;
34
31
  FirmwareRevision!: CharacteristicValue;
35
- CurrentTemperature!: CharacteristicValue;
36
- CurrentRelativeHumidity!: CharacteristicValue;
37
32
 
38
33
  // OpenAPI Status
39
34
  OpenAPI_BatteryLevel: deviceStatus['battery'];
40
35
  OpenAPI_FirmwareRevision: deviceStatus['version'];
41
- OpenAPI_CurrentTemperature: deviceStatus['temperature'];
42
- OpenAPI_CurrentRelativeHumidity: deviceStatus['humidity'];
36
+ OpenAPI_LeakDetected: deviceStatus['status'];
43
37
 
44
38
  // BLE Status
45
- BLE_Celsius!: temperature['c'];
46
- BLE_Fahrenheit!: temperature['f'];
47
39
  BLE_BatteryLevel!: serviceData['battery'];
48
- BLE_CurrentTemperature!: serviceData['temperature'];
49
- BLE_CurrentRelativeHumidity!: serviceData['humidity'];
40
+ BLE_LeakDetected!: number;//serviceData['status'];
50
41
 
51
42
  // BLE Others
52
43
  BLE_IsConnected?: boolean;
@@ -61,6 +52,8 @@ export class WaterDetector {
61
52
  scanDuration!: number;
62
53
  deviceLogging!: string;
63
54
  deviceRefreshRate!: number;
55
+ maxRetries!: number;
56
+ delayBetweenRetries!: number;
64
57
 
65
58
  // Updates
66
59
  WaterDetectorUpdateInProgress!: boolean;
@@ -89,6 +82,7 @@ export class WaterDetector {
89
82
  this.deviceContext();
90
83
  this.setupHistoryService(device);
91
84
  this.setupMqtt(device);
85
+ this.deviceRetry(device);
92
86
  this.deviceConfig(device);
93
87
 
94
88
  // this is subject we use to track when we need to POST changes to the SwitchBot API
@@ -125,64 +119,6 @@ export class WaterDetector {
125
119
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Leak Sensor Service Not Added`);
126
120
  }
127
121
 
128
- // Temperature Sensor Service
129
- if (device.waterdetector?.hide_temperature) {
130
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Temperature Sensor Service`);
131
- this.temperatureservice = this.accessory.getService(this.hap.Service.TemperatureSensor);
132
- accessory.removeService(this.temperatureservice!);
133
- } else if (!this.temperatureservice) {
134
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Temperature Sensor Service`);
135
- const temperatureservice = `${accessory.displayName} Temperature Sensor`;
136
- (this.temperatureservice = this.accessory.getService(this.hap.Service.TemperatureSensor)
137
- || this.accessory.addService(this.hap.Service.TemperatureSensor)), temperatureservice;
138
-
139
- this.temperatureservice.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Temperature Sensor`);
140
- if (!this.temperatureservice.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
141
- this.temperatureservice.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Temperature Sensor`);
142
- }
143
- this.temperatureservice
144
- .getCharacteristic(this.hap.Characteristic.CurrentTemperature)
145
- .setProps({
146
- unit: Units['CELSIUS'],
147
- validValueRanges: [-273.15, 100],
148
- minValue: -273.15,
149
- maxValue: 100,
150
- minStep: 0.1,
151
- })
152
- .onGet(() => {
153
- return this.CurrentTemperature!;
154
- });
155
- } else {
156
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Temperature Sensor Service Not Added`);
157
- }
158
-
159
- // Humidity Sensor Service
160
- if (device.waterdetector?.hide_humidity) {
161
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Humidity Sensor Service`);
162
- this.humidityservice = this.accessory.getService(this.hap.Service.HumiditySensor);
163
- accessory.removeService(this.humidityservice!);
164
- } else if (!this.humidityservice) {
165
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Humidity Sensor Service`);
166
- const humidityservice = `${accessory.displayName} Humidity Sensor`;
167
- (this.humidityservice = this.accessory.getService(this.hap.Service.HumiditySensor)
168
- || this.accessory.addService(this.hap.Service.HumiditySensor)), humidityservice;
169
-
170
- this.humidityservice.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Humidity Sensor`);
171
- if (!this.humidityservice.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
172
- this.humidityservice.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Humidity Sensor`);
173
- }
174
- this.humidityservice
175
- .getCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity)
176
- .setProps({
177
- minStep: 0.1,
178
- })
179
- .onGet(() => {
180
- return this.CurrentRelativeHumidity;
181
- });
182
- } else {
183
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Humidity Sensor Service Not Added`);
184
- }
185
-
186
122
  // Battery Service
187
123
  const batteryService = `${accessory.displayName} Battery`;
188
124
  (this.batteryService = this.accessory.getService(this.hap.Service.Battery)
@@ -210,17 +146,14 @@ export class WaterDetector {
210
146
  this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
211
147
  try {
212
148
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
213
- if (context.scale === 'CELSIUS') {
214
- const { temperature, humidity } = context;
215
- const { CurrentTemperature, CurrentRelativeHumidity } = this;
216
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
217
- '(temperature, humidity) = ' +
218
- `Webhook:(${temperature}, ${humidity}), ` +
219
- `current:(${CurrentTemperature}, ${CurrentRelativeHumidity})`);
220
- this.CurrentRelativeHumidity = humidity;
221
- this.CurrentTemperature = temperature;
222
- this.updateHomeKitCharacteristics();
223
- }
149
+ const { status } = context;
150
+ const { LeakDetected } = this;
151
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
152
+ '(status) = ' +
153
+ `Webhook:(${status}), ` +
154
+ `current:(${LeakDetected})`);
155
+ this.LeakDetected = status;
156
+ this.updateHomeKitCharacteristics();
224
157
  } catch (e: any) {
225
158
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
226
159
  + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
@@ -259,55 +192,31 @@ export class WaterDetector {
259
192
  }
260
193
  this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
261
194
 
262
- // Humidity
263
- if (!this.device.waterdetector?.hide_humidity) {
264
- this.CurrentRelativeHumidity = this.BLE_CurrentRelativeHumidity!;
265
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
266
- }
267
-
268
- // Current Temperature
269
- if (!this.device.waterdetector?.hide_temperature) {
270
- this.BLE_Celsius < 0 ? 0 : this.BLE_Celsius > 100 ? 100 : this.BLE_Celsius;
271
- this.CurrentTemperature = this.BLE_Celsius;
272
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
273
- }
195
+ // LeakDetected
196
+ this.LeakDetected = this.BLE_LeakDetected!;
197
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LeakDetected: ${this.LeakDetected}`);
274
198
  }
275
199
 
276
200
  async openAPIparseStatus(): Promise<void> {
277
201
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
278
- // Battery
202
+ // StatusLowBattery
279
203
  this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
280
- if (this.BatteryLevel < 15) {
204
+ if (this.BatteryLevel < 10) {
281
205
  this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
282
206
  } else {
283
207
  this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
284
208
  }
285
209
  this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
286
210
 
287
- // Current Relative Humidity
288
- if (!this.device.waterdetector?.hide_humidity) {
289
- this.CurrentRelativeHumidity = this.OpenAPI_CurrentRelativeHumidity!;
290
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
291
- }
292
-
293
- // Current Temperature
294
- if (!this.device.waterdetector?.hide_temperature) {
295
- this.CurrentTemperature = this.OpenAPI_CurrentTemperature!;
296
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
297
- }
298
-
299
211
  // BatteryLevel
300
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
301
- if (this.BatteryLevel < 10) {
302
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
303
- } else {
304
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
305
- }
306
212
  if (Number.isNaN(this.BatteryLevel)) {
307
213
  this.BatteryLevel = 100;
308
214
  }
309
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
310
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
215
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
216
+
217
+ // LeakDetected
218
+ this.LeakDetected = this.OpenAPI_LeakDetected!;
219
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LeakDetected: ${this.LeakDetected}`);
311
220
 
312
221
  // FirmwareRevision
313
222
  this.FirmwareRevision = this.OpenAPI_FirmwareRevision!;
@@ -347,18 +256,16 @@ export class WaterDetector {
347
256
  (async () => {
348
257
  // Start to monitor advertisement packets
349
258
  await switchbot.startScan({
350
- model: 'w',
259
+ model: 'l',
351
260
  id: this.device.bleMac,
352
261
  });
353
262
  // Set an event handler
354
263
  switchbot.onadvertisement = (ad: any) => {
355
264
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
356
265
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.serviceData.model}`);
357
- if (this.device.bleMac === ad.address && ad.serviceData.model === 'w') {
266
+ if (this.device.bleMac === ad.address && ad.serviceData.model === 'l') {
358
267
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
359
- this.BLE_CurrentTemperature = ad.serviceData.temperature;
360
- this.BLE_Celsius = ad.serviceData.temperature!.c;
361
- this.BLE_Fahrenheit = ad.serviceData.temperature!.f;
268
+ this.BLE_LeakDetected = ad.serviceData.status;
362
269
  this.BLE_BatteryLevel = ad.serviceData.battery;
363
270
  } else {
364
271
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
@@ -372,69 +279,15 @@ export class WaterDetector {
372
279
  await this.BLEparseStatus();
373
280
  await this.updateHomeKitCharacteristics();
374
281
  })();
375
- /*if (switchbot !== false) {
376
- switchbot
377
- .startScan({
378
- model: 'w',
379
- id: this.device.bleMac,
380
- })
381
- .then(async () => {
382
- // Set an event handler
383
- switchbot.onadvertisement = async (ad: ad) => {
384
- this.debugLog(
385
- `${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
386
- ` BLE Address Found: ${ad.address}`,
387
- );
388
- if (ad.serviceData.humidity! > 0) {
389
- // reject unreliable data
390
- this.BLE_CurrentRelativeHumidity = ad.serviceData.humidity;
391
- }
392
- this.BLE_CurrentTemperature = ad.serviceData.temperature;
393
- this.BLE_Celsius = ad.serviceData.temperature!.c;
394
- this.BLE_Fahrenheit = ad.serviceData.temperature!.f;
395
- this.BLE_BatteryLevel = ad.serviceData.battery;
396
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
397
- this.debugLog(
398
- `${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
399
- `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
400
- `battery: ${ad.serviceData.battery}`,
401
- );
402
-
403
- if (ad.serviceData) {
404
- this.BLE_IsConnected = true;
405
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
406
- await this.stopScanning(switchbot);
407
- } else {
408
- this.BLE_IsConnected = false;
409
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
410
- }
411
- };
412
- // Wait
413
- return await sleep(this.scanDuration * 1000);
414
- })
415
- .then(async () => {
416
- // Stop to monitor
417
- await this.stopScanning(switchbot);
418
- })
419
- .catch(async (e: any) => {
420
- this.apiError(e);
421
- this.errorLog(
422
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
423
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
424
- );
425
- await this.BLERefreshConnection(switchbot);
426
- });
427
- } else {
428
- await this.BLERefreshConnection(switchbot);
429
- }*/
430
282
  }
431
283
 
432
284
  async openAPIRefreshStatus(): Promise<void> {
433
285
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
434
286
  try {
435
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
436
- headers: this.platform.generateHeaders(),
437
- });
287
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
288
+ `${Devices}/${this.device.deviceId}/status`, {
289
+ headers: this.platform.generateHeaders(),
290
+ });
438
291
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
439
292
  const deviceStatus: any = await body.json();
440
293
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -442,8 +295,7 @@ export class WaterDetector {
442
295
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
443
296
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
444
297
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
445
- this.OpenAPI_CurrentRelativeHumidity = deviceStatus.body.humidity!;
446
- this.OpenAPI_CurrentTemperature = deviceStatus.body.temperature!;
298
+ this.OpenAPI_LeakDetected = deviceStatus.body.status;
447
299
  this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
448
300
  this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
449
301
  this.openAPIparseStatus();
@@ -482,39 +334,6 @@ export class WaterDetector {
482
334
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic LeakDetected: ${this.LeakDetected}`);
483
335
  }
484
336
  }
485
- if (!this.device.waterdetector?.hide_humidity) {
486
- if (this.CurrentRelativeHumidity === undefined) {
487
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
488
- } else {
489
- this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
490
- this.humidityservice?.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
491
- this.debugLog(
492
- `${this.device.deviceType}: ${this.accessory.displayName}` +
493
- ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`,
494
- );
495
- if (this.device.mqttURL) {
496
- mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
497
- }
498
- if (this.device.history) {
499
- entry['humidity'] = this.CurrentRelativeHumidity;
500
- }
501
- }
502
- }
503
- if (!this.device.waterdetector?.hide_temperature) {
504
- if (this.CurrentTemperature === undefined) {
505
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
506
- } else {
507
- if (this.device.mqttURL) {
508
- mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
509
- }
510
- if (this.device.history) {
511
- entry['temp'] = this.CurrentTemperature;
512
- }
513
- this.accessory.context.CurrentTemperature = this.CurrentTemperature;
514
- this.temperatureservice?.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.CurrentTemperature);
515
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
516
- }
517
- }
518
337
  if (this.BatteryLevel === undefined) {
519
338
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
520
339
  } else {
@@ -538,7 +357,7 @@ export class WaterDetector {
538
357
  if (this.device.mqttURL) {
539
358
  this.mqttPublish(`{${mqttmessage.join(',')}}`);
540
359
  }
541
- if (Number(this.CurrentRelativeHumidity) > 0) {
360
+ if (Number(this.LeakDetected) > 0) {
542
361
  // reject unreliable data
543
362
  if (this.device.history) {
544
363
  this.historyService?.addEntry(entry);
@@ -736,26 +555,15 @@ export class WaterDetector {
736
555
  if (!this.device.waterdetector?.hide_leak) {
737
556
  this.leakService?.updateCharacteristic(this.hap.Characteristic.LeakDetected, e);
738
557
  }
739
- if (!this.device.waterdetector?.hide_humidity) {
740
- this.humidityservice?.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, e);
741
- }
742
- if (!this.device.waterdetector?.hide_temperature) {
743
- this.temperatureservice?.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, e);
744
- }
745
558
  this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
746
559
  this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
747
560
  }
748
561
 
749
562
  async deviceContext() {
750
- if (this.CurrentRelativeHumidity === undefined) {
751
- this.CurrentRelativeHumidity = 0;
752
- } else {
753
- this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
754
- }
755
- if (this.CurrentTemperature === undefined) {
756
- this.CurrentTemperature = 0;
563
+ if (this.LeakDetected === undefined) {
564
+ this.LeakDetected = 0;
757
565
  } else {
758
- this.CurrentTemperature = this.accessory.context.CurrentTemperature;
566
+ this.LeakDetected = this.accessory.context.LeakDetected;
759
567
  }
760
568
  if (this.BatteryLevel === undefined) {
761
569
  this.BatteryLevel = 100;
@@ -784,6 +592,23 @@ export class WaterDetector {
784
592
  }
785
593
  }
786
594
 
595
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
596
+ if (!device.maxRetries) {
597
+ this.maxRetries = 5; // Maximum number of retries
598
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
599
+ } else {
600
+ this.maxRetries = device.maxRetries;
601
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
602
+ }
603
+ if (!device.delayBetweenRetries) {
604
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
605
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
606
+ } else {
607
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
608
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
609
+ }
610
+ }
611
+
787
612
  async deviceConfig(device: device & devicesConfig): Promise<void> {
788
613
  let config = {};
789
614
  if (device.waterdetector) {
@@ -834,6 +659,12 @@ export class WaterDetector {
834
659
  /**
835
660
  * Logging for Device
836
661
  */
662
+ successLog(...log: any[]): void {
663
+ if (this.enablingDeviceLogging()) {
664
+ this.platform.log.success(String(...log));
665
+ }
666
+ }
667
+
837
668
  infoLog(...log: any[]): void {
838
669
  if (this.enablingDeviceLogging()) {
839
670
  this.platform.log.info(String(...log));
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- /* Copyright(C) 2021-2023, SwitchBot (https://github.com/SwitchBot). All rights reserved.
1
+ /* Copyright(C) 2021-2024, SwitchBot (https://github.com/SwitchBot). All rights reserved.
2
2
  *
3
3
  * index.ts: @switchbot/homebridge-switchbot plugin registration.
4
4
  */
@@ -275,6 +275,7 @@ export class AirConditioner {
275
275
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
276
276
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
277
277
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
278
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
278
279
  this.updateHomeKitCharacteristics();
279
280
  } else {
280
281
  this.statusCode(statusCode);
@@ -799,6 +800,12 @@ export class AirConditioner {
799
800
  /**
800
801
  * Logging for Device
801
802
  */
803
+ successLog(...log: any[]): void {
804
+ if (this.enablingDeviceLogging()) {
805
+ this.platform.log.success(String(...log));
806
+ }
807
+ }
808
+
802
809
  infoLog(...log: any[]): void {
803
810
  if (this.enablingDeviceLogging()) {
804
811
  this.platform.log.info(String(...log));