@switchbot/homebridge-switchbot 3.5.0-beta.8 → 3.5.0

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 (178) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +4 -1
  3. package/config.schema.json +170 -26
  4. package/dist/device/blindtilt.d.ts +21 -96
  5. package/dist/device/blindtilt.d.ts.map +1 -1
  6. package/dist/device/blindtilt.js +439 -817
  7. package/dist/device/blindtilt.js.map +1 -1
  8. package/dist/device/bot.d.ts +27 -72
  9. package/dist/device/bot.d.ts.map +1 -1
  10. package/dist/device/bot.js +835 -865
  11. package/dist/device/bot.js.map +1 -1
  12. package/dist/device/ceilinglight.d.ts +15 -69
  13. package/dist/device/ceilinglight.d.ts.map +1 -1
  14. package/dist/device/ceilinglight.js +287 -653
  15. package/dist/device/ceilinglight.js.map +1 -1
  16. package/dist/device/colorbulb.d.ts +15 -76
  17. package/dist/device/colorbulb.d.ts.map +1 -1
  18. package/dist/device/colorbulb.js +354 -732
  19. package/dist/device/colorbulb.js.map +1 -1
  20. package/dist/device/contact.d.ts +14 -66
  21. package/dist/device/contact.d.ts.map +1 -1
  22. package/dist/device/contact.js +268 -576
  23. package/dist/device/contact.js.map +1 -1
  24. package/dist/device/curtain.d.ts +18 -89
  25. package/dist/device/curtain.d.ts.map +1 -1
  26. package/dist/device/curtain.js +431 -851
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/device.d.ts +60 -0
  29. package/dist/device/device.d.ts.map +1 -0
  30. package/dist/device/device.js +739 -0
  31. package/dist/device/device.js.map +1 -0
  32. package/dist/device/fan.d.ts +63 -0
  33. package/dist/device/fan.d.ts.map +1 -0
  34. package/dist/device/fan.js +698 -0
  35. package/dist/device/fan.js.map +1 -0
  36. package/dist/device/hub.d.ts +15 -60
  37. package/dist/device/hub.d.ts.map +1 -1
  38. package/dist/device/hub.js +257 -631
  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 +266 -629
  43. package/dist/device/humidifier.js.map +1 -1
  44. package/dist/device/iosensor.d.ts +12 -64
  45. package/dist/device/iosensor.d.ts.map +1 -1
  46. package/dist/device/iosensor.js +215 -615
  47. package/dist/device/iosensor.js.map +1 -1
  48. package/dist/device/lightstrip.d.ts +12 -70
  49. package/dist/device/lightstrip.d.ts.map +1 -1
  50. package/dist/device/lightstrip.js +336 -645
  51. package/dist/device/lightstrip.js.map +1 -1
  52. package/dist/device/lock.d.ts +17 -63
  53. package/dist/device/lock.d.ts.map +1 -1
  54. package/dist/device/lock.js +290 -595
  55. package/dist/device/lock.js.map +1 -1
  56. package/dist/device/meter.d.ts +15 -64
  57. package/dist/device/meter.d.ts.map +1 -1
  58. package/dist/device/meter.js +211 -608
  59. package/dist/device/meter.js.map +1 -1
  60. package/dist/device/meterplus.d.ts +15 -65
  61. package/dist/device/meterplus.d.ts.map +1 -1
  62. package/dist/device/meterplus.js +205 -615
  63. package/dist/device/meterplus.js.map +1 -1
  64. package/dist/device/motion.d.ts +12 -69
  65. package/dist/device/motion.d.ts.map +1 -1
  66. package/dist/device/motion.js +202 -563
  67. package/dist/device/motion.js.map +1 -1
  68. package/dist/device/plug.d.ts +10 -57
  69. package/dist/device/plug.d.ts.map +1 -1
  70. package/dist/device/plug.js +125 -484
  71. package/dist/device/plug.js.map +1 -1
  72. package/dist/device/robotvacuumcleaner.d.ts +13 -63
  73. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  74. package/dist/device/robotvacuumcleaner.js +233 -549
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +11 -63
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +170 -493
  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 +10 -50
  88. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  89. package/dist/irdevice/airconditioner.js +340 -468
  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 +105 -319
  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 +44 -285
  98. package/dist/irdevice/camera.js.map +1 -1
  99. package/dist/irdevice/fan.d.ts +7 -43
  100. package/dist/irdevice/fan.d.ts.map +1 -1
  101. package/dist/irdevice/fan.js +92 -350
  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 +369 -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 +118 -362
  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 +438 -570
  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 +91 -339
  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 +45 -285
  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 +47 -291
  126. package/dist/irdevice/waterheater.js.map +1 -1
  127. package/dist/platform.d.ts +22 -8
  128. package/dist/platform.d.ts.map +1 -1
  129. package/dist/platform.js +342 -191
  130. package/dist/platform.js.map +1 -1
  131. package/dist/settings.d.ts +64 -17
  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 +20 -16
  141. package/src/custom.d.ts +2 -1
  142. package/src/device/blindtilt.ts +472 -888
  143. package/src/device/bot.ts +893 -968
  144. package/src/device/ceilinglight.ts +304 -709
  145. package/src/device/colorbulb.ts +370 -803
  146. package/src/device/contact.ts +301 -611
  147. package/src/device/curtain.ts +460 -908
  148. package/src/device/device.ts +755 -0
  149. package/src/device/fan.ts +749 -0
  150. package/src/device/hub.ts +294 -664
  151. package/src/device/humidifier.ts +299 -696
  152. package/src/device/iosensor.ts +251 -644
  153. package/src/device/lightstrip.ts +362 -712
  154. package/src/device/lock.ts +328 -653
  155. package/src/device/meter.ts +247 -637
  156. package/src/device/meterplus.ts +240 -644
  157. package/src/device/motion.ts +230 -598
  158. package/src/device/plug.ts +139 -525
  159. package/src/device/robotvacuumcleaner.ts +258 -593
  160. package/src/device/waterdetector.ts +191 -522
  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 +370 -527
  165. package/src/irdevice/airpurifier.ts +132 -356
  166. package/src/irdevice/camera.ts +58 -311
  167. package/src/irdevice/fan.ts +109 -379
  168. package/src/irdevice/irdevice.ts +382 -0
  169. package/src/irdevice/light.ts +157 -412
  170. package/src/irdevice/other.ts +507 -648
  171. package/src/irdevice/tv.ts +121 -375
  172. package/src/irdevice/vacuumcleaner.ts +59 -311
  173. package/src/irdevice/waterheater.ts +61 -320
  174. package/src/platform.ts +395 -259
  175. package/src/settings.ts +118 -609
  176. package/src/utils.ts +642 -1
  177. package/.github/npm-version-script.cjs +0 -81
  178. package/src/device/waterdetector.json +0 -11
package/src/platform.ts CHANGED
@@ -1,27 +1,27 @@
1
- /* Copyright(C) 2017-2023, donavanbecker (https://github.com/donavanbecker). All rights reserved.
1
+ /* Copyright(C) 2017-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
2
  *
3
3
  * platform.ts: @switchbot/homebridge-switchbot platform class.
4
4
  */
5
- import { API, DynamicPlatformPlugin, Logging, PlatformAccessory } from 'homebridge';
6
- import { PLATFORM_NAME, PLUGIN_NAME, irdevice, device, SwitchBotPlatformConfig, devicesConfig, irDevicesConfig, Devices } from './settings.js';
5
+ import { Hub } from './device/hub.js';
7
6
  import { Bot } from './device/bot.js';
8
7
  import { Plug } from './device/plug.js';
9
8
  import { Lock } from './device/lock.js';
10
9
  import { Meter } from './device/meter.js';
11
10
  import { Motion } from './device/motion.js';
