@switchbot/homebridge-switchbot 1.3.1-beta.1 → 1.3.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 (89) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/config.schema.json +12 -3
  3. package/dist/devices/bots.d.ts +2 -0
  4. package/dist/devices/bots.d.ts.map +1 -1
  5. package/dist/devices/bots.js +136 -95
  6. package/dist/devices/bots.js.map +1 -1
  7. package/dist/devices/colorbulb.d.ts +1 -0
  8. package/dist/devices/colorbulb.d.ts.map +1 -1
  9. package/dist/devices/colorbulb.js +18 -4
  10. package/dist/devices/colorbulb.js.map +1 -1
  11. package/dist/devices/contact.js +1 -1
  12. package/dist/devices/contact.js.map +1 -1
  13. package/dist/devices/curtains.d.ts.map +1 -1
  14. package/dist/devices/curtains.js +6 -1
  15. package/dist/devices/curtains.js.map +1 -1
  16. package/dist/devices/humidifiers.d.ts +1 -0
  17. package/dist/devices/humidifiers.d.ts.map +1 -1
  18. package/dist/devices/humidifiers.js +15 -2
  19. package/dist/devices/humidifiers.js.map +1 -1
  20. package/dist/devices/indoorcam.d.ts.map +1 -1
  21. package/dist/devices/indoorcam.js +12 -1
  22. package/dist/devices/indoorcam.js.map +1 -1
  23. package/dist/devices/plugs.d.ts +2 -0
  24. package/dist/devices/plugs.d.ts.map +1 -1
  25. package/dist/devices/plugs.js +41 -16
  26. package/dist/devices/plugs.js.map +1 -1
  27. package/dist/irdevices/airconditioners.d.ts +2 -0
  28. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  29. package/dist/irdevices/airconditioners.js +17 -1
  30. package/dist/irdevices/airconditioners.js.map +1 -1
  31. package/dist/irdevices/airpurifiers.d.ts +2 -0
  32. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  33. package/dist/irdevices/airpurifiers.js +17 -0
  34. package/dist/irdevices/airpurifiers.js.map +1 -1
  35. package/dist/irdevices/cameras.d.ts +1 -0
  36. package/dist/irdevices/cameras.d.ts.map +1 -1
  37. package/dist/irdevices/cameras.js +9 -0
  38. package/dist/irdevices/cameras.js.map +1 -1
  39. package/dist/irdevices/fans.d.ts +1 -0
  40. package/dist/irdevices/fans.d.ts.map +1 -1
  41. package/dist/irdevices/fans.js +9 -0
  42. package/dist/irdevices/fans.js.map +1 -1
  43. package/dist/irdevices/lights.d.ts +1 -0
  44. package/dist/irdevices/lights.d.ts.map +1 -1
  45. package/dist/irdevices/lights.js +9 -0
  46. package/dist/irdevices/lights.js.map +1 -1
  47. package/dist/irdevices/others.d.ts +1 -0
  48. package/dist/irdevices/others.d.ts.map +1 -1
  49. package/dist/irdevices/others.js +9 -0
  50. package/dist/irdevices/others.js.map +1 -1
  51. package/dist/irdevices/tvs.d.ts +1 -0
  52. package/dist/irdevices/tvs.d.ts.map +1 -1
  53. package/dist/irdevices/tvs.js +9 -0
  54. package/dist/irdevices/tvs.js.map +1 -1
  55. package/dist/irdevices/vacuumcleaners.d.ts +1 -0
  56. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  57. package/dist/irdevices/vacuumcleaners.js +9 -0
  58. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  59. package/dist/irdevices/waterheaters.d.ts +1 -0
  60. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  61. package/dist/irdevices/waterheaters.js +9 -0
  62. package/dist/irdevices/waterheaters.js.map +1 -1
  63. package/dist/platform.d.ts +2 -0
  64. package/dist/platform.d.ts.map +1 -1
  65. package/dist/platform.js +106 -20
  66. package/dist/platform.js.map +1 -1
  67. package/dist/settings.d.ts +1 -0
  68. package/dist/settings.d.ts.map +1 -1
  69. package/dist/settings.js.map +1 -1
  70. package/homebridge-ui/public/index.html +5 -1
  71. package/package.json +7 -7
  72. package/src/devices/bots.ts +124 -85
  73. package/src/devices/colorbulb.ts +18 -4
  74. package/src/devices/contact.ts +1 -1
  75. package/src/devices/curtains.ts +7 -2
  76. package/src/devices/humidifiers.ts +17 -3
  77. package/src/devices/indoorcam.ts +13 -2
  78. package/src/devices/plugs.ts +45 -18
  79. package/src/irdevices/airconditioners.ts +17 -1
  80. package/src/irdevices/airpurifiers.ts +18 -0
  81. package/src/irdevices/cameras.ts +10 -0
  82. package/src/irdevices/fans.ts +10 -0
  83. package/src/irdevices/lights.ts +10 -0
  84. package/src/irdevices/others.ts +10 -0
  85. package/src/irdevices/tvs.ts +10 -0
  86. package/src/irdevices/vacuumcleaners.ts +10 -0
  87. package/src/irdevices/waterheaters.ts +10 -0
  88. package/src/platform.ts +104 -20
  89. package/src/settings.ts +1 -0
