@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
@@ -79,6 +79,8 @@ export class BlindTilt {
79
79
  deviceRefreshRate!: number;
80
80
  setCloseMode!: string;
81
81
  setOpenMode!: string;
82
+ maxRetries!: number;
83
+ delayBetweenRetries!: number;
82
84
 
83
85
  // Updates
84
86
  blindTiltUpdateInProgress!: boolean;
@@ -106,6 +108,7 @@ export class BlindTilt {
106
108
  this.scan(device);
107
109
  this.setupMqtt(device);
108
110
  this.deviceContext();
111
+ this.deviceRetry(device);
109
112
  this.deviceConfig(device);
110
113
 
111
114
  this.mappingMode = (device.blindTilt?.mode as BlindTiltMappingMode) ?? BlindTiltMappingMode.OnlyUp;
@@ -594,9 +597,10 @@ export class BlindTilt {
594
597
  async openAPIRefreshStatus(): Promise<void> {
595
598
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
596
599
  try {
597
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
598
- headers: this.platform.generateHeaders(),
599
- });
600
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
601
+ `${Devices}/${this.device.deviceId}/status`, {
602
+ headers: this.platform.generateHeaders(),
603
+ });
600
604
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
601
605
  const deviceStatus: any = await body.json();
602
606
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -677,6 +681,8 @@ export class BlindTilt {
677
681
  })
678
682
  .then(() => {
679
683
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
684
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
685
+ + `Target Position: ${this.TargetPosition} sent over BLE, sent successfully`);
680
686
  })
681
687
  .catch(async (e: any) => {
682
688
  this.apiError(e);
@@ -759,6 +765,8 @@ export class BlindTilt {
759
765
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
760
766
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
761
767
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
768
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
769
+ + `request to SwitchBot API, body: ${bodyChange} sent successfully`);
762
770
  } else {
763
771
  this.statusCode(statusCode);
764
772
  this.statusCode(deviceStatus.statusCode);
@@ -1152,39 +1160,39 @@ export class BlindTilt {
1152
1160
  break;
1153
1161
  case 400:
1154
1162
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
1155
- + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
1163
+ + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
1156
1164
  break;
1157
1165
  case 401:
1158
1166
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
1159
- + `but the request has not been authenticated, statusCode: ${statusCode}`);
1167
+ + `but the request has not been authenticated, statusCode: ${statusCode}`);
1160
1168
  break;
1161
1169
  case 403:
1162
1170
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
1163
- + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
1171
+ + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
1164
1172
  break;
1165
1173
  case 404:
1166
1174
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
1167
- + `statusCode: ${statusCode}`);
1175
+ + `statusCode: ${statusCode}`);
1168
1176
  break;
1169
1177
  case 406:
1170
1178
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
1171
- + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
1179
+ + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
1172
1180
  break;
1173
1181
  case 415:
1174
1182
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
1175
- + `header that is not supported by the server, statusCode: ${statusCode}`);
1183
+ + `header that is not supported by the server, statusCode: ${statusCode}`);
1176
1184
  break;
1177
1185
  case 422:
1178
1186
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
1179
- + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
1187
+ + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
1180
1188
  break;
1181
1189
  case 429:
1182
1190
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
1183
- + `requests allowed for a given time window, statusCode: ${statusCode}`);
1191
+ + `requests allowed for a given time window, statusCode: ${statusCode}`);
1184
1192
  break;
1185
1193
  case 500:
1186
1194
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
1187
- + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
1195
+ + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
1188
1196
  break;
1189
1197
  default:
1190
1198
  this.infoLog(
@@ -1378,6 +1386,23 @@ export class BlindTilt {
1378
1386
  }
1379
1387
  }
1380
1388
 