12
- import { Hub } from './device/hub.js';
13
11
  import { Contact } from './device/contact.js';
14
12
  import { Curtain } from './device/curtain.js';
15
13
  import { IOSensor } from './device/iosensor.js';
16
- import { WaterDetector } from './device/waterdetector.js';
17
14
  import { MeterPlus } from './device/meterplus.js';
18
15
  import { ColorBulb } from './device/colorbulb.js';
19
- import { CeilingLight } from './device/ceilinglight.js';
20
16
  import { StripLight } from './device/lightstrip.js';
21
17
  import { Humidifier } from './device/humidifier.js';
18
+ import { CeilingLight } from './device/ceilinglight.js';
19
+ import { WaterDetector } from './device/waterdetector.js';
22
20
  import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js';
21
+
22
+ import { Fan } from './device/fan.js';
23
23
  import { TV } from './irdevice/tv.js';
24
- import { Fan } from './irdevice/fan.js';
24
+ import { IRFan } from './irdevice/fan.js';
25
25
  import { Light } from './irdevice/light.js';
26
26
  import { Others } from './irdevice/other.js';
27
27
  import { Camera } from './irdevice/camera.js';
@@ -30,18 +30,25 @@ import { AirPurifier } from './irdevice/airpurifier.js';
30
30
  import { WaterHeater } from './irdevice/waterheater.js';
31
31
  import { VacuumCleaner } from './irdevice/vacuumcleaner.js';
32
32
  import { AirConditioner } from './irdevice/airconditioner.js';
33
- import * as http from 'http';
33
+
34
34
  import { Buffer } from 'buffer';
35
35
  import { request } from 'undici';
36
- import { MqttClient } from 'mqtt';
36
+ import asyncmqtt from 'async-mqtt';
37
+ import { sleep } from './utils.js';
38
+ import { createServer } from 'http';
37
39
  import { queueScheduler } from 'rxjs';
38
40
  import fakegato from 'fakegato-history';
39
- import asyncmqtt from 'async-mqtt';
40
41
  import crypto, { randomUUID } from 'crypto';
41
42
  import { readFileSync, writeFileSync } from 'fs';
42
- import hbLib from 'homebridge-lib';
43
-
43
+ import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes';
44
+ import { PLATFORM_NAME, PLUGIN_NAME, Devices, setupWebhook, updateWebhook, deleteWebhook, queryWebhook } from './settings.js';
44
45
 
46
+ import type { UrlObject } from 'url';
47
+ import type { MqttClient } from 'mqtt';
48
+ import type { Dispatcher } from 'undici';
49
+ import type { Server, IncomingMessage, ServerResponse } from 'http';
50
+ import type { API, DynamicPlatformPlugin, Logging, PlatformAccessory } from 'homebridge';
51
+ import type { irdevice, device, SwitchBotPlatformConfig, devicesConfig, irDevicesConfig } from './settings.js';
45
52
 
46
53
  /**
47
54
  * HomebridgePlatform
@@ -56,11 +63,13 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
56
63
  version!: string;
57
64
  Logging?: string;
58
65
  debugMode!: boolean;
66
+ maxRetries!: number;
67
+ delayBetweenRetries!: number;
59
68
  platformConfig!: SwitchBotPlatformConfig['options'];
60
69
  platformLogging!: SwitchBotPlatformConfig['logging'];
61
70
  config!: SwitchBotPlatformConfig;
62
71
 
63
- webhookEventListener: http.Server | null = null;
72
+ webhookEventListener: Server | null = null;
64
73
  mqttClient: MqttClient | null = null;
65
74
 
66
75
  public readonly fakegatoAPI: any;
@@ -72,9 +81,11 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
72
81
  config: SwitchBotPlatformConfig,
73
82
  api: API,
74
83
  ) {
84
+ // initialize
75
85
  this.accessories = [];
76
86
  this.api = api;
77
87
  this.log = log;
88
+
78
89
  // only load if configured
79
90
  if (!config) {
80
91
  return;
@@ -87,10 +98,13 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
87
98
  credentials: config.credentials as object,
88
99
  options: config.options as object,
89
100
  };
90
- this.platformLogging = this.config.options?.logging ?? 'standard';
91
- this.platformConfigOptions();
92
- this.platformLogs();
101
+
102
+ // Plugin Configuration
103
+ this.getPlatformConfigSettings();
104
+ this.getPlatformLogSettings();
93
105
  this.getVersion();
106
+
107
+ // Finish initializing the platform
94
108
  this.debugLog(`Finished initializing platform: ${config.name}`);
95
109
 
96
110
  // verify the config
@@ -104,7 +118,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
104
118
  }
105
119
 
106
120
  // import fakegato-history module and EVE characteristics
107
- const { EveHomeKitTypes } = hbLib;
108
121
  this.fakegatoAPI = fakegato(api);
109
122
  this.eve = new EveHomeKitTypes(api);
110
123
 
@@ -119,7 +132,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
119
132
  if (this.config.credentials?.openToken && !this.config.credentials.token) {
120
133
  await this.updateToken();
121
134
  } else if (this.config.credentials?.token && !this.config.credentials?.secret) {
122
- // eslint-disable-next-line no-useless-escape
135
+
123
136
  this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
124
137
  } else {
125
138
  this.discoverDevices();
@@ -173,7 +186,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
173
186
  const xurl = new URL(url);
174
187
  const port = Number(xurl.port);
175
188
  const path = xurl.pathname;
176
- this.webhookEventListener = http.createServer((request: http.IncomingMessage, response: http.ServerResponse) => {
189
+ this.webhookEventListener = createServer((request: IncomingMessage, response: ServerResponse) => {
177
190
  try {
178
191
  if (request.url === path && request.method === 'POST') {
179
192
  request.on('data', async (data) => {
@@ -210,16 +223,15 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
210
223
  }
211
224
 
212
225
  try {
213
- const { body, statusCode } = await request(
214
- 'https://api.switch-bot.com/v1.1/webhook/setupWebhook', {
215
- method: 'POST',
216
- headers: this.generateHeaders(),
217
- body: JSON.stringify({
218
- 'action': 'setupWebhook',
219
- 'url': url,
220
- 'deviceList': 'ALL',
221
- }),
222
- });
226
+ const { body, statusCode } = await request(setupWebhook, {
227
+ method: 'POST',
228
+ headers: this.generateHeaders(),
229
+ body: JSON.stringify({
230
+ 'action': 'setupWebhook',
231
+ 'url': url,
232
+ 'deviceList': 'ALL',
233
+ }),
234
+ });
223
235
  const response: any = await body.json();
224
236
  this.debugLog(`setupWebhook: url:${url}`);
225
237
  this.debugLog(`setupWebhook: body:${JSON.stringify(response)}`);
@@ -233,18 +245,15 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
233
245
  }
234
246
 
235
247
  try {
236
- const { body, statusCode } = await request(
237
- 'https://api.switch-bot.com/v1.1/webhook/updateWebhook', {
238
- method: 'POST',
239
- headers: this.generateHeaders(),
240
- body: JSON.stringify({
241
- 'action': 'updateWebhook',
242
- 'config': {
243
- 'url': url,
244
- 'enable': true,
245
- },
246
- }),
247
- });
248
+ const { body, statusCode } = await request(updateWebhook, {
249
+ method: 'POST', headers: this.generateHeaders(), body: JSON.stringify({
250
+ 'action': 'updateWebhook',
251
+ 'config': {
252
+ 'url': url,
253
+ 'enable': true,
254
+ },
255
+ }),
256
+ });
248
257
  const response: any = await body.json();
249
258
  this.debugLog(`updateWebhook: url:${url}`);
250
259
  this.debugLog(`updateWebhook: body:${JSON.stringify(response)}`);
@@ -257,14 +266,13 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
257
266
  }
258
267
 
259
268
  try {
260
- const { body, statusCode } = await request(
261
- 'https://api.switch-bot.com/v1.1/webhook/queryWebhook', {
262
- method: 'POST',
263
- headers: this.generateHeaders(),
264
- body: JSON.stringify({
265
- 'action': 'queryUrl',
266
- }),
267
- });
269
+ const { body, statusCode } = await request(queryWebhook, {
270
+ method: 'POST',
271
+ headers: this.generateHeaders(),
272
+ body: JSON.stringify({
273
+ 'action': 'queryUrl',
274
+ }),
275
+ });
268
276
  const response: any = await body.json();
269
277
  this.debugLog(`queryWebhook: body:${JSON.stringify(response)}`);
270
278
  this.debugLog(`queryWebhook: statusCode:${statusCode}`);
@@ -279,15 +287,14 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
279
287
 
280
288
  this.api.on('shutdown', async () => {
281
289
  try {
282
- const { body, statusCode } = await request(
283
- 'https://api.switch-bot.com/v1.1/webhook/deleteWebhook', {
284
- method: 'POST',
285
- headers: this.generateHeaders(),
286
- body: JSON.stringify({
287
- 'action': 'deleteWebhook',
288
- 'url': url,
289
- }),
290
- });
290
+ const { body, statusCode } = await request(deleteWebhook, {
291
+ method: 'POST',
292
+ headers: this.generateHeaders(),
293
+ body: JSON.stringify({
294
+ 'action': 'deleteWebhook',
295
+ 'url': url,
296
+ }),
297
+ });
291
298
  const response: any = await body.json();
292
299
  this.debugLog(`deleteWebhook: url:${url}`);
293
300
  this.debugLog(`deleteWebhook: body:${JSON.stringify(response)}`);
@@ -383,6 +390,21 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
383
390
  this.debugWarnLog('Using Default Push Rate.');
384
391
  }
385
392
 
393
+ if (!this.config.options.maxRetries) {
394
+ this.config.options.maxRetries = 5;
395
+ this.debugWarnLog('Using Default Max Retries.');
396
+ } else {
397
+ this.maxRetries = this.config.options.maxRetries;
398
+ }
399
+
400
+ if (!this.config.options.delayBetweenRetries) {
401
+ // default 3 seconds
402
+ this.config.options!.delayBetweenRetries! = 3000;
403
+ this.debugWarnLog('Using Default Delay Between Retries.');
404
+ } else {
405
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
406
+ }
407
+
386
408
  if (!this.config.credentials && !this.config.options) {
387
409
  this.debugWarnLog('Missing Credentials');
388
410
  } else if (this.config.credentials && !this.config.credentials.notice) {
@@ -432,18 +454,12 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
432
454
  }
433
455
  // Move openToken to token
434
456
  if (!this.config.credentials.secret) {
435
- // eslint-disable-next-line no-useless-escape, max-len
436
- this.warnLog(
437
- 'This plugin has been updated to use OpenAPI v1.1, config is set with openToken, "openToken" cconfig has been moved to the "token" config',
438
- );
439
- // eslint-disable-next-line no-useless-escape
457
+ this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken,'
458
+ + ' "openToken" cconfig has been moved to the "token" config');
440
459
  this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
441
460
  } else {
442
- // eslint-disable-next-line no-useless-escape, max-len
443
- this.warnLog(
444
- 'This plugin has been updated to use OpenAPI v1.1, config is set with openToken, '
445
- + '"openToken" config has been moved to the "token" config, please restart Homebridge.',
446
- );
461
+ this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, '
462
+ + '"openToken" config has been moved to the "token" config, please restart Homebridge.');
447
463
  }
448
464
 
449
465
  // set the refresh token
@@ -492,44 +508,98 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
492
508
  */
