@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
@@ -227,6 +227,7 @@ export class AirPurifier {
227
227
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
228
228
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
229
229
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
230
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
230
231
  this.updateHomeKitCharacteristics();
231
232
  } else {
232
233
  this.statusCode(statusCode);
@@ -478,6 +479,12 @@ export class AirPurifier {
478
479
  /**
479
480
  * Logging for Device
480
481
  */
482
+ successLog(...log: any[]): void {
483
+ if (this.enablingDeviceLogging()) {
484
+ this.platform.log.success(String(...log));
485
+ }
486
+ }
487
+
481
488
  infoLog(...log: any[]): void {
482
489
  if (this.enablingDeviceLogging()) {
483
490
  this.platform.log.info(String(...log));
@@ -132,6 +132,7 @@ export class Camera {
132
132
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
133
133
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
134
134
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
135
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
135
136
  this.updateHomeKitCharacteristics();
136
137
  } else {
137
138
  this.statusCode(statusCode);
@@ -354,6 +355,12 @@ export class Camera {
354
355
  /**
355
356
  * Logging for Device
356
357
  */
358
+ successLog(...log: any[]): void {
359
+ if (this.enablingDeviceLogging()) {
360
+ this.platform.log.success(String(...log));
361
+ }
362
+ }
363
+
357
364
  infoLog(...log: any[]): void {
358
365
  if (this.enablingDeviceLogging()) {
359
366
  this.platform.log.info(String(...log));
@@ -249,6 +249,7 @@ export class Fan {
249
249
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
250
250
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
251
251
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
252
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
252
253
  this.updateHomeKitCharacteristics();
253
254
  } else {
254
255
  this.statusCode(statusCode);
@@ -486,6 +487,12 @@ export class Fan {
486
487
  /**
487
488
  * Logging for Device
488
489
  */
490
+ successLog(...log: any[]): void {
491
+ if (this.enablingDeviceLogging()) {
492
+ this.platform.log.success(String(...log));
493
+ }
494
+ }
495
+
489
496
  infoLog(...log: any[]): void {
490
497
  if (this.enablingDeviceLogging()) {
491
498
  this.platform.log.info(String(...log));
@@ -247,6 +247,7 @@ export class Light {
247
247
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
248
248
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
249
249
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
250
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
250
251
  this.accessory.context.On = this.On;
251
252
  this.updateHomeKitCharacteristics();
252
253
  } else {
@@ -502,6 +503,12 @@ export class Light {
502
503
  /**
503
504
  * Logging for Device
504
505
  */
506
+ successLog(...log: any[]): void {
507
+ if (this.enablingDeviceLogging()) {
508
+ this.platform.log.success(String(...log));
509
+ }
510
+ }
511
+
505
512
  infoLog(...log: any[]): void {
506
513
  if (this.enablingDeviceLogging()) {
507
514
  this.platform.log.info(String(...log));
@@ -439,6 +439,7 @@ export class Others {
439
439
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
440
440
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
441
441
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
442
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
442
443
  this.updateHomeKitCharacteristics();
443
444
  } else {
444
445
  this.statusCode(statusCode);
@@ -975,6 +976,12 @@ export class Others {
975
976
  /**
976
977
  * Logging for Device
977
978
  */
979
+ successLog(...log: any[]): void {
980
+ if (this.enablingDeviceLogging()) {
981
+ this.platform.log.success(String(...log));
982
+ }
983
+ }
984
+
978
985
  infoLog(...log: any[]): void {
979
986
  if (this.enablingDeviceLogging()) {
980
987
  this.platform.log.info(String(...log));
@@ -381,6 +381,7 @@ export class TV {
381
381
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
382
382
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
383
383
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
384
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
384
385
  this.updateHomeKitCharacteristics();
385
386
  } else {
386
387
  this.statusCode(statusCode);
@@ -628,6 +629,12 @@ export class TV {
628
629
  /**
629
630
  * Logging for Device
630
631
  */
632
+ successLog(...log: any[]): void {
633
+ if (this.enablingDeviceLogging()) {
634
+ this.platform.log.success(String(...log));
635
+ }
636
+ }
637
+
631
638
  infoLog(...log: any[]): void {
632
639
  if (this.enablingDeviceLogging()) {
633
640
  this.platform.log.info(String(...log));
@@ -128,6 +128,7 @@ export class VacuumCleaner {
128
128
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
129
129
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
130
130
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
131
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
131
132
  this.updateHomeKitCharacteristics();
132
133
  } else {
133
134
  this.statusCode(statusCode);
@@ -350,6 +351,12 @@ export class VacuumCleaner {
350
351
  /**
351
352
  * Logging for Device
352
353
  */
354
+ successLog(...log: any[]): void {
355
+ if (this.enablingDeviceLogging()) {
356
+ this.platform.log.success(String(...log));
357
+ }
358
+ }
359
+
353
360
  infoLog(...log: any[]): void {
354
361
  if (this.enablingDeviceLogging()) {
355
362
  this.platform.log.info(String(...log));
@@ -137,6 +137,7 @@ export class WaterHeater {
137
137
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
138
138
  this.debugErrorLog(`${this.device.remoteType}: ${this.accessory.displayName} `
139
139
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
140
+ this.successLog(`${this.device.remoteType}: ${this.accessory.displayName} request to SwitchBot API, body: ${bodyChange} sent successfully`);
140
141
  this.updateHomeKitCharacteristics();
141
142
  } else {
142
143
  this.statusCode(statusCode);
@@ -359,6 +360,12 @@ export class WaterHeater {
359
360
  /**
360
361
  * Logging for Device
361
362
  */
363
+ successLog(...log: any[]): void {
364
+ if (this.enablingDeviceLogging()) {
365
+ this.platform.log.success(String(...log));
366
+ }
367
+ }
368
+
362
369
  infoLog(...log: any[]): void {
363
370
  if (this.enablingDeviceLogging()) {
364
371
  this.platform.log.info(String(...log));
package/src/platform.ts CHANGED
@@ -1,4 +1,4 @@
1
- /* Copyright(C) 2017-2023, donavanbecker (https://github.com/donavanbecker). All rights reserved.
1
+ /* Copyright(C) 2017-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
2
  *
3
3
  * platform.ts: @switchbot/homebridge-switchbot platform class.
4
4
  */
@@ -32,14 +32,16 @@ import { VacuumCleaner } from './irdevice/vacuumcleaner.js';
32
32
  import { AirConditioner } from './irdevice/airconditioner.js';
33
33
  import * as http from 'http';
34
34
  import { Buffer } from 'buffer';
35
- import { request } from 'undici';
35
+ import { Dispatcher, request } from 'undici';
36
36
  import { MqttClient } from 'mqtt';
37
37
  import { queueScheduler } from 'rxjs';
38
38
  import fakegato from 'fakegato-history';
39
39
  import asyncmqtt from 'async-mqtt';
40
40
  import crypto, { randomUUID } from 'crypto';
41
41
  import { readFileSync, writeFileSync } from 'fs';
42
- import hbLib from 'homebridge-lib';
42
+ import { EveHomeKitTypes } from 'homebridge-lib';
43
+ import { UrlObject } from 'url';
44
+ import { sleep } from './utils.js';
43
45
 
44
46
 
45
47
 
@@ -56,6 +58,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
56
58
  version!: string;
57
59
  Logging?: string;
58
60
  debugMode!: boolean;
61
+ maxRetries!: number;
62
+ delayBetweenRetries!: number;
59
63
  platformConfig!: SwitchBotPlatformConfig['options'];
60
64
  platformLogging!: SwitchBotPlatformConfig['logging'];
61
65
  config!: SwitchBotPlatformConfig;
@@ -104,7 +108,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
104
108
  }
105
109
 
106
110
  // import fakegato-history module and EVE characteristics
107
- const { EveHomeKitTypes } = hbLib;
108
111
  this.fakegatoAPI = fakegato(api);
109
112
  this.eve = new EveHomeKitTypes(api);
110
113
 
@@ -383,6 +386,21 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
383
386
  this.debugWarnLog('Using Default Push Rate.');
384
387
  }
385
388
 
389
+ if (!this.config.options.maxRetries) {
390
+ this.config.options!.maxRetries! = 5;
391
+ this.debugWarnLog('Using Default Max Retries.');
392
+ } else {
393
+ this.maxRetries = this.config.options.maxRetries;
394
+ }
395
+
396
+ if (!this.config.options.delayBetweenRetries) {
397
+ // default 3 seconds
398
+ this.config.options!.delayBetweenRetries! = 3000;
399
+ this.debugWarnLog('Using Default Delay Between Retries.');
400
+ } else {
401
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
402
+ }
403
+
386
404
  if (!this.config.credentials && !this.config.options) {
387
405
  this.debugWarnLog('Missing Credentials');
388
406
  } else if (this.config.credentials && !this.config.credentials.notice) {
@@ -492,44 +510,95 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
492
510
  */
493
511
  async discoverDevices() {
494
512
  if (this.config.credentials?.token) {
495
- try {
496
- const { body, statusCode } = await request(Devices, {
497
- headers: this.generateHeaders(),
498
- });
499
- this.debugWarnLog(`statusCode: ${statusCode}`);
500
- const devicesAPI: any = await body.json();
501
- this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
502
- this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
503
- this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
504
- if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
505
- this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
506
- // SwitchBot Devices
507
- const deviceLists = devicesAPI.body.deviceList;
508
- this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
509
- this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
510
- if (!this.config.options?.devices) {
511
- this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
512
- if (deviceLists.length === 0) {
513
- this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
514
- } else {
515
- const devices = deviceLists.map((v: any) => v);
516
- for (const device of devices) {
517
- if (device.deviceType) {
518
- if (device.configDeviceName) {
519
- device.deviceName = device.configDeviceName;
513
+ let retryCount = 0;
514
+ const maxRetries = this.maxRetries; // Maximum number of retries
515
+ const delayBetweenRetries = this.delayBetweenRetries; // Delay between retries in milliseconds
516
+ while (retryCount < maxRetries) {
517
+ try {
518
+ const { body, statusCode } = await request(Devices, {
519
+ headers: this.generateHeaders(),
520
+ });
521
+ this.debugWarnLog(`statusCode: ${statusCode}`);
522
+ const devicesAPI: any = await body.json();
523
+ this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
524
+ this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
525
+ this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
526
+ if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
527
+ this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
528
+ // SwitchBot Devices
529
+ const deviceLists = devicesAPI.body.deviceList;
530
+ this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
531
+ this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
532
+ if (!this.config.options?.devices) {
533
+ this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
534
+ if (deviceLists.length === 0) {
535
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
536
+ } else {
537
+ const devices = deviceLists.map((v: any) => v);
538
+ for (const device of devices) {
539
+ if (device.deviceType) {
540
+ if (device.configDeviceName) {
541
+ device.deviceName = device.configDeviceName;
542
+ }
543
+ this.createDevice(device);
520
544
  }
521
- this.createDevice(device);
522
545
  }
523
546
  }
547
+ } else if (this.config.credentials?.token && this.config.options.devices) {
548
+ this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
549
+ if (deviceLists.length === 0) {
550
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
551
+ } else {
552
+ const deviceConfigs = this.config.options?.devices;
553
+
554
+ const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
555
+ a1.map((itm: { deviceId: string }) => ({
556
+ ...a2.find(
557
+ (item: { deviceId: string }) =>
558
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
559
+ ),
560
+ ...itm,
561
+ }));
562
+
563
+ const devices = mergeBydeviceId(deviceLists, deviceConfigs);
564
+ this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
565
+ for (const device of devices) {
566
+ if (!device.deviceType) {
567
+ device.deviceType = device.configDeviceType;
568
+ this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
569
+ }
570
+ if (device.deviceType) {
571
+ if (device.configDeviceName) {
572
+ device.deviceName = device.configDeviceName;
573
+ }
574
+ this.createDevice(device);
575
+ }
576
+ }
577
+ }
578
+ } else {
579
+ this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
524
580
  }
525
- } else if (this.config.credentials?.token && this.config.options.devices) {
526
- this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
527
- if (deviceLists.length === 0) {
528
- this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
581
+ if (devicesAPI.body.deviceList.length !== 0) {
582
+ this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
529
583
  } else {
530
- const deviceConfigs = this.config.options?.devices;
584
+ this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
585
+ }
531
586
 
532
- const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
587
+ // IR Devices
588
+ const irDeviceLists = devicesAPI.body.infraredRemoteList;
589
+ if (!this.config.options?.irdevices) {
590
+ this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
591
+ const devices = irDeviceLists.map((v: any) => v);
592
+ for (const device of devices) {
593
+ if (device.remoteType) {
594
+ this.createIRDevice(device);
595
+ }
596
+ }
597
+ } else {
598
+ this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
599
+ const irDeviceConfig = this.config.options?.irdevices;
600
+
601
+ const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
533
602
  a1.map((itm: { deviceId: string }) => ({
534
603
  ...a2.find(
535
604
  (item: { deviceId: string }) =>
@@ -538,73 +607,34 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
538
607
  ...itm,
539
608
  }));
540
609
 
541
- const devices = mergeBydeviceId(deviceLists, deviceConfigs);
542
- this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
610
+ const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
611
+ this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
543
612
  for (const device of devices) {
544
- if (!device.deviceType) {
545
- device.deviceType = device.configDeviceType;
546
- this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
547
- }
548
- if (device.deviceType) {
549
- if (device.configDeviceName) {
550
- device.deviceName = device.configDeviceName;
551
- }
552
- this.createDevice(device);
553
- }
554
- }
555
- }
556
- } else {
557
- this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
558
- }
559
- if (devicesAPI.body.deviceList.length !== 0) {
560
- this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
561
- } else {
562
- this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
563
- }
564
-
565
- // IR Devices
566
- const irDeviceLists = devicesAPI.body.infraredRemoteList;
567
- if (!this.config.options?.irdevices) {
568
- this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
569
- const devices = irDeviceLists.map((v: any) => v);
570
- for (const device of devices) {
571
- if (device.remoteType) {
572
613
  this.createIRDevice(device);
573
614
  }
574
615
  }
575
- } else {
576
- this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
577
- const irDeviceConfig = this.config.options?.irdevices;
578
-
579
- const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
580
- a1.map((itm: { deviceId: string }) => ({
581
- ...a2.find(
582
- (item: { deviceId: string }) =>
583
- item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
584
- ),
585
- ...itm,
586
- }));
587
-
588
- const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
589
- this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
590
- for (const device of devices) {
591
- this.createIRDevice(device);
616
+ if (devicesAPI.body.infraredRemoteList.length !== 0) {
617
+ this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
618
+ } else {
619
+ this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
592
620
  }
593
- }
594
- if (devicesAPI.body.infraredRemoteList.length !== 0) {
595
- this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
621
+ break;
596
622
  } else {
597
- this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
623
+ this.statusCode(statusCode);
624
+ this.statusCode(devicesAPI.statusCode);
625
+ if (statusCode === 500) {
626
+ retryCount++;
627
+ this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
628
+ await sleep(delayBetweenRetries);
629
+ }
598
630
  }
599
- } else {
600
- this.statusCode(statusCode);
601
- this.statusCode(devicesAPI.statusCode);
631
+ } catch (e: any) {
632
+ retryCount++;
633
+ this.debugErrorLog(
634
+ `Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug',
635
+ );
636
+ this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
602
637
  }
603
- } catch (e: any) {
604
- this.debugErrorLog(
605
- `Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug',
606
- );
607
- this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
608
638
  }
609
639
  } else if (!this.config.credentials?.token && this.config.options?.devices) {
610
640
  this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
@@ -691,6 +721,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
691
721
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
692
722
  this.createColorBulb(device);
693
723
  break;
724
+ case 'K10+':
694
725
  case 'WoSweeper':
695
726
  case 'WoSweeperMini':
696
727
  case 'Robot Vacuum Cleaner S1':
@@ -712,6 +743,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
712
743
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
713
744
  break;
714
745
  case 'Remote':
746
+ case 'remote with screen+':
715
747
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
716
748
  break;
717
749
  default:
@@ -2626,6 +2658,30 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2626
2658
  }
2627
2659
  }
2628
2660
 
2661
+ async retryRequest(deviceMaxRetries: number, deviceDelayBetweenRetries: number, url: string | URL | UrlObject,
2662
+ options?: { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions,
2663
+ 'origin' | 'path' | 'method'> & Partial<Pick<Dispatcher.RequestOptions, 'method'>>): Promise<{ body: any; statusCode: number }> {
2664
+ let retryCount = 0;
2665
+ const maxRetries = deviceMaxRetries;
2666
+ const delayBetweenRetries = deviceDelayBetweenRetries;
2667
+ while (retryCount < maxRetries) {
2668
+ try {
2669
+ const { body, statusCode } = await request(url, options);
2670
+ if (statusCode === 200 || statusCode === 100) {
2671
+ return { body, statusCode };
2672
+ } else {
2673
+ this.debugLog(`Received status code: ${statusCode}`);
2674
+ }
2675
+ } catch (error: any) {
2676
+ this.errorLog(`Error making request: ${error.message}`);
2677
+ }
2678
+ retryCount++;
2679
+ this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
2680
+ await sleep(delayBetweenRetries);
2681
+ }
2682
+ return { body: null, statusCode: -1 };
2683
+ }
2684
+
2629
2685
  // BLE Connection
2630
2686
  async connectBLE() {
2631
2687
  let switchbot: any;
@@ -2687,6 +2743,12 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2687
2743
  * If device level logging is turned on, log to log.warn
2688
2744
  * Otherwise send debug logs to log.debug
2689
2745
  */
2746
+ successLog(...log: any[]): void {
2747
+ if (this.enablingPlatformLogging()) {
2748
+ this.log.success(String(...log));
2749
+ }
2750
+ }
2751
+
2690
2752
  infoLog(...log: any[]): void {
2691
2753
  if (this.enablingPlatformLogging()) {
2692
2754
  this.log.info(String(...log));