@@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
3
3
  import Switchbot from 'node-switchbot';
4
4
  import { interval, Subject } from 'rxjs';
5
5
  import { SwitchBotPlatform } from '../platform';
6
- import { debounceTime, skipWhile, tap } from 'rxjs/operators';
6
+ import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
7
7
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
8
8
  import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, payload } from '../settings';
9
9
 
@@ -20,6 +20,7 @@ export class Bot {
20
20
 
21
21
  // Characteristic Values
22
22
  On!: CharacteristicValue;
23
+ OnCached!: CharacteristicValue;
23
24
  BatteryLevel!: CharacteristicValue;
24
25
  StatusLowBattery!: CharacteristicValue;
25
26
 
@@ -48,11 +49,15 @@ export class Bot {
48
49
  public device: device & devicesConfig,
49
50
  ) {
50
51
  // Bot Config
51
- this.platform.device(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, mode: ${device.bot?.mode},`
52
+ this.platform.device(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, mode: ${device.bot?.mode},`
52
53
  + ` deviceType: ${device.bot?.deviceType})`);
53
54
 
54
55
  // default placeholders
55
- this.On = false;
56
+ if (this.On === undefined) {
57
+ this.On = false;
58
+ } else {
59
+ this.On = this.accessory.context.On;
60
+ }
56
61
  this.BatteryLevel = 100;
57
62
  this.StatusLowBattery = 1;
58
63
 
@@ -61,7 +66,7 @@ export class Bot {
61
66
  this.botUpdateInProgress = false;
62
67
 
63
68
  // Retrieve initial values and updateHomekit
64
- this.parseStatus();
69
+ this.refreshStatus();
65
70
 
66
71
  // set accessory information
67
72
  accessory
@@ -122,7 +127,6 @@ export class Bot {
122
127
  }
123
128
 
124
129
  // Retrieve initial values and updateHomekit
125
- this.refreshStatus();
126
130
  this.updateHomeKitCharacteristics();
127
131
 
128
132
  // Start an update interval
@@ -197,6 +201,12 @@ export class Bot {
197
201
  this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI parseStatus`);
198
202
  if (this.device.bot?.mode === 'press') {
199
203
  this.On = false;
204
+ } else {
205
+ if (this.deviceStatus.body.power === 'on') {
206
+ this.On = true;
207
+ } else {
208
+ this.On = false;
209
+ }
200
210
  }
201
211
  this.platform.debug(`Bot ${this.accessory.displayName} On: ${this.On}`);
202
212
  }
@@ -284,7 +294,9 @@ export class Bot {
284
294
  if (this.platform.config.credentials?.openToken) {
285
295
  this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI refreshStatus`);
286
296
  try {
287
- this.deviceStatus = {
297
+ this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
298
+ this.platform.device(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
299
+ /*this.deviceStatus = {
288
300
  statusCode: 100,
289
301
  body: {
290
302
  deviceId: this.device.deviceId!,
@@ -293,7 +305,7 @@ export class Bot {
293
305
  power: 'on',
294
306
  },
295
307
  message: 'success',
296
- };
308
+ };*/
297
309
  this.parseStatus();
298
310
  this.updateHomeKitCharacteristics();
299
311
  } catch (e: any) {
@@ -324,61 +336,71 @@ export class Bot {
324
336
  } else {
325
337
  await this.openAPIpushChanges();
326
338
  }
327
- this.refreshStatus();
339
+ interval(5000)
340
+ .pipe(skipWhile(() => this.botUpdateInProgress))
341
+ .pipe(take(1))
342
+ .subscribe(() => {
343
+ this.refreshStatus();
344
+ });
328
345
  }
329
346
 
330
347
  private async BLEpushChanges() {
331
- this.platform.debug(`Bot: ${this.accessory.displayName} BLE pushChanges`);
332
- const switchbot = this.connectBLE();
333
- if (this.device.bot?.mode === 'press') {
334
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
335
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list) => {
336
- this.platform.log.info(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
337
- return device_list[0].press({ id: this.device.bleMac });
338
- }).then(() => {
339
- this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
340
- }).catch(async (e: any) => {
341
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
342
- if (this.deviceDebug) {
343
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
344
- + ` Error Message: ${JSON.stringify(e.message)}`);
345
- }
346
- if (this.debugDebug) {
347
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
348
- + ` Error: ${JSON.stringify(e)}`);
349
- }
350
- if (this.platform.config.credentials?.openToken) {
351
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
352
- await this.openAPIpushChanges();
353
- }
354
- this.apiError(e);
355
- });
356
- } else if (this.device.bot?.mode === 'switch') {
357
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
358
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
359
- this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.On}`);
360
- return this.turnOnOff(device_list);
361
- }).then(() => {
362
- this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
363
- }).catch(async (e: any) => {
364
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
365
- if (this.deviceDebug) {
366
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
367
- + ` Error Message: ${JSON.stringify(e.message)}`);
368
- }
369
- if (this.debugDebug) {
370
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
371
- + ` Error: ${JSON.stringify(e)}`);
372
- }
373
- if (this.platform.config.credentials?.openToken) {
374
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
375
- await this.openAPIpushChanges();
376
- }
377
- this.apiError(e);
378
- });
379
- } else {
380
- this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
348
+ if (this.On !== this.OnCached) {
349
+ this.platform.debug(`Bot: ${this.accessory.displayName} BLE pushChanges`);
350
+ const switchbot = this.connectBLE();
351
+ if (this.device.bot?.mode === 'press') {
352
+ this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
353
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac })
354
+ .then((device_list: { press: (arg0: { id: string | undefined; }) => any; }[]) => {
355
+ this.platform.log.info(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
356
+ return device_list[0].press({ id: this.device.bleMac });
357
+ }).then(() => {
358
+ this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
359
+ }).catch(async (e: any) => {
360
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
361
+ if (this.deviceDebug) {
362
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
363
+ + ` Error Message: ${JSON.stringify(e.message)}`);
364
+ }
365
+ if (this.debugDebug) {
366
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
367
+ + ` Error: ${JSON.stringify(e)}`);
368
+ }
369
+ if (this.platform.config.credentials?.openToken) {
370
+ this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
371
+ await this.openAPIpushChanges();
372
+ }
373
+ this.apiError(e);
374
+ });
375
+ } else if (this.device.bot?.mode === 'switch') {
376
+ this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
377
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
378
+ this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.On}`);
379
+ return this.turnOnOff(device_list);
380
+ }).then(() => {
381
+ this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
382
+ }).catch(async (e: any) => {
383
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
384
+ if (this.deviceDebug) {
385
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
386
+ + ` Error Message: ${JSON.stringify(e.message)}`);
387
+ }
388
+ if (this.debugDebug) {
389
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
390
+ + ` Error: ${JSON.stringify(e)}`);
391
+ }
392
+ if (this.platform.config.credentials?.openToken) {
393
+ this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
394
+ await this.openAPIpushChanges();
395
+ }
396
+ this.apiError(e);
397
+ });
398
+ } else {
399
+ this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
400
+ }
381
401
  }