1389
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
1390
+ if (!device.maxRetries) {
1391
+ this.maxRetries = 5; // Maximum number of retries
1392
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
1393
+ } else {
1394
+ this.maxRetries = device.maxRetries;
1395
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
1396
+ }
1397
+ if (!device.delayBetweenRetries) {
1398
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
1399
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
1400
+ } else {
1401
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
1402
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
1403
+ }
1404
+ }
1405
+
1381
1406
  async deviceConfig(device: device & devicesConfig): Promise<void> {
1382
1407
  let config = {};
1383
1408
  if (device.blindTilt) {
@@ -1407,6 +1432,12 @@ export class BlindTilt {
1407
1432
  if (device.webhook !== undefined) {
1408
1433
  config['webhook'] = device.webhook;
1409
1434
  }
1435
+ if (device.maxRetries !== undefined) {
1436
+ config['maxRetries'] = device.maxRetries;
1437
+ }
1438
+ if (device.delayBetweenRetries !== undefined) {
1439
+ config['delayBetweenRetries'] = device.delayBetweenRetries;
1440
+ }
1410
1441
  if (device.blindTilt?.mode === undefined) {
1411
1442
  config['mode'] = BlindTiltMappingMode.OnlyUp;
1412
1443
  } else {
@@ -1437,6 +1468,12 @@ export class BlindTilt {
1437
1468
  /**
1438
1469
  * Logging for Device
1439
1470
  */
1471
+ successLog(...log: any[]): void {
1472
+ if (this.enablingDeviceLogging()) {
1473
+ this.platform.log.success(String(...log));
1474
+ }
1475
+ }
1476
+
1440
1477
  infoLog(...log: any[]): void {
1441
1478
  if (this.enablingDeviceLogging()) {
1442
1479
  this.platform.log.info(String(...log));
package/src/device/bot.ts CHANGED
@@ -58,6 +58,8 @@ export class Bot {
58
58
  deviceLogging!: string;
59
59
  multiPressCount!: number;
60
60
  deviceRefreshRate!: number;
61
+ maxRetries!: number;
62
+ delayBetweenRetries!: number;
61
63
 
62
64
  // Updates
63
65
  botUpdateInProgress!: boolean;
@@ -88,6 +90,7 @@ export class Bot {
88
90
  this.allowPushChanges(device);
89
91
  this.deviceContext();
90
92
  this.DoublePress(device);
93
+ this.deviceRetry(device);
91
94
  this.deviceConfig(device);
92
95
 
93
96
  this.multiPressCount = 0;
@@ -623,9 +626,10 @@ export class Bot {
623
626
  async openAPIRefreshStatus(): Promise<void> {
624
627
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
625
628
  try {
626
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
627
- headers: this.platform.generateHeaders(),
628
- });
629
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
630
+ `${Devices}/${this.device.deviceId}/status`, {
631
+ headers: this.platform.generateHeaders(),
632
+ });
629
633
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
630
634
  const deviceStatus: any = await body.json();
631
635
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -702,6 +706,8 @@ export class Bot {
702
706
  })
703
707
  .then(() => {
704
708
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
709
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
710
+ + `On: ${this.On} sent over BLE, sent successfully`);
705
711
  this.accessory.context.On = this.On;
706
712
  setTimeout(() => {
707
713
  if (this.botDeviceType === 'switch') {
@@ -802,6 +808,8 @@ export class Bot {
802
808
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
803
809
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
804
810
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
811
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
812
+ + `request to SwitchBot API, body: ${bodyChange} sent successfully`);
805
813
  } else {
806
814
  this.statusCode(statusCode);
807
815
  this.statusCode(deviceStatus.statusCode);
@@ -1479,6 +1487,23 @@ export class Bot {
1479
1487
  }
1480
1488
  }
1481
1489
 
1490
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
1491
+ if (!device.maxRetries) {
1492
+ this.maxRetries = 5; // Maximum number of retries
1493
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
1494
+ } else {
1495
+ this.maxRetries = device.maxRetries;
1496
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
1497
+ }
1498
+ if (!device.delayBetweenRetries) {
1499
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
1500
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
1501
+ } else {
1502
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
1503
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
1504
+ }
1505
+ }
1506
+
1482
1507
  async deviceConfig(device: device & devicesConfig): Promise<void> {
1483
1508
  let config = {};
1484
1509
  if (device.bot) {
@@ -1532,6 +1557,12 @@ export class Bot {
1532
1557
  /**
1533
1558
  * Logging for Device
1534
1559
  */
1560
+ successLog(...log: any[]): void {
1561
+ if (this.enablingDeviceLogging()) {
1562
+ this.platform.log.success(String(...log));
1563
+ }
1564
+ }
1565
+
1535
1566
  infoLog(...log: any[]): void {
1536
1567
  if (this.enablingDeviceLogging()) {
1537
1568
  this.platform.log.info(String(...log));
@@ -1,9 +1,9 @@
1
1
  import { request } from 'undici';
2
- import { sleep } from '../utils.js';
2
+ import { hs2rgb, rgb2hs, m2hs, sleep } from '../utils.js';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform.js';
5
5
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { device, devicesConfig, deviceStatus, hs2rgb, rgb2hs, m2hs, serviceData, Devices, SwitchBotPlatformConfig } from '../settings.js';
6
+ import { device, devicesConfig, deviceStatus, serviceData, Devices, SwitchBotPlatformConfig } from '../settings.js';
7
7
  import {
8
8
  Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap, API, Logging, HAP,
9
9
  } from 'homebridge';
@@ -50,6 +50,8 @@ export class CeilingLight {
50
50
  deviceLogging!: string;
51
51
  deviceRefreshRate!: number;
52
52
  adaptiveLightingShift?: number;
53
+ maxRetries!: number;
54
+ delayBetweenRetries!: number;
53
55
 
54
56
  // Adaptive Lighting
55
57
  AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
@@ -85,6 +87,7 @@ export class CeilingLight {
85
87
  this.refreshRate(device);
86
88
  this.adaptiveLighting(device);
87
89
  this.deviceContext();
90
+ this.deviceRetry(device);
88
91
  this.deviceConfig(device);
89
92
 
90
93
  // this is subject we use to track when we need to POST changes to the SwitchBot API
@@ -461,9 +464,10 @@ export class CeilingLight {
461
464
  async openAPIRefreshStatus() {
462
465
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
463
466
  try {
464
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
465
- headers: this.platform.generateHeaders(),
466
- });
467
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
468
+ `${Devices}/${this.device.deviceId}/status`, {
469
+ headers: this.platform.generateHeaders(),
470
+ });
467
471
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
468
472
  const deviceStatus: any = await body.json();
469
473
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -555,6 +559,8 @@ export class CeilingLight {
555
559
  })
556
560
  .then(() => {
557
561
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
562
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
563
+ + `On: ${this.On} sent over BLE, sent successfully`);
558
564
  this.On = false;
559
565
  })
560
566
  .catch(async (e: any) => {
@@ -601,6 +607,8 @@ export class CeilingLight {
601
607
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
602
608
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
603
609
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
610
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
611
+ + `request to SwitchBot API, body: ${bodyChange} sent successfully`);
604
612
  } else {
605
613
  this.statusCode(statusCode);
606
614
  this.statusCode(deviceStatus.statusCode);
@@ -660,6 +668,8 @@ export class CeilingLight {
660
668
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
661
669
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
662
670
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
671
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
672
+ + `request to SwitchBot API, body: ${bodyChange} sent successfully`);
663
673
  } else {
664
674
  this.statusCode(statusCode);
665
675
  this.statusCode(deviceStatus.statusCode);
@@ -746,6 +756,8 @@ export class CeilingLight {
746
756
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
747
757
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
748
758
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
759
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
760
+ + `request to SwitchBot API, body: ${bodyChange} sent successfully`);
749
761
  } else {
750
762
  this.statusCode(statusCode);
751
763
  this.statusCode(deviceStatus.statusCode);
@@ -1136,6 +1148,23 @@ export class CeilingLight {
1136
1148
  }
1137
1149
  }
1138
1150
 
1151
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
1152
+ if (!device.maxRetries) {
1153
+ this.maxRetries = 5; // Maximum number of retries
1154
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
1155
+ } else {
1156
+ this.maxRetries = device.maxRetries;
1157
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
1158
+ }
1159
+ if (!device.delayBetweenRetries) {
1160
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
1161
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
1162
+ } else {
1163
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
1164
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
1165
+ }
1166
+ }
1167
+
1139
1168
  async deviceConfig(device: device & devicesConfig): Promise<void> {
1140
1169
  let config = {};
1141
1170
  if (device.ceilinglight) {
@@ -1189,6 +1218,12 @@ export class CeilingLight {
1189
1218
  /**
1190
1219
  * Logging for Device
1191
1220
  */
1221
+ successLog(...log: any[]): void {
1222
+ if (this.enablingDeviceLogging()) {
1223
+ this.platform.log.success(String(...log));
1224
+ }
1225
+ }
1226
+
1192
1227
  infoLog(...log: any[]): void {
1193
1228
  if (this.enablingDeviceLogging()) {
1194
1229
  this.platform.log.info(String(...log));
@@ -1,9 +1,9 @@
1
1
  import { request } from 'undici';
2
- import { sleep } from '../utils.js';
2
+ import { hs2rgb, rgb2hs, m2hs, sleep } from '../utils.js';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform.js';
5
5
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { device, devicesConfig, deviceStatus, hs2rgb, rgb2hs, m2hs, serviceData, Devices, SwitchBotPlatformConfig } from '../settings.js';
6
+ import { device, devicesConfig, deviceStatus, serviceData, Devices, SwitchBotPlatformConfig } from '../settings.js';
7
7
  import {
8
8
  Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap, API, Logging, HAP,
9
9
  } from 'homebridge';
@@ -58,6 +58,8 @@ export class ColorBulb {
58
58
  deviceLogging!: string;
59
59
  deviceRefreshRate!: number;
60
60
  adaptiveLightingShift?: number;
61
+ maxRetries!: number;
62
+ delayBetweenRetries!: number;
61
63
 
62
64
  // Adaptive Lighting
63
65
  AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
@@ -93,6 +95,7 @@ export class ColorBulb {
93
95
  this.refreshRate(device);
94
96
  this.adaptiveLighting(device);
95
97
  this.deviceContext();
98
+ this.deviceRetry(device);
96
99
  this.deviceConfig(device);
97
100
 
98
101
  // this is subject we use to track when we need to POST changes to the SwitchBot API
@@ -527,9 +530,10 @@ export class ColorBulb {
527
530
  async openAPIRefreshStatus() {
528
531
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
529
532
  try {
530
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
531
- headers: this.platform.generateHeaders(),
532
- });
533
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
534
+ `${Devices}/${this.device.deviceId}/status`, {
535
+ headers: this.platform.generateHeaders(),
536
+ });
533
537
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
534
538
  const deviceStatus: any = await body.json();
535
539
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -621,6 +625,8 @@ export class ColorBulb {
621
625
  })
622
626
  .then(() => {
623
627
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
628
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
629
+ + `On: ${this.On} sent over BLE, sent successfully`);
624
630
  this.On = false;
625
631
  })
626
632
  .catch(async (e: any) => {
@@ -803,6 +809,8 @@ export class ColorBulb {
803
809
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
804
810
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
805
811
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
812
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
813
+ + `request to SwitchBot API, body: ${bodyChange} sent successfully`);
806
814
  } else {
807
815
  this.statusCode(statusCode);
808
816
  this.statusCode(deviceStatus.statusCode);
@@ -862,6 +870,8 @@ export class ColorBulb {
862
870
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
863
871
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
864
872
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
873
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
874
+ + `request to SwitchBot API, body: ${deviceStatus} sent successfully`);
865
875
  } else {
866
876
  this.statusCode(statusCode);
867
877
  this.statusCode(deviceStatus.statusCode);
@@ -906,6 +916,8 @@ export class ColorBulb {
906
916
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
907
917
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
908
918
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
919
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
920
+ + `request to SwitchBot API, body: ${deviceStatus} sent successfully`);
909
921
  } else {
910
922
  this.statusCode(statusCode);
911
923
  this.statusCode(deviceStatus.statusCode);
@@ -948,6 +960,8 @@ export class ColorBulb {
948
960
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
949
961
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
950
962
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
963
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
964
+ + `request to SwitchBot API, body: ${deviceStatus} sent successfully`);
951
965
  } else {
952
966
  this.statusCode(statusCode);
953
967
  this.statusCode(deviceStatus.statusCode);
@@ -1343,6 +1357,23 @@ export class ColorBulb {
1343
1357
  }
1344
1358
  }
1345
1359
 
1360
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
1361
+ if (!device.maxRetries) {
1362
+ this.maxRetries = 5; // Maximum number of retries
1363
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
1364
+ } else {
1365
+ this.maxRetries = device.maxRetries;
1366
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
1367
+ }
1368
+ if (!device.delayBetweenRetries) {
1369
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
1370
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
1371
+ } else {
1372
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
1373
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
1374
+ }
1375
+ }
1376
+
1346
1377
  async deviceConfig(device: device & devicesConfig): Promise<void> {
1347
1378
  let config = {};
1348
1379
  if (device.colorbulb) {
@@ -1396,6 +1427,12 @@ export class ColorBulb {
1396
1427
  /**
1397
1428
  * Logging for Device
1398
1429
  */
1430
+ successLog(...log: any[]): void {
1431
+ if (this.enablingDeviceLogging()) {
1432
+ this.platform.log.success(String(...log));
1433
+ }
1434
+ }
1435
+
1399
1436
  infoLog(...log: any[]): void {
1400
1437
  if (this.enablingDeviceLogging()) {
1401
1438
  this.platform.log.info(String(...log));
@@ -1,4 +1,3 @@
1
- import { request } from 'undici';
2
1
  import { sleep } from '../utils.js';
3
2
  import { interval, Subject } from 'rxjs';
4
3
  import { skipWhile } from 'rxjs/operators';
@@ -53,6 +52,8 @@ export class Contact {
53
52
  scanDuration!: number;
54
53
  deviceLogging!: string;
55
54
  deviceRefreshRate!: number;
55
+ maxRetries!: number;
56
+ delayBetweenRetries!: number;
56
57
 
57
58
  // Updates
58
59
  contactUbpdateInProgress!: boolean;
@@ -79,6 +80,7 @@ export class Contact {
79
80
  this.scan(device);
80
81
  this.refreshRate(device);
81
82
  this.deviceContext();
83
+ this.deviceRetry(device);
82
84
  this.deviceConfig(device);
83
85
 
84
86
  // this is subject we use to track when we need to POST changes to the SwitchBot API
@@ -437,9 +439,10 @@ export class Contact {
437
439
  async openAPIRefreshStatus(): Promise<void> {
438
440
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
439
441
  try {
440
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
441
- headers: this.platform.generateHeaders(),
442
- });
442
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
443
+ `${Devices}/${this.device.deviceId}/status`, {
444
+ headers: this.platform.generateHeaders(),
445
+ });
443
446
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
444
447
  const deviceStatus: any = await body.json();
445
448
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -708,6 +711,23 @@ export class Contact {
708
711
  }
709
712
  }
710
713
 
714
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
715
+ if (!device.maxRetries) {
716
+ this.maxRetries = 5; // Maximum number of retries
717
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
718
+ } else {
719
+ this.maxRetries = device.maxRetries;
720
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
721
+ }
722
+ if (!device.delayBetweenRetries) {
723
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
724
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
725
+ } else {
726
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
727
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
728
+ }
729
+ }
730
+
711
731
  async deviceConfig(device: device & devicesConfig): Promise<void> {
712
732
  let config = {};
713
733
  if (device.contact) {
@@ -755,6 +775,12 @@ export class Contact {
755
775
  /**
756
776
  * Logging for Device
757
777
  */
778
+ successLog(...log: any[]): void {
779
+ if (this.enablingDeviceLogging()) {
780
+ this.platform.log.success(String(...log));
781
+ }
782
+ }
783
+
758
784
  infoLog(...log: any[]): void {
759
785
  if (this.enablingDeviceLogging()) {
760
786
  this.platform.log.info(String(...log));
@@ -68,6 +68,8 @@ export class Curtain {
68
68
  scanDuration!: number;
69
69
  deviceLogging!: string;
70
70
  deviceRefreshRate!: number;
71
+ maxRetries!: number;
72
+ delayBetweenRetries!: number;
71
73
 
72
74
  // Updates
73
75
  curtainUpdateInProgress!: boolean;
@@ -98,6 +100,7 @@ export class Curtain {
98
100
  this.scan(device);
99
101
  this.setupMqtt(device);
100
102
  this.deviceContext();
103
+ this.deviceRetry(device);
101
104
  this.deviceConfig(device);
102
105
 
103
106
  // this is subject we use to track when we need to POST changes to the SwitchBot API
@@ -634,9 +637,10 @@ export class Curtain {
634
637
  async openAPIRefreshStatus(): Promise<void> {
635
638
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
636
639
  try {
637
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
638
- headers: this.platform.generateHeaders(),
639
- });
640
+ const { body, statusCode } = await this.platform.retryRequest(this.maxRetries, this.delayBetweenRetries,
641
+ `${Devices}/${this.device.deviceId}/status`, {
642
+ headers: this.platform.generateHeaders(),
643
+ });
640
644
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
641
645
  const deviceStatus: any = await body.json();
642
646
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
@@ -712,6 +716,8 @@ export class Curtain {
712
716
  });
713
717
 
714
718
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
719
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
720
+ + `TargetPosition: ${this.TargetPosition} sent over BLE, sent successfully`);
715
721
  } catch (e) {
716
722
  this.apiError(e);
717
723
  this.errorLog(
@@ -804,6 +810,8 @@ export class Curtain {
804
810
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
805
811
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
806
812
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
813
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
814
+ + `request to SwitchBot API, body: ${deviceStatus} sent successfully`);
807
815
  } else {
808
816
  this.statusCode(statusCode);
809
817
  this.statusCode(deviceStatus.statusCode);
@@ -1306,6 +1314,23 @@ export class Curtain {
1306
1314
  }
1307
1315
  }
1308
1316
 
1317
+ async deviceRetry(device: device & devicesConfig): Promise<void> {
1318
+ if (!device.maxRetries) {
1319
+ this.maxRetries = 5; // Maximum number of retries
1320
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Max Retries Not Set, Using: ${this.maxRetries}`);
1321
+ } else {
1322
+ this.maxRetries = device.maxRetries;
1323
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Max Retries: ${this.maxRetries}`);
1324
+ }
1325
+ if (!device.delayBetweenRetries) {
1326
+ this.delayBetweenRetries = 3000; // Delay between retries in milliseconds
1327
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Delay Between Retries Not Set, Using: ${this.delayBetweenRetries}`);
1328
+ } else {
1329
+ this.delayBetweenRetries = device.delayBetweenRetries * 1000;
1330
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Delay Between Retries: ${this.delayBetweenRetries}`);
1331
+ }
1332
+ }
1333
+
1309
1334
  async deviceConfig(device: device & devicesConfig): Promise<void> {
1310
1335
  let config = {};
1311
1336
  if (device.curtain) {
@@ -1359,6 +1384,12 @@ export class Curtain {
1359
1384
  /**
1360
1385
  * Logging for Device
1361
1386
  */
1387
+ successLog(...log: any[]): void {
1388
+ if (this.enablingDeviceLogging()) {
1389
+ this.platform.log.success(String(...log));
1390
+ }
1391
+ }
1392
+
1362
1393
  infoLog(...log: any[]): void {
1363
1394
  if (this.enablingDeviceLogging()) {
1364
1395
  this.platform.log.info(String(...log));