@switchbot/homebridge-switchbot 3.5.0-beta.3 → 3.5.0-beta.30

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 (166) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/config.schema.json +147 -9
  3. package/dist/device/blindtilt.d.ts +21 -94
  4. package/dist/device/blindtilt.d.ts.map +1 -1
  5. package/dist/device/blindtilt.js +347 -756
  6. package/dist/device/blindtilt.js.map +1 -1
  7. package/dist/device/bot.d.ts +25 -71
  8. package/dist/device/bot.d.ts.map +1 -1
  9. package/dist/device/bot.js +582 -759
  10. package/dist/device/bot.js.map +1 -1
  11. package/dist/device/ceilinglight.d.ts +13 -67
  12. package/dist/device/ceilinglight.d.ts.map +1 -1
  13. package/dist/device/ceilinglight.js +209 -587
  14. package/dist/device/ceilinglight.js.map +1 -1
  15. package/dist/device/colorbulb.d.ts +13 -74
  16. package/dist/device/colorbulb.d.ts.map +1 -1
  17. package/dist/device/colorbulb.js +250 -632
  18. package/dist/device/colorbulb.js.map +1 -1
  19. package/dist/device/contact.d.ts +14 -65
  20. package/dist/device/contact.d.ts.map +1 -1
  21. package/dist/device/contact.js +204 -531
  22. package/dist/device/contact.js.map +1 -1
  23. package/dist/device/curtain.d.ts +17 -86
  24. package/dist/device/curtain.d.ts.map +1 -1
  25. package/dist/device/curtain.js +335 -786
  26. package/dist/device/curtain.js.map +1 -1
  27. package/dist/device/device.d.ts +59 -0
  28. package/dist/device/device.d.ts.map +1 -0
  29. package/dist/device/device.js +646 -0
  30. package/dist/device/device.js.map +1 -0
  31. package/dist/device/fan.d.ts +51 -0
  32. package/dist/device/fan.d.ts.map +1 -0
  33. package/dist/device/fan.js +499 -0
  34. package/dist/device/fan.js.map +1 -0
  35. package/dist/device/hub.d.ts +15 -59
  36. package/dist/device/hub.d.ts.map +1 -1
  37. package/dist/device/hub.js +242 -596
  38. package/dist/device/hub.js.map +1 -1
  39. package/dist/device/humidifier.d.ts +10 -65
  40. package/dist/device/humidifier.d.ts.map +1 -1
  41. package/dist/device/humidifier.js +207 -571
  42. package/dist/device/humidifier.js.map +1 -1
  43. package/dist/device/iosensor.d.ts +11 -64
  44. package/dist/device/iosensor.d.ts.map +1 -1
  45. package/dist/device/iosensor.js +174 -584
  46. package/dist/device/iosensor.js.map +1 -1
  47. package/dist/device/lightstrip.d.ts +10 -68
  48. package/dist/device/lightstrip.d.ts.map +1 -1
  49. package/dist/device/lightstrip.js +252 -568
  50. package/dist/device/lightstrip.js.map +1 -1
  51. package/dist/device/lock.d.ts +15 -62
  52. package/dist/device/lock.d.ts.map +1 -1
  53. package/dist/device/lock.js +210 -542
  54. package/dist/device/lock.js.map +1 -1
  55. package/dist/device/meter.d.ts +13 -63
  56. package/dist/device/meter.d.ts.map +1 -1
  57. package/dist/device/meter.js +170 -577
  58. package/dist/device/meter.js.map +1 -1
  59. package/dist/device/meterplus.d.ts +13 -64
  60. package/dist/device/meterplus.d.ts.map +1 -1
  61. package/dist/device/meterplus.js +159 -577
  62. package/dist/device/meterplus.js.map +1 -1
  63. package/dist/device/motion.d.ts +13 -69
  64. package/dist/device/motion.d.ts.map +1 -1
  65. package/dist/device/motion.js +136 -518
  66. package/dist/device/motion.js.map +1 -1
  67. package/dist/device/plug.d.ts +9 -57
  68. package/dist/device/plug.d.ts.map +1 -1
  69. package/dist/device/plug.js +82 -452
  70. package/dist/device/plug.js.map +1 -1
  71. package/dist/device/robotvacuumcleaner.d.ts +11 -62
  72. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  73. package/dist/device/robotvacuumcleaner.js +140 -451
  74. package/dist/device/robotvacuumcleaner.js.map +1 -1
  75. package/dist/device/waterdetector.d.ts +9 -70
  76. package/dist/device/waterdetector.d.ts.map +1 -1
  77. package/dist/device/waterdetector.js +121 -664
  78. package/dist/device/waterdetector.js.map +1 -1
  79. package/dist/index.js +1 -1
  80. package/dist/irdevice/airconditioner.d.ts +8 -48
  81. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  82. package/dist/irdevice/airconditioner.js +309 -419
  83. package/dist/irdevice/airconditioner.js.map +1 -1
  84. package/dist/irdevice/airpurifier.d.ts +7 -38
  85. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  86. package/dist/irdevice/airpurifier.js +72 -304
  87. package/dist/irdevice/airpurifier.js.map +1 -1
  88. package/dist/irdevice/camera.d.ts +6 -35
  89. package/dist/irdevice/camera.d.ts.map +1 -1
  90. package/dist/irdevice/camera.js +34 -278
  91. package/dist/irdevice/camera.js.map +1 -1
  92. package/dist/irdevice/fan.d.ts +6 -39
  93. package/dist/irdevice/fan.d.ts.map +1 -1
  94. package/dist/irdevice/fan.js +67 -311
  95. package/dist/irdevice/fan.js.map +1 -1
  96. package/dist/irdevice/irdevice.d.ts +40 -0
  97. package/dist/irdevice/irdevice.d.ts.map +1 -0
  98. package/dist/irdevice/irdevice.js +509 -0
  99. package/dist/irdevice/irdevice.js.map +1 -0
  100. package/dist/irdevice/light.d.ts +6 -34
  101. package/dist/irdevice/light.d.ts.map +1 -1
  102. package/dist/irdevice/light.js +23 -272
  103. package/dist/irdevice/light.js.map +1 -1
  104. package/dist/irdevice/other.d.ts +18 -47
  105. package/dist/irdevice/other.d.ts.map +1 -1
  106. package/dist/irdevice/other.js +352 -546
  107. package/dist/irdevice/other.js.map +1 -1
  108. package/dist/irdevice/tv.d.ts +7 -39
  109. package/dist/irdevice/tv.d.ts.map +1 -1
  110. package/dist/irdevice/tv.js +82 -321
  111. package/dist/irdevice/tv.js.map +1 -1
  112. package/dist/irdevice/vacuumcleaner.d.ts +6 -35
  113. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  114. package/dist/irdevice/vacuumcleaner.js +41 -284
  115. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  116. package/dist/irdevice/waterheater.d.ts +6 -35
  117. package/dist/irdevice/waterheater.d.ts.map +1 -1
  118. package/dist/irdevice/waterheater.js +42 -287
  119. package/dist/irdevice/waterheater.js.map +1 -1
  120. package/dist/platform.d.ts +14 -1
  121. package/dist/platform.d.ts.map +1 -1
  122. package/dist/platform.js +237 -94
  123. package/dist/platform.js.map +1 -1
  124. package/dist/settings.d.ts +40 -10
  125. package/dist/settings.d.ts.map +1 -1
  126. package/dist/settings.js +0 -552
  127. package/dist/settings.js.map +1 -1
  128. package/dist/utils.d.ts +77 -0
  129. package/dist/utils.d.ts.map +1 -1
  130. package/dist/utils.js +638 -1
  131. package/dist/utils.js.map +1 -1
  132. package/package.json +16 -15
  133. package/src/custom.d.ts +2 -1
  134. package/src/device/blindtilt.ts +373 -782
  135. package/src/device/bot.ts +616 -844
  136. package/src/device/ceilinglight.ts +222 -607
  137. package/src/device/colorbulb.ts +264 -656
  138. package/src/device/contact.ts +229 -553
  139. package/src/device/curtain.ts +355 -810
  140. package/src/device/device.ts +673 -0
  141. package/src/device/fan.ts +548 -0
  142. package/src/device/hub.ts +268 -623
  143. package/src/device/humidifier.ts +237 -618
  144. package/src/device/iosensor.ts +200 -610
  145. package/src/device/lightstrip.ts +273 -596
  146. package/src/device/lock.ts +247 -582
  147. package/src/device/meter.ts +196 -601
  148. package/src/device/meterplus.ts +184 -602
  149. package/src/device/motion.ts +156 -541
  150. package/src/device/plug.ts +92 -480
  151. package/src/device/robotvacuumcleaner.ts +161 -477
  152. package/src/device/waterdetector.ts +139 -689
  153. package/src/index.ts +1 -1
  154. package/src/irdevice/airconditioner.ts +330 -446
  155. package/src/irdevice/airpurifier.ts +89 -321
  156. package/src/irdevice/camera.ts +42 -293
  157. package/src/irdevice/fan.ts +78 -327
  158. package/src/irdevice/irdevice.ts +526 -0
  159. package/src/irdevice/light.ts +32 -287
  160. package/src/irdevice/other.ts +396 -615
  161. package/src/irdevice/tv.ts +100 -339
  162. package/src/irdevice/vacuumcleaner.ts +49 -305
  163. package/src/irdevice/waterheater.ts +50 -310
  164. package/src/platform.ts +247 -102
  165. package/src/settings.ts +56 -565
  166. package/src/utils.ts +642 -1
