@switchbot/homebridge-switchbot 3.5.0-beta.7 → 3.5.0-beta.70

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 +425 -778
  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 +803 -837
  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 +241 -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 +283 -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 +254 -545
  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 +412 -806
  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 +711 -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 +540 -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 +261 -616
  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 +240 -594
  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 +196 -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 +281 -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 +252 -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 +191 -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 +180 -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 +188 -532
  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 +96 -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 +202 -521
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +10 -63
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +146 -475
  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 +324 -452
  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 +93 -307
  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 +39 -281
  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 +113 -341
  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 +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 +87 -335
  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 +19 -6
  128. package/dist/platform.d.ts.map +1 -1
  129. package/dist/platform.js +310 -172
  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 +462 -817
  143. package/src/device/bot.ts +862 -931
  144. package/src/device/ceilinglight.ts +259 -633
  145. package/src/device/colorbulb.ts +300 -688
  146. package/src/device/contact.ts +288 -571
  147. package/src/device/curtain.ts +441 -838
  148. package/src/device/device.ts +734 -0
  149. package/src/device/fan.ts +596 -0
  150. package/src/device/hub.ts +299 -645
  151. package/src/device/humidifier.ts +274 -647
  152. package/src/device/iosensor.ts +233 -626
  153. package/src/device/lightstrip.ts +309 -620
  154. package/src/device/lock.ts +292 -601
  155. package/src/device/meter.ts +228 -619
  156. package/src/device/meterplus.ts +216 -619
  157. package/src/device/motion.ts +218 -559
  158. package/src/device/plug.ts +111 -490
  159. package/src/device/robotvacuumcleaner.ts +228 -550
  160. package/src/device/waterdetector.ts +169 -501
  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 +350 -477
  165. package/src/irdevice/airpurifier.ts +120 -330
  166. package/src/irdevice/camera.ts +53 -301
  167. package/src/irdevice/fan.ts +130 -360
  168. package/src/irdevice/irdevice.ts +346 -0
  169. package/src/irdevice/light.ts +157 -412
  170. package/src/irdevice/other.ts +507 -648
  171. package/src/irdevice/tv.ts +117 -367
  172. package/src/irdevice/vacuumcleaner.ts +59 -311
  173. package/src/irdevice/waterheater.ts +61 -320
  174. package/src/platform.ts +355 -219
  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;
@@ -662,17 +695,17 @@ export class SwitchBotPlatform {
662
695
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
663
696
  this.createStripLight(device);
664
697
  break;
665
- case 'Indoor Cam':
698
+ case 'Battery Circulator Fan':
666
699
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
667
- this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
700
+ this.createFan(device);
668
701
  break;
669
702
  case 'Remote':
670
- this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
703
+ case 'Indoor Cam':
704
+ case 'remote with screen+':
705
+ this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`);
671
706
  break;
672
707
  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');
708
+ this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`, +`Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`);
676
709
  }
677
710
  }
