@switchbot/homebridge-switchbot 3.5.0-beta.6 → 3.5.0-beta.60

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 (177) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +4 -1
  3. package/config.schema.json +120 -17
  4. package/dist/device/blindtilt.d.ts +23 -96
  5. package/dist/device/blindtilt.d.ts.map +1 -1
  6. package/dist/device/blindtilt.js +408 -779
  7. package/dist/device/blindtilt.js.map +1 -1
  8. package/dist/device/bot.d.ts +26 -72
  9. package/dist/device/bot.d.ts.map +1 -1
  10. package/dist/device/bot.js +696 -822
  11. package/dist/device/bot.js.map +1 -1
  12. package/dist/device/ceilinglight.d.ts +14 -68
  13. package/dist/device/ceilinglight.d.ts.map +1 -1
  14. package/dist/device/ceilinglight.js +237 -606
  15. package/dist/device/ceilinglight.js.map +1 -1
  16. package/dist/device/colorbulb.d.ts +14 -75
  17. package/dist/device/colorbulb.d.ts.map +1 -1
  18. package/dist/device/colorbulb.js +279 -658
  19. package/dist/device/colorbulb.js.map +1 -1
  20. package/dist/device/contact.d.ts +15 -66
  21. package/dist/device/contact.d.ts.map +1 -1
  22. package/dist/device/contact.js +242 -544
  23. package/dist/device/contact.js.map +1 -1
  24. package/dist/device/curtain.d.ts +19 -88
  25. package/dist/device/curtain.d.ts.map +1 -1
  26. package/dist/device/curtain.js +402 -805
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/device.d.ts +59 -0
  29. package/dist/device/device.d.ts.map +1 -0
  30. package/dist/device/device.js +684 -0
  31. package/dist/device/device.js.map +1 -0
  32. package/dist/device/fan.d.ts +51 -0
  33. package/dist/device/fan.d.ts.map +1 -0
  34. package/dist/device/fan.js +535 -0
  35. package/dist/device/fan.js.map +1 -0
  36. package/dist/device/hub.d.ts +16 -60
  37. package/dist/device/hub.d.ts.map +1 -1
  38. package/dist/device/hub.js +246 -613
  39. package/dist/device/hub.js.map +1 -1
  40. package/dist/device/humidifier.d.ts +11 -66
  41. package/dist/device/humidifier.d.ts.map +1 -1
  42. package/dist/device/humidifier.js +232 -593
  43. package/dist/device/humidifier.js.map +1 -1
  44. package/dist/device/iosensor.d.ts +11 -64
  45. package/dist/device/iosensor.d.ts.map +1 -1
  46. package/dist/device/iosensor.js +185 -600
  47. package/dist/device/iosensor.js.map +1 -1
  48. package/dist/device/lightstrip.d.ts +11 -69
  49. package/dist/device/lightstrip.d.ts.map +1 -1
  50. package/dist/device/lightstrip.js +277 -586
  51. package/dist/device/lightstrip.js.map +1 -1
  52. package/dist/device/lock.d.ts +16 -63
  53. package/dist/device/lock.d.ts.map +1 -1
  54. package/dist/device/lock.js +241 -560
  55. package/dist/device/lock.js.map +1 -1
  56. package/dist/device/meter.d.ts +14 -64
  57. package/dist/device/meter.d.ts.map +1 -1
  58. package/dist/device/meter.js +181 -593
  59. package/dist/device/meter.js.map +1 -1
  60. package/dist/device/meterplus.d.ts +14 -65
  61. package/dist/device/meterplus.d.ts.map +1 -1
  62. package/dist/device/meterplus.js +170 -593
  63. package/dist/device/meterplus.js.map +1 -1
  64. package/dist/device/motion.d.ts +13 -69
  65. package/dist/device/motion.d.ts.map +1 -1
  66. package/dist/device/motion.js +178 -531
  67. package/dist/device/motion.js.map +1 -1
  68. package/dist/device/plug.d.ts +9 -57
  69. package/dist/device/plug.d.ts.map +1 -1
  70. package/dist/device/plug.js +92 -458
  71. package/dist/device/plug.js.map +1 -1
  72. package/dist/device/robotvacuumcleaner.d.ts +12 -63
  73. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  74. package/dist/device/robotvacuumcleaner.js +197 -521
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +10 -65
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +139 -495
  79. package/dist/device/waterdetector.js.map +1 -1
  80. package/dist/homebridge-ui/public/index.html +22 -16
  81. package/dist/homebridge-ui/server.js +1 -1
  82. package/dist/homebridge-ui/server.js.map +1 -1
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +2 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/irdevice/airconditioner.d.ts +9 -49
  88. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  89. package/dist/irdevice/airconditioner.js +309 -419
  90. package/dist/irdevice/airconditioner.js.map +1 -1
  91. package/dist/irdevice/airpurifier.d.ts +8 -39
  92. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  93. package/dist/irdevice/airpurifier.js +72 -304
  94. package/dist/irdevice/airpurifier.js.map +1 -1
  95. package/dist/irdevice/camera.d.ts +7 -36
  96. package/dist/irdevice/camera.d.ts.map +1 -1
  97. package/dist/irdevice/camera.js +34 -278
  98. package/dist/irdevice/camera.js.map +1 -1
  99. package/dist/irdevice/fan.d.ts +10 -43
  100. package/dist/irdevice/fan.d.ts.map +1 -1
  101. package/dist/irdevice/fan.js +100 -338
  102. package/dist/irdevice/fan.js.map +1 -1
  103. package/dist/irdevice/irdevice.d.ts +40 -0
  104. package/dist/irdevice/irdevice.d.ts.map +1 -0
  105. package/dist/irdevice/irdevice.js +330 -0
  106. package/dist/irdevice/irdevice.js.map +1 -0
  107. package/dist/irdevice/light.d.ts +12 -45
  108. package/dist/irdevice/light.d.ts.map +1 -1
  109. package/dist/irdevice/light.js +87 -357
  110. package/dist/irdevice/light.js.map +1 -1
  111. package/dist/irdevice/other.d.ts +19 -48
  112. package/dist/irdevice/other.d.ts.map +1 -1
  113. package/dist/irdevice/other.js +352 -546
  114. package/dist/irdevice/other.js.map +1 -1
  115. package/dist/irdevice/tv.d.ts +8 -40
  116. package/dist/irdevice/tv.d.ts.map +1 -1
  117. package/dist/irdevice/tv.js +82 -321
  118. package/dist/irdevice/tv.js.map +1 -1
  119. package/dist/irdevice/vacuumcleaner.d.ts +7 -36
  120. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  121. package/dist/irdevice/vacuumcleaner.js +41 -284
  122. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  123. package/dist/irdevice/waterheater.d.ts +7 -36
  124. package/dist/irdevice/waterheater.d.ts.map +1 -1
  125. package/dist/irdevice/waterheater.js +42 -287
  126. package/dist/irdevice/waterheater.js.map +1 -1
  127. package/dist/platform.d.ts +19 -6
  128. package/dist/platform.d.ts.map +1 -1
  129. package/dist/platform.js +310 -169
  130. package/dist/platform.js.map +1 -1
  131. package/dist/settings.d.ts +62 -19
  132. package/dist/settings.d.ts.map +1 -1
  133. package/dist/settings.js +16 -552
  134. package/dist/settings.js.map +1 -1
  135. package/dist/utils.d.ts +77 -0
  136. package/dist/utils.d.ts.map +1 -1
  137. package/dist/utils.js +638 -1
  138. package/dist/utils.js.map +1 -1
  139. package/eslint.config.js +96 -0
  140. package/package.json +19 -15
  141. package/src/custom.d.ts +2 -1
  142. package/src/device/blindtilt.ts +442 -814
  143. package/src/device/bot.ts +754 -915
  144. package/src/device/ceilinglight.ts +255 -633
  145. package/src/device/colorbulb.ts +294 -685
  146. package/src/device/contact.ts +277 -571
  147. package/src/device/curtain.ts +431 -835
  148. package/src/device/device.ts +709 -0
  149. package/src/device/fan.ts +591 -0
  150. package/src/device/hub.ts +286 -644
  151. package/src/device/humidifier.ts +266 -646
  152. package/src/device/iosensor.ts +220 -625
  153. package/src/device/lightstrip.ts +305 -620
  154. package/src/device/lock.ts +280 -600
  155. package/src/device/meter.ts +216 -617
  156. package/src/device/meterplus.ts +205 -619
  157. package/src/device/motion.ts +206 -556
  158. package/src/device/plug.ts +107 -490
  159. package/src/device/robotvacuumcleaner.ts +223 -550
  160. package/src/device/waterdetector.ts +160 -519
  161. package/src/homebridge-ui/public/index.html +22 -16
  162. package/src/homebridge-ui/server.ts +1 -1
  163. package/src/index.ts +4 -3
  164. package/src/irdevice/airconditioner.ts +333 -447
  165. package/src/irdevice/airpurifier.ts +92 -322
  166. package/src/irdevice/camera.ts +45 -294
  167. package/src/irdevice/fan.ts +115 -353
  168. package/src/irdevice/irdevice.ts +346 -0
  169. package/src/irdevice/light.ts +110 -385
  170. package/src/irdevice/other.ts +399 -616
  171. package/src/irdevice/tv.ts +103 -340
  172. package/src/irdevice/vacuumcleaner.ts +52 -306
  173. package/src/irdevice/waterheater.ts +53 -311
  174. package/src/platform.ts +355 -216
  175. package/src/settings.ts +116 -611
  176. package/src/utils.ts +642 -1
  177. package/src/device/waterdetector.json +0 -11