493
509
  async discoverDevices() {
494
510
  if (this.config.credentials?.token) {
495
- try {
496
- const { body, statusCode } = await request(Devices, {
497
- headers: this.generateHeaders(),
498
- });
499
- this.debugWarnLog(`statusCode: ${statusCode}`);
500
- const devicesAPI: any = await body.json();
501
- this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
502
- this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
503
- this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
504
- if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
505
- this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
506
- // SwitchBot Devices
507
- const deviceLists = devicesAPI.body.deviceList;
508
- this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
509
- this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
510
- if (!this.config.options?.devices) {
511
- this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
512
- if (deviceLists.length === 0) {
513
- this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
514
- } else {
515
- const devices = deviceLists.map((v: any) => v);
516
- for (const device of devices) {
517
- if (device.deviceType) {
518
- if (device.configDeviceName) {
519
- device.deviceName = device.configDeviceName;
511
+ let retryCount = 0;
512
+ const maxRetries = this.maxRetries; // Maximum number of retries
513
+ const delayBetweenRetries = this.delayBetweenRetries; // Delay between retries in milliseconds
514
+ this.debugWarnLog(`Retry Count: ${retryCount}`);
515
+ this.debugWarnLog(`Max Retries: ${maxRetries}`);
516
+ this.debugWarnLog(`Delay Between Retries: ${delayBetweenRetries}`);
517
+ while (retryCount < maxRetries) {
518
+ try {
519
+ const { body, statusCode } = await request(Devices, {
520
+ headers: this.generateHeaders(),
521
+ });
522
+ this.debugWarnLog(`statusCode: ${statusCode}`);
523
+ const devicesAPI: any = await body.json();
524
+ this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
525
+ this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
526
+ this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
527
+ if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
528
+ this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
529
+ // SwitchBot Devices
530
+ const deviceLists = devicesAPI.body.deviceList;
531
+ this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
532
+ this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
533
+ if (!this.config.options?.devices) {
534
+ this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
535
+ if (deviceLists.length === 0) {
536
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
537
+ } else {
538
+ const devices = deviceLists.map((v: any) => v);
539
+ for (const device of devices) {
540
+ if (device.deviceType) {
541
+ if (device.configDeviceName) {
542
+ device.deviceName = device.configDeviceName;
543
+ }
544
+ this.createDevice(device);
520
545
  }
521
- this.createDevice(device);
522
546
  }
523
547
  }
548
+ } else if (this.config.credentials?.token && this.config.options.devices) {
549
+ this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
550
+ if (deviceLists.length === 0) {
551
+ this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
552
+ } else {
553
+ const deviceConfigs = this.config.options?.devices;
554
+
555
+ const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
556
+ a1.map((itm: { deviceId: string }) => ({
557
+ ...a2.find(
558
+ (item: { deviceId: string }) =>
559
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
560
+ ),
561
+ ...itm,
562
+ }));
563
+
564
+ const devices = mergeBydeviceId(deviceLists, deviceConfigs);
565
+ this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
566
+ for (const device of devices) {
567
+ if (!device.deviceType) {
568
+ device.deviceType = device.configDeviceType;
569
+ this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
570
+ }
571
+ if (device.deviceType) {
572
+ if (device.configDeviceName) {
573
+ device.deviceName = device.configDeviceName;
574
+ }
575
+ this.createDevice(device);
576
+ }
577
+ }
578
+ }
579
+ } else {
580
+ this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
524
581
  }
525
- } else if (this.config.credentials?.token && this.config.options.devices) {
526
- this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
527
- if (deviceLists.length === 0) {
528
- this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
582
+ if (devicesAPI.body.deviceList.length !== 0) {
583
+ this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
529
584
  } else {
530
- const deviceConfigs = this.config.options?.devices;
585
+ this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
586
+ }
531
587
 
532
- const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
588
+ // IR Devices
589
+ const irDeviceLists = devicesAPI.body.infraredRemoteList;
590
+ if (!this.config.options?.irdevices) {
591
+ this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
592
+ const devices = irDeviceLists.map((v: any) => v);
593
+ for (const device of devices) {
594
+ if (device.remoteType) {
595
+ this.createIRDevice(device);
596
+ }
597
+ }
598
+ } else {
599
+ this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
600
+ const irDeviceConfig = this.config.options?.irdevices;
601
+
602
+ const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
533
603
  a1.map((itm: { deviceId: string }) => ({
534
604
  ...a2.find(
535
605
  (item: { deviceId: string }) =>
@@ -538,73 +608,33 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
538
608
  ...itm,
539
609
  }));
540
610
 
541
- const devices = mergeBydeviceId(deviceLists, deviceConfigs);
542
- this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
611
+ const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
612
+ this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
543
613
  for (const device of devices) {
544
- if (!device.deviceType) {
545
- device.deviceType = device.configDeviceType;
546
- this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
547
- }
548
- if (device.deviceType) {
549
- if (device.configDeviceName) {
550
- device.deviceName = device.configDeviceName;
551
- }
552
- this.createDevice(device);
553
- }
554
- }
555
- }
556
- } else {
557
- this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
558
- }
559
- if (devicesAPI.body.deviceList.length !== 0) {
560
- this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
561
- } else {
562
- this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
563
- }
564
-
565
- // IR Devices
566
- const irDeviceLists = devicesAPI.body.infraredRemoteList;
567
- if (!this.config.options?.irdevices) {
568
- this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
569
- const devices = irDeviceLists.map((v: any) => v);
570
- for (const device of devices) {
571
- if (device.remoteType) {
572
614
  this.createIRDevice(device);
573
615
  }
574
616
  }
575
- } else {
576
- this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
577
- const irDeviceConfig = this.config.options?.irdevices;
578
-
579
- const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
580
- a1.map((itm: { deviceId: string }) => ({
581
- ...a2.find(
582
- (item: { deviceId: string }) =>
583
- item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
584
- ),
585
- ...itm,
586
- }));
587
-
588
- const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
589
- this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
590
- for (const device of devices) {
591
- this.createIRDevice(device);
617
+ if (devicesAPI.body.infraredRemoteList.length !== 0) {
618
+ this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
619
+ } else {
620
+ this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
592
621
  }
593
- }
594
- if (devicesAPI.body.infraredRemoteList.length !== 0) {
595
- this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
622
+ break;
596
623
  } else {
597
- this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
624
+ this.statusCode(statusCode);
625
+ this.statusCode(devicesAPI.statusCode);
626
+ if (statusCode === 500) {
627
+ retryCount++;
628
+ this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
629
+ await sleep(delayBetweenRetries);
630
+ }
598
631
  }
599
- } else {
600
- this.statusCode(statusCode);
601
- this.statusCode(devicesAPI.statusCode);
632
+ } catch (e: any) {
633
+ retryCount++;
634
+ this.debugErrorLog(
635
+ `Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
636
+ this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
602
637
  }
603
- } catch (e: any) {
604
- this.debugErrorLog(
605
- `Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug',
606
- );
607
- this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
608
638
  }
609
639
  } else if (!this.config.credentials?.token && this.config.options?.devices) {
610
640
  this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
@@ -696,6 +726,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
696
726
  case 'WoSweeperMini':
697
727
  case 'Robot Vacuum Cleaner S1':
698
728
  case 'Robot Vacuum Cleaner S1 Plus':
729
+ case 'Robot Vacuum Cleaner S10':
699
730
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
700
731
  this.createRobotVacuumCleaner(device);
701
732
  break;
@@ -708,17 +739,18 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
708
739
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
709
740
  this.createStripLight(device);
710
741
  break;
711
- case 'Indoor Cam':
742
+ case 'Battery Circulator Fan':
712
743
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
713
- this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
744
+ this.createFan(device);
714
745
  break;
715
746
  case 'Remote':
716
- this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
747
+ case 'Indoor Cam':
748
+ case 'remote with screen+':
749
+ this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`);
717
750
  break;
718
751
  default:
719
- this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
720
- // eslint-disable-next-line max-len
721
- this.warnLog('Submit Feature Requests Here: ' + 'https://tinyurl.com/SwitchBotFeatureRequest');
752
+ this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`,
753
+ + `Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`);
722
754
  }
723
755
  }
724
756
 
@@ -750,7 +782,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
750
782
  case 'Fan':
751
783
  case 'DIY Fan':
752
784
  this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
753
- this.createFan(device);
785
+ this.createIRFan(device);
754
786
  break;
755
787
  case 'Air Conditioner':
756
788
  case 'DIY Air Conditioner':
@@ -808,7 +840,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
808
840
  existingAccessory.context.deviceID = device.deviceId;
809
841
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
810
842
  if (device.firmware) {
811
- existingAccessory.context.FirmwareRevision = device.firmware;
843
+ existingAccessory.context.version = device.firmware;
812
844
  }
813
845
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
814
846
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -836,7 +868,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
836
868
  accessory.context.model = device.deviceType;
837
869
  accessory.context.deviceID = device.deviceId;
838
870
  if (device.firmware) {
839
- accessory.context.FirmwareRevision = device.firmware;
871
+ accessory.context.version = device.firmware;
840
872
  }
841
873
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
842
874
  accessory.context.connectionType = await this.connectionType(device);
@@ -868,7 +900,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
868
900
  existingAccessory.context.deviceID = device.deviceId;
869
901
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
870
902
  if (device.firmware) {
871
- existingAccessory.context.FirmwareRevision = device.firmware;
903
+ existingAccessory.context.version = device.firmware;
872
904
  }
873
905
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
874
906
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -896,11 +928,11 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
896
928
  accessory.context.model = device.deviceType;
897
929
  accessory.context.deviceID = device.deviceId;
898
930
  if (device.firmware) {
899
- accessory.context.FirmwareRevision = device.firmware;
931
+ accessory.context.version = device.firmware;
900
932
  }
901
933
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
902
934
  accessory.context.connectionType = await this.connectionType(device);
903
- // accessory.context.FirmwareRevision = findaccessories.accessoryAttribute.softwareRevision;
935
+ // accessory.context.version = findaccessories.accessoryAttribute.softwareRevision;
904
936
  // create the accessory handler for the newly create accessory
905
937
  // this is imported from `platformAccessory.ts`
906
938
  new Bot(this, accessory, device);
@@ -929,7 +961,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
929
961
  existingAccessory.context.deviceID = device.deviceId;
930
962
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
931
963
  if (device.firmware) {
932
- existingAccessory.context.FirmwareRevision = device.firmware;
964
+ existingAccessory.context.version = device.firmware;
933
965
  }
934
966
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
935
967
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -957,7 +989,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
957
989
  accessory.context.model = device.deviceType;
958
990
  accessory.context.deviceID = device.deviceId;
959
991
  if (device.firmware) {
960
- accessory.context.FirmwareRevision = device.firmware;
992
+ accessory.context.version = device.firmware;
961
993
  }
962
994
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
963
995
  accessory.context.connectionType = await this.connectionType(device);
@@ -990,7 +1022,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
990
1022
  existingAccessory.context.deviceID = device.deviceId;
991
1023
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
992
1024
  if (device.firmware) {
993
- existingAccessory.context.FirmwareRevision = device.firmware;
1025
+ existingAccessory.context.version = device.firmware;
994
1026
  }
995
1027
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
996
1028
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1018,7 +1050,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1018
1050
  accessory.context.model = device.deviceType;
1019
1051
  accessory.context.deviceID = device.deviceId;
1020
1052
  if (device.firmware) {
1021
- accessory.context.FirmwareRevision = device.firmware;
1053
+ accessory.context.version = device.firmware;
1022
1054
  }
1023
1055
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1024
1056
  accessory.context.connectionType = await this.connectionType(device);
@@ -1051,7 +1083,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1051
1083
  existingAccessory.context.deviceID = device.deviceId;
1052
1084
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1053
1085
  if (device.firmware) {
1054
- existingAccessory.context.FirmwareRevision = device.firmware;
1086
+ existingAccessory.context.version = device.firmware;
1055
1087
  }
1056
1088
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1057
1089
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1079,7 +1111,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1079
1111
  accessory.context.model = device.deviceType;
1080
1112
  accessory.context.deviceID = device.deviceId;
1081
1113
  if (device.firmware) {
1082
- accessory.context.FirmwareRevision = device.firmware;
1114
+ accessory.context.version = device.firmware;
1083
1115
  }
1084
1116
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1085
1117
  accessory.context.connectionType = await this.connectionType(device);
@@ -1111,7 +1143,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1111
1143
  existingAccessory.context.deviceID = device.deviceId;
1112
1144
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1113
1145
  if (device.firmware) {
1114
- existingAccessory.context.FirmwareRevision = device.firmware;
1146
+ existingAccessory.context.version = device.firmware;
1115
1147
  }
1116
1148
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1117
1149
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1139,7 +1171,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1139
1171
  accessory.context.model = device.deviceType;
1140
1172
  accessory.context.deviceID = device.deviceId;
1141
1173
  if (device.firmware) {
1142
- accessory.context.FirmwareRevision = device.firmware;
1174
+ accessory.context.version = device.firmware;
1143
1175
  }
1144
1176
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1145
1177
  accessory.context.connectionType = await this.connectionType(device);
@@ -1171,7 +1203,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1171
1203
  existingAccessory.context.deviceID = device.deviceId;
1172
1204
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1173
1205
  if (device.firmware) {
1174
- existingAccessory.context.FirmwareRevision = device.firmware;
1206
+ existingAccessory.context.version = device.firmware;
1175
1207
  }
1176
1208
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1177
1209
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1199,7 +1231,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1199
1231
  accessory.context.model = device.deviceType;
1200
1232
  accessory.context.deviceID = device.deviceId;
1201
1233
  if (device.firmware) {
1202
- accessory.context.FirmwareRevision = device.firmware;
1234
+ accessory.context.version = device.firmware;
1203
1235
  }
1204
1236
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1205
1237
  accessory.context.connectionType = await this.connectionType(device);
@@ -1231,7 +1263,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1231
1263
  existingAccessory.context.deviceID = device.deviceId;
1232
1264
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1233
1265
  if (device.firmware) {
1234
- existingAccessory.context.FirmwareRevision = device.firmware;
1266
+ existingAccessory.context.version = device.firmware;
1235
1267
  }
1236
1268
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1237
1269
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1259,7 +1291,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1259
1291
  accessory.context.model = device.deviceType;
1260
1292
  accessory.context.deviceID = device.deviceId;
1261
1293
  if (device.firmware) {
1262
- accessory.context.FirmwareRevision = device.firmware;
1294
+ accessory.context.version = device.firmware;
1263
1295
  }
1264
1296
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1265
1297
  accessory.context.connectionType = await this.connectionType(device);
@@ -1291,7 +1323,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1291
1323
  existingAccessory.context.deviceID = device.deviceId;
1292
1324
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1293
1325
  if (device.firmware) {
1294
- existingAccessory.context.FirmwareRevision = device.firmware;
1326
+ existingAccessory.context.version = device.firmware;
1295
1327
  }
1296
1328
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1297
1329
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1319,7 +1351,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1319
1351
  accessory.context.model = device.deviceType;
1320
1352
  accessory.context.deviceID = device.deviceId;
1321
1353
  if (device.firmware) {
1322
- accessory.context.FirmwareRevision = device.firmware;
1354
+ accessory.context.version = device.firmware;
1323
1355
  }
1324
1356
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1325
1357
  accessory.context.connectionType = await this.connectionType(device);
@@ -1351,7 +1383,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1351
1383
  existingAccessory.context.deviceID = device.deviceId;
1352
1384
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1353
1385
  if (device.firmware) {
1354
- existingAccessory.context.FirmwareRevision = device.firmware;
1386
+ existingAccessory.context.version = device.firmware;
1355
1387
  }
1356
1388
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1357
1389
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1373,8 +1405,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1373
1405
  if (device.group && !device.curtain?.disable_group) {
1374
1406
  this.debugLog(
1375
1407
  'Your Curtains are grouped, ' +
1376
- `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, DeviceID: ${device.deviceId}`,
1377
- );
1408
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, DeviceID: ${device.deviceId}`);
1378
1409
  } else {
1379
1410
  if (device.master) {
1380
1411
  this.warnLog(`Main Curtain: ${device.deviceName}, DeviceID: ${device.deviceId}`);
@@ -1392,7 +1423,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1392
1423
  accessory.context.model = device.deviceType;
1393
1424
  accessory.context.deviceID = device.deviceId;
1394
1425
  if (device.firmware) {
1395
- accessory.context.FirmwareRevision = device.firmware;
1426
+ accessory.context.version = device.firmware;
1396
1427
  }
1397
1428
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1398
1429
  accessory.context.connectionType = await this.connectionType(device);
@@ -1424,7 +1455,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1424
1455
  existingAccessory.context.deviceID = device.deviceId;
1425
1456
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1426
1457
  if (device.firmware) {
1427
- existingAccessory.context.FirmwareRevision = device.firmware;
1458
+ existingAccessory.context.version = device.firmware;
1428
1459
  }
1429
1460
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1430
1461
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1446,8 +1477,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1446
1477
  if (device.group && !device.curtain?.disable_group) {
1447
1478
  this.debugLog(
1448
1479
  'Your Curtains are grouped, ' +
1449
- `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, DeviceID: ${device.deviceId}`,
1450
- );
1480
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, DeviceID: ${device.deviceId}`);
1451
1481
  } else {
1452
1482
  if (device.master) {
1453
1483
  this.warnLog(`Main Curtain: ${device.deviceName}, DeviceID: ${device.deviceId}`);
@@ -1465,7 +1495,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1465
1495
  accessory.context.model = device.deviceType;
1466
1496
  accessory.context.deviceID = device.deviceId;
1467
1497
  if (device.firmware) {
1468
- accessory.context.FirmwareRevision = device.firmware;
1498
+ accessory.context.version = device.firmware;
1469
1499
  }
1470
1500
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1471
1501
  accessory.context.connectionType = await this.connectionType(device);
@@ -1497,7 +1527,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1497
1527
  existingAccessory.context.deviceID = device.deviceId;
1498
1528
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1499
1529
  if (device.firmware) {
1500
- existingAccessory.context.FirmwareRevision = device.firmware;
1530
+ existingAccessory.context.version = device.firmware;
1501
1531
  }
1502
1532
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1503
1533
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1525,7 +1555,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1525
1555
  accessory.context.model = device.deviceType;
1526
1556
  accessory.context.deviceID = device.deviceId;
1527
1557
  if (device.firmware) {
1528
- accessory.context.FirmwareRevision = device.firmware;
1558
+ accessory.context.version = device.firmware;
1529
1559
  }
1530
1560
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1531
1561
  accessory.context.connectionType = await this.connectionType(device);
@@ -1557,7 +1587,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1557
1587
  existingAccessory.context.deviceID = device.deviceId;
1558
1588
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1559
1589
  if (device.firmware) {
1560
- existingAccessory.context.FirmwareRevision = device.firmware;
1590
+ existingAccessory.context.version = device.firmware;
1561
1591
  }
1562
1592
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1563
1593
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1585,7 +1615,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1585
1615
  accessory.context.model = device.deviceType;
1586
1616
  accessory.context.deviceID = device.deviceId;
1587
1617
  if (device.firmware) {
1588
- accessory.context.FirmwareRevision = device.firmware;
1618
+ accessory.context.version = device.firmware;
1589
1619
  }
1590
1620
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1591
1621
  accessory.context.connectionType = await this.connectionType(device);
@@ -1617,7 +1647,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1617
1647
  existingAccessory.context.deviceID = device.deviceId;
1618
1648
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1619
1649
  if (device.firmware) {
1620
- existingAccessory.context.FirmwareRevision = device.firmware;
1650
+ existingAccessory.context.version = device.firmware;
1621
1651
  }
1622
1652
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1623
1653
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1645,7 +1675,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1645
1675
  accessory.context.model = device.deviceType;
1646
1676
  accessory.context.deviceID = device.deviceId;
1647
1677
  if (device.firmware) {
1648
- accessory.context.FirmwareRevision = device.firmware;
1678
+ accessory.context.version = device.firmware;
1649
1679
  }
1650
1680
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1651
1681
  accessory.context.connectionType = await this.connectionType(device);
@@ -1677,7 +1707,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1677
1707
  existingAccessory.context.deviceID = device.deviceId;
1678
1708
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1679
1709
  if (device.firmware) {
1680
- existingAccessory.context.FirmwareRevision = device.firmware;
1710
+ existingAccessory.context.version = device.firmware;
1681
1711
  }
1682
1712
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1683
1713
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1705,7 +1735,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1705
1735
  accessory.context.model = device.deviceType;
1706
1736
  accessory.context.deviceID = device.deviceId;
1707
1737
  if (device.firmware) {
1708
- accessory.context.FirmwareRevision = device.firmware;
1738
+ accessory.context.version = device.firmware;
1709
1739
  }
1710
1740
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1711
1741
  accessory.context.connectionType = await this.connectionType(device);
@@ -1737,7 +1767,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1737
1767
  existingAccessory.context.deviceID = device.deviceId;
1738
1768
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1739
1769
  if (device.firmware) {
1740
- existingAccessory.context.FirmwareRevision = device.firmware;
1770
+ existingAccessory.context.version = device.firmware;
1741
1771
  }
1742
1772
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1743
1773
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1765,7 +1795,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1765
1795
  accessory.context.model = device.deviceType;
1766
1796
  accessory.context.deviceID = device.deviceId;
1767
1797
  if (device.firmware) {
1768
- accessory.context.FirmwareRevision = device.firmware;
1798
+ accessory.context.version = device.firmware;
1769
1799
  }
1770
1800
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1771
1801
  accessory.context.connectionType = await this.connectionType(device);
@@ -1782,6 +1812,66 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1782
1812
  }
1783
1813
  }
1784
1814
 
1815
+ private async createFan(device: device & devicesConfig) {
1816
+ const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1817
+
1818
+ // see if an accessory with the same uuid has already been registered and restored from
1819
+ // the cached devices we stored in the `configureAccessory` method above
1820
+ const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid);
1821
+
1822
+ if (existingAccessory) {
1823
+ // the accessory already exists
1824
+ if (await this.registerDevice(device)) {
1825
+ // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1826
+ existingAccessory.context.model = device.deviceType;
1827
+ existingAccessory.context.deviceID = device.deviceId;
1828
+ existingAccessory.displayName = device.configDeviceName || device.deviceName;
1829
+ if (device.firmware) {
1830
+ existingAccessory.context.version = device.firmware;
1831
+ }
1832
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1833
+ this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1834
+ existingAccessory.context.connectionType = await this.connectionType(device);
1835
+ this.api.updatePlatformAccessories([existingAccessory]);
1836
+ // create the accessory handler for the restored accessory
1837
+ // this is imported from `platformAccessory.ts`
1838
+ new Fan(this, existingAccessory, device);
1839
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`);
1840
+ } else {
1841
+ this.unregisterPlatformAccessories(existingAccessory);
1842
+ }
1843
+ } else if (await this.registerDevice(device)) {
1844
+ // the accessory does not yet exist, so we need to create it
1845
+ if (!device.external) {
1846
+ this.infoLog(`Adding new accessory: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1847
+ }
1848
+
1849
+ // create a new accessory
1850
+ const accessory = new this.api.platformAccessory(device.deviceName, uuid);
1851
+
1852
+ // store a copy of the device object in the `accessory.context`
1853
+ // the `context` property can be used to store any data about the accessory you may need
1854
+ accessory.context.device = device;
1855
+ accessory.context.model = device.deviceType;
1856
+ accessory.context.deviceID = device.deviceId;
1857
+ if (device.firmware) {
1858
+ accessory.context.version = device.firmware;
1859
+ }
1860
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1861
+ accessory.context.connectionType = await this.connectionType(device);
1862
+ // create the accessory handler for the newly create accessory
1863
+ // this is imported from `platformAccessory.ts`
1864
+ new Fan(this, accessory, device);
1865
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`);
1866
+
1867
+ // publish device externally or link the accessory to your platform
1868
+ this.externalOrPlatform(device, accessory);
1869
+ this.accessories.push(accessory);
1870
+ } else {
1871
+ this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1872
+ }
1873
+ }
1874
+
1785
1875
  private async createRobotVacuumCleaner(device: device & devicesConfig) {
1786
1876
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1787
1877
 
@@ -1797,7 +1887,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1797
1887
  existingAccessory.context.deviceID = device.deviceId;
1798
1888
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1799
1889
  if (device.firmware) {
1800
- existingAccessory.context.FirmwareRevision = device.firmware;
1890
+ existingAccessory.context.version = device.firmware;
1801
1891
  }
1802
1892
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1803
1893
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1825,7 +1915,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1825
1915
  accessory.context.model = device.deviceType;
1826
1916
  accessory.context.deviceID = device.deviceId;
1827
1917
  if (device.firmware) {
1828
- accessory.context.FirmwareRevision = device.firmware;
1918
+ accessory.context.version = device.firmware;
1829
1919
  }
1830
1920
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1831
1921
  accessory.context.connectionType = await this.connectionType(device);
@@ -1854,7 +1944,9 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1854
1944
  existingAccessory.context.model = device.remoteType;
1855
1945
  existingAccessory.context.deviceID = device.deviceId;
1856
1946
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1857
- existingAccessory.context.FirmwareRevision = device.firmware;
1947
+ if (device.version && !device.firmware) {
1948
+ existingAccessory.context.version = device.version;
1949
+ }
1858
1950
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1859
1951
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1860
1952
  existingAccessory.context.connectionType = device.connectionType;
@@ -1878,7 +1970,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1878
1970
  accessory.context.model = device.remoteType;
1879
1971
  accessory.context.deviceID = device.deviceId;
1880
1972
  if (device.firmware) {
1881
- accessory.context.FirmwareRevision = device.firmware;
1973
+ accessory.context.version = device.firmware;
1882
1974
  }
1883
1975
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1884
1976
  accessory.context.connectionType = device.connectionType;
@@ -1894,7 +1986,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1894
1986
  }
1895
1987
  }
1896
1988
 
1897
- private async createFan(device: irdevice & devicesConfig) {
1989
+ private async createIRFan(device: irdevice & devicesConfig) {
1898
1990
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
1899
1991
 
1900
1992
  // see if an accessory with the same uuid has already been registered and restored from
@@ -1909,7 +2001,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1909
2001
  existingAccessory.context.deviceID = device.deviceId;
1910
2002
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1911
2003
  if (device.firmware) {
1912
- existingAccessory.context.FirmwareRevision = device.firmware;
2004
+ existingAccessory.context.version = device.firmware;
1913
2005
  }
1914
2006
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1915
2007
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1917,7 +2009,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1917
2009
  this.api.updatePlatformAccessories([existingAccessory]);
1918
2010
  // create the accessory handler for the restored accessory
1919
2011
  // this is imported from `platformAccessory.ts`
1920
- new Fan(this, existingAccessory, device);
2012
+ new IRFan(this, existingAccessory, device);
1921
2013
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`);
1922
2014
  } else {
1923
2015
  this.unregisterPlatformAccessories(existingAccessory);
@@ -1937,13 +2029,13 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1937
2029
  accessory.context.model = device.remoteType;
1938
2030
  accessory.context.deviceID = device.deviceId;
1939
2031
  if (device.firmware) {
1940
- accessory.context.FirmwareRevision = device.firmware;
2032
+ accessory.context.version = device.firmware;
1941
2033
  }
1942
2034
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1943
2035
  accessory.context.connectionType = device.connectionType;
1944
2036
  // create the accessory handler for the newly create accessory
1945
2037
  // this is imported from `platformAccessory.ts`
1946
- new Fan(this, accessory, device);
2038
+ new IRFan(this, accessory, device);
1947
2039
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
1948
2040
 
1949
2041
  // publish device externally or link the accessory to your platform
@@ -1969,7 +2061,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1969
2061
  existingAccessory.context.deviceID = device.deviceId;
1970
2062
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1971
2063
  if (device.firmware) {
1972
- existingAccessory.context.FirmwareRevision = device.firmware;
2064
+ existingAccessory.context.version = device.firmware;
1973
2065
  }
1974
2066
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1975
2067
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1997,7 +2089,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1997
2089
  accessory.context.model = device.remoteType;
1998
2090
  accessory.context.deviceID = device.deviceId;
1999
2091
  if (device.firmware) {
2000
- accessory.context.FirmwareRevision = device.firmware;
2092
+ accessory.context.version = device.firmware;
2001
2093
  }
2002
2094
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2003
2095
  accessory.context.connectionType = device.connectionType;
@@ -2029,7 +2121,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2029
2121
  existingAccessory.context.deviceID = device.deviceId;
2030
2122
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2031
2123
  if (device.firmware) {
2032
- existingAccessory.context.FirmwareRevision = device.firmware;
2124
+ existingAccessory.context.version = device.firmware;
2033
2125
  }
2034
2126
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2035
2127
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2057,7 +2149,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2057
2149
  accessory.context.model = device.remoteType;
2058
2150
  accessory.context.deviceID = device.deviceId;
2059
2151
  if (device.firmware) {
2060
- accessory.context.FirmwareRevision = device.firmware;
2152
+ accessory.context.version = device.firmware;
2061
2153
  }
2062
2154
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2063
2155
  accessory.context.connectionType = device.connectionType;
@@ -2089,7 +2181,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2089
2181
  existingAccessory.context.deviceID = device.deviceId;
2090
2182
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2091
2183
  if (device.firmware) {
2092
- existingAccessory.context.FirmwareRevision = device.firmware;
2184
+ existingAccessory.context.version = device.firmware;
2093
2185
  }
2094
2186
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2095
2187
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2117,7 +2209,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2117
2209
  accessory.context.model = device.remoteType;
2118
2210
  accessory.context.deviceID = device.deviceId;
2119
2211
  if (device.firmware) {
2120
- accessory.context.FirmwareRevision = device.firmware;
2212
+ accessory.context.version = device.firmware;
2121
2213
  }
2122
2214
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2123
2215
  accessory.context.connectionType = device.connectionType;
@@ -2149,7 +2241,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2149
2241
  existingAccessory.context.deviceID = device.deviceId;
2150
2242
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2151
2243
  if (device.firmware) {
2152
- existingAccessory.context.FirmwareRevision = device.firmware;
2244
+ existingAccessory.context.version = device.firmware;
2153
2245
  }
2154
2246
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2155
2247
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2177,7 +2269,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2177
2269
  accessory.context.model = device.remoteType;
2178
2270
  accessory.context.deviceID = device.deviceId;
2179
2271
  if (device.firmware) {
2180
- accessory.context.FirmwareRevision = device.firmware;
2272
+ accessory.context.version = device.firmware;
2181
2273
  }
2182
2274
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2183
2275
  accessory.context.connectionType = device.connectionType;
@@ -2209,7 +2301,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2209
2301
  existingAccessory.context.deviceID = device.deviceId;
2210
2302
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2211
2303
  if (device.firmware) {
2212
- existingAccessory.context.FirmwareRevision = device.firmware;
2304
+ existingAccessory.context.version = device.firmware;
2213
2305
  }
2214
2306
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2215
2307
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2237,7 +2329,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2237
2329
  accessory.context.model = device.remoteType;
2238
2330
  accessory.context.deviceID = device.deviceId;
2239
2331
  if (device.firmware) {
2240
- accessory.context.FirmwareRevision = device.firmware;
2332
+ accessory.context.version = device.firmware;
2241
2333
  }
2242
2334
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2243
2335
  accessory.context.connectionType = device.connectionType;
@@ -2269,7 +2361,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2269
2361
  existingAccessory.context.deviceID = device.deviceId;
2270
2362
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2271
2363
  if (device.firmware) {
2272
- existingAccessory.context.FirmwareRevision = device.firmware;
2364
+ existingAccessory.context.version = device.firmware;
2273
2365
  }
2274
2366
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2275
2367
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2297,7 +2389,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2297
2389
  accessory.context.model = device.remoteType;
2298
2390
  accessory.context.deviceID = device.deviceId;
2299
2391
  if (device.firmware) {
2300
- accessory.context.FirmwareRevision = device.firmware;
2392
+ accessory.context.version = device.firmware;
2301
2393
  }
2302
2394
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2303
2395
  accessory.context.connectionType = device.connectionType;
@@ -2329,7 +2421,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2329
2421
  existingAccessory.context.deviceID = device.deviceId;
2330
2422
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2331
2423
  if (device.firmware) {
2332
- existingAccessory.context.FirmwareRevision = device.firmware;
2424
+ existingAccessory.context.version = device.firmware;
2333
2425
  }
2334
2426
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2335
2427
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2357,7 +2449,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2357
2449
  accessory.context.model = device.remoteType;
2358
2450
  accessory.context.deviceID = device.deviceId;
2359
2451
  if (device.firmware) {
2360
- accessory.context.FirmwareRevision = device.firmware;
2452
+ accessory.context.version = device.firmware;
2361
2453
  }
2362
2454
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2363
2455
  accessory.context.connectionType = device.connectionType;
@@ -2378,8 +2470,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2378
2470
  switch (device.deviceType) {
2379
2471
  case 'Curtain':
2380
2472
  case 'Curtain3':
2381
- this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, curtainDevicesIds: ${device.curtainDevicesIds}, master: ` +
2382
- `${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group}, connectionType: ${device.connectionType}`);
2473
+ this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, curtainDevicesIds: ${device.curtainDevicesIds}, master: `
2474
+ + `${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group}, connectionType: ${device.connectionType}`);
2383
2475
  break;
2384
2476
  default:
2385
2477
  this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, blindTiltDevicesIds: ${device.blindTiltDevicesIds}, master:`
@@ -2390,41 +2482,32 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2390
2482
  if (device.master && device.group) {
2391
2483
  // OpenAPI: Master Curtains/Blind Tilt in Group
2392
2484
  registerCurtain = true;
2393
- this.debugLog(
2394
- `deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group}` +
2395
- ` connectionType; ${device.connectionType}`,
2396
- );
2485
+ this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group}`
2486
+ + ` connectionType; ${device.connectionType}`);
2397
2487
  this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
2398
2488
  } else if (!device.master && device.curtain?.disable_group) {
2399
2489
  //!device.group && device.connectionType === 'BLE'
2400
2490
  // OpenAPI: Non-Master Curtains/Blind Tilts that has Disable Grouping Checked
2401
2491
  registerCurtain = true;
2402
- this.debugLog(
2403
- `deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: ` +
2404
- `${device.curtain?.disable_group}, connectionType; ${device.connectionType}`,
2405
- );
2492
+ this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: `
2493
+ + `${device.curtain?.disable_group}, connectionType; ${device.connectionType}`);
2406
2494
  this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
2407
2495
  } else if (device.master && !device.group) {
2408
2496
  // OpenAPI: Master Curtains/Blind Tilts not in Group
2409
2497
  registerCurtain = true;
2410
- this.debugLog(
2411
- `deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group}` +
2412
- ` connectionType; ${device.connectionType}`,
2413
- );
2498
+ this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group}`
2499
+ + ` connectionType; ${device.connectionType}`);
2414
2500
  this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
2415
2501
  } else if (device.connectionType === 'BLE') {
2416
2502
  // BLE: Curtains/Blind Tilt
2417
2503
  registerCurtain = true;
2418
- this.debugLog(
2419
- `deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, ` + ` group: ${device.group}`,
2420
- );
2504
+ this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, `
2505
+ + ` group: ${device.group}`);
2421
2506
  this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
2422
2507
  } else {
2423
2508
  registerCurtain = false;
2424
- this.debugErrorLog(
2425
- `deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${device.curtain?.disable_group},` +
2426
- ` device.master: ${device.master}, device.group: ${device.group}`,
2427
- );
2509
+ this.debugErrorLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${device.curtain?.disable_group},`
2510
+ + ` device.master: ${device.master}, device.group: ${device.group}`);
2428
2511
  this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}, device.connectionType: ${device.connectionType}`);
2429
2512
  }
2430
2513
  return registerCurtain;
@@ -2515,10 +2598,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2515
2598
  this.debugErrorLog(`Device: ${device.deviceName} hide_device: ${device.hide_device}, will not display in HomeKit`);
2516
2599
  } else {
2517
2600
  registerDevice = false;
2518
- this.debugErrorLog(
2519
- `Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: ` +
2520
- `${device.hide_device}, will not display in HomeKit`,
2521
- );
2601
+ this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: `
2602
+ + `${device.hide_device}, will not display in HomeKit`);
2522
2603
  }