678
711
  createIRDevice(device) {
@@ -704,7 +737,7 @@ export class SwitchBotPlatform {
704
737
  case 'Fan':
705
738
  case 'DIY Fan':
706
739
  this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
707
- this.createFan(device);
740
+ this.createIRFan(device);
708
741
  break;
709
742
  case 'Air Conditioner':
710
743
  case 'DIY Air Conditioner':
@@ -759,7 +792,7 @@ export class SwitchBotPlatform {
759
792
  existingAccessory.context.deviceID = device.deviceId;
760
793
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
761
794
  if (device.firmware) {
762
- existingAccessory.context.FirmwareRevision = device.firmware;
795
+ existingAccessory.context.version = device.firmware;
763
796
  }
764
797
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
765
798
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -787,7 +820,7 @@ export class SwitchBotPlatform {
787
820
  accessory.context.model = device.deviceType;
788
821
  accessory.context.deviceID = device.deviceId;
789
822
  if (device.firmware) {
790
- accessory.context.FirmwareRevision = device.firmware;
823
+ accessory.context.version = device.firmware;
791
824
  }
792
825
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
793
826
  accessory.context.connectionType = await this.connectionType(device);
@@ -816,7 +849,7 @@ export class SwitchBotPlatform {
816
849
  existingAccessory.context.deviceID = device.deviceId;
817
850
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
818
851
  if (device.firmware) {
819
- existingAccessory.context.FirmwareRevision = device.firmware;
852
+ existingAccessory.context.version = device.firmware;
820
853
  }
821
854
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
822
855
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -844,11 +877,11 @@ export class SwitchBotPlatform {
844
877
  accessory.context.model = device.deviceType;
845
878
  accessory.context.deviceID = device.deviceId;
846
879
  if (device.firmware) {
847
- accessory.context.FirmwareRevision = device.firmware;
880
+ accessory.context.version = device.firmware;
848
881
  }
849
882
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
850
883
  accessory.context.connectionType = await this.connectionType(device);
851
- // accessory.context.FirmwareRevision = findaccessories.accessoryAttribute.softwareRevision;
884
+ // accessory.context.version = findaccessories.accessoryAttribute.softwareRevision;
852
885
  // create the accessory handler for the newly create accessory
853
886
  // this is imported from `platformAccessory.ts`
854
887
  new Bot(this, accessory, device);
@@ -874,7 +907,7 @@ export class SwitchBotPlatform {
874
907
  existingAccessory.context.deviceID = device.deviceId;
875
908
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
876
909
  if (device.firmware) {
877
- existingAccessory.context.FirmwareRevision = device.firmware;
910
+ existingAccessory.context.version = device.firmware;
878
911
  }
879
912
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
880
913
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -902,7 +935,7 @@ export class SwitchBotPlatform {
902
935
  accessory.context.model = device.deviceType;
903
936
  accessory.context.deviceID = device.deviceId;
904
937
  if (device.firmware) {
905
- accessory.context.FirmwareRevision = device.firmware;
938
+ accessory.context.version = device.firmware;
906
939
  }
907
940
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
908
941
  accessory.context.connectionType = await this.connectionType(device);
@@ -932,7 +965,7 @@ export class SwitchBotPlatform {
932
965
  existingAccessory.context.deviceID = device.deviceId;
933
966
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
934
967
  if (device.firmware) {
935
- existingAccessory.context.FirmwareRevision = device.firmware;
968
+ existingAccessory.context.version = device.firmware;
936
969
  }
937
970
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
938
971
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -960,7 +993,7 @@ export class SwitchBotPlatform {
960
993
  accessory.context.model = device.deviceType;
961
994
  accessory.context.deviceID = device.deviceId;
962
995
  if (device.firmware) {
963
- accessory.context.FirmwareRevision = device.firmware;
996
+ accessory.context.version = device.firmware;
964
997
  }
965
998
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
966
999
  accessory.context.connectionType = await this.connectionType(device);
@@ -990,7 +1023,7 @@ export class SwitchBotPlatform {
990
1023
  existingAccessory.context.deviceID = device.deviceId;
991
1024
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
992
1025
  if (device.firmware) {
993
- existingAccessory.context.FirmwareRevision = device.firmware;
1026
+ existingAccessory.context.version = device.firmware;
994
1027
  }
995
1028
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
996
1029
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1018,7 +1051,7 @@ export class SwitchBotPlatform {
1018
1051
  accessory.context.model = device.deviceType;
1019
1052
  accessory.context.deviceID = device.deviceId;
1020
1053
  if (device.firmware) {
1021
- accessory.context.FirmwareRevision = device.firmware;
1054
+ accessory.context.version = device.firmware;
1022
1055
  }
1023
1056
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1024
1057
  accessory.context.connectionType = await this.connectionType(device);
@@ -1047,7 +1080,7 @@ export class SwitchBotPlatform {
1047
1080
  existingAccessory.context.deviceID = device.deviceId;
1048
1081
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1049
1082
  if (device.firmware) {
1050
- existingAccessory.context.FirmwareRevision = device.firmware;
1083
+ existingAccessory.context.version = device.firmware;
1051
1084
  }
1052
1085
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1053
1086
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1075,7 +1108,7 @@ export class SwitchBotPlatform {
1075
1108
  accessory.context.model = device.deviceType;
1076
1109
  accessory.context.deviceID = device.deviceId;
1077
1110
  if (device.firmware) {
1078
- accessory.context.FirmwareRevision = device.firmware;
1111
+ accessory.context.version = device.firmware;
1079
1112
  }
1080
1113
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1081
1114
  accessory.context.connectionType = await this.connectionType(device);
@@ -1104,7 +1137,7 @@ export class SwitchBotPlatform {
1104
1137
  existingAccessory.context.deviceID = device.deviceId;
1105
1138
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1106
1139
  if (device.firmware) {
1107
- existingAccessory.context.FirmwareRevision = device.firmware;
1140
+ existingAccessory.context.version = device.firmware;
1108
1141
  }
1109
1142
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1110
1143
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1132,7 +1165,7 @@ export class SwitchBotPlatform {
1132
1165
  accessory.context.model = device.deviceType;
1133
1166
  accessory.context.deviceID = device.deviceId;
1134
1167
  if (device.firmware) {
1135
- accessory.context.FirmwareRevision = device.firmware;
1168
+ accessory.context.version = device.firmware;
1136
1169
  }
1137
1170
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1138
1171
  accessory.context.connectionType = await this.connectionType(device);
@@ -1161,7 +1194,7 @@ export class SwitchBotPlatform {
1161
1194
  existingAccessory.context.deviceID = device.deviceId;
1162
1195
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1163
1196
  if (device.firmware) {
1164
- existingAccessory.context.FirmwareRevision = device.firmware;
1197
+ existingAccessory.context.version = device.firmware;
1165
1198
  }
1166
1199
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1167
1200
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1189,7 +1222,7 @@ export class SwitchBotPlatform {
1189
1222
  accessory.context.model = device.deviceType;
1190
1223
  accessory.context.deviceID = device.deviceId;
1191
1224
  if (device.firmware) {
1192
- accessory.context.FirmwareRevision = device.firmware;
1225
+ accessory.context.version = device.firmware;
1193
1226
  }
1194
1227
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1195
1228
  accessory.context.connectionType = await this.connectionType(device);
@@ -1218,7 +1251,7 @@ export class SwitchBotPlatform {
1218
1251
  existingAccessory.context.deviceID = device.deviceId;
1219
1252
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1220
1253
  if (device.firmware) {
1221
- existingAccessory.context.FirmwareRevision = device.firmware;
1254
+ existingAccessory.context.version = device.firmware;
1222
1255
  }
1223
1256
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1224
1257
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1246,7 +1279,7 @@ export class SwitchBotPlatform {
1246
1279
  accessory.context.model = device.deviceType;
1247
1280
  accessory.context.deviceID = device.deviceId;
1248
1281
  if (device.firmware) {
1249
- accessory.context.FirmwareRevision = device.firmware;
1282
+ accessory.context.version = device.firmware;
1250
1283
  }
1251
1284
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1252
1285
  accessory.context.connectionType = await this.connectionType(device);
@@ -1275,7 +1308,7 @@ export class SwitchBotPlatform {
1275
1308
  existingAccessory.context.deviceID = device.deviceId;
1276
1309
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1277
1310
  if (device.firmware) {
1278
- existingAccessory.context.FirmwareRevision = device.firmware;
1311
+ existingAccessory.context.version = device.firmware;
1279
1312
  }
1280
1313
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1281
1314
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1315,7 +1348,7 @@ export class SwitchBotPlatform {
1315
1348
  accessory.context.model = device.deviceType;
1316
1349
  accessory.context.deviceID = device.deviceId;
1317
1350
  if (device.firmware) {
1318
- accessory.context.FirmwareRevision = device.firmware;
1351
+ accessory.context.version = device.firmware;
1319
1352
  }
1320
1353
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1321
1354
  accessory.context.connectionType = await this.connectionType(device);
@@ -1344,7 +1377,7 @@ export class SwitchBotPlatform {
1344
1377
  existingAccessory.context.deviceID = device.deviceId;
1345
1378
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1346
1379
  if (device.firmware) {
1347
- existingAccessory.context.FirmwareRevision = device.firmware;
1380
+ existingAccessory.context.version = device.firmware;
1348
1381
  }
1349
1382
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1350
1383
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1384,7 +1417,7 @@ export class SwitchBotPlatform {
1384
1417
  accessory.context.model = device.deviceType;
1385
1418
  accessory.context.deviceID = device.deviceId;
1386
1419
  if (device.firmware) {
1387
- accessory.context.FirmwareRevision = device.firmware;
1420
+ accessory.context.version = device.firmware;
1388
1421
  }
1389
1422
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1390
1423
  accessory.context.connectionType = await this.connectionType(device);
@@ -1413,7 +1446,7 @@ export class SwitchBotPlatform {
1413
1446
  existingAccessory.context.deviceID = device.deviceId;
1414
1447
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1415
1448
  if (device.firmware) {
1416
- existingAccessory.context.FirmwareRevision = device.firmware;
1449
+ existingAccessory.context.version = device.firmware;
1417
1450
  }
1418
1451
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1419
1452
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1441,7 +1474,7 @@ export class SwitchBotPlatform {
1441
1474
  accessory.context.model = device.deviceType;
1442
1475
  accessory.context.deviceID = device.deviceId;
1443
1476
  if (device.firmware) {
1444
- accessory.context.FirmwareRevision = device.firmware;
1477
+ accessory.context.version = device.firmware;
1445
1478
  }
1446
1479
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1447
1480
  accessory.context.connectionType = await this.connectionType(device);
@@ -1470,7 +1503,7 @@ export class SwitchBotPlatform {
1470
1503
  existingAccessory.context.deviceID = device.deviceId;
1471
1504
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1472
1505
  if (device.firmware) {
1473
- existingAccessory.context.FirmwareRevision = device.firmware;
1506
+ existingAccessory.context.version = device.firmware;
1474
1507
  }
1475
1508
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1476
1509
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1498,7 +1531,7 @@ export class SwitchBotPlatform {
1498
1531
  accessory.context.model = device.deviceType;
1499
1532
  accessory.context.deviceID = device.deviceId;
1500
1533
  if (device.firmware) {
1501
- accessory.context.FirmwareRevision = device.firmware;
1534
+ accessory.context.version = device.firmware;
1502
1535
  }
1503
1536
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1504
1537
  accessory.context.connectionType = await this.connectionType(device);
@@ -1527,7 +1560,7 @@ export class SwitchBotPlatform {
1527
1560
  existingAccessory.context.deviceID = device.deviceId;
1528
1561
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1529
1562
  if (device.firmware) {
1530
- existingAccessory.context.FirmwareRevision = device.firmware;
1563
+ existingAccessory.context.version = device.firmware;
1531
1564
  }
1532
1565
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1533
1566
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1555,7 +1588,7 @@ export class SwitchBotPlatform {
1555
1588
  accessory.context.model = device.deviceType;
1556
1589
  accessory.context.deviceID = device.deviceId;
1557
1590
  if (device.firmware) {
1558
- accessory.context.FirmwareRevision = device.firmware;
1591
+ accessory.context.version = device.firmware;
1559
1592
  }
1560
1593
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1561
1594
  accessory.context.connectionType = await this.connectionType(device);
@@ -1584,7 +1617,7 @@ export class SwitchBotPlatform {
1584
1617
  existingAccessory.context.deviceID = device.deviceId;
1585
1618
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1586
1619
  if (device.firmware) {
1587
- existingAccessory.context.FirmwareRevision = device.firmware;
1620
+ existingAccessory.context.version = device.firmware;
1588
1621
  }
1589
1622
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1590
1623
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1612,7 +1645,7 @@ export class SwitchBotPlatform {
1612
1645
  accessory.context.model = device.deviceType;
1613
1646
  accessory.context.deviceID = device.deviceId;
1614
1647
  if (device.firmware) {
1615
- accessory.context.FirmwareRevision = device.firmware;
1648
+ accessory.context.version = device.firmware;
1616
1649
  }
1617
1650
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1618
1651
  accessory.context.connectionType = await this.connectionType(device);
@@ -1641,7 +1674,7 @@ export class SwitchBotPlatform {
1641
1674
  existingAccessory.context.deviceID = device.deviceId;
1642
1675
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1643
1676
  if (device.firmware) {
1644
- existingAccessory.context.FirmwareRevision = device.firmware;
1677
+ existingAccessory.context.version = device.firmware;
1645
1678
  }
1646
1679
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1647
1680
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1669,7 +1702,7 @@ export class SwitchBotPlatform {
1669
1702
  accessory.context.model = device.deviceType;
1670
1703
  accessory.context.deviceID = device.deviceId;
1671
1704
  if (device.firmware) {
1672
- accessory.context.FirmwareRevision = device.firmware;
1705
+ accessory.context.version = device.firmware;
1673
1706
  }
1674
1707
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1675
1708
  accessory.context.connectionType = await this.connectionType(device);
@@ -1685,6 +1718,63 @@ export class SwitchBotPlatform {
1685
1718
  this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1686
1719
  }
1687
1720
  }
1721
+ async createFan(device) {
1722
+ const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1723
+ // see if an accessory with the same uuid has already been registered and restored from
1724
+ // the cached devices we stored in the `configureAccessory` method above
1725
+ const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid);
1726
+ if (existingAccessory) {
1727
+ // the accessory already exists
1728
+ if (await this.registerDevice(device)) {
1729
+ // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
1730
+ existingAccessory.context.model = device.deviceType;
1731
+ existingAccessory.context.deviceID = device.deviceId;
1732
+ existingAccessory.displayName = device.configDeviceName || device.deviceName;
1733
+ if (device.firmware) {
1734
+ existingAccessory.context.version = device.firmware;
1735
+ }
1736
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1737
+ this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1738
+ existingAccessory.context.connectionType = await this.connectionType(device);
1739
+ this.api.updatePlatformAccessories([existingAccessory]);
1740
+ // create the accessory handler for the restored accessory
1741
+ // this is imported from `platformAccessory.ts`
1742
+ new Fan(this, existingAccessory, device);
1743
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`);
1744
+ }
1745
+ else {
1746
+ this.unregisterPlatformAccessories(existingAccessory);
1747
+ }
1748
+ }
1749
+ else if (await this.registerDevice(device)) {
1750
+ // the accessory does not yet exist, so we need to create it
1751
+ if (!device.external) {
1752
+ this.infoLog(`Adding new accessory: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1753
+ }
1754
+ // create a new accessory
1755
+ const accessory = new this.api.platformAccessory(device.deviceName, uuid);
1756
+ // store a copy of the device object in the `accessory.context`
1757
+ // the `context` property can be used to store any data about the accessory you may need
1758
+ accessory.context.device = device;
1759
+ accessory.context.model = device.deviceType;
1760
+ accessory.context.deviceID = device.deviceId;
1761
+ if (device.firmware) {
1762
+ accessory.context.version = device.firmware;
1763
+ }
1764
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1765
+ accessory.context.connectionType = await this.connectionType(device);
1766
+ // create the accessory handler for the newly create accessory
1767
+ // this is imported from `platformAccessory.ts`
1768
+ new Fan(this, accessory, device);
1769
+ this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`);
1770
+ // publish device externally or link the accessory to your platform
1771
+ this.externalOrPlatform(device, accessory);
1772
+ this.accessories.push(accessory);
1773
+ }
1774
+ else {
1775
+ this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
1776
+ }
1777
+ }
1688
1778
  async createRobotVacuumCleaner(device) {
1689
1779
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
1690
1780
  // see if an accessory with the same uuid has already been registered and restored from
@@ -1698,7 +1788,7 @@ export class SwitchBotPlatform {
1698
1788
  existingAccessory.context.deviceID = device.deviceId;
1699
1789
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1700
1790
  if (device.firmware) {
1701
- existingAccessory.context.FirmwareRevision = device.firmware;
1791
+ existingAccessory.context.version = device.firmware;
1702
1792
  }
1703
1793
  existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1704
1794
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1726,7 +1816,7 @@ export class SwitchBotPlatform {
1726
1816
  accessory.context.model = device.deviceType;
1727
1817
  accessory.context.deviceID = device.deviceId;
1728
1818
  if (device.firmware) {
1729
- accessory.context.FirmwareRevision = device.firmware;
1819
+ accessory.context.version = device.firmware;
1730
1820
  }
1731
1821
  accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
1732
1822
  accessory.context.connectionType = await this.connectionType(device);
@@ -1752,7 +1842,9 @@ export class SwitchBotPlatform {
1752
1842
  existingAccessory.context.model = device.remoteType;
1753
1843
  existingAccessory.context.deviceID = device.deviceId;
1754
1844
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1755
- existingAccessory.context.FirmwareRevision = device.firmware;
1845
+ if (device.version && !device.firmware) {
1846
+ existingAccessory.context.version = device.version;
1847
+ }
1756
1848
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1757
1849
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
1758
1850
  existingAccessory.context.connectionType = device.connectionType;
@@ -1775,7 +1867,7 @@ export class SwitchBotPlatform {
1775
1867
  accessory.context.model = device.remoteType;
1776
1868
  accessory.context.deviceID = device.deviceId;
1777
1869
  if (device.firmware) {
1778
- accessory.context.FirmwareRevision = device.firmware;
1870
+ accessory.context.version = device.firmware;
1779
1871
  }
1780
1872
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1781
1873
  accessory.context.connectionType = device.connectionType;
@@ -1790,7 +1882,7 @@ export class SwitchBotPlatform {
1790
1882
  this.debugLog(`Device not registered: ${device.deviceName} ${device.remoteType} DeviceID: ${device.deviceId}`);
1791
1883
  }
1792
1884
  }
1793
- async createFan(device) {
1885
+ async createIRFan(device) {
1794
1886
  const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
1795
1887
  // see if an accessory with the same uuid has already been registered and restored from
1796
1888
  // the cached devices we stored in the `configureAccessory` method above
@@ -1803,7 +1895,7 @@ export class SwitchBotPlatform {
1803
1895
  existingAccessory.context.deviceID = device.deviceId;
1804
1896
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1805
1897
  if (device.firmware) {
1806
- existingAccessory.context.FirmwareRevision = device.firmware;
1898
+ existingAccessory.context.version = device.firmware;
1807
1899
  }
1808
1900
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1809
1901
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1811,7 +1903,7 @@ export class SwitchBotPlatform {
1811
1903
  this.api.updatePlatformAccessories([existingAccessory]);
1812
1904
  // create the accessory handler for the restored accessory
1813
1905
  // this is imported from `platformAccessory.ts`
1814
- new Fan(this, existingAccessory, device);
1906
+ new IRFan(this, existingAccessory, device);
1815
1907
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`);
1816
1908
  }
1817
1909
  else {
@@ -1831,13 +1923,13 @@ export class SwitchBotPlatform {
1831
1923
  accessory.context.model = device.remoteType;
1832
1924
  accessory.context.deviceID = device.deviceId;
1833
1925
  if (device.firmware) {
1834
- accessory.context.FirmwareRevision = device.firmware;
1926
+ accessory.context.version = device.firmware;
1835
1927
  }
1836
1928
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1837
1929
  accessory.context.connectionType = device.connectionType;
1838
1930
  // create the accessory handler for the newly create accessory
1839
1931
  // this is imported from `platformAccessory.ts`
1840
- new Fan(this, accessory, device);
1932
+ new IRFan(this, accessory, device);
1841
1933
  this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
1842
1934
  // publish device externally or link the accessory to your platform
1843
1935
  this.externalOrPlatformIR(device, accessory);
@@ -1860,7 +1952,7 @@ export class SwitchBotPlatform {
1860
1952
  existingAccessory.context.deviceID = device.deviceId;
1861
1953
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1862
1954
  if (device.firmware) {
1863
- existingAccessory.context.FirmwareRevision = device.firmware;
1955
+ existingAccessory.context.version = device.firmware;
1864
1956
  }
1865
1957
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1866
1958
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1888,7 +1980,7 @@ export class SwitchBotPlatform {
1888
1980
  accessory.context.model = device.remoteType;
1889
1981
  accessory.context.deviceID = device.deviceId;
1890
1982
  if (device.firmware) {
1891
- accessory.context.FirmwareRevision = device.firmware;
1983
+ accessory.context.version = device.firmware;
1892
1984
  }
1893
1985
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1894
1986
  accessory.context.connectionType = device.connectionType;
@@ -1917,7 +2009,7 @@ export class SwitchBotPlatform {
1917
2009
  existingAccessory.context.deviceID = device.deviceId;
1918
2010
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1919
2011
  if (device.firmware) {
1920
- existingAccessory.context.FirmwareRevision = device.firmware;
2012
+ existingAccessory.context.version = device.firmware;
1921
2013
  }
1922
2014
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1923
2015
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -1945,7 +2037,7 @@ export class SwitchBotPlatform {
1945
2037
  accessory.context.model = device.remoteType;
1946
2038
  accessory.context.deviceID = device.deviceId;
1947
2039
  if (device.firmware) {
1948
- accessory.context.FirmwareRevision = device.firmware;
2040
+ accessory.context.version = device.firmware;
1949
2041
  }
1950
2042
  accessory.context.deviceType = `IR: ${device.remoteType}`;
1951
2043
  accessory.context.connectionType = device.connectionType;
@@ -1974,7 +2066,7 @@ export class SwitchBotPlatform {
1974
2066
  existingAccessory.context.deviceID = device.deviceId;
1975
2067
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
1976
2068
  if (device.firmware) {
1977
- existingAccessory.context.FirmwareRevision = device.firmware;
2069
+ existingAccessory.context.version = device.firmware;
1978
2070
  }
1979
2071
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
1980
2072
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2002,7 +2094,7 @@ export class SwitchBotPlatform {
2002
2094
  accessory.context.model = device.remoteType;
2003
2095
  accessory.context.deviceID = device.deviceId;
2004
2096
  if (device.firmware) {
2005
- accessory.context.FirmwareRevision = device.firmware;
2097
+ accessory.context.version = device.firmware;
2006
2098
  }
2007
2099
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2008
2100
  accessory.context.connectionType = device.connectionType;
@@ -2031,7 +2123,7 @@ export class SwitchBotPlatform {
2031
2123
  existingAccessory.context.deviceID = device.deviceId;
2032
2124
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2033
2125
  if (device.firmware) {
2034
- existingAccessory.context.FirmwareRevision = device.firmware;
2126
+ existingAccessory.context.version = device.firmware;
2035
2127
  }
2036
2128
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2037
2129
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2059,7 +2151,7 @@ export class SwitchBotPlatform {
2059
2151
  accessory.context.model = device.remoteType;
2060
2152
  accessory.context.deviceID = device.deviceId;
2061
2153
  if (device.firmware) {
2062
- accessory.context.FirmwareRevision = device.firmware;
2154
+ accessory.context.version = device.firmware;
2063
2155
  }
2064
2156
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2065
2157
  accessory.context.connectionType = device.connectionType;
@@ -2088,7 +2180,7 @@ export class SwitchBotPlatform {
2088
2180
  existingAccessory.context.deviceID = device.deviceId;
2089
2181
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2090
2182
  if (device.firmware) {
2091
- existingAccessory.context.FirmwareRevision = device.firmware;
2183
+ existingAccessory.context.version = device.firmware;
2092
2184
  }
2093
2185
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2094
2186
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2116,7 +2208,7 @@ export class SwitchBotPlatform {
2116
2208
  accessory.context.model = device.remoteType;
2117
2209
  accessory.context.deviceID = device.deviceId;
2118
2210
  if (device.firmware) {
2119
- accessory.context.FirmwareRevision = device.firmware;
2211
+ accessory.context.version = device.firmware;
2120
2212
  }
2121
2213
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2122
2214
  accessory.context.connectionType = device.connectionType;
@@ -2145,7 +2237,7 @@ export class SwitchBotPlatform {
2145
2237
  existingAccessory.context.deviceID = device.deviceId;
2146
2238
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2147
2239
  if (device.firmware) {
2148
- existingAccessory.context.FirmwareRevision = device.firmware;
2240
+ existingAccessory.context.version = device.firmware;
2149
2241
  }
2150
2242
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2151
2243
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2173,7 +2265,7 @@ export class SwitchBotPlatform {
2173
2265
  accessory.context.model = device.remoteType;
2174
2266
  accessory.context.deviceID = device.deviceId;
2175
2267
  if (device.firmware) {
2176
- accessory.context.FirmwareRevision = device.firmware;
2268
+ accessory.context.version = device.firmware;
2177
2269
  }
2178
2270
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2179
2271
  accessory.context.connectionType = device.connectionType;
@@ -2202,7 +2294,7 @@ export class SwitchBotPlatform {
2202
2294
  existingAccessory.context.deviceID = device.deviceId;
2203
2295
  existingAccessory.displayName = device.configDeviceName || device.deviceName;
2204
2296
  if (device.firmware) {
2205
- existingAccessory.context.FirmwareRevision = device.firmware;
2297
+ existingAccessory.context.version = device.firmware;
2206
2298
  }
2207
2299
  existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
2208
2300
  this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
@@ -2230,7 +2322,7 @@ export class SwitchBotPlatform {
2230
2322
  accessory.context.model = device.remoteType;
2231
2323
  accessory.context.deviceID = device.deviceId;
2232
2324
  if (device.firmware) {
2233
- accessory.context.FirmwareRevision = device.firmware;
2325
+ accessory.context.version = device.firmware;
2234
2326
  }
2235
2327
  accessory.context.deviceType = `IR: ${device.remoteType}`;
2236
2328
  accessory.context.connectionType = device.connectionType;
@@ -2492,6 +2584,29 @@ export class SwitchBotPlatform {
2492
2584
  this.errorLog(`Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
2493
2585
  }
2494
2586
  }
2587
+ async retryRequest(deviceMaxRetries, deviceDelayBetweenRetries, url, options) {
2588
+ let retryCount = 0;
2589
+ const maxRetries = deviceMaxRetries;
2590
+ const delayBetweenRetries = deviceDelayBetweenRetries;
2591
+ while (retryCount < maxRetries) {
2592
+ try {
2593
+ const { body, statusCode } = await request(url, options);
2594
+ if (statusCode === 200 || statusCode === 100) {
2595
+ return { body, statusCode };
2596
+ }
2597
+ else {
2598
+ this.debugLog(`Received status code: ${statusCode}`);
2599
+ }
2600
+ }
2601
+ catch (error) {
2602
+ this.errorLog(`Error making request: ${error.message}`);
2603
+ }
2604
+ retryCount++;
2605
+ this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
2606
+ await sleep(delayBetweenRetries);
2607
+ }
2608
+ return { body: null, statusCode: -1 };
2609
+ }
2495
2610
  // BLE Connection
2496
2611
  async connectBLE() {
2497
2612
  let switchbot;
@@ -2522,6 +2637,24 @@ export class SwitchBotPlatform {
2522
2637
  if (this.config.options.pushRate) {
2523
2638
  platformConfig.pushRate = this.config.options.pushRate;
2524
2639
  }
2640
+ if (this.config.options.maxRetries) {
2641
+ this.maxRetries = this.config.options.maxRetries;
2642
+ platformConfig.maxRetries = this.config.options.maxRetries;
2643
+ }
2644
+ else {
2645
+ this.maxRetries = 3;
2646
+ this.debugWarnLog('Using Default Max Retries');
2647
+ platformConfig.maxRetries = this.maxRetries;
2648
+ }
2649
+ if (this.config.options.delayBetweenRetries) {
2650
+ this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
2651
+ platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries;
2652
+ }
2653
+ else {
2654
+ this.delayBetweenRetries = 3000;
2655
+ this.debugWarnLog('Using Default Delay Between Retries');
2656
+ platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
2657
+ }
2525
2658
  if (Object.entries(platformConfig).length !== 0) {
2526
2659
  this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
2527
2660
  }
@@ -2547,6 +2680,11 @@ export class SwitchBotPlatform {
2547
2680
  * If device level logging is turned on, log to log.warn
2548
2681
  * Otherwise send debug logs to log.debug
2549
2682
  */
2683
+ successLog(...log) {
2684
+ if (this.enablingPlatformLogging()) {
2685
+ this.log.success(String(...log));
2686
+ }
2687
+ }
2550
2688
  infoLog(...log) {
2551
2689
  if (this.enablingPlatformLogging()) {
2552
2690
  this.log.info(String(...log));