package/dist/platform.js CHANGED
@@ -1,22 +1,26 @@
1
- import { PLATFORM_NAME, PLUGIN_NAME, Devices } from './settings.js';
1
+ /* Copyright(C) 2017-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * platform.ts: @switchbot/homebridge-switchbot platform class.
4
+ */
5
+ import { Hub } from './device/hub.js';
2
6
  import { Bot } from './device/bot.js';
3
7
  import { Plug } from './device/plug.js';
4
8
  import { Lock } from './device/lock.js';
5
9
  import { Meter } from './device/meter.js';
6
10
  import { Motion } from './device/motion.js';
7
- import { Hub } from './device/hub.js';
8
11
  import { Contact } from './device/contact.js';
9
12
  import { Curtain } from './device/curtain.js';
10
13
  import { IOSensor } from './device/iosensor.js';
11
- import { WaterDetector } from './device/waterdetector.js';
12
14
  import { MeterPlus } from './device/meterplus.js';
13
15
  import { ColorBulb } from './device/colorbulb.js';
14
- import { CeilingLight } from './device/ceilinglight.js';
15
16
  import { StripLight } from './device/lightstrip.js';
16
17
  import { Humidifier } from './device/humidifier.js';
18
+ import { CeilingLight } from './device/ceilinglight.js';
19
+ import { WaterDetector } from './device/waterdetector.js';
17
20
  import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js';
21
+ import { Fan } from './device/fan.js';
18
22
  import { TV } from './irdevice/tv.js';
19
- import { Fan } from './irdevice/fan.js';
23
+ import { IRFan } from './irdevice/fan.js';
20
24
  import { Light } from './irdevice/light.js';
21
25
  import { Others } from './irdevice/other.js';
22
26
  import { Camera } from './irdevice/camera.js';
@@ -25,15 +29,17 @@ import { AirPurifier } from './irdevice/airpurifier.js';
25
29
  import { WaterHeater } from './irdevice/waterheater.js';
26
30
  import { VacuumCleaner } from './irdevice/vacuumcleaner.js';
27
31
  import { AirConditioner } from './irdevice/airconditioner.js';
28
- import * as http from 'http';
29
32
  import { Buffer } from 'buffer';
30
33
  import { request } from 'undici';
34
+ import asyncmqtt from 'async-mqtt';
35
+ import { sleep } from './utils.js';
36
+ import { createServer } from 'http';
31
37
  import { queueScheduler } from 'rxjs';
32
38
  import fakegato from 'fakegato-history';
33
- import asyncmqtt from 'async-mqtt';
34
39
  import crypto, { randomUUID } from 'crypto';
35
40
  import { readFileSync, writeFileSync } from 'fs';