package/dist/platform.js CHANGED
@@ -15,8 +15,9 @@ import { CeilingLight } from './device/ceilinglight.js';
15
15
  import { StripLight } from './device/lightstrip.js';
16
16
  import { Humidifier } from './device/humidifier.js';
17
17
  import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js';
18
+ import { Fan } from './device/fan.js';
18
19
  import { TV } from './irdevice/tv.js';
19
- import { Fan } from './irdevice/fan.js';
20
+ import { IRFan } from './irdevice/fan.js';
20
21
  import { Light } from './irdevice/light.js';
21
22
  import { Others } from './irdevice/other.js';
22
23
  import { Camera } from './irdevice/camera.js';
@@ -33,7 +34,8 @@ import fakegato from 'fakegato-history';
33
34
  import asyncmqtt from 'async-mqtt';
34
35
  import crypto, { randomUUID } from 'crypto';
35
36
  import { readFileSync, writeFileSync } from 'fs';
36
- import hbLib from 'homebridge-lib';
37
+ import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes';
38
+ import { sleep } from './utils.js';
37
39
  /**
38
40
  * HomebridgePlatform
39
41
  * This class is the main constructor for your plugin, this is where you should
@@ -46,6 +48,8 @@ export class SwitchBotPlatform {
46
48
  version;
47
49
  Logging;
48
50
  debugMode;
51
+ maxRetries;
52
+ delayBetweenRetries;
49
53
  platformConfig;
50
54
  platformLogging;
51
55
  config;
@@ -85,7 +89,6 @@ export class SwitchBotPlatform {
85
89
  return;
86
90
  }
87
91
  // import fakegato-history module and EVE characteristics
88
- const { EveHomeKitTypes } = hbLib;
89
92
  this.fakegatoAPI = fakegato(api);
90
93
  this.eve = new EveHomeKitTypes(api);
91
94
  // When this event is fired it means Homebridge has restored all cached accessories from disk.
@@ -355,6 +358,21 @@ export class SwitchBotPlatform {
355
358
  this.config.options.pushRate = 0.1;
356
359
  this.debugWarnLog('Using Default Push Rate.');
357
360
  }
361
+ if (!this.config.options.maxRetries) {
362
+ this.config.options.maxRetries = 5;
363
+ this.debugWarnLog('Using Default Max Retries.');
364
+ }
365
+ else {
366
+ this.maxRetries = this.config.options.maxRetries;
367
+ }
368
+ if (!this.config.options.delayBetweenRetries) {
369
+ // default 3 seconds
370
+ this.config.options.delayBetweenRetries = 3000;
371
+ this.debugWarnLog('Using Default Delay Between Retries.');
372
+ }
373
+ else {
374
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
375
+ }
358
376
  if (!this.config.credentials && !this.config.options) {
359
377
  this.debugWarnLog('Missing Credentials');
360
378
  }
@@ -451,114 +469,129 @@ export class SwitchBotPlatform {
451
469
  */
