@switchbot/homebridge-switchbot 1.6.4-beta.5 → 1.7.1-beta.10

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 (97) hide show
  1. package/CHANGELOG.md +23 -2
  2. package/config.schema.json +125 -33
  3. package/dist/devices/bots.d.ts +21 -9
  4. package/dist/devices/bots.d.ts.map +1 -1
  5. package/dist/devices/bots.js +352 -48
  6. package/dist/devices/bots.js.map +1 -1
  7. package/dist/devices/colorbulb.d.ts +6 -1
  8. package/dist/devices/colorbulb.d.ts.map +1 -1
  9. package/dist/devices/colorbulb.js +18 -11
  10. package/dist/devices/colorbulb.js.map +1 -1
  11. package/dist/devices/contact.d.ts +10 -2
  12. package/dist/devices/contact.d.ts.map +1 -1
  13. package/dist/devices/contact.js +92 -51
  14. package/dist/devices/contact.js.map +1 -1
  15. package/dist/devices/curtains.d.ts +10 -3
  16. package/dist/devices/curtains.d.ts.map +1 -1
  17. package/dist/devices/curtains.js +52 -34
  18. package/dist/devices/curtains.js.map +1 -1
  19. package/dist/devices/humidifiers.d.ts +8 -2
  20. package/dist/devices/humidifiers.d.ts.map +1 -1
  21. package/dist/devices/humidifiers.js +28 -35
  22. package/dist/devices/humidifiers.js.map +1 -1
  23. package/dist/devices/meters.d.ts +14 -12
  24. package/dist/devices/meters.d.ts.map +1 -1
  25. package/dist/devices/meters.js +63 -103
  26. package/dist/devices/meters.js.map +1 -1
  27. package/dist/devices/motion.d.ts +10 -3
  28. package/dist/devices/motion.d.ts.map +1 -1
  29. package/dist/devices/motion.js +114 -68
  30. package/dist/devices/motion.js.map +1 -1
  31. package/dist/devices/plugs.d.ts +3 -1
  32. package/dist/devices/plugs.d.ts.map +1 -1
  33. package/dist/devices/plugs.js +8 -1
  34. package/dist/devices/plugs.js.map +1 -1
  35. package/dist/irdevices/airconditioners.d.ts +1 -0
  36. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  37. package/dist/irdevices/airconditioners.js +6 -0
  38. package/dist/irdevices/airconditioners.js.map +1 -1
  39. package/dist/irdevices/airpurifiers.d.ts +1 -0
  40. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  41. package/dist/irdevices/airpurifiers.js +6 -0
  42. package/dist/irdevices/airpurifiers.js.map +1 -1
  43. package/dist/irdevices/cameras.d.ts +1 -0
  44. package/dist/irdevices/cameras.d.ts.map +1 -1
  45. package/dist/irdevices/cameras.js +6 -0
  46. package/dist/irdevices/cameras.js.map +1 -1
  47. package/dist/irdevices/fans.d.ts +1 -0
  48. package/dist/irdevices/fans.d.ts.map +1 -1
  49. package/dist/irdevices/fans.js +6 -0
  50. package/dist/irdevices/fans.js.map +1 -1
  51. package/dist/irdevices/lights.d.ts +1 -0
  52. package/dist/irdevices/lights.d.ts.map +1 -1
  53. package/dist/irdevices/lights.js +6 -0
  54. package/dist/irdevices/lights.js.map +1 -1
  55. package/dist/irdevices/others.d.ts +1 -0
  56. package/dist/irdevices/others.d.ts.map +1 -1
  57. package/dist/irdevices/others.js +6 -0
  58. package/dist/irdevices/others.js.map +1 -1
  59. package/dist/irdevices/tvs.d.ts +1 -0
  60. package/dist/irdevices/tvs.d.ts.map +1 -1
  61. package/dist/irdevices/tvs.js +6 -0
  62. package/dist/irdevices/tvs.js.map +1 -1
  63. package/dist/irdevices/vacuumcleaners.d.ts +1 -0
  64. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  65. package/dist/irdevices/vacuumcleaners.js +6 -0
  66. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  67. package/dist/irdevices/waterheaters.d.ts +1 -0
  68. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  69. package/dist/irdevices/waterheaters.js +6 -0
  70. package/dist/irdevices/waterheaters.js.map +1 -1
  71. package/dist/platform.d.ts +2 -1
  72. package/dist/platform.d.ts.map +1 -1
  73. package/dist/platform.js +14 -1
  74. package/dist/platform.js.map +1 -1
  75. package/dist/settings.d.ts +14 -0
  76. package/dist/settings.d.ts.map +1 -1
  77. package/dist/settings.js.map +1 -1
  78. package/package.json +5 -5
  79. package/src/devices/bots.ts +355 -52
  80. package/src/devices/colorbulb.ts +24 -14
  81. package/src/devices/contact.ts +99 -55
  82. package/src/devices/curtains.ts +60 -36
  83. package/src/devices/humidifiers.ts +36 -36
  84. package/src/devices/meters.ts +79 -113
  85. package/src/devices/motion.ts +125 -74
  86. package/src/devices/plugs.ts +11 -2
  87. package/src/irdevices/airconditioners.ts +7 -0
  88. package/src/irdevices/airpurifiers.ts +7 -0
  89. package/src/irdevices/cameras.ts +7 -0
  90. package/src/irdevices/fans.ts +7 -0
  91. package/src/irdevices/lights.ts +7 -0
  92. package/src/irdevices/others.ts +7 -0
  93. package/src/irdevices/tvs.ts +7 -0
  94. package/src/irdevices/vacuumcleaners.ts +7 -0
  95. package/src/irdevices/waterheaters.ts +7 -0
  96. package/src/platform.ts +14 -1
  97. package/src/settings.ts +15 -0