36
- import hbLib from 'homebridge-lib';
41
+ import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes';
42
+ import { PLATFORM_NAME, PLUGIN_NAME, Devices, setupWebhook, updateWebhook, deleteWebhook, queryWebhook } from './settings.js';
37
43
  /**
38
44
  * HomebridgePlatform
39
45
  * This class is the main constructor for your plugin, this is where you should
@@ -46,6 +52,8 @@ export class SwitchBotPlatform {
46
52
  version;
47
53
  Logging;
48
54
  debugMode;
55
+ maxRetries;
56
+ delayBetweenRetries;
49
57
  platformConfig;
50
58
  platformLogging;
51
59
  config;
@@ -85,7 +93,6 @@ export class SwitchBotPlatform {
85
93
  return;
86
94
  }
87
95
  // import fakegato-history module and EVE characteristics
88
- const { EveHomeKitTypes } = hbLib;
89
96
  this.fakegatoAPI = fakegato(api);
90
97
  this.eve = new EveHomeKitTypes(api);
91
98
  // When this event is fired it means Homebridge has restored all cached accessories from disk.
@@ -100,7 +107,6 @@ export class SwitchBotPlatform {
100
107
  await this.updateToken();
101
108
  }
102
109
  else if (this.config.credentials?.token && !this.config.credentials?.secret) {
103
- // eslint-disable-next-line no-useless-escape
104
110
  this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
105
111
  }
106
112
  else {
@@ -154,7 +160,7 @@ export class SwitchBotPlatform {
154
160
  const xurl = new URL(url);
155
161
  const port = Number(xurl.port);
156
162
  const path = xurl.pathname;
157
- this.webhookEventListener = http.createServer((request, response) => {
163
+ this.webhookEventListener = createServer((request, response) => {
158
164
  try {
159
165
  if (request.url === path && request.method === 'POST') {
160
166
  request.on('data', async (data) => {
@@ -193,7 +199,7 @@ export class SwitchBotPlatform {
193
199
  return;
194
200
  }
195
201
  try {
196
- const { body, statusCode } = await request('https://api.switch-bot.com/v1.1/webhook/setupWebhook', {
202
+ const { body, statusCode } = await request(setupWebhook, {
197
203
  method: 'POST',
198
204
  headers: this.generateHeaders(),
199
205
  body: JSON.stringify({
@@ -215,10 +221,8 @@ export class SwitchBotPlatform {
215
221
  this.errorLog(`Failed to configure webhook. Error: ${e.message}`);
216
222
  }
217
223
  try {
218
- const { body, statusCode } = await request('https://api.switch-bot.com/v1.1/webhook/updateWebhook', {
219
- method: 'POST',
220
- headers: this.generateHeaders(),
221
- body: JSON.stringify({
224
+ const { body, statusCode } = await request(updateWebhook, {
225
+ method: 'POST', headers: this.generateHeaders(), body: JSON.stringify({
222
226
  'action': 'updateWebhook',
223
227
  'config': {
224
228
  'url': url,
@@ -238,7 +242,7 @@ export class SwitchBotPlatform {
238
242
  this.errorLog(`Failed to update webhook. Error:${e.message}`);
239
243
  }
240
244
  try {
241
- const { body, statusCode } = await request('https://api.switch-bot.com/v1.1/webhook/queryWebhook', {
245
+ const { body, statusCode } = await request(queryWebhook, {
242
246
  method: 'POST',
243
247
  headers: this.generateHeaders(),
244
248
  body: JSON.stringify({
@@ -260,7 +264,7 @@ export class SwitchBotPlatform {
260
264
  }
261
265
  this.api.on('shutdown', async () => {
262
266
  try {
263
- const { body, statusCode } = await request('https://api.switch-bot.com/v1.1/webhook/deleteWebhook', {
267
+ const { body, statusCode } = await request(deleteWebhook, {
264
268
  method: 'POST',
265
269
  headers: this.generateHeaders(),
266
270
  body: JSON.stringify({
@@ -355,6 +359,21 @@ export class SwitchBotPlatform {
355
359
  this.config.options.pushRate = 0.1;
356
360
  this.debugWarnLog('Using Default Push Rate.');
357
361
  }
362
+ if (!this.config.options.maxRetries) {
363
+ this.config.options.maxRetries = 5;
364
+ this.debugWarnLog('Using Default Max Retries.');
365
+ }
366
+ else {
367
+ this.maxRetries = this.config.options.maxRetries;
368
+ }
369
+ if (!this.config.options.delayBetweenRetries) {
370
+ // default 3 seconds
371
+ this.config.options.delayBetweenRetries = 3000;
372
+ this.debugWarnLog('Using Default Delay Between Retries.');
373
+ }
374
+ else {
375
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
376
+ }
358
377
  if (!this.config.credentials && !this.config.options) {
359
378
  this.debugWarnLog('Missing Credentials');
360
379
  }
@@ -399,13 +418,11 @@ export class SwitchBotPlatform {
399
418
  }
400
419
  // Move openToken to token
401
420
  if (!this.config.credentials.secret) {
402
- // eslint-disable-next-line no-useless-escape, max-len
403
- this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, "openToken" cconfig has been moved to the "token" config');
404
- // eslint-disable-next-line no-useless-escape
421
+ this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken,'
422
+ + ' "openToken" cconfig has been moved to the "token" config');
405
423
  this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
406
424
  }
407
425
  else {
408
- // eslint-disable-next-line no-useless-escape, max-len
409
426
  this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, '
410
427
  + '"openToken" config has been moved to the "token" config, please restart Homebridge.');
411
428
  }
@@ -451,114 +468,129 @@ export class SwitchBotPlatform {
451
468
  */
452
469
  async discoverDevices() {
453
470
  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)}`);
471
+ let retryCount = 0;
472
+ const maxRetries = this.maxRetries; // Maximum number of retries
473
+ const delayBetweenRetries = this.delayBetweenRetries; // Delay between retries in milliseconds
474
+ this.debugWarnLog(`Retry Count: ${retryCount}`);
475
+ this.debugWarnLog(`Max Retries: ${maxRetries}`);
476
+ this.debugWarnLog(`Delay Between Retries: ${delayBetweenRetries}`);
477
+ while (retryCount < maxRetries) {
478
+ try {
479
+ const { body, statusCode } = await request(Devices, {
480
+ headers: this.generateHeaders(),
481
+ });
482
+ this.debugWarnLog(`statusCode: ${statusCode}`);
483
+ const devicesAPI = await body.json();
484
+ this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
485
+ this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
486
+ this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
487
+ if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
488
+ this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
489
+ // SwitchBot Devices
490
+ const deviceLists = devicesAPI.body.deviceList;
491
+ this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
492
+ this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
493
+ if (!this.config.options?.devices) {
494
+ this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
495
+ if (deviceLists.length === 0) {
496
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
497
+ }
498
+ else {
499
+ const devices = deviceLists.map((v) => v);
500
+ for (const device of devices) {
501
+ if (device.deviceType) {
502
+ if (device.configDeviceName) {
503
+ device.deviceName = device.configDeviceName;
504
+ }
505
+ this.createDevice(device);
506
+ }
507
+ }
508
+ }
473
509
  }
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;
510
+ else if (this.config.credentials?.token && this.config.options.devices) {
511
+ this.debugLog(`SwitchBot Device Config 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
+ }
515
+ else {
516
+ const deviceConfigs = this.config.options?.devices;
517
+ const mergeBydeviceId = (a1, a2) => a1.map((itm) => ({
518
+ ...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
519
+ ...itm,
520
+ }));
521
+ const devices = mergeBydeviceId(deviceLists, deviceConfigs);
522
+ this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
523
+ for (const device of devices) {
524
+ if (!device.deviceType) {
525
+ device.deviceType = device.configDeviceType;
526
+ this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
527
+ }
528
+ if (device.deviceType) {
529
+ if (device.configDeviceName) {
530
+ device.deviceName = device.configDeviceName;
531
+ }
532
+ this.createDevice(device);
480
533
  }
481
- this.createDevice(device);
482
534
  }
483
535
  }
