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

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 +45 -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 +10 -0
  109. package/dist/platform.d.ts.map +1 -1
  110. package/dist/platform.js +130 -87
  111. package/dist/platform.js.map +1 -1
  112. package/dist/settings.d.ts +3 -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 +139 -93
  150. package/src/settings.ts +4 -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,7 +32,7 @@ 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';
@@ -40,6 +40,8 @@ import asyncmqtt from 'async-mqtt';
40
40
  import crypto, { randomUUID } from 'crypto';
41
41
  import { readFileSync, writeFileSync } from 'fs';
42
42
  import hbLib from 'homebridge-lib';
43
+ import { UrlObject } from 'url';
44
+ import { sleep } from './utils.js';
43
45
 
44
46
 
45
47
 
@@ -492,44 +494,95 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
492
494
  */
493
495
  async discoverDevices() {
494
496
  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;
497
+ let retryCount = 0;
498
+ const maxRetries = 5; // Maximum number of retries
499
+ const delayBetweenRetries = 5000; // Delay between retries in milliseconds
500
+ while (retryCount < maxRetries) {
501
+ try {
502
+ const { body, statusCode } = await request(Devices, {
503
+ headers: this.generateHeaders(),
504
+ });
505
+ this.debugWarnLog(`statusCode: ${statusCode}`);
506
+ const devicesAPI: any = await body.json();
507
+ this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
508
+ this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
509
+ this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
510
+ if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
511
+ this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
512
+ // SwitchBot Devices
513
+ const deviceLists = devicesAPI.body.deviceList;
514
+ this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
515
+ this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
516
+ if (!this.config.options?.devices) {
517
+ this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
518
+ if (deviceLists.length === 0) {
519
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
520
+ } else {
521
+ const devices = deviceLists.map((v: any) => v);
522
+ for (const device of devices) {
523
+ if (device.deviceType) {
524
+ if (device.configDeviceName) {
525
+ device.deviceName = device.configDeviceName;
526
+ }
527
+ this.createDevice(device);
528
+ }
529
+ }
530
+ }
531
+ } else if (this.config.credentials?.token && this.config.options.devices) {
532
+ this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
533
+ if (deviceLists.length === 0) {
534
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
535
+ } else {
536
+ const deviceConfigs = this.config.options?.devices;
537
+
538
+ const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
539
+ a1.map((itm: { deviceId: string }) => ({
540
+ ...a2.find(
541
+ (item: { deviceId: string }) =>
542
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
543
+ ),
544
+ ...itm,
545
+ }));
546
+
547
+ const devices = mergeBydeviceId(deviceLists, deviceConfigs);
548
+ this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
549
+ for (const device of devices) {
550
+ if (!device.deviceType) {
551
+ device.deviceType = device.configDeviceType;
552
+ this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
553
+ }
554
+ if (device.deviceType) {
555
+ if (device.configDeviceName) {
556
+ device.deviceName = device.configDeviceName;
557
+ }
558
+ this.createDevice(device);
520
559
  }
521
- this.createDevice(device);
522
560
  }
523
561
  }
562
+ } else {
563
+ this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
524
564
  }
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)}`);
565
+ if (devicesAPI.body.deviceList.length !== 0) {
566
+ this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
529
567
  } else {
530
- const deviceConfigs = this.config.options?.devices;
568
+ this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
569
+ }
570
+
571
+ // IR Devices
572
+ const irDeviceLists = devicesAPI.body.infraredRemoteList;
573
+ if (!this.config.options?.irdevices) {
574
+ this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
575
+ const devices = irDeviceLists.map((v: any) => v);
576
+ for (const device of devices) {
577
+ if (device.remoteType) {
578
+ this.createIRDevice(device);
579
+ }
580
+ }
581
+ } else {
582
+ this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
583
+ const irDeviceConfig = this.config.options?.irdevices;
531
584
 
532
- const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
585
+ const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
533
586
  a1.map((itm: { deviceId: string }) => ({
534
587
  ...a2.find(
535
588
  (item: { deviceId: string }) =>
@@ -538,73 +591,34 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
538
591
  ...itm,
539
592
  }));
540
593
 
541
- const devices = mergeBydeviceId(deviceLists, deviceConfigs);
542
- this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
594
+ const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
595
+ this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
543
596
  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
597
  this.createIRDevice(device);
573
598
  }
574
599
  }
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);
600
+ if (devicesAPI.body.infraredRemoteList.length !== 0) {
601
+ this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
602
+ } else {
603
+ this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
592
604
  }
593
- }
594
- if (devicesAPI.body.infraredRemoteList.length !== 0) {
595
- this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
605
+ break;
596
606
  } else {
597
- this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
607
+ this.statusCode(statusCode);
608
+ this.statusCode(devicesAPI.statusCode);
609
+ if (statusCode === 500) {
610
+ retryCount++;
611
+ this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
612
+ await sleep(delayBetweenRetries);
613
+ }
598
614
  }
599
- } else {
600
- this.statusCode(statusCode);
601
- this.statusCode(devicesAPI.statusCode);
615
+ } catch (e: any) {
616
+ retryCount++;
617
+ this.debugErrorLog(
618
+ `Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug',
619
+ );
620
+ this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
602
621
  }
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
622
  }