@@ -4,7 +4,7 @@ import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform';
5
5
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
6
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
7
- import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, payload } from '../settings';
7
+ import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, payload, deviceStatus } from '../settings';
8
8
 
9
9
  /**
10
10
  * Platform Accessory
@@ -13,12 +13,17 @@ import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceSta
13
13
  */
14
14
  export class Bot {
15
15
  // Services
16
- private switchService?: Service;
16
+ private fanService?: Service;
17
17
  private doorService?: Service;
18
18
  private lockService?: Service;
19
- private garageDoorService?: Service;
19
+ private faucetService?: Service;
20
+ private windowService?: Service;
21
+ private switchService?: Service;
20
22
  private outletService?: Service;
21
23
  private batteryService?: Service;
24
+ private garageDoorService?: Service;
25
+ private windowCoveringService?: Service;
26
+ private statefulProgrammableSwitchService?: Service;
22
27
 
23
28
 
24
29
  // Characteristic Values
@@ -28,11 +33,13 @@ export class Bot {
28
33
  StatusLowBattery!: CharacteristicValue;
29
34
 
30
35
  // OpenAPI Others
36
+ power: deviceStatus['power'];
31
37
  deviceStatus!: deviceStatusResponse;
32
38
 
33
39
  // BLE Others
34
40
  connected?: boolean;
35
41
  switchbot!: switchbot;
42
+ SwitchToOpenAPI?: boolean;
36
43
  serviceData!: serviceData;
37
44
  mode!: serviceData['mode'];
38
45
  state!: serviceData['state'];
@@ -61,7 +68,7 @@ export class Bot {
61
68
  this.scan();
62
69
  this.refreshRate();
63
70
  this.PressOrSwitch();
64
-
71
+ this.config(device);
65
72
  if (this.On === undefined) {
66
73
  this.On = false;
67
74
  this.accessory.context.On = this.On;
@@ -77,10 +84,6 @@ export class Bot {
77
84
  this.BatteryLevel = 100;
78
85
  this.StatusLowBattery = 0;
79
86
 
80
- // Bot Config
81
- this.debugLog(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, mode: ${device.bot?.mode},`
82
- + ` deviceType: ${device.bot?.deviceType}, doublePress: ${this.doublePress})`);
83
-
84
87
  // this is subject we use to track when we need to POST changes to the SwitchBot API
85
88
  this.doBotUpdate = new Subject();
86
89
  this.botUpdateInProgress = false;
@@ -98,10 +101,15 @@ export class Bot {
98
101
  // get the LightBulb service if it exists, otherwise create a new LightBulb service
99
102
  // you can create multiple services for each accessory
100
103
  if (device.bot?.deviceType === 'switch') {
104
+ this.removeFanService(accessory);
101
105
  this.removeLockService(accessory);
102
106
  this.removeDoorService(accessory);
107
+ this.removeFaucetService(accessory);
103
108
  this.removeOutletService(accessory);
109
+ this.removeWindowService(accessory);
104
110
  this.removeGarageDoorService(accessory);
111
+ this.removeWindowCoveringService(accessory);
112
+ this.removeStatefulProgrammableSwitchService(accessory);
105
113
 
106
114
  // Add switchService
107
115
  (this.switchService =
@@ -112,10 +120,15 @@ export class Bot {
112
120
  this.switchService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
113
121
  this.switchService.getCharacteristic(this.platform.Characteristic.On).onSet(this.handleOnSet.bind(this));
114
122
  } else if (device.bot?.deviceType === 'garagedoor') {
123
+ this.removeFanService(accessory);
115
124
  this.removeLockService(accessory);
116
125
  this.removeDoorService(accessory);
126
+ this.removeFaucetService(accessory);
117
127
  this.removeOutletService(accessory);
118
128
  this.removeSwitchService(accessory);
129
+ this.removeWindowService(accessory);
130
+ this.removeWindowCoveringService(accessory);
131
+ this.removeStatefulProgrammableSwitchService(accessory);
119
132
 
120
133
  // Add switchService
121
134
  (this.garageDoorService =
@@ -127,10 +140,15 @@ export class Bot {
127
140
  this.garageDoorService.getCharacteristic(this.platform.Characteristic.TargetDoorState).onSet(this.handleOnSet.bind(this));
128
141
  this.garageDoorService.setCharacteristic(this.platform.Characteristic.ObstructionDetected, false);
129
142
  } else if (device.bot?.deviceType === 'door') {
143
+ this.removeFanService(accessory);
130
144
  this.removeLockService(accessory);
131
145
  this.removeOutletService(accessory);
146
+ this.removeFaucetService(accessory);
132
147
  this.removeSwitchService(accessory);
148
+ this.removeWindowService(accessory);
133
149
  this.removeGarageDoorService(accessory);
150
+ this.removeWindowCoveringService(accessory);
151
+ this.removeStatefulProgrammableSwitchService(accessory);
134
152
 
135
153
  // Add switchService
136
154
  (this.doorService =
@@ -147,11 +165,68 @@ export class Bot {
147
165
  minStep: 100,
148
166
  }).onSet(this.handleOnSet.bind(this));
149
167
  this.doorService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
168
+ } else if (device.bot?.deviceType === 'window') {
169
+ this.removeFanService(accessory);
170
+ this.removeLockService(accessory);
171
+ this.removeDoorService(accessory);
172
+ this.removeOutletService(accessory);
173
+ this.removeFaucetService(accessory);
174
+ this.removeSwitchService(accessory);
175
+ this.removeGarageDoorService(accessory);
176
+ this.removeWindowCoveringService(accessory);
177
+ this.removeStatefulProgrammableSwitchService(accessory);
178
+
179
+ // Add switchService
180
+ (this.windowService =
181
+ accessory.getService(this.platform.Service.Window) ||
182
+ accessory.addService(this.platform.Service.Window)), `${accessory.displayName} Window`;
183
+ this.infoLog(`Bot: ${accessory.displayName} Displaying as Window`);
184
+
185
+ this.windowService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
186
+ this.windowService.getCharacteristic(this.platform.Characteristic.TargetPosition)
187
+ .setProps({
188
+ validValues: [0, 100],
189
+ minValue: 0,
190
+ maxValue: 100,
191
+ minStep: 100,
192
+ }).onSet(this.handleOnSet.bind(this));
193
+ this.windowService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
194
+ } else if (device.bot?.deviceType === 'windowcovering') {
195
+ this.removeFanService(accessory);
196
+ this.removeLockService(accessory);
197
+ this.removeDoorService(accessory);
198
+ this.removeOutletService(accessory);
199
+ this.removeFaucetService(accessory);
200
+ this.removeSwitchService(accessory);
201
+ this.removeWindowService(accessory);
202
+ this.removeGarageDoorService(accessory);
203
+ this.removeStatefulProgrammableSwitchService(accessory);
204
+
205
+ // Add switchService
206
+ (this.windowCoveringService =
207
+ accessory.getService(this.platform.Service.WindowCovering) ||
208
+ accessory.addService(this.platform.Service.WindowCovering)), `${accessory.displayName} Window Covering`;
209
+ this.infoLog(`Bot: ${accessory.displayName} Displaying as Window Covering`);
210
+
211
+ this.windowCoveringService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
212
+ this.windowCoveringService.getCharacteristic(this.platform.Characteristic.TargetPosition)
213
+ .setProps({
214
+ validValues: [0, 100],
215
+ minValue: 0,
216
+ maxValue: 100,
217
+ minStep: 100,
218
+ }).onSet(this.handleOnSet.bind(this));
219
+ this.windowCoveringService.setCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED);
150
220
  } else if (device.bot?.deviceType === 'lock') {
221
+ this.removeFanService(accessory);
151
222
  this.removeDoorService(accessory);
152
223
  this.removeOutletService(accessory);
153
224
  this.removeSwitchService(accessory);
225
+ this.removeFaucetService(accessory);
226
+ this.removeWindowService(accessory);
154
227
  this.removeGarageDoorService(accessory);
228
+ this.removeWindowCoveringService(accessory);
229
+ this.removeStatefulProgrammableSwitchService(accessory);
155
230
 
156
231
  // Add switchService
157
232
  (this.lockService =
@@ -161,11 +236,74 @@ export class Bot {
161
236
 
162
237
  this.lockService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
163
238
  this.lockService.getCharacteristic(this.platform.Characteristic.LockTargetState).onSet(this.handleOnSet.bind(this));
239
+ } else if (device.bot?.deviceType === 'faucet') {
240
+ this.removeFanService(accessory);
241
+ this.removeLockService(accessory);
242
+ this.removeDoorService(accessory);
243
+ this.removeOutletService(accessory);
244
+ this.removeSwitchService(accessory);
245
+ this.removeWindowService(accessory);
246
+ this.removeGarageDoorService(accessory);
247
+ this.removeWindowCoveringService(accessory);
248
+ this.removeStatefulProgrammableSwitchService(accessory);
249
+
250
+ // Add switchService
251
+ (this.faucetService =
252
+ accessory.getService(this.platform.Service.Faucet) ||
253
+ accessory.addService(this.platform.Service.Faucet)), `${accessory.displayName} Faucet`;
254
+ this.infoLog(`Bot: ${accessory.displayName} Displaying as Faucet`);
255
+
256
+ this.faucetService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
257
+ this.faucetService.getCharacteristic(this.platform.Characteristic.Active).onSet(this.handleOnSet.bind(this));
258
+ } else if (device.bot?.deviceType === 'fan') {
259
+ this.removeLockService(accessory);
260
+ this.removeDoorService(accessory);
261
+ this.removeFaucetService(accessory);
262
+ this.removeOutletService(accessory);
263
+ this.removeSwitchService(accessory);
264
+ this.removeWindowService(accessory);
265
+ this.removeGarageDoorService(accessory);
266
+ this.removeWindowCoveringService(accessory);
267
+ this.removeStatefulProgrammableSwitchService(accessory);
268
+
269
+ // Add switchService
270
+ (this.fanService =
271
+ accessory.getService(this.platform.Service.Fan) ||
272
+ accessory.addService(this.platform.Service.Fan)), `${accessory.displayName} Fan`;
273
+ this.infoLog(`Bot: ${accessory.displayName} Displaying as Fan`);
274
+
275
+ this.fanService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
276
+ this.fanService.getCharacteristic(this.platform.Characteristic.On).onSet(this.handleOnSet.bind(this));
277
+ } else if (device.bot?.deviceType === 'stateful') {
278
+ this.removeFanService(accessory);
279
+ this.removeLockService(accessory);
280
+ this.removeDoorService(accessory);
281
+ this.removeFaucetService(accessory);
282
+ this.removeOutletService(accessory);
283
+ this.removeSwitchService(accessory);
284
+ this.removeWindowService(accessory);
285
+ this.removeGarageDoorService(accessory);
286
+ this.removeWindowCoveringService(accessory);
287
+
288
+ // Add switchService
289
+ (this.statefulProgrammableSwitchService =
290
+ accessory.getService(this.platform.Service.StatefulProgrammableSwitch) ||
291
+ accessory.addService(this.platform.Service.StatefulProgrammableSwitch)), `${accessory.displayName} Stateful Programmable Switch`;
292
+ this.infoLog(`Bot: ${accessory.displayName} Displaying as Stateful Programmable Switch`);
293
+
294
+ this.statefulProgrammableSwitchService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
295
+ this.statefulProgrammableSwitchService.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState)
296
+ .onSet(this.handleOnSet.bind(this));
164
297
  } else {
298
+ this.removeFanService(accessory);
165
299
  this.removeLockService(accessory);
166
300
  this.removeDoorService(accessory);
301
+ this.removeFaucetService(accessory);
167
302
  this.removeSwitchService(accessory);
303
+ this.removeWindowService(accessory);
168
304
  this.removeGarageDoorService(accessory);
305
+ this.removeWindowCoveringService(accessory);
306
+ this.removeStatefulProgrammableSwitchService(accessory);
169
307
 
170
308
  // Add outletService
171
309
  (this.outletService =
@@ -177,12 +315,21 @@ export class Bot {
177
315
  this.outletService.getCharacteristic(this.platform.Characteristic.On).onSet(this.handleOnSet.bind(this));
178
316
  }
179
317
 
180
- if (device.ble) {
318
+ // Battery Service
319
+ if (!device.ble) {
320
+ this.debugLog(`Bot: ${accessory.displayName} Removing Battery Service`);
321
+ this.batteryService = this.accessory.getService(this.platform.Service.Battery);
322
+ accessory.removeService(this.batteryService!);
323
+ } else if (device.ble && !this.batteryService) {
324
+ this.debugLog(`Bot: ${accessory.displayName} Add Battery Service`);
181
325
  (this.batteryService =
182
- accessory.getService(this.platform.Service.Battery) ||
183
- accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
326
+ this.accessory.getService(this.platform.Service.Battery) ||
327
+ this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
184
328
 
185
329
  this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
330
+
331
+ } else {
332
+ this.debugLog(`Bot: ${accessory.displayName} Battery Service Not Added`);
186
333
  }
187
334
 
188
335
  // Retrieve initial values and updateHomekit
@@ -226,7 +373,13 @@ export class Bot {
226
373
  });
227
374
  }
228
375
 
229
- private removeOutletService(accessory: PlatformAccessory) {
376
+ config(device: device & devicesConfig) {
377
+ if (device.bot !== undefined || device.ble !== undefined) {
378
+ this.warnLog(`Bot: ${this.accessory.displayName} Config: ${JSON.stringify(device.bot)}, BLE: ${device.ble}`);
379
+ }
380
+ }
381
+
382
+ public removeOutletService(accessory: PlatformAccessory) {
230
383
  // If outletService still pressent, then remove first
231
384
  this.outletService = this.accessory.getService(this.platform.Service.Outlet);
232
385
  if (this.outletService) {
@@ -235,7 +388,7 @@ export class Bot {
235
388
  accessory.removeService(this.outletService!);
236
389
  }
237
390
 
238
- private removeGarageDoorService(accessory: PlatformAccessory) {
391
+ public removeGarageDoorService(accessory: PlatformAccessory) {
239
392
  // If garageDoorService still pressent, then remove first
240
393
  this.garageDoorService = this.accessory.getService(this.platform.Service.GarageDoorOpener);
241
394
  if (this.garageDoorService) {
@@ -244,7 +397,7 @@ export class Bot {
244
397
  accessory.removeService(this.garageDoorService!);
245
398
  }
246
399
 
247
- private removeDoorService(accessory: PlatformAccessory) {
400
+ public removeDoorService(accessory: PlatformAccessory) {
248
401
  // If doorService still pressent, then remove first
249
402
  this.doorService = this.accessory.getService(this.platform.Service.Door);
250
403
  if (this.doorService) {
@@ -253,7 +406,7 @@ export class Bot {
253
406
  accessory.removeService(this.doorService!);
254
407
  }
255
408
 
256
- private removeLockService(accessory: PlatformAccessory) {
409
+ public removeLockService(accessory: PlatformAccessory) {
257
410
  // If lockService still pressent, then remove first
258
411
  this.lockService = this.accessory.getService(this.platform.Service.LockMechanism);
259
412
  if (this.lockService) {
@@ -262,7 +415,52 @@ export class Bot {
262
415
  accessory.removeService(this.lockService!);
263
416
  }
264
417
 
265
- private removeSwitchService(accessory: PlatformAccessory) {
418
+ public removeFaucetService(accessory: PlatformAccessory) {
419
+ // If faucetService still pressent, then remove first
420
+ this.faucetService = this.accessory.getService(this.platform.Service.Faucet);
421
+ if (this.faucetService) {
422
+ this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Faucet Service`);
423
+ }
424
+ accessory.removeService(this.faucetService!);
425
+ }
426
+
427
+ public removeFanService(accessory: PlatformAccessory) {
428
+ // If fanService still pressent, then remove first
429
+ this.fanService = this.accessory.getService(this.platform.Service.Fan);
430
+ if (this.fanService) {
431
+ this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Fan Service`);
432
+ }
433
+ accessory.removeService(this.fanService!);
434
+ }
435
+
436
+ public removeWindowService(accessory: PlatformAccessory) {
437
+ // If windowService still pressent, then remove first
438
+ this.windowService = this.accessory.getService(this.platform.Service.Window);
439
+ if (this.windowService) {
440
+ this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Window Service`);
441
+ }
442
+ accessory.removeService(this.windowService!);
443
+ }
444
+
445
+ public removeWindowCoveringService(accessory: PlatformAccessory) {
446
+ // If windowCoveringService still pressent, then remove first
447
+ this.windowCoveringService = this.accessory.getService(this.platform.Service.WindowCovering);
448
+ if (this.windowCoveringService) {
449
+ this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Window Covering Service`);
450
+ }
451
+ accessory.removeService(this.windowCoveringService!);
452
+ }
453
+
454
+ public removeStatefulProgrammableSwitchService(accessory: PlatformAccessory) {
455
+ // If statefulProgrammableSwitchService still pressent, then remove first
456
+ this.statefulProgrammableSwitchService = this.accessory.getService(this.platform.Service.StatefulProgrammableSwitch);
457
+ if (this.statefulProgrammableSwitchService) {
458
+ this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
459
+ }
460
+ accessory.removeService(this.statefulProgrammableSwitchService!);
461
+ }
462
+
463
+ public removeSwitchService(accessory: PlatformAccessory) {
266
464
  // If switchService still pressent, then remove first
267
465
  this.switchService = this.accessory.getService(this.platform.Service.Switch);
268
466
  if (this.switchService) {
@@ -274,12 +472,12 @@ export class Bot {
274
472
  refreshRate() {
275
473
  if (this.device.refreshRate) {
276
474
  this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
277
- if (this.platform.debugMode || (this.deviceLogging === 'debug')) {
475
+ if (this.deviceLogging === 'debug' || this.deviceLogging === 'standard') {
278
476
  this.warnLog(`Bot: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
279
477
  }
280
478
  } else if (this.platform.config.options!.refreshRate) {
281
479
  this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
282
- if (this.platform.debugMode || (this.deviceLogging === 'debug')) {
480
+ if (this.deviceLogging === 'debug') {
283
481
  this.warnLog(`Bot: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
284
482
  }
285
483
  }
@@ -288,12 +486,12 @@ export class Bot {
288
486
  scan() {
289
487
  if (this.device.scanDuration) {
290
488
  this.scanDuration = this.accessory.context.scanDuration = this.device.scanDuration;
291
- if (this.platform.debugMode || (this.deviceLogging === 'debug')) {
489
+ if (this.device.ble && (this.deviceLogging === 'debug' || this.deviceLogging === 'standard')) {
292
490
  this.warnLog(`Bot: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
293
491
  }
294
492
  } else {
295
493
  this.scanDuration = this.accessory.context.scanDuration = 1;
296
- if (this.platform.debugMode || (this.deviceLogging === 'debug')) {
494
+ if (this.device.ble && this.deviceLogging === 'debug') {
297
495
  this.warnLog(`Bot: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
298
496
  }
299
497
  }
@@ -338,10 +536,10 @@ export class Bot {
338
536
  * Parse the device status from the SwitchBot api
339
537
  */
340
538
  async parseStatus() {
341
- if (this.device.ble) {
342
- await this.BLEparseStatus();
343
- } else {
539
+ if (this.SwitchToOpenAPI || !this.device.ble) {
344
540
  await this.openAPIparseStatus();
541
+ } else {
542
+ await this.BLEparseStatus();
345
543
  }
346
544
  }
347
545
 
@@ -375,6 +573,9 @@ export class Bot {
375
573
  }
376
574
 
377
575
  private async openAPIparseStatus() {
576
+ if (this.device.ble) {
577
+ this.SwitchToOpenAPI = false;
578
+ }
378
579
  if (this.platform.config.credentials?.openToken) {
379
580
  this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI parseStatus`);
380
581
  if (this.botMode === 'press') {
@@ -382,7 +583,7 @@ export class Bot {
382
583
  this.OnCached = this.On;
383
584
  this.accessory.context.On = this.OnCached;
384
585
  } else {
385
- if (this.deviceStatus.body.power === 'on') {
586
+ /*if (this.power === 'on') {
386
587
  this.On = true;
387
588
  this.OnCached = this.On;
388
589
  this.accessory.context.On = this.OnCached;
@@ -390,6 +591,11 @@ export class Bot {
390
591
  this.On = false;
391
592
  this.OnCached = this.On;
392
593
  this.accessory.context.On = this.OnCached;
594
+ }*/
595
+ this.OnCached = this.On;
596
+ this.accessory.context.On = this.OnCached;
597
+ if (this.On === undefined) {
598
+ this.On = false;
393
599
  }
394
600
  }
395
601
  this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
@@ -407,35 +613,12 @@ export class Bot {
407
613
  }
408
614
  }
409
615
 
410
- public async connectBLE() {
411
- let switchbot: any;
412
- try {
413
- // eslint-disable-next-line @typescript-eslint/no-var-requires
414
- const Switchbot = require('node-switchbot');
415
- switchbot = new Switchbot();
416
- // Convert to BLE Address
417
- this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
418
- this.debugLog(`Bot: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
419
- } catch (e: any) {
420
- switchbot = false;
421
- this.errorLog(`Bot: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot}`);
422
- if (this.deviceLogging === 'debug') {
423
- this.errorLog(`Bot: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
424
- + ` Error Message: ${JSON.stringify(e.message)}`);
425
- }
426
- if (this.platform.debugMode) {
427
- this.errorLog(`Bot: ${this.accessory.displayName} 'node-switchbot' found: ${switchbot},`
428
- + ` Error: ${JSON.stringify(e)}`);
429
- }
430
- }
431
- return switchbot;
432
- }
433
-
434
616
  private async BLERefreshStatus() {
435
617
  this.debugLog(`Bot: ${this.accessory.displayName} BLE refreshStatus`);
436
-
618
+ const switchbot = await this.platform.connectBLE();
437
619
  // Convert to BLE Address
438
- const switchbot = await this.connectBLE();
620
+ this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
621
+ this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
439
622
  // Start to monitor advertisement packets
440
623
  if (switchbot === false) {
441
624
  this.errorLog(`Bot: ${this.accessory.displayName} wasn't able to establish BLE Connection: ${switchbot}`);
@@ -474,6 +657,7 @@ export class Bot {
474
657
  this.errorLog(`Bot: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
475
658
  if (this.platform.config.credentials?.openToken) {
476
659
  this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
660
+ this.SwitchToOpenAPI = true;
477
661
  await this.openAPIRefreshStatus();
478
662
  }
479
663
  }
@@ -489,6 +673,7 @@ export class Bot {
489
673
  }
490
674
  if (this.platform.config.credentials?.openToken) {
491
675
  this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
676
+ this.SwitchToOpenAPI = true;
492
677
  await this.openAPIRefreshStatus();
493
678
  }
494
679
  this.apiError(e);
@@ -501,6 +686,7 @@ export class Bot {
501
686
  try {
502
687
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
503
688
  this.debugLog(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
689
+ this.power = this.deviceStatus.body.power;
504
690
  this.parseStatus();
505
691
  this.updateHomeKitCharacteristics();
506
692
  } catch (e: any) {
@@ -543,7 +729,10 @@ export class Bot {
543
729
  this.debugLog(`Bot: ${this.accessory.displayName} BLE pushChanges On: ${this.On} OnCached: ${this.OnCached}`);
544
730
  if (this.On !== this.OnCached) {
545
731
  this.debugLog(`Bot: ${this.accessory.displayName} BLE pushChanges`);
546
- const switchbot = await this.connectBLE();
732
+ const switchbot = await this.platform.connectBLE();
733
+ // Convert to BLE Address
734
+ this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
735
+ this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
547
736
  //if (switchbot !== false) {
548
737
  if (this.botMode === 'press') {
549
738
  this.debugLog(`Bot: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
@@ -721,6 +910,44 @@ export class Bot {
721
910
  }
722
911
  }
723
912
  this.debugLog(`Bot: ${this.accessory.displayName} Door On: ${this.On}`);
913
+ } else if (this.device.bot?.deviceType === 'window') {
914
+ if (this.On === undefined) {
915
+ this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
916
+ } else {
917
+ if (this.On) {
918
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 100);
919
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 100);
920
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState,
921
+ this.platform.Characteristic.PositionState.STOPPED);
922
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
923
+ } else {
924
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 0);
925
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 0);
926
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState,
927
+ this.platform.Characteristic.PositionState.STOPPED);
928
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
929
+ }
930
+ }
931
+ this.debugLog(`Bot: ${this.accessory.displayName} Window On: ${this.On}`);
932
+ } else if (this.device.bot?.deviceType === 'windowcovering') {
933
+ if (this.On === undefined) {
934
+ this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
935
+ } else {
936
+ if (this.On) {
937
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 100);
938
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 100);
939
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.PositionState,
940
+ this.platform.Characteristic.PositionState.STOPPED);
941
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
942
+ } else {
943
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, 0);
944
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, 0);
945
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.PositionState,
946
+ this.platform.Characteristic.PositionState.STOPPED);
947
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
948
+ }
949
+ }
950
+ this.debugLog(`Bot: ${this.accessory.displayName} Window Covering On: ${this.On}`);
724
951
  } else if (this.device.bot?.deviceType === 'lock') {
725
952
  if (this.On === undefined) {
726
953
  this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
@@ -740,6 +967,51 @@ export class Bot {
740
967
  }
741
968
  }
742
969
  this.debugLog(`Bot: ${this.accessory.displayName} Lock On: ${this.On}`);
970
+ } else if (this.device.bot?.deviceType === 'faucet') {
971
+ if (this.On === undefined) {
972
+ this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
973
+ } else {
974
+ if (this.On) {
975
+ this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active,
976
+ this.platform.Characteristic.Active.ACTIVE);
977
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
978
+ } else {
979
+ this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active,
980
+ this.platform.Characteristic.Active.INACTIVE);
981
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
982
+ }
983
+ }
984
+ this.debugLog(`Bot: ${this.accessory.displayName} Faucet On: ${this.On}`);
985
+ } else if (this.device.bot?.deviceType === 'fan') {
986
+ if (this.On === undefined) {
987
+ this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
988
+ } else {
989
+ if (this.On) {
990
+ this.fanService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
991
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
992
+ } else {
993
+ this.fanService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
994
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
995
+ }
996
+ }
997
+ this.debugLog(`Bot: ${this.accessory.displayName} Fan On: ${this.On}`);
998
+ } else if (this.device.bot?.deviceType === 'stateful') {
999
+ if (this.On === undefined) {
1000
+ this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
1001
+ } else {
1002
+ if (this.On) {
1003
+ this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent,
1004
+ this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
1005
+ this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, 1);
1006
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1`);
1007
+ } else {
1008
+ this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent,
1009
+ this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
1010
+ this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, 0);
1011
+ this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0`);
1012
+ }
1013
+ }
1014
+ this.debugLog(`Bot: ${this.accessory.displayName} StatefulProgrammableSwitch On: ${this.On}`);
743
1015
  } else if (this.device.bot?.deviceType === 'switch') {
744
1016
  if (this.On === undefined) {
745
1017
  this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
@@ -780,9 +1052,24 @@ export class Bot {
780
1052
  this.doorService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
781
1053
  this.doorService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
782
1054
  this.doorService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
1055
+ } else if (this.device.bot?.deviceType === 'window') {
1056
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
1057
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
1058
+ this.windowService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
1059
+ } else if (this.device.bot?.deviceType === 'windowcovering') {
1060
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.TargetPosition, e);
1061
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.CurrentPosition, e);
1062
+ this.windowCoveringService?.updateCharacteristic(this.platform.Characteristic.PositionState, e);
783
1063
  } else if (this.device.bot?.deviceType === 'lock') {
784
1064
  this.doorService?.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
785
1065
  this.doorService?.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
1066
+ } else if (this.device.bot?.deviceType === 'faucet') {
1067
+ this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, e);
1068
+ } else if (this.device.bot?.deviceType === 'fan') {
1069
+ this.fanService?.updateCharacteristic(this.platform.Characteristic.On, e);
1070
+ } else if (this.device.bot?.deviceType === 'stateful') {
1071
+ this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent, e);
1072
+ this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, e);
786
1073
  } else if (this.device.bot?.deviceType === 'switch') {
787
1074
  this.switchService?.updateCharacteristic(this.platform.Characteristic.On, e);
788
1075
  } else {
@@ -848,7 +1135,9 @@ export class Bot {
848
1135
  } else {
849
1136
  this.On = true;
850
1137
  }
851
- } else if (this.device.bot?.deviceType === 'door') {
1138
+ } else if (this.device.bot?.deviceType === 'door'
1139
+ || this.device.bot?.deviceType === 'window'
1140
+ || this.device.bot?.deviceType === 'windowcovering') {
852
1141
  this.debugLog(`Bot: ${this.accessory.displayName} TargetPosition: ${value}`);
853
1142
  if (value === 0) {
854
1143
  this.On = false;
@@ -862,6 +1151,20 @@ export class Bot {
862
1151
  } else {
863
1152
  this.On = true;
864
1153
  }
1154
+ } else if (this.device.bot?.deviceType === 'faucet') {
1155
+ this.debugLog(`Bot: ${this.accessory.displayName} Active: ${value}`);
1156
+ if (value === this.platform.Characteristic.Active.INACTIVE) {
1157
+ this.On = false;
1158
+ } else {
1159
+ this.On = true;
1160
+ }
1161
+ } else if (this.device.bot?.deviceType === 'stateful') {
1162
+ this.debugLog(`Bot: ${this.accessory.displayName} ProgrammableSwitchOutputState: ${value}`);
1163
+ if (value === 0) {
1164
+ this.On = false;
1165
+ } else {
1166
+ this.On = true;
1167
+ }
865
1168
  } else {
866
1169
  this.debugLog(`Bot: ${this.accessory.displayName} On: ${value}`);
867
1170
  this.On = value;