484
536
  }
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)}`);
537
+ else {
538
+ this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
539
+ }
540
+ if (devicesAPI.body.deviceList.length !== 0) {
541
+ this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
490
542
  }
491
543
  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)}`);
544
+ this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
545
+ }
546
+ // IR Devices
547
+ const irDeviceLists = devicesAPI.body.infraredRemoteList;
548
+ if (!this.config.options?.irdevices) {
549
+ this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
550
+ const devices = irDeviceLists.map((v) => v);
499
551
  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);
552
+ if (device.remoteType) {
553
+ this.createIRDevice(device);
509
554
  }
510
555
  }
511
556
  }
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) {
557
+ else {
558
+ this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
559
+ const irDeviceConfig = this.config.options?.irdevices;
560
+ const mergeIRBydeviceId = (a1, a2) => a1.map((itm) => ({
561
+ ...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
562
+ ...itm,
563
+ }));
564
+ const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
565
+ this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
566
+ for (const device of devices) {
529
567
  this.createIRDevice(device);
530
568
  }
531
569
  }
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);
570
+ if (devicesAPI.body.infraredRemoteList.length !== 0) {
571
+ this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
544
572
  }
545
- }
546
- if (devicesAPI.body.infraredRemoteList.length !== 0) {
547
- this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
573
+ else {
574
+ this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
575
+ }
576
+ break;
548
577
  }
549
578
  else {
550
- this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
579
+ this.statusCode(statusCode);
580
+ this.statusCode(devicesAPI.statusCode);
581
+ if (statusCode === 500) {
582
+ retryCount++;
583
+ this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
584
+ await sleep(delayBetweenRetries);
585
+ }
551
586
  }
552
587
  }
553
- else {
554
- this.statusCode(statusCode);
555
- this.statusCode(devicesAPI.statusCode);
588
+ catch (e) {
589
+ retryCount++;
590
+ this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
591
+ this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
556
592
  }
557
593
  }
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
594
  }