2523
2604
  return registerDevice;
2524
2605
  }
@@ -2561,16 +2642,14 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2561
2642
  async statusCode(statusCode: number): Promise<void> {
2562
2643
  switch (statusCode) {
2563
2644
  case 151:
2564
- this.errorLog(
2565
- `Command not supported by this device type, statusCode: ${statusCode}, Submit Feature Request Here: ` +
2566
- 'https://tinyurl.com/SwitchBotFeatureRequest',
2567
- );
2645
+ this.errorLog(`Command not supported by this device type, statusCode: ${statusCode}, Submit Feature Request Here: ` +
2646
+ 'https://tinyurl.com/SwitchBotFeatureRequest');
2568
2647
  break;
2569
2648
  case 152:
2570
2649
  this.errorLog(`Device not found, statusCode: ${statusCode}`);
2571
2650
  break;
2572
2651
  case 160:
2573
- this.errorLog(`Command is not supported, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
2652
+ this.errorLog(`Command is not supported, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`);
2574
2653
  break;
2575
2654
  case 161:
2576
2655
  this.errorLog(`Device is offline, statusCode: ${statusCode}`);
@@ -2627,6 +2706,30 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2627
2706
  }
2628
2707
  }
2629
2708
 
2709
+ async retryRequest(deviceMaxRetries: number, deviceDelayBetweenRetries: number, url: string | URL | UrlObject,
2710
+ options?: { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions,
2711
+ 'origin' | 'path' | 'method'> & Partial<Pick<Dispatcher.RequestOptions, 'method'>>): Promise<{ body: any; statusCode: number }> {
2712
+ let retryCount = 0;
2713
+ const maxRetries = deviceMaxRetries;
2714
+ const delayBetweenRetries = deviceDelayBetweenRetries;
2715
+ while (retryCount < maxRetries) {
2716
+ try {
2717
+ const { body, statusCode } = await request(url, options);
2718
+ if (statusCode === 200 || statusCode === 100) {
2719
+ return { body, statusCode };
2720
+ } else {
2721
+ this.debugLog(`Received status code: ${statusCode}`);
2722
+ }
2723
+ } catch (error: any) {
2724
+ this.errorLog(`Error making request: ${error.message}`);
2725
+ }
2726
+ retryCount++;
2727
+ this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
2728
+ await sleep(delayBetweenRetries);
2729
+ }
2730
+ return { body: null, statusCode: -1 };
2731
+ }
2732
+
2630
2733
  // BLE Connection
2631
2734
  async connectBLE() {
2632
2735
  let switchbot: any;
@@ -2651,7 +2754,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2651
2754
  this.version = json.version;
2652
2755
  }
2653
2756
 
2654
- async platformConfigOptions() {
2757
+ async getPlatformConfigSettings() {
2655
2758
  const platformConfig: SwitchBotPlatformConfig['options'] = {};
2656
2759
  if (this.config.options) {
2657
2760
  if (this.config.options.logging) {
@@ -2660,9 +2763,28 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2660
2763
  if (this.config.options.refreshRate) {
2661
2764
  platformConfig.refreshRate = this.config.options.refreshRate;
2662
2765
  }
2766
+ if (this.config.options.updateRate) {
2767
+ platformConfig.updateRate = this.config.options.updateRate;
2768
+ }
2663
2769
  if (this.config.options.pushRate) {
2664
2770
  platformConfig.pushRate = this.config.options.pushRate;
2665
2771
  }
2772
+ if (this.config.options.maxRetries) {
2773
+ this.maxRetries = this.config.options.maxRetries;
2774
+ platformConfig.maxRetries = this.config.options.maxRetries;
2775
+ } else {
2776
+ this.maxRetries = 3;
2777
+ this.debugWarnLog('Using Default Max Retries');
2778
+ platformConfig.maxRetries = this.maxRetries;
2779
+ }
2780
+ if (this.config.options.delayBetweenRetries) {
2781
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
2782
+ platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries;
2783
+ } else {
2784
+ this.delayBetweenRetries = 3000;
2785
+ this.debugWarnLog('Using Default Delay Between Retries');
2786
+ platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
2787
+ }
2666
2788
  if (Object.entries(platformConfig).length !== 0) {
2667
2789
  this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
2668
2790
  }
@@ -2670,10 +2792,10 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2670
2792
  }
2671
2793
  }
2672
2794
 
2673
- async platformLogs() {
2795
+ async getPlatformLogSettings() {
2674
2796
  this.debugMode = process.argv.includes('-D') || process.argv.includes('--debug');
2675
2797
  if (this.config.options?.logging === 'debug' || this.config.options?.logging === 'standard' || this.config.options?.logging === 'none') {
2676
- this.platformLogging = this.config.options!.logging;
2798
+ this.platformLogging = this.config.options.logging;
2677
2799
  this.debugWarnLog(`Using Config Logging: ${this.platformLogging}`);
2678
2800
  } else if (this.debugMode) {
2679
2801
  this.platformLogging = 'debugMode';
@@ -2694,6 +2816,20 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2694
2816
  }
2695
2817
  }
2696
2818
 
2819
+ successLog(...log: any[]): void {
2820
+ if (this.enablingPlatformLogging()) {
2821
+ this.log.success(String(...log));
2822
+ }
2823
+ }
2824
+
2825
+ debugSuccessLog(...log: any[]): void {
2826
+ if (this.enablingPlatformLogging()) {
2827
+ if (this.platformLogging?.includes('debug')) {
2828
+ this.log.success('[DEBUG]', String(...log));
2829
+ }
2830
+ }
2831
+ }
2832
+
2697
2833
  warnLog(...log: any[]): void {
2698
2834
  if (this.enablingPlatformLogging()) {
2699
2835
  this.log.warn(String(...log));