452
470
  async discoverDevices() {
453
471
  if (this.config.credentials?.token) {
454
- try {
455
- const { body, statusCode } = await request(Devices, {
456
- headers: this.generateHeaders(),
457
- });
458
- this.debugWarnLog(`statusCode: ${statusCode}`);
459
- const devicesAPI = await body.json();
460
- this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
461
- this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
462
- this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
463
- if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
464
- this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
465
- // SwitchBot Devices
466
- const deviceLists = devicesAPI.body.deviceList;
467
- this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
468
- this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
469
- if (!this.config.options?.devices) {
470
- this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
471
- if (deviceLists.length === 0) {
472
- this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
472
+ let retryCount = 0;
473
+ const maxRetries = this.maxRetries; // Maximum number of retries
474
+ const delayBetweenRetries = this.delayBetweenRetries; // Delay between retries in milliseconds
475
+ this.debugWarnLog(`Retry Count: ${retryCount}`);
476
+ this.debugWarnLog(`Max Retries: ${maxRetries}`);
477
+ this.debugWarnLog(`Delay Between Retries: ${delayBetweenRetries}`);
478
+ while (retryCount < maxRetries) {
479
+ try {
480
+ const { body, statusCode } = await request(Devices, {
481
+ headers: this.generateHeaders(),
482
+ });
483
+ this.debugWarnLog(`statusCode: ${statusCode}`);
484
+ const devicesAPI = await body.json();
485
+ this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
486
+ this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
487
+ this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
488
+ if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
489
+ this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
490
+ // SwitchBot Devices
491
+ const deviceLists = devicesAPI.body.deviceList;
492
+ this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
493
+ this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
494
+ if (!this.config.options?.devices) {
495
+ this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
496
+ if (deviceLists.length === 0) {
497
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
498
+ }
499
+ else {
500
+ const devices = deviceLists.map((v) => v);
501
+ for (const device of devices) {
502
+ if (device.deviceType) {
503
+ if (device.configDeviceName) {
504
+ device.deviceName = device.configDeviceName;
505
+ }
506
+ this.createDevice(device);
507
+ }
508
+ }
509
+ }
473
510
  }
474
- else {
475
- const devices = deviceLists.map((v) => v);
476
- for (const device of devices) {
477
- if (device.deviceType) {
478
- if (device.configDeviceName) {
479
- device.deviceName = device.configDeviceName;
511
+ else if (this.config.credentials?.token && this.config.options.devices) {
512
+ this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
513
+ if (deviceLists.length === 0) {
514
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
515
+ }
516
+ else {
517
+ const deviceConfigs = this.config.options?.devices;
518
+ const mergeBydeviceId = (a1, a2) => a1.map((itm) => ({
519
+ ...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
520
+ ...itm,
521
+ }));
522
+ const devices = mergeBydeviceId(deviceLists, deviceConfigs);
523
+ this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
524
+ for (const device of devices) {
525
+ if (!device.deviceType) {
526
+ device.deviceType = device.configDeviceType;
527
+ this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
528
+ }
529
+ if (device.deviceType) {
530
+ if (device.configDeviceName) {
531
+ device.deviceName = device.configDeviceName;
532
+ }
533
+ this.createDevice(device);
480
534
  }
481
- this.createDevice(device);
482
535
  }
483
536
  }
484
537
  }
485
- }
486
- else if (this.config.credentials?.token && this.config.options.devices) {
487
- this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
488
- if (deviceLists.length === 0) {
489
- this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
538
+ else {
539
+ this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
540
+ }
541
+ if (devicesAPI.body.deviceList.length !== 0) {
542
+ this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
490
543
  }
491
544
  else {
492
- const deviceConfigs = this.config.options?.devices;
493
- const mergeBydeviceId = (a1, a2) => a1.map((itm) => ({
494
- ...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
495
- ...itm,
496
- }));
497
- const devices = mergeBydeviceId(deviceLists, deviceConfigs);
498
- this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
545
+ this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
546
+ }
547
+ // IR Devices
548
+ const irDeviceLists = devicesAPI.body.infraredRemoteList;
549
+ if (!this.config.options?.irdevices) {
550
+ this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
551
+ const devices = irDeviceLists.map((v) => v);
499
552
  for (const device of devices) {
500
- if (!device.deviceType) {
501
- device.deviceType = device.configDeviceType;
502
- this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
503
- }
504
- if (device.deviceType) {
505
- if (device.configDeviceName) {
506
- device.deviceName = device.configDeviceName;
507
- }
508
- this.createDevice(device);
553
+ if (device.remoteType) {
554
+ this.createIRDevice(device);
509
555
  }
510
556
  }
511
557
  }
512
- }
513
- else {
514
- this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
515
- }
516
- if (devicesAPI.body.deviceList.length !== 0) {
517
- this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
518
- }
519
- else {
520
- this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
521
- }
522
- // IR Devices
523
- const irDeviceLists = devicesAPI.body.infraredRemoteList;
524
- if (!this.config.options?.irdevices) {
525
- this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
526
- const devices = irDeviceLists.map((v) => v);
527
- for (const device of devices) {
528
- if (device.remoteType) {
558
+ else {
559
+ this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
560
+ const irDeviceConfig = this.config.options?.irdevices;
561
+ const mergeIRBydeviceId = (a1, a2) => a1.map((itm) => ({
562
+ ...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
563
+ ...itm,
564
+ }));
565
+ const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
566
+ this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
567
+ for (const device of devices) {
529
568
  this.createIRDevice(device);
530
569
  }
531
570
  }
532
- }
533
- else {
534
- this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
535
- const irDeviceConfig = this.config.options?.irdevices;
536
- const mergeIRBydeviceId = (a1, a2) => a1.map((itm) => ({
537
- ...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
538
- ...itm,
539
- }));
540
- const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
541
- this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
542
- for (const device of devices) {
543
- this.createIRDevice(device);
571
+ if (devicesAPI.body.infraredRemoteList.length !== 0) {
572
+ this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
544
573
  }
545
- }
546
- if (devicesAPI.body.infraredRemoteList.length !== 0) {
547
- this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
574
+ else {
575
+ this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
576
+ }
577
+ break;
548
578
  }
549
579
  else {
550
- this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
580
+ this.statusCode(statusCode);
581
+ this.statusCode(devicesAPI.statusCode);
582
+ if (statusCode === 500) {
583
+ retryCount++;
584
+ this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
585
+ await sleep(delayBetweenRetries);
586
+ }
551
587
  }
552
588
  }
553
- else {
554
- this.statusCode(statusCode);
555
- this.statusCode(devicesAPI.statusCode);
589
+ catch (e) {
590
+ retryCount++;
591
+ this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
592
+ this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
556
593
  }
557
594
  }
558
- catch (e) {
559
- this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
560
- this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
561
- }
562
595
  }
563
596
  else if (!this.config.credentials?.token && this.config.options?.devices) {
564
597
  this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
@@ -645,10 +678,12 @@ export class SwitchBotPlatform {
645
678
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
646
679
  this.createColorBulb(device);
647
680
  break;
681
+ case 'K10+':
648
682
  case 'WoSweeper':
649
683
  case 'WoSweeperMini':
650
684
  case 'Robot Vacuum Cleaner S1':
651
685
  case 'Robot Vacuum Cleaner S1 Plus':
686
+ case 'Robot Vacuum Cleaner S10':
652
687
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
653
688
  this.createRobotVacuumCleaner(device);
654
689
  break;
@@ -666,8 +701,13 @@ export class SwitchBotPlatform {
666
701
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
667
702
  break;
668
703
  case 'Remote':
704
+ case 'remote with screen+':
669
705
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
670
706
  break;
707
+ case 'Battery Circulator Fan':
708
+ this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
709
+ this.createFan(device);
710
+ break;
671
711
  default:
672
712
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
673
713
  // eslint-disable-next-line max-len
@@ -703,7 +743,7 @@ export class SwitchBotPlatform {
703
743
  case 'Fan':
704
744
  case 'DIY Fan':
705
745
  this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
706
- this.createFan(device);
746
+ this.createIRFan(device);
707
747
  break;
708
748
  case 'Air Conditioner':
709
749
  case 'DIY Air Conditioner':
@@ -1684,6 +1724,63 @@ export class SwitchBotPlatform {
1684
1724
  this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1685
1725
  }
1686
1726
  }
1727
+ async createFan(device) {
1728
+ const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1729
+ // see if an accessory with the same uuid has already been registered and restored from
1730
+ // the cached devices we stored in the `configureAccessory` method above
1731
+ const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid);
1732
+ if (existingAccessory) {
1733
+ // the accessory already exists
1734
+ if (await this.registerDevice(device)) {
1735
+ // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1736
+ existingAccessory.context.model = device.deviceType;
1737
+ existingAccessory.context.deviceID = device.deviceId;
1738
+ existingAccessory.displayName = device.configDeviceName || device.deviceName;
1739
+ if (device.firmware) {
1740
+ existingAccessory.context.FirmwareRevision = device.firmware;
1741
+ }
1742
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1743
+ this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1744
+ existingAccessory.context.connectionType = await this.connectionType(device);
1745
+ this.api.updatePlatformAccessories([existingAccessory]);
1746
+ // create the accessory handler for the restored accessory
1747
+ // this is imported from `platformAccessory.ts`
1748
+ new Fan(this, existingAccessory, device);
1749
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`);
1750
+ }
1751
+ else {
1752
+ this.unregisterPlatformAccessories(existingAccessory);
1753
+ }
1754
+ }
1755
+ else if (await this.registerDevice(device)) {
1756
+ // the accessory does not yet exist, so we need to create it
1757
+ if (!device.external) {
1758
+ this.infoLog(`Adding new accessory: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1759
+ }
1760
+ // create a new accessory
1761
+ const accessory = new this.api.platformAccessory(device.deviceName, uuid);
1762
+ // store a copy of the device object in the `accessory.context`
1763
+ // the `context` property can be used to store any data about the accessory you may need
1764
+ accessory.context.device = device;
1765
+ accessory.context.model = device.deviceType;
1766
+ accessory.context.deviceID = device.deviceId;
1767
+ if (device.firmware) {
1768
+ accessory.context.FirmwareRevision = device.firmware;
1769
+ }
1770
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1771
+ accessory.context.connectionType = await this.connectionType(device);
1772
+ // create the accessory handler for the newly create accessory
1773
+ // this is imported from `platformAccessory.ts`
1774
+ new Fan(this, accessory, device);
1775
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`);
1776
+ // publish device externally or link the accessory to your platform
1777
+ this.externalOrPlatform(device, accessory);
1778
+ this.accessories.push(accessory);
1779
+ }
1780
+ else {
1781
+ this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1782
+ }
1783
+ }
1687
1784
  async createRobotVacuumCleaner(device) {
1688
1785
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1689
1786
  // see if an accessory with the same uuid has already been registered and restored from
@@ -1789,7 +1886,7 @@ export class SwitchBotPlatform {
1789
1886
  this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} DeviceID: ${device.deviceId}`);
1790
1887
  }
1791
1888
  }
1792
- async createFan(device) {
1889
+ async createIRFan(device) {
1793
1890
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
1794
1891
  // see if an accessory with the same uuid has already been registered and restored from
1795
1892
  // the cached devices we stored in the `configureAccessory` method above
@@ -1810,7 +1907,7 @@ export class SwitchBotPlatform {
1810
1907
  this.api.updatePlatformAccessories([existingAccessory]);
1811
1908
  // create the accessory handler for the restored accessory
1812
1909
  // this is imported from `platformAccessory.ts`
1813
- new Fan(this, existingAccessory, device);
1910
+ new IRFan(this, existingAccessory, device);
1814
1911
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`);
1815
1912
  }
1816
1913
  else {
@@ -1836,7 +1933,7 @@ export class SwitchBotPlatform {
1836
1933
  accessory.context.connectionType = device.connectionType;
1837
1934
  // create the accessory handler for the newly create accessory
1838
1935
  // this is imported from `platformAccessory.ts`
1839
- new Fan(this, accessory, device);
1936
+ new IRFan(this, accessory, device);
1840
1937
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
1841
1938
  // publish device externally or link the accessory to your platform
1842
1939
  this.externalOrPlatformIR(device, accessory);
@@ -2491,6 +2588,29 @@ export class SwitchBotPlatform {
2491
2588
  this.errorLog(`Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
2492
2589
  }
2493
2590
  }
2591
+ async retryRequest(deviceMaxRetries, deviceDelayBetweenRetries, url, options) {
2592
+ let retryCount = 0;
2593
+ const maxRetries = deviceMaxRetries;
2594
+ const delayBetweenRetries = deviceDelayBetweenRetries;
2595
+ while (retryCount < maxRetries) {
2596
+ try {
2597
+ const { body, statusCode } = await request(url, options);
2598
+ if (statusCode === 200 || statusCode === 100) {
2599
+ return { body, statusCode };
2600
+ }
2601
+ else {
2602
+ this.debugLog(`Received status code: ${statusCode}`);
2603
+ }
2604
+ }
2605
+ catch (error) {
2606
+ this.errorLog(`Error making request: ${error.message}`);
2607
+ }
2608
+ retryCount++;
2609
+ this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
2610
+ await sleep(delayBetweenRetries);
2611
+ }
2612
+ return { body: null, statusCode: -1 };
2613
+ }
2494
2614
  // BLE Connection
2495
2615
  async connectBLE() {
2496
2616
  let switchbot;
@@ -2521,6 +2641,24 @@ export class SwitchBotPlatform {
2521
2641
  if (this.config.options.pushRate) {
2522
2642
  platformConfig.pushRate = this.config.options.pushRate;
2523
2643
  }
2644
+ if (this.config.options.maxRetries) {
2645
+ this.maxRetries = this.config.options.maxRetries;
2646
+ platformConfig.maxRetries = this.config.options.maxRetries;
2647
+ }
2648
+ else {
2649
+ this.maxRetries = 3;
2650
+ this.debugWarnLog('Using Default Max Retries');
2651
+ platformConfig.maxRetries = this.maxRetries;
2652
+ }
2653
+ if (this.config.options.delayBetweenRetries) {
2654
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
2655
+ platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries;
2656
+ }
2657
+ else {
2658
+ this.delayBetweenRetries = 3000;
2659
+ this.debugWarnLog('Using Default Delay Between Retries');
2660
+ platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
2661
+ }
2524
2662
  if (Object.entries(platformConfig).length !== 0) {
2525
2663
  this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
2526
2664
  }
@@ -2546,6 +2684,11 @@ export class SwitchBotPlatform {
2546
2684
  * If device level logging is turned on, log to log.warn
2547
2685
  * Otherwise send debug logs to log.debug
2548
2686
  */
2687
+ successLog(...log) {
2688
+ if (this.enablingPlatformLogging()) {
2689
+ this.log.success(String(...log));
2690
+ }
2691
+ }
2549
2692
  infoLog(...log) {
2550
2693
  if (this.enablingPlatformLogging()) {
2551
2694
  this.log.info(String(...log));