563
595
  else if (!this.config.credentials?.token && this.config.options?.devices) {
564
596
  this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
@@ -650,6 +682,7 @@ export class SwitchBotPlatform {
650
682
  case 'WoSweeperMini':
651
683
  case 'Robot Vacuum Cleaner S1':
652
684
  case 'Robot Vacuum Cleaner S1 Plus':
685
+ case 'Robot Vacuum Cleaner S10':
653
686
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
654
687
  this.createRobotVacuumCleaner(device);
655
688
  break;
@@ -667,12 +700,15 @@ export class SwitchBotPlatform {
667
700
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
668
701
  break;
669
702
  case 'Remote':
703
+ case 'remote with screen+':
670
704
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
671
705
  break;
706
+ case 'Battery Circulator Fan':
707
+ this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
708
+ this.createFan(device);
709
+ break;
672
710
  default:
673
- this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
674
- // eslint-disable-next-line max-len
675
- this.warnLog('Submit Feature Requests Here: ' + 'https://tinyurl.com/SwitchBotFeatureRequest');
711
+ this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`, +'Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest');
676
712
  }
677
713
  }
678
714
  createIRDevice(device) {
@@ -704,7 +740,7 @@ export class SwitchBotPlatform {
704
740
  case 'Fan':
705
741
  case 'DIY Fan':
706
742
  this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
707
- this.createFan(device);
743
+ this.createIRFan(device);
708
744
  break;
709
745
  case 'Air Conditioner':
710
746
  case 'DIY Air Conditioner':
@@ -759,7 +795,7 @@ export class SwitchBotPlatform {
759
795
  existingAccessory.context.deviceID = device.deviceId;
760
796
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
761
797
  if (device.firmware) {
762
- existingAccessory.context.FirmwareRevision = device.firmware;
798
+ existingAccessory.context.version = device.firmware;
763
799
  }
764
800
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
765
801
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -787,7 +823,7 @@ export class SwitchBotPlatform {
787
823
  accessory.context.model = device.deviceType;
788
824
  accessory.context.deviceID = device.deviceId;
789
825
  if (device.firmware) {
790
- accessory.context.FirmwareRevision = device.firmware;
826
+ accessory.context.version = device.firmware;
791
827
  }
792
828
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
793
829
  accessory.context.connectionType = await this.connectionType(device);
@@ -816,7 +852,7 @@ export class SwitchBotPlatform {
816
852
  existingAccessory.context.deviceID = device.deviceId;
817
853
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
818
854
  if (device.firmware) {
819
- existingAccessory.context.FirmwareRevision = device.firmware;
855
+ existingAccessory.context.version = device.firmware;
820
856
  }
821
857
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
822
858
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -844,11 +880,11 @@ export class SwitchBotPlatform {
844
880
  accessory.context.model = device.deviceType;
845
881
  accessory.context.deviceID = device.deviceId;
846
882
  if (device.firmware) {
847
- accessory.context.FirmwareRevision = device.firmware;
883
+ accessory.context.version = device.firmware;
848
884
  }
849
885
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
850
886
  accessory.context.connectionType = await this.connectionType(device);
851
- // accessory.context.FirmwareRevision = findaccessories.accessoryAttribute.softwareRevision;
887
+ // accessory.context.version = findaccessories.accessoryAttribute.softwareRevision;
852
888
  // create the accessory handler for the newly create accessory
853
889
  // this is imported from `platformAccessory.ts`
854
890
  new Bot(this, accessory, device);
@@ -874,7 +910,7 @@ export class SwitchBotPlatform {
874
910
  existingAccessory.context.deviceID = device.deviceId;
875
911
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
876
912
  if (device.firmware) {
877
- existingAccessory.context.FirmwareRevision = device.firmware;
913
+ existingAccessory.context.version = device.firmware;
878
914
  }
879
915
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
880
916
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -902,7 +938,7 @@ export class SwitchBotPlatform {
902
938
  accessory.context.model = device.deviceType;
903
939
  accessory.context.deviceID = device.deviceId;
904
940
  if (device.firmware) {
905
- accessory.context.FirmwareRevision = device.firmware;
941
+ accessory.context.version = device.firmware;
906
942
  }
907
943
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
908
944
  accessory.context.connectionType = await this.connectionType(device);
@@ -932,7 +968,7 @@ export class SwitchBotPlatform {
932
968
  existingAccessory.context.deviceID = device.deviceId;
933
969
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
934
970
  if (device.firmware) {
935
- existingAccessory.context.FirmwareRevision = device.firmware;
971
+ existingAccessory.context.version = device.firmware;
936
972
  }
937
973
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
938
974
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -960,7 +996,7 @@ export class SwitchBotPlatform {
960
996
  accessory.context.model = device.deviceType;
961
997
  accessory.context.deviceID = device.deviceId;
962
998
  if (device.firmware) {
963
- accessory.context.FirmwareRevision = device.firmware;
999
+ accessory.context.version = device.firmware;
964
1000
  }
965
1001
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
966
1002
  accessory.context.connectionType = await this.connectionType(device);
@@ -990,7 +1026,7 @@ export class SwitchBotPlatform {
990
1026
  existingAccessory.context.deviceID = device.deviceId;
991
1027
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
992
1028
  if (device.firmware) {
993
- existingAccessory.context.FirmwareRevision = device.firmware;
1029
+ existingAccessory.context.version = device.firmware;
994
1030
  }
995
1031
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
996
1032
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1018,7 +1054,7 @@ export class SwitchBotPlatform {
1018
1054
  accessory.context.model = device.deviceType;
1019
1055
  accessory.context.deviceID = device.deviceId;
1020
1056
  if (device.firmware) {
1021
- accessory.context.FirmwareRevision = device.firmware;
1057
+ accessory.context.version = device.firmware;
1022
1058
  }
1023
1059
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1024
1060
  accessory.context.connectionType = await this.connectionType(device);
@@ -1047,7 +1083,7 @@ export class SwitchBotPlatform {
1047
1083
  existingAccessory.context.deviceID = device.deviceId;
1048
1084
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1049
1085
  if (device.firmware) {
1050
- existingAccessory.context.FirmwareRevision = device.firmware;
1086
+ existingAccessory.context.version = device.firmware;
1051
1087
  }
1052
1088
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1053
1089
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1075,7 +1111,7 @@ export class SwitchBotPlatform {
1075
1111
  accessory.context.model = device.deviceType;
1076
1112
  accessory.context.deviceID = device.deviceId;
1077
1113
  if (device.firmware) {
1078
- accessory.context.FirmwareRevision = device.firmware;
1114
+ accessory.context.version = device.firmware;
1079
1115
  }
1080
1116
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1081
1117
  accessory.context.connectionType = await this.connectionType(device);
@@ -1104,7 +1140,7 @@ export class SwitchBotPlatform {
1104
1140
  existingAccessory.context.deviceID = device.deviceId;
1105
1141
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1106
1142
  if (device.firmware) {
1107
- existingAccessory.context.FirmwareRevision = device.firmware;
1143
+ existingAccessory.context.version = device.firmware;
1108
1144
  }
1109
1145
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1110
1146
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1132,7 +1168,7 @@ export class SwitchBotPlatform {
1132
1168
  accessory.context.model = device.deviceType;
1133
1169
  accessory.context.deviceID = device.deviceId;
1134
1170
  if (device.firmware) {
1135
- accessory.context.FirmwareRevision = device.firmware;
1171
+ accessory.context.version = device.firmware;
1136
1172
  }
1137
1173
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1138
1174
  accessory.context.connectionType = await this.connectionType(device);
@@ -1161,7 +1197,7 @@ export class SwitchBotPlatform {
1161
1197
  existingAccessory.context.deviceID = device.deviceId;
1162
1198
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1163
1199
  if (device.firmware) {
1164
- existingAccessory.context.FirmwareRevision = device.firmware;
1200
+ existingAccessory.context.version = device.firmware;
1165
1201
  }
1166
1202
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1167
1203
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1189,7 +1225,7 @@ export class SwitchBotPlatform {
1189
1225
  accessory.context.model = device.deviceType;
1190
1226
  accessory.context.deviceID = device.deviceId;
1191
1227
  if (device.firmware) {
1192
- accessory.context.FirmwareRevision = device.firmware;
1228
+ accessory.context.version = device.firmware;
1193
1229
  }
1194
1230
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1195
1231
  accessory.context.connectionType = await this.connectionType(device);
@@ -1218,7 +1254,7 @@ export class SwitchBotPlatform {
1218
1254
  existingAccessory.context.deviceID = device.deviceId;
1219
1255
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1220
1256
  if (device.firmware) {
1221
- existingAccessory.context.FirmwareRevision = device.firmware;
1257
+ existingAccessory.context.version = device.firmware;
1222
1258
  }
1223
1259
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1224
1260
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1246,7 +1282,7 @@ export class SwitchBotPlatform {
1246
1282
  accessory.context.model = device.deviceType;
1247
1283
  accessory.context.deviceID = device.deviceId;
1248
1284
  if (device.firmware) {
1249
- accessory.context.FirmwareRevision = device.firmware;
1285
+ accessory.context.version = device.firmware;
1250
1286
  }
1251
1287
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1252
1288
  accessory.context.connectionType = await this.connectionType(device);
@@ -1275,7 +1311,7 @@ export class SwitchBotPlatform {
1275
1311
  existingAccessory.context.deviceID = device.deviceId;
1276
1312
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1277
1313
  if (device.firmware) {
1278
- existingAccessory.context.FirmwareRevision = device.firmware;
1314
+ existingAccessory.context.version = device.firmware;
1279
1315
  }
1280
1316
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1281
1317
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1315,7 +1351,7 @@ export class SwitchBotPlatform {
1315
1351
  accessory.context.model = device.deviceType;
1316
1352
  accessory.context.deviceID = device.deviceId;
1317
1353
  if (device.firmware) {
1318
- accessory.context.FirmwareRevision = device.firmware;
1354
+ accessory.context.version = device.firmware;
1319
1355
  }
1320
1356
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1321
1357
  accessory.context.connectionType = await this.connectionType(device);
@@ -1344,7 +1380,7 @@ export class SwitchBotPlatform {
1344
1380
  existingAccessory.context.deviceID = device.deviceId;
1345
1381
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1346
1382
  if (device.firmware) {
1347
- existingAccessory.context.FirmwareRevision = device.firmware;
1383
+ existingAccessory.context.version = device.firmware;
1348
1384
  }
1349
1385
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1350
1386
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1384,7 +1420,7 @@ export class SwitchBotPlatform {
1384
1420
  accessory.context.model = device.deviceType;
1385
1421
  accessory.context.deviceID = device.deviceId;
1386
1422
  if (device.firmware) {
1387
- accessory.context.FirmwareRevision = device.firmware;
1423
+ accessory.context.version = device.firmware;
1388
1424
  }
1389
1425
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1390
1426
  accessory.context.connectionType = await this.connectionType(device);
@@ -1413,7 +1449,7 @@ export class SwitchBotPlatform {
1413
1449
  existingAccessory.context.deviceID = device.deviceId;
1414
1450
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1415
1451
  if (device.firmware) {
1416
- existingAccessory.context.FirmwareRevision = device.firmware;
1452
+ existingAccessory.context.version = device.firmware;
1417
1453
  }
1418
1454
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1419
1455
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1441,7 +1477,7 @@ export class SwitchBotPlatform {
1441
1477
  accessory.context.model = device.deviceType;
1442
1478
  accessory.context.deviceID = device.deviceId;
1443
1479
  if (device.firmware) {
1444
- accessory.context.FirmwareRevision = device.firmware;
1480
+ accessory.context.version = device.firmware;
1445
1481
  }
1446
1482
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1447
1483
  accessory.context.connectionType = await this.connectionType(device);
@@ -1470,7 +1506,7 @@ export class SwitchBotPlatform {
1470
1506
  existingAccessory.context.deviceID = device.deviceId;
1471
1507
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1472
1508
  if (device.firmware) {
1473
- existingAccessory.context.FirmwareRevision = device.firmware;
1509
+ existingAccessory.context.version = device.firmware;
1474
1510
  }
1475
1511
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1476
1512
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1498,7 +1534,7 @@ export class SwitchBotPlatform {
1498
1534
  accessory.context.model = device.deviceType;
1499
1535
  accessory.context.deviceID = device.deviceId;
1500
1536
  if (device.firmware) {
1501
- accessory.context.FirmwareRevision = device.firmware;
1537
+ accessory.context.version = device.firmware;
1502
1538
  }
1503
1539
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1504
1540
  accessory.context.connectionType = await this.connectionType(device);
@@ -1527,7 +1563,7 @@ export class SwitchBotPlatform {
1527
1563
  existingAccessory.context.deviceID = device.deviceId;
1528
1564
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1529
1565
  if (device.firmware) {
1530
- existingAccessory.context.FirmwareRevision = device.firmware;
1566
+ existingAccessory.context.version = device.firmware;
1531
1567
  }
1532
1568
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1533
1569
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1555,7 +1591,7 @@ export class SwitchBotPlatform {
1555
1591
  accessory.context.model = device.deviceType;
1556
1592
  accessory.context.deviceID = device.deviceId;
1557
1593
  if (device.firmware) {
1558
- accessory.context.FirmwareRevision = device.firmware;
1594
+ accessory.context.version = device.firmware;
1559
1595
  }
1560
1596
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1561
1597
  accessory.context.connectionType = await this.connectionType(device);
@@ -1584,7 +1620,7 @@ export class SwitchBotPlatform {
1584
1620
  existingAccessory.context.deviceID = device.deviceId;
1585
1621
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1586
1622
  if (device.firmware) {
1587
- existingAccessory.context.FirmwareRevision = device.firmware;
1623
+ existingAccessory.context.version = device.firmware;
1588
1624
  }
1589
1625
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1590
1626
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1612,7 +1648,7 @@ export class SwitchBotPlatform {
1612
1648
  accessory.context.model = device.deviceType;
1613
1649
  accessory.context.deviceID = device.deviceId;
1614
1650
  if (device.firmware) {
1615
- accessory.context.FirmwareRevision = device.firmware;
1651
+ accessory.context.version = device.firmware;
1616
1652
  }
1617
1653
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1618
1654
  accessory.context.connectionType = await this.connectionType(device);
@@ -1641,7 +1677,7 @@ export class SwitchBotPlatform {
1641
1677
  existingAccessory.context.deviceID = device.deviceId;
1642
1678
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1643
1679
  if (device.firmware) {
1644
- existingAccessory.context.FirmwareRevision = device.firmware;
1680
+ existingAccessory.context.version = device.firmware;
1645
1681
  }
1646
1682
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1647
1683
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1669,7 +1705,7 @@ export class SwitchBotPlatform {
1669
1705
  accessory.context.model = device.deviceType;
1670
1706
  accessory.context.deviceID = device.deviceId;
1671
1707
  if (device.firmware) {
1672
- accessory.context.FirmwareRevision = device.firmware;
1708
+ accessory.context.version = device.firmware;
1673
1709
  }
1674
1710
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1675
1711
  accessory.context.connectionType = await this.connectionType(device);
@@ -1685,6 +1721,63 @@ export class SwitchBotPlatform {
1685
1721
  this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1686
1722
  }
1687
1723
  }
1724
+ async createFan(device) {
1725
+ const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1726
+ // see if an accessory with the same uuid has already been registered and restored from
1727
+ // the cached devices we stored in the `configureAccessory` method above
1728
+ const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid);
1729
+ if (existingAccessory) {
1730
+ // the accessory already exists
1731
+ if (await this.registerDevice(device)) {
1732
+ // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1733
+ existingAccessory.context.model = device.deviceType;
1734
+ existingAccessory.context.deviceID = device.deviceId;
1735
+ existingAccessory.displayName = device.configDeviceName || device.deviceName;
1736
+ if (device.firmware) {
1737
+ existingAccessory.context.version = device.firmware;
1738
+ }
1739
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1740
+ this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1741
+ existingAccessory.context.connectionType = await this.connectionType(device);
1742
+ this.api.updatePlatformAccessories([existingAccessory]);
1743
+ // create the accessory handler for the restored accessory
1744
+ // this is imported from `platformAccessory.ts`
1745
+ new Fan(this, existingAccessory, device);
1746
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`);
1747
+ }
1748
+ else {
1749
+ this.unregisterPlatformAccessories(existingAccessory);
1750
+ }
1751
+ }
1752
+ else if (await this.registerDevice(device)) {
1753
+ // the accessory does not yet exist, so we need to create it
1754
+ if (!device.external) {
1755
+ this.infoLog(`Adding new accessory: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1756
+ }
1757
+ // create a new accessory
1758
+ const accessory = new this.api.platformAccessory(device.deviceName, uuid);
1759
+ // store a copy of the device object in the `accessory.context`
1760
+ // the `context` property can be used to store any data about the accessory you may need
1761
+ accessory.context.device = device;
1762
+ accessory.context.model = device.deviceType;
1763
+ accessory.context.deviceID = device.deviceId;
1764
+ if (device.firmware) {
1765
+ accessory.context.version = device.firmware;
1766
+ }
1767
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1768
+ accessory.context.connectionType = await this.connectionType(device);
1769
+ // create the accessory handler for the newly create accessory
1770
+ // this is imported from `platformAccessory.ts`
1771
+ new Fan(this, accessory, device);
1772
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`);
1773
+ // publish device externally or link the accessory to your platform
1774
+ this.externalOrPlatform(device, accessory);
1775
+ this.accessories.push(accessory);
1776
+ }
1777
+ else {
1778
+ this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1779
+ }
1780
+ }
1688
1781
  async createRobotVacuumCleaner(device) {
1689
1782
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1690
1783
  // see if an accessory with the same uuid has already been registered and restored from
@@ -1698,7 +1791,7 @@ export class SwitchBotPlatform {
1698
1791
  existingAccessory.context.deviceID = device.deviceId;
1699
1792
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1700
1793
  if (device.firmware) {
1701
- existingAccessory.context.FirmwareRevision = device.firmware;
1794
+ existingAccessory.context.version = device.firmware;
1702
1795
  }
1703
1796
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1704
1797
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1726,7 +1819,7 @@ export class SwitchBotPlatform {
1726
1819
  accessory.context.model = device.deviceType;
1727
1820
  accessory.context.deviceID = device.deviceId;
1728
1821
  if (device.firmware) {
1729
- accessory.context.FirmwareRevision = device.firmware;
1822
+ accessory.context.version = device.firmware;
1730
1823
  }
1731
1824
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1732
1825
  accessory.context.connectionType = await this.connectionType(device);
@@ -1752,7 +1845,9 @@ export class SwitchBotPlatform {
1752
1845
  existingAccessory.context.model = device.remoteType;
1753
1846
  existingAccessory.context.deviceID = device.deviceId;
1754
1847
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1755
- existingAccessory.context.FirmwareRevision = device.firmware;
1848
+ if (device.version && !device.firmware) {
1849
+ existingAccessory.context.version = device.version;
1850
+ }
1756
1851
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1757
1852
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1758
1853
  existingAccessory.context.connectionType = device.connectionType;
@@ -1775,7 +1870,7 @@ export class SwitchBotPlatform {
1775
1870
  accessory.context.model = device.remoteType;
1776
1871
  accessory.context.deviceID = device.deviceId;
1777
1872
  if (device.firmware) {
1778
- accessory.context.FirmwareRevision = device.firmware;
1873
+ accessory.context.version = device.firmware;
1779
1874
  }
1780
1875
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1781
1876
  accessory.context.connectionType = device.connectionType;
@@ -1790,7 +1885,7 @@ export class SwitchBotPlatform {
1790
1885
  this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} DeviceID: ${device.deviceId}`);
1791
1886
  }
1792
1887
  }
1793
- async createFan(device) {
1888
+ async createIRFan(device) {
1794
1889
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
1795
1890
  // see if an accessory with the same uuid has already been registered and restored from
1796
1891
  // the cached devices we stored in the `configureAccessory` method above
@@ -1803,7 +1898,7 @@ export class SwitchBotPlatform {
1803
1898
  existingAccessory.context.deviceID = device.deviceId;
1804
1899
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1805
1900
  if (device.firmware) {
1806
- existingAccessory.context.FirmwareRevision = device.firmware;
1901
+ existingAccessory.context.version = device.firmware;
1807
1902
  }
1808
1903
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1809
1904
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1811,7 +1906,7 @@ export class SwitchBotPlatform {
1811
1906
  this.api.updatePlatformAccessories([existingAccessory]);
1812
1907
  // create the accessory handler for the restored accessory
1813
1908
  // this is imported from `platformAccessory.ts`
1814
- new Fan(this, existingAccessory, device);
1909
+ new IRFan(this, existingAccessory, device);
1815
1910
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`);
1816
1911
  }
1817
1912
  else {
@@ -1831,13 +1926,13 @@ export class SwitchBotPlatform {
1831
1926
  accessory.context.model = device.remoteType;
1832
1927
  accessory.context.deviceID = device.deviceId;
1833
1928
  if (device.firmware) {
1834
- accessory.context.FirmwareRevision = device.firmware;
1929
+ accessory.context.version = device.firmware;
1835
1930
  }
1836
1931
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1837
1932
  accessory.context.connectionType = device.connectionType;
1838
1933
  // create the accessory handler for the newly create accessory
1839
1934
  // this is imported from `platformAccessory.ts`
1840
- new Fan(this, accessory, device);
1935
+ new IRFan(this, accessory, device);
1841
1936
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
1842
1937
  // publish device externally or link the accessory to your platform
1843
1938
  this.externalOrPlatformIR(device, accessory);
@@ -1860,7 +1955,7 @@ export class SwitchBotPlatform {
1860
1955
  existingAccessory.context.deviceID = device.deviceId;
1861
1956
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1862
1957
  if (device.firmware) {
1863
- existingAccessory.context.FirmwareRevision = device.firmware;
1958
+ existingAccessory.context.version = device.firmware;
1864
1959
  }
1865
1960
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1866
1961
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1888,7 +1983,7 @@ export class SwitchBotPlatform {
1888
1983
  accessory.context.model = device.remoteType;
1889
1984
  accessory.context.deviceID = device.deviceId;
1890
1985
  if (device.firmware) {
1891
- accessory.context.FirmwareRevision = device.firmware;
1986
+ accessory.context.version = device.firmware;
1892
1987
  }
1893
1988
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1894
1989
  accessory.context.connectionType = device.connectionType;
@@ -1917,7 +2012,7 @@ export class SwitchBotPlatform {
1917
2012
  existingAccessory.context.deviceID = device.deviceId;
1918
2013
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1919
2014
  if (device.firmware) {
1920
- existingAccessory.context.FirmwareRevision = device.firmware;
2015
+ existingAccessory.context.version = device.firmware;
1921
2016
  }
1922
2017
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1923
2018
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1945,7 +2040,7 @@ export class SwitchBotPlatform {
1945
2040
  accessory.context.model = device.remoteType;
1946
2041
  accessory.context.deviceID = device.deviceId;
1947
2042
  if (device.firmware) {
1948
- accessory.context.FirmwareRevision = device.firmware;
2043
+ accessory.context.version = device.firmware;
1949
2044
  }
1950
2045
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1951
2046
  accessory.context.connectionType = device.connectionType;
@@ -1974,7 +2069,7 @@ export class SwitchBotPlatform {
1974
2069
  existingAccessory.context.deviceID = device.deviceId;
1975
2070
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1976
2071
  if (device.firmware) {
1977
- existingAccessory.context.FirmwareRevision = device.firmware;
2072
+ existingAccessory.context.version = device.firmware;
1978
2073
  }
1979
2074
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1980
2075
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2002,7 +2097,7 @@ export class SwitchBotPlatform {
2002
2097
  accessory.context.model = device.remoteType;
2003
2098
  accessory.context.deviceID = device.deviceId;
2004
2099
  if (device.firmware) {
2005
- accessory.context.FirmwareRevision = device.firmware;
2100
+ accessory.context.version = device.firmware;
2006
2101
  }
2007
2102
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2008
2103
  accessory.context.connectionType = device.connectionType;
@@ -2031,7 +2126,7 @@ export class SwitchBotPlatform {
2031
2126
  existingAccessory.context.deviceID = device.deviceId;
2032
2127
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2033
2128
  if (device.firmware) {
2034
- existingAccessory.context.FirmwareRevision = device.firmware;
2129
+ existingAccessory.context.version = device.firmware;
2035
2130
  }
2036
2131
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2037
2132
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2059,7 +2154,7 @@ export class SwitchBotPlatform {
2059
2154
  accessory.context.model = device.remoteType;
2060
2155
  accessory.context.deviceID = device.deviceId;
2061
2156
  if (device.firmware) {
2062
- accessory.context.FirmwareRevision = device.firmware;
2157
+ accessory.context.version = device.firmware;
2063
2158
  }
2064
2159
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2065
2160
  accessory.context.connectionType = device.connectionType;
@@ -2088,7 +2183,7 @@ export class SwitchBotPlatform {
2088
2183
  existingAccessory.context.deviceID = device.deviceId;
2089
2184
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2090
2185
  if (device.firmware) {
2091
- existingAccessory.context.FirmwareRevision = device.firmware;
2186
+ existingAccessory.context.version = device.firmware;
2092
2187
  }
2093
2188
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2094
2189
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2116,7 +2211,7 @@ export class SwitchBotPlatform {
2116
2211
  accessory.context.model = device.remoteType;
2117
2212
  accessory.context.deviceID = device.deviceId;
2118
2213
  if (device.firmware) {
2119
- accessory.context.FirmwareRevision = device.firmware;
2214
+ accessory.context.version = device.firmware;
2120
2215
  }
2121
2216
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2122
2217
  accessory.context.connectionType = device.connectionType;
@@ -2145,7 +2240,7 @@ export class SwitchBotPlatform {
2145
2240
  existingAccessory.context.deviceID = device.deviceId;
2146
2241
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2147
2242
  if (device.firmware) {
2148
- existingAccessory.context.FirmwareRevision = device.firmware;
2243
+ existingAccessory.context.version = device.firmware;
2149
2244
  }
2150
2245
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2151
2246
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2173,7 +2268,7 @@ export class SwitchBotPlatform {
2173
2268
  accessory.context.model = device.remoteType;
2174
2269
  accessory.context.deviceID = device.deviceId;
2175
2270
  if (device.firmware) {
2176
- accessory.context.FirmwareRevision = device.firmware;
2271
+ accessory.context.version = device.firmware;
2177
2272
  }
2178
2273
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2179
2274
  accessory.context.connectionType = device.connectionType;
@@ -2202,7 +2297,7 @@ export class SwitchBotPlatform {
2202
2297
  existingAccessory.context.deviceID = device.deviceId;
2203
2298
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2204
2299
  if (device.firmware) {
2205
- existingAccessory.context.FirmwareRevision = device.firmware;
2300
+ existingAccessory.context.version = device.firmware;
2206
2301
  }
2207
2302
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2208
2303
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2230,7 +2325,7 @@ export class SwitchBotPlatform {
2230
2325
  accessory.context.model = device.remoteType;
2231
2326
  accessory.context.deviceID = device.deviceId;
2232
2327
  if (device.firmware) {
2233
- accessory.context.FirmwareRevision = device.firmware;
2328
+ accessory.context.version = device.firmware;
2234
2329
  }
2235
2330
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2236
2331
  accessory.context.connectionType = device.connectionType;
@@ -2492,6 +2587,29 @@ export class SwitchBotPlatform {
2492
2587
  this.errorLog(`Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
2493
2588
  }
2494
2589
  }
2590
+ async retryRequest(deviceMaxRetries, deviceDelayBetweenRetries, url, options) {
2591
+ let retryCount = 0;
2592
+ const maxRetries = deviceMaxRetries;
2593
+ const delayBetweenRetries = deviceDelayBetweenRetries;
2594
+ while (retryCount < maxRetries) {
2595
+ try {
2596
+ const { body, statusCode } = await request(url, options);
2597
+ if (statusCode === 200 || statusCode === 100) {
2598
+ return { body, statusCode };
2599
+ }
2600
+ else {
2601
+ this.debugLog(`Received status code: ${statusCode}`);
2602
+ }
2603
+ }
2604
+ catch (error) {
2605
+ this.errorLog(`Error making request: ${error.message}`);
2606
+ }
2607
+ retryCount++;
2608
+ this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
2609
+ await sleep(delayBetweenRetries);
2610
+ }
2611
+ return { body: null, statusCode: -1 };
2612
+ }
2495
2613
  // BLE Connection
2496
2614
  async connectBLE() {
2497
2615
  let switchbot;
@@ -2522,6 +2640,24 @@ export class SwitchBotPlatform {
2522
2640
  if (this.config.options.pushRate) {
2523
2641
  platformConfig.pushRate = this.config.options.pushRate;
2524
2642
  }
2643
+ if (this.config.options.maxRetries) {
2644
+ this.maxRetries = this.config.options.maxRetries;
2645
+ platformConfig.maxRetries = this.config.options.maxRetries;
2646
+ }
2647
+ else {
2648
+ this.maxRetries = 3;
2649
+ this.debugWarnLog('Using Default Max Retries');
2650
+ platformConfig.maxRetries = this.maxRetries;
2651
+ }
2652
+ if (this.config.options.delayBetweenRetries) {
2653
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
2654
+ platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries;
2655
+ }
2656
+ else {
2657
+ this.delayBetweenRetries = 3000;
2658
+ this.debugWarnLog('Using Default Delay Between Retries');
2659
+ platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
2660
+ }
2525
2661
  if (Object.entries(platformConfig).length !== 0) {
2526
2662
  this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
2527
2663
  }
@@ -2547,6 +2683,11 @@ export class SwitchBotPlatform {
2547
2683
  * If device level logging is turned on, log to log.warn
2548
2684
  * Otherwise send debug logs to log.debug
2549
2685
  */
2686
+ successLog(...log) {
2687
+ if (this.enablingPlatformLogging()) {
2688
+ this.log.success(String(...log));
2689
+ }
2690
+ }
2550
2691
  infoLog(...log) {
2551
2692
  if (this.enablingPlatformLogging()) {
2552
2693
  this.log.info(String(...log));