609
623
  } else if (!this.config.credentials?.token && this.config.options?.devices) {
610
624
  this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
@@ -691,6 +705,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
691
705
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
692
706
  this.createColorBulb(device);
693
707
  break;
708
+ case 'K10+':
694
709
  case 'WoSweeper':
695
710
  case 'WoSweeperMini':
696
711
  case 'Robot Vacuum Cleaner S1':
@@ -712,6 +727,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
712
727
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
713
728
  break;
714
729
  case 'Remote':
730
+ case 'remote with screen+':
715
731
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
716
732
  break;
717
733
  default:
@@ -2626,6 +2642,30 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2626
2642
  }
2627
2643
  }
2628
2644
 
2645
+ async retryRequest(deviceMaxRetries: number, deviceDelayBetweenRetries: number, url: string | URL | UrlObject,
2646
+ options?: { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions,
2647
+ 'origin' | 'path' | 'method'> & Partial<Pick<Dispatcher.RequestOptions, 'method'>>): Promise<{ body: any; statusCode: number }> {
2648
+ let retryCount = 0;
2649
+ const maxRetries = deviceMaxRetries;
2650
+ const delayBetweenRetries = deviceDelayBetweenRetries;
2651
+ while (retryCount < maxRetries) {
2652
+ try {
2653
+ const { body, statusCode } = await request(url, options);
2654
+ if (statusCode === 200 || statusCode === 100) {
2655
+ return { body, statusCode };
2656
+ } else {
2657
+ this.debugLog(`Received status code: ${statusCode}`);
2658
+ }
2659
+ } catch (error: any) {
2660
+ this.errorLog(`Error making request: ${error.message}`);
2661
+ }
2662
+ retryCount++;
2663
+ this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
2664
+ await sleep(delayBetweenRetries);
2665
+ }
2666
+ return { body: null, statusCode: -1 };
2667
+ }
2668
+
2629
2669
  // BLE Connection
2630
2670
  async connectBLE() {
2631
2671
  let switchbot: any;
@@ -2687,6 +2727,12 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2687
2727
  * If device level logging is turned on, log to log.warn
2688
2728
  * Otherwise send debug logs to log.debug
2689
2729
  */
2730
+ successLog(...log: any[]): void {
2731
+ if (this.enablingPlatformLogging()) {
2732
+ this.log.success(String(...log));
2733
+ }
2734
+ }
2735
+
2690
2736
  infoLog(...log: any[]): void {
2691
2737
  if (this.enablingPlatformLogging()) {
2692
2738
  this.log.info(String(...log));