402
+ this.OnCached = this.On;
403
+ this.accessory.context.On = this.OnCached;
382
404
  }
383
405
 
384
406
  private turnOnOff(device_list: any) {
@@ -392,35 +414,39 @@ export class Bot {
392
414
  private async openAPIpushChanges() {
393
415
  if (this.platform.config.credentials?.openToken) {
394
416
  try {
395
- this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
396
- const payload = {
397
- commandType: 'command',
398
- parameter: 'default',
399
- } as payload;
400
-
401
- if (this.device.bot?.mode === 'switch' && this.On) {
402
- payload.command = 'turnOn';
403
- this.On = true;
404
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
405
- } else if (this.device.bot?.mode === 'switch' && !this.On) {
406
- payload.command = 'turnOff';
407
- this.On = false;
408
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
409
- } else if (this.device.bot?.mode === 'press') {
410
- payload.command = 'press';
411
- this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
412
- this.On = false;
413
- } else {
414
- throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
415
- }
417
+ if (this.On !== this.OnCached) {
418
+ this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
419
+ const payload = {
420
+ commandType: 'command',
421
+ parameter: 'default',
422
+ } as payload;
423
+
424
+ if (this.device.bot?.mode === 'switch' && this.On) {
425
+ payload.command = 'turnOn';
426
+ this.On = true;
427
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
428
+ } else if (this.device.bot?.mode === 'switch' && !this.On) {
429
+ payload.command = 'turnOff';
430
+ this.On = false;
431
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
432
+ } else if (this.device.bot?.mode === 'press') {
433
+ payload.command = 'press';
434
+ this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
435
+ this.On = false;
436
+ } else {
437
+ throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
438
+ }
416
439
 
417
- this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
418
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
440
+ this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
441
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
419
442
 
420
- // Make the API request
421
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
422
- this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
423
- this.statusCode(push);
443
+ // Make the API request
444
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
445
+ this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
446
+ this.statusCode(push);
447
+ this.OnCached = this.On;
448
+ this.accessory.context.On = this.OnCached;
449
+ }
424
450
  } catch (e: any) {
425
451
  this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
426
452
  if (this.deviceDebug) {
@@ -491,9 +517,11 @@ export class Bot {
491
517
  break;
492
518
  case 161:
493
519
  this.platform.log.error(`Bot: ${this.accessory.displayName} Device is offline.`);
520
+ this.offlineOff();
494
521
  break;
495
522
  case 171:
496
523
  this.platform.log.error(`Bot: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
524
+ this.offlineOff();
497
525
  break;
498
526
  case 190:
499
527
  this.platform.log.error(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -507,6 +535,17 @@ export class Bot {
507
535
  }
508
536
  }
509
537
 
538
+ private offlineOff() {
539
+ if (this.device.offline) {
540
+ this.On = false;
541
+ if (this.device.bot?.deviceType === 'switch') {
542
+ this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
543
+ } else {
544
+ this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
545
+ }
546
+ }
547
+ }
548
+
510
549
  /**
511
550
  * Handle requests to set the "On" characteristic
512
551
  */
@@ -56,13 +56,17 @@ export class ColorBulb {
56
56
  this.platform.device(`Color Bulb: ${this.accessory.displayName} Config: (ble: ${device.ble}, set_minStep: ${device.colorbulb?.set_minStep}`);
57
57
 
58
58
  // default placeholders
59
- this.minKelvin = 2000;
60
- this.maxKelvin = 9000;
59
+ if (this.On === undefined) {
60
+ this.On = false;
61
+ } else {
62
+ this.On = this.accessory.context.On;
63
+ }
61
64
  this.Hue = 0;
62
- this.On = false;
63
65
  this.Brightness = 0;
64
66
  this.Saturation = 0;
65
67
  this.ColorTemperature = 140;
68
+ this.minKelvin = 2000;
69
+ this.maxKelvin = 9000;
66
70
 
67
71
  // this is subject we use to track when we need to POST changes to the SwitchBot API
68
72
  this.doColorBulbUpdate = new Subject();
@@ -299,6 +303,7 @@ export class ColorBulb {
299
303
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
300
304
  this.statusCode(push);
301
305
  this.OnCached = this.On;
306
+ this.accessory.context.On = this.OnCached;
302
307
  }
303
308
  // Push Brightness Update
304
309
  if (this.On) {
@@ -498,9 +503,11 @@ export class ColorBulb {
498
503
  break;
499
504
  case 161:
500
505
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device is offline.`);
506
+ this.offlineOff();
501
507
  break;
502
508
  case 171:
503
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
509
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
510
+ this.offlineOff();
504
511
  break;
505
512
  case 190:
506
513
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -514,6 +521,13 @@ export class ColorBulb {
514
521
  }
515
522
  }
516
523
 
524
+ private offlineOff() {
525
+ if (this.device.offline) {
526
+ this.On = false;
527
+ this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
528
+ }
529
+ }
530
+
517
531
  /**
518
532
  * Handle requests to set the value of the "On" characteristic
519
533
  */
@@ -50,7 +50,7 @@ export class Contact {
50
50
  public device: device & devicesConfig,
51
51
  ) {
52
52
  // Contact Config
53
- this.platform.device(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble},`
53
+ this.platform.device(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},`
54
54
  + ` hide_lightsensor: ${device.contact?.hide_lightsensor}, hide_motionsensor: ${device.contact?.hide_motionsensor})`);
55
55
 
56
56
 
@@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
3
3
  import Switchbot from 'node-switchbot';
4
4
  import { interval, Subject } from 'rxjs';
5
5
  import { SwitchBotPlatform } from '../platform';
6
- import { debounceTime, skipWhile, tap } from 'rxjs/operators';
6
+ import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
7
7
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
8
8
  import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, payload } from '../settings';
9
9
 
@@ -487,7 +487,12 @@ export class Curtain {
487
487
  } else {
488
488
  await this.OpenAPIpushChanges();
489
489
  }
490
- this.refreshStatus();
490
+ interval(5000)
491
+ .pipe(skipWhile(() => this.curtainUpdateInProgress))
492
+ .pipe(take(1))
493
+ .subscribe(() => {
494
+ this.refreshStatus();
495
+ });
491
496
  }
492
497
 
493
498
  private async BLEpushChanges() {
@@ -2,7 +2,7 @@ import { AxiosResponse } from 'axios';
2
2
  import Switchbot from 'node-switchbot';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform';
5
- import { debounceTime, skipWhile, tap } from 'rxjs/operators';
5
+ import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
6
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
7
7
  import { DeviceURL, device, devicesConfig, serviceData, ad, deviceStatusResponse, payload } from '../settings';
8
8
 
@@ -50,7 +50,7 @@ export class Humidifier {
50
50
  public device: device & devicesConfig,
51
51
  ) {
52
52
  // Humidifiers Config
53
- this.platform.device(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, hide_temperature: `
53
+ this.platform.device(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, hide_temperature: `
54
54
  + `${device.humidifier?.hide_temperature}, set_minStep: ${device.humidifier?.set_minStep})`);
55
55
 
56
56
  // default placeholders
@@ -394,7 +394,12 @@ export class Humidifier {
394
394
  //} else {
395
395
  await this.OpenAPIpushChanges();
396
396
  //}
397
- this.refreshStatus();
397
+ interval(5000)
398
+ .pipe(skipWhile(() => this.humidifierUpdateInProgress))
399
+ .pipe(take(1))
400
+ .subscribe(() => {
401
+ this.refreshStatus();
402
+ });
398
403
  }
399
404
 
400
405
  private async BLEpushChanges() {
@@ -628,9 +633,11 @@ export class Humidifier {
628
633
  break;
629
634
  case 161:
630
635
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device is offline.`);
636
+ this.offlineOff();
631
637
  break;
632
638
  case 171:
633
639
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
640
+ this.offlineOff();
634
641
  break;
635
642
  case 190:
636
643
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -644,6 +651,13 @@ export class Humidifier {
644
651
  }
645
652
  }
646
653
 
654
+ private offlineOff() {
655
+ if (this.device.offline) {
656
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
657
+ this.service.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.Active);
658
+ }
659
+ }
660
+
647
661
  /**
648
662
  * Handle requests to set the "Target Humidifier Dehumidifier State" characteristic
649
663
  */
@@ -1,7 +1,7 @@
1
1
  import { AxiosResponse } from 'axios';
2
2
  import { interval, Subject } from 'rxjs';
3
3
  import { SwitchBotPlatform } from '../platform';
4
- import { debounceTime, skipWhile, tap } from 'rxjs/operators';
4
+ import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
5
5
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
6
  import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
7
7
 
@@ -178,7 +178,12 @@ export class IndoorCam {
178
178
  const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
179
179
  this.platform.debug(`Indoor Cam: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
180
180
  this.statusCode(push);
181
- this.refreshStatus();
181
+ interval(5000)
182
+ .pipe(skipWhile(() => this.cameraUpdateInProgress))
183
+ .pipe(take(1))
184
+ .subscribe(() => {
185
+ this.refreshStatus();
186
+ });
182
187
  } else {
183
188
  this.platform.device(`Indoor Cam: ${this.accessory.displayName} No pushChanges. Active: ${this.Active}`);
184
189
  }
@@ -210,9 +215,15 @@ export class IndoorCam {
210
215
  break;
211
216
  case 161:
212
217
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device is offline.`);
218
+ if (this.device.offline) {
219
+ this.Active = false;
220
+ }
213
221
  break;
214
222
  case 171:
215
223
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
224
+ if (this.device.offline) {
225
+ this.Active = false;
226
+ }
216
227
  break;
217
228
  case 190:
218
229
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -2,7 +2,7 @@
2
2
  import { AxiosResponse } from 'axios';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform';
5
- import { debounceTime, skipWhile, tap } from 'rxjs/operators';
5
+ import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
6
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
7
7
  import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
8
8
 
@@ -12,6 +12,7 @@ export class Plug {
12
12
 
13
13
  // Characteristic Values
14
14
  On!: CharacteristicValue;
15
+ OnCached!: CharacteristicValue;
15
16
 
16
17
  // OpenAPI Others
17
18
  deviceStatus!: deviceStatusResponse;
@@ -29,8 +30,15 @@ export class Plug {
29
30
  private accessory: PlatformAccessory,
30
31
  public device: device & devicesConfig,
31
32
  ) {
33
+ // Bot Config
34
+ this.platform.device(`Plug: ${this.accessory.displayName} Config: (offline: ${device.offline})`);
35
+
32
36
  // default placeholders
33
- this.On = false;
37
+ if (this.On === undefined) {
38
+ this.On = false;
39
+ } else {
40
+ this.On = this.accessory.context.On;
41
+ }
34
42
 
35
43
  // this is subject we use to track when we need to POST changes to the SwitchBot API
36
44
  this.doPlugUpdate = new Subject();
@@ -142,24 +150,34 @@ export class Plug {
142
150
  * Plug - "command" "turnOn" "default" = set to ON state
143
151
  */
144
152
  async pushChanges() {
145
- const payload = {
146
- commandType: 'command',
147
- parameter: 'default',
148
- } as payload;
149
-
150
- if (this.On) {
151
- payload.command = 'turnOn';
152
- } else {
153
- payload.command = 'turnOff';
154
- }
153
+ if (this.On !== this.OnCached) {
154
+ const payload = {
155
+ commandType: 'command',
156
+ parameter: 'default',
157
+ } as payload;
158
+
159
+ if (this.On) {
160
+ payload.command = 'turnOn';
161
+ } else {
162
+ payload.command = 'turnOff';
163
+ }
155
164
 
156
- this.platform.log.info(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
157
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
165
+ this.platform.log.info(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
166
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
158
167
 
159
- // Make the API request
160
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
161
- this.platform.debug(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
162
- this.statusCode(push);
168
+ // Make the API request
169
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
170
+ this.platform.debug(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
171
+ this.statusCode(push);
172
+ this.OnCached = this.On;
173
+ this.accessory.context.On = this.OnCached;
174
+ }
175
+ interval(5000)
176
+ .pipe(skipWhile(() => this.plugUpdateInProgress))
177
+ .pipe(take(1))
178
+ .subscribe(() => {
179
+ this.refreshStatus();
180
+ });
163
181
  }
164
182
 
165
183
  updateHomeKitCharacteristics() {
@@ -188,9 +206,11 @@ export class Plug {
188
206
  break;
189
207
  case 161:
190
208
  this.platform.log.error(`Plug: ${this.accessory.displayName} Device is offline.`);
209
+ this.offlineOff();
191
210
  break;
192
211
  case 171:
193
212
  this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
213
+ this.offlineOff();
194
214
  break;
195
215
  case 190:
196
216
  this.platform.log.error(`Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -204,6 +224,13 @@ export class Plug {
204
224
  }
205
225
  }
206
226
 
227
+ private offlineOff() {
228
+ if (this.device.offline) {
229
+ this.On = false;
230
+ this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
231
+ }
232
+ }
233
+
207
234
  /**
208
235
  * Handle requests to set the value of the "On" characteristic
209
236
  */
@@ -14,9 +14,11 @@ export class AirConditioner {
14
14
 
15
15
  // Characteristic Values
16
16
  Active!: CharacteristicValue;
17
+ ActiveCached!: CharacteristicValue;
17
18
  RotationSpeed!: CharacteristicValue;
18
19
  LastTemperature!: CharacteristicValue;
19
20
  CurrentTemperature!: CharacteristicValue;
21
+ CurrentTemperatureCached!: CharacteristicValue;
20
22
  TargetHeaterCoolerState?: CharacteristicValue;
21
23
  CurrentHeaterCoolerState!: CharacteristicValue;
22
24
  HeatingThresholdTemperature?: CharacteristicValue;
@@ -41,7 +43,17 @@ export class AirConditioner {
41
43
  private accessory: PlatformAccessory,
42
44
  public device: irdevice & irDevicesConfig,
43
45
  ) {
44
- this.CurrentTemperature = 24;
46
+ // default placeholders
47
+ if (this.Active === undefined) {
48
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
49
+ } else {
50
+ this.Active = this.accessory.context.Active;
51
+ }
52
+ if (this.CurrentTemperature === undefined) {
53
+ this.CurrentTemperature = 24;
54
+ } else {
55
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
56
+ }
45
57
 
46
58
  // set accessory information
47
59
  accessory
@@ -161,6 +173,8 @@ export class AirConditioner {
161
173
  this.platform.device(`Air Conditioner: ${this.accessory.displayName} pushAirConditionerOffChanges, Active: ${this.Active}`);
162
174
  }
163
175
  this.Active = value;
176
+ this.ActiveCached = this.Active;
177
+ this.accessory.context.Active = this.ActiveCached;
164
178
  }
165
179
 
166
180
  private updateHomeKitCharacteristics() {
@@ -349,6 +363,8 @@ export class AirConditioner {
349
363
  const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
350
364
  this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
351
365
  this.statusCode(push);
366
+ this.CurrentTemperatureCached = this.CurrentTemperature;
367
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
352
368
  this.updateHomeKitCharacteristics();
353
369
  } catch (e: any) {
354
370
  this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} failed pushChanges`);