@switchbot/homebridge-switchbot 1.2.6-beta.3 → 1.3.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/config.schema.json +11 -1
  3. package/dist/devices/bots.js +1 -1
  4. package/dist/devices/bots.js.map +1 -1
  5. package/dist/devices/colorbulb.d.ts +14 -2
  6. package/dist/devices/colorbulb.d.ts.map +1 -1
  7. package/dist/devices/colorbulb.js +127 -30
  8. package/dist/devices/colorbulb.js.map +1 -1
  9. package/dist/devices/curtains.js +1 -1
  10. package/dist/devices/curtains.js.map +1 -1
  11. package/dist/devices/humidifiers.js +1 -1
  12. package/dist/devices/humidifiers.js.map +1 -1
  13. package/dist/devices/indoorcam.d.ts +32 -3
  14. package/dist/devices/indoorcam.d.ts.map +1 -1
  15. package/dist/devices/indoorcam.js +92 -45
  16. package/dist/devices/indoorcam.js.map +1 -1
  17. package/dist/devices/plugs.js +1 -1
  18. package/dist/devices/plugs.js.map +1 -1
  19. package/dist/irdevices/airconditioners.js +1 -1
  20. package/dist/irdevices/airconditioners.js.map +1 -1
  21. package/dist/irdevices/airpurifiers.js +1 -1
  22. package/dist/irdevices/airpurifiers.js.map +1 -1
  23. package/dist/irdevices/cameras.js +1 -1
  24. package/dist/irdevices/cameras.js.map +1 -1
  25. package/dist/irdevices/fans.js +1 -1
  26. package/dist/irdevices/fans.js.map +1 -1
  27. package/dist/irdevices/lights.js +1 -1
  28. package/dist/irdevices/lights.js.map +1 -1
  29. package/dist/irdevices/others.js +1 -1
  30. package/dist/irdevices/others.js.map +1 -1
  31. package/dist/irdevices/tvs.js +1 -1
  32. package/dist/irdevices/tvs.js.map +1 -1
  33. package/dist/irdevices/vacuumcleaners.js +1 -1
  34. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  35. package/dist/irdevices/waterheaters.js +1 -1
  36. package/dist/irdevices/waterheaters.js.map +1 -1
  37. package/dist/platform.d.ts.map +1 -1
  38. package/dist/platform.js +3 -3
  39. package/dist/platform.js.map +1 -1
  40. package/dist/settings.d.ts +1 -0
  41. package/dist/settings.d.ts.map +1 -1
  42. package/dist/settings.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/devices/bots.ts +1 -1
  45. package/src/devices/colorbulb.ts +149 -37
  46. package/src/devices/curtains.ts +1 -1
  47. package/src/devices/humidifiers.ts +1 -1
  48. package/src/devices/indoorcam.ts +117 -49
  49. package/src/devices/plugs.ts +1 -1
  50. package/src/irdevices/airconditioners.ts +1 -1
  51. package/src/irdevices/airpurifiers.ts +1 -1
  52. package/src/irdevices/cameras.ts +1 -1
  53. package/src/irdevices/fans.ts +1 -1
  54. package/src/irdevices/lights.ts +1 -1
  55. package/src/irdevices/others.ts +1 -1
  56. package/src/irdevices/tvs.ts +1 -1
  57. package/src/irdevices/vacuumcleaners.ts +1 -1
  58. package/src/irdevices/waterheaters.ts +1 -1
  59. package/src/platform.ts +5 -3
  60. package/src/settings.ts +1 -0
@@ -2,8 +2,8 @@ import { AxiosResponse } from 'axios';
2
2
  import { interval, Subject } from 'rxjs';
3
3
  import { SwitchBotPlatform } from '../platform';
4
4
  import { debounceTime, skipWhile, tap } from 'rxjs/operators';
5
- import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
- import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload, hs2rgb, rgb2hs } from '../settings';
5
+ import { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
6
+ import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload, hs2rgb, rgb2hs, m2hs } from '../settings';
7
7
 
8
8
  /**
9
9
  * Platform Accessory
@@ -16,10 +16,15 @@ export class ColorBulb {
16
16
 
17
17
  // Characteristic Values
18
18
  On!: CharacteristicValue;
19
+ OnCached!: CharacteristicValue;
19
20
  Hue!: CharacteristicValue;
20
- Brightness!: CharacteristicValue;
21
+ HueCached!: CharacteristicValue;
21
22
  Saturation!: CharacteristicValue;
23
+ SaturationCached!: CharacteristicValue;
24
+ Brightness!: CharacteristicValue;
25
+ BrightnessCached!: CharacteristicValue;
22
26
  ColorTemperature!: CharacteristicValue;
27
+ ColorTemperatureCached!: CharacteristicValue;
23
28
 
24
29
  // OpenAPI Others
25
30
  deviceStatus!: deviceStatusResponse;
@@ -32,9 +37,15 @@ export class ColorBulb {
32
37
  private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
33
38
  private readonly debugDebug = this.platform.config.options?.debug === 'debug' || this.platform.debugMode;
34
39
 
40
+ // Adaptive Lighting
41
+ AdaptiveLightingController: ControllerConstructor | Controller<ControllerServiceMap>;
42
+ minKelvin: number;
43
+ maxKelvin: number;
44
+
35
45
  // Updates
36
46
  colorBulbUpdateInProgress!: boolean;
37
47
  doColorBulbUpdate!: Subject<void>;
48
+ cacheKelvin!: number;
38
49
 
39
50
  constructor(
40
51
  private readonly platform: SwitchBotPlatform,
@@ -45,11 +56,13 @@ export class ColorBulb {
45
56
  this.platform.device(`Color Bulb: ${this.accessory.displayName} Config: (ble: ${device.ble}, set_minStep: ${device.colorbulb?.set_minStep}`);
46
57
 
47
58
  // default placeholders
59
+ this.minKelvin = 2000;
60
+ this.maxKelvin = 9000;
61
+ this.Hue = 0;
48
62
  this.On = false;
49
- this.ColorTemperature = 140;
50
63
  this.Brightness = 0;
51
64
  this.Saturation = 0;
52
- this.Hue = 0;
65
+ this.ColorTemperature = 140;
53
66
 
54
67
  // this is subject we use to track when we need to POST changes to the SwitchBot API
55
68
  this.doColorBulbUpdate = new Subject();
@@ -109,6 +122,7 @@ export class ColorBulb {
109
122
  })
110
123
  .onSet(this.ColorTemperatureSet.bind(this));
111
124
 
125
+
112
126
  // handle Hue events using the Hue characteristic
113
127
  this.service.getCharacteristic(this.platform.Characteristic.Hue)
114
128
  .setProps({
@@ -133,6 +147,12 @@ export class ColorBulb {
133
147
  })
134
148
  .onSet(this.SaturationSet.bind(this));
135
149
 
150
+ const adaptiveLightingShift = device.colorbulb?.adaptiveLightingShift || 0;
151
+ this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.service, {
152
+ customTemperatureAdjustment: adaptiveLightingShift,
153
+ });
154
+ this.accessory.configureController(this.AdaptiveLightingController);
155
+
136
156
  // Update Homekit
137
157
  this.updateHomeKitCharacteristics();
138
158
 
@@ -258,32 +278,70 @@ export class ColorBulb {
258
278
  */
259
279
  async pushChanges() {
260
280
  try {
261
- // Push On Update
262
- const payload = {
263
- commandType: 'command',
264
- parameter: 'default',
265
- } as payload;
281
+ if (this.On !== this.OnCached) {
282
+ // Push On Update
283
+ const payload = {
284
+ commandType: 'command',
285
+ parameter: 'default',
286
+ } as payload;
287
+
288
+ if (this.On) {
289
+ payload.command = 'turnOn';
290
+ } else {
291
+ payload.command = 'turnOff';
292
+ }
266
293
 
294
+ this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
295
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
296
+
297
+ // Make the API request
298
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
299
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
300
+ this.statusCode(push);
301
+ this.OnCached = this.On;
302
+ }
303
+ // Push Brightness Update
267
304
  if (this.On) {
268
- payload.command = 'turnOn';
269
- } else {
270
- payload.command = 'turnOff';
305
+ await this.pushBrightnessChanges();
271
306
  }
272
307
 
273
- this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
274
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
275
-
276
- // Make the API request
277
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
278
- this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
279
- this.statusCode(push);
308
+ // Push ColorTemperature Update
309
+ if (this.On) {
310
+ await this.pushColorTemperatureChanges();
311
+ }
280
312
 
281
- // Push Brightness Update
313
+ // Push Hue & Saturation Update
282
314
  if (this.On) {
315
+ await this.pushHueSaturationChanges();
316
+ }
317
+
318
+ } catch (e: any) {
319
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
320
+ if (this.deviceDebug) {
321
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
322
+ + ` Error Message: ${JSON.stringify(e.message)}`);
323
+ }
324
+ if (this.debugDebug) {
325
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
326
+ + ` Error: ${JSON.stringify(e)}`);
327
+ }
328
+ this.apiError(e);
329
+ }
330
+ }
331
+
332
+ private async pushHueSaturationChanges() {
333
+ try {
334
+ if ((this.Hue !== this.HueCached) || (this.Saturation !== this.SaturationCached)) {
335
+ this.platform.device(`Color Bulb: ${this.accessory.displayName} Hue: ${JSON.stringify(this.Hue)}`);
336
+ this.platform.device(`Color Bulb: ${this.accessory.displayName} Saturation: ${JSON.stringify(this.Saturation)}`);
337
+
338
+ const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
339
+ this.platform.device(`Color Bulb: ${this.accessory.displayName} rgb: ${JSON.stringify([red, green, blue])}`);
340
+
283
341
  const payload = {
284
342
  commandType: 'command',
285
- command: 'setBrightness',
286
- parameter: `${this.Brightness}`,
343
+ command: 'setColor',
344
+ parameter: `${red}:${green}:${blue}`,
287
345
  } as payload;
288
346
 
289
347
  this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
@@ -293,11 +351,31 @@ export class ColorBulb {
293
351
  const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
294
352
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
295
353
  this.statusCode(push);
354
+ this.HueCached = this.Hue;
355
+ this.SaturationCached = this.Saturation;
356
+ } else {
357
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} No Changes.`
358
+ + `Hue: ${this.Hue}, HueCached: ${this.HueCached}, Saturation: ${this.Saturation}, SaturationCached: ${this.SaturationCached}`);
359
+ }
360
+ } catch (e: any) {
361
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
362
+ if (this.deviceDebug) {
363
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
364
+ + ` Error Message: ${JSON.stringify(e.message)}`);
296
365
  }
366
+ if (this.debugDebug) {
367
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
368
+ + ` Error: ${JSON.stringify(e)}`);
369
+ }
370
+ this.apiError(e);
371
+ }
372
+ }
297
373
 
298
- // Push ColorTemperature Update
299
- if (this.On) {
374
+ private async pushColorTemperatureChanges() {
375
+ try {
376
+ if (this.ColorTemperature !== this.ColorTemperatureCached) {
300
377
  const kelvin = Math.round(1000000 / Number(this.ColorTemperature));
378
+ this.cacheKelvin = kelvin;
301
379
 
302
380
  const payload = {
303
381
  commandType: 'command',
@@ -312,20 +390,32 @@ export class ColorBulb {
312
390
  const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
313
391
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
314
392
  this.statusCode(push);
393
+ this.ColorTemperatureCached = this.ColorTemperature;
394
+ } else {
395
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} No Changes.`
396
+ + `ColorTemperature: ${this.ColorTemperature}, ColorTemperatureCached: ${this.ColorTemperatureCached}`);
315
397
  }
398
+ } catch (e: any) {
399
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
400
+ if (this.deviceDebug) {
401
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
402
+ + ` Error Message: ${JSON.stringify(e.message)}`);
403
+ }
404
+ if (this.debugDebug) {
405
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
406
+ + ` Error: ${JSON.stringify(e)}`);
407
+ }
408
+ this.apiError(e);
409
+ }
410
+ }
316
411
 
317
- // Push Hue & Saturation Update
318
- if (this.On) {
319
- this.platform.device(`Color Bulb: ${this.accessory.displayName} Hue: ${JSON.stringify(this.Hue)}`);
320
- this.platform.device(`Color Bulb: ${this.accessory.displayName} Saturation: ${JSON.stringify(this.Saturation)}`);
321
-
322
- const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
323
- this.platform.device(`Color Bulb: ${this.accessory.displayName} rgb: ${JSON.stringify([red, green, blue])}`);
324
-
412
+ private async pushBrightnessChanges() {
413
+ try {
414
+ if (this.Brightness !== this.BrightnessCached) {
325
415
  const payload = {
326
416
  commandType: 'command',
327
- command: 'setColor',
328
- parameter: `${red}:${green}:${blue}`,
417
+ command: 'setBrightness',
418
+ parameter: `${this.Brightness}`,
329
419
  } as payload;
330
420
 
331
421
  this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
@@ -335,8 +425,11 @@ export class ColorBulb {
335
425
  const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
336
426
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
337
427
  this.statusCode(push);
428
+ this.BrightnessCached = this.Brightness;
429
+ } else {
430
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} No Changes.`
431
+ + `Brightness: ${this.Brightness}, BrightnessCached: ${this.BrightnessCached}`);
338
432
  }
339
-
340
433
  } catch (e: any) {
341
434
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
342
435
  if (this.deviceDebug) {
@@ -407,7 +500,7 @@ export class ColorBulb {
407
500
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device is offline.`);
408
501
  break;
409
502
  case 171:
410
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Hub Device is offline.`);
503
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
411
504
  break;
412
505
  case 190:
413
506
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -447,6 +540,21 @@ export class ColorBulb {
447
540
  ColorTemperatureSet(value: CharacteristicValue) {
448
541
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} ColorTemperature: ${value}`);
449
542
 
543
+ // Convert mired to kelvin to nearest 100 (SwitchBot seems to need this)
544
+ const kelvin = Math.round(1000000 / Number(value) / 100) * 100;
545
+
546
+ // Check and increase/decrease kelvin to range of device
547
+ const k = Math.min(Math.max(kelvin, this.minKelvin), this.maxKelvin);
548
+
549
+ if (!this.OnCached || this.cacheKelvin === k) {
550
+ return;
551
+ }
552
+
553
+ // Updating the hue/sat to the corresponding values mimics native adaptive lighting
554
+ const hs = m2hs(value);
555
+ this.service.updateCharacteristic(this.platform.Characteristic.Hue, hs[0]);
556
+ this.service.updateCharacteristic(this.platform.Characteristic.Saturation, hs[1]);
557
+
450
558
  this.ColorTemperature = value;
451
559
  this.doColorBulbUpdate.next();
452
560
  }
@@ -457,6 +565,8 @@ export class ColorBulb {
457
565
  HueSet(value: CharacteristicValue) {
458
566
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} Hue: ${value}`);
459
567
 
568
+ this.service.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
569
+
460
570
  this.Hue = value;
461
571
  this.doColorBulbUpdate.next();
462
572
  }
@@ -467,6 +577,8 @@ export class ColorBulb {
467
577
  SaturationSet(value: CharacteristicValue) {
468
578
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} Saturation: ${value}`);
469
579
 
580
+ this.service.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
581
+
470
582
  this.Saturation = value;
471
583
  this.doColorBulbUpdate.next();
472
584
  }
@@ -632,7 +632,7 @@ export class Curtain {
632
632
  this.platform.log.error(`Curtain: ${this.accessory.displayName} Device is offline.`);
633
633
  break;
634
634
  case 171:
635
- this.platform.log.error(`Curtain: ${this.accessory.displayName} Hub Device is offline.`);
635
+ this.platform.log.error(`Curtain: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
636
636
  break;
637
637
  case 190:
638
638
  this.platform.log.error(`Curtain: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -630,7 +630,7 @@ export class Humidifier {
630
630
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device is offline.`);
631
631
  break;
632
632
  case 171:
633
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline.`);
633
+ this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
634
634
  break;
635
635
  case 190:
636
636
  this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -10,8 +10,13 @@ export class IndoorCam {
10
10
  private service: Service;
11
11
 
12
12
  // Characteristic Values
13
- On!: CharacteristicValue;
14
- OutletInUse!: CharacteristicValue;
13
+ Active!: CharacteristicValue;
14
+ SetupEndpoints!: CharacteristicValue;
15
+ StreamingStatus!: CharacteristicValue;
16
+ SupportedRTPConfiguration!: CharacteristicValue;
17
+ SelectedRTPStreamConfiguration!: CharacteristicValue;
18
+ SupportedVideoStreamConfiguration!: CharacteristicValue;
19
+ SupportedAudioStreamConfiguration!: CharacteristicValue;
15
20
 
16
21
  // OpenAPI Others
17
22
  deviceStatus!: deviceStatusResponse;
@@ -29,9 +34,12 @@ export class IndoorCam {
29
34
  private accessory: PlatformAccessory,
30
35
  public device: device & devicesConfig,
31
36
  ) {
37
+ // Indoor Cam Config
38
+ this.platform.device(`Indoor Cam: ${this.accessory.displayName} Config: (hide_device: ${device.hide_device})`);
39
+
40
+ this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} was added but will not work as OpenAPI doesn't support it yet.`);
32
41
  // default placeholders
33
- this.On = false;
34
- this.OutletInUse = true;
42
+ this.SelectedRTPStreamConfiguration;
35
43
 
36
44
  // this is subject we use to track when we need to POST changes to the SwitchBot API
37
45
  this.doCameraUpdate = new Subject();
@@ -50,8 +58,8 @@ export class IndoorCam {
50
58
  // get the WindowCovering service if it exists, otherwise create a new WindowCovering service
51
59
  // you can create multiple services for each accessory
52
60
  (this.service =
53
- accessory.getService(this.platform.Service.Outlet) ||
54
- accessory.addService(this.platform.Service.Outlet)), `${accessory.displayName} Indoor Camera`;
61
+ accessory.getService(this.platform.Service.CameraRTPStreamManagement) ||
62
+ accessory.addService(this.platform.Service.CameraRTPStreamManagement)), `${accessory.displayName} Indoor Camera`;
55
63
 
56
64
  // To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
57
65
  // when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
@@ -65,9 +73,26 @@ export class IndoorCam {
65
73
  // see https://developers.homebridge.io/#/service/WindowCovering
66
74
 
67
75
  // create handlers for required characteristics
68
- this.service.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
76
+ this.service.getCharacteristic(this.platform.Characteristic.Active)
77
+ .onSet(this.ActiveSet.bind(this));
78
+
79
+ this.service.getCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration)
80
+ .onSet(this.SelectedRTPStreamConfigurationSet.bind(this));
81
+
82
+ this.service.getCharacteristic(this.platform.Characteristic.SetupEndpoints)
83
+ .onSet(this.SetupEndpointsSet.bind(this));
84
+
85
+ this.service.getCharacteristic(this.platform.Characteristic.StreamingStatus)
86
+ .onSet(this.StreamingStatusSet.bind(this));
69
87
 
70
- this.service.setCharacteristic(this.platform.Characteristic.OutletInUse, this.OutletInUse || true);
88
+ this.service.getCharacteristic(this.platform.Characteristic.SupportedAudioStreamConfiguration)
89
+ .onSet(this.SupportedAudioStreamConfigurationSet.bind(this));
90
+
91
+ this.service.getCharacteristic(this.platform.Characteristic.SupportedRTPConfiguration)
92
+ .onSet(this.SupportedRTPConfigurationSet.bind(this));
93
+
94
+ this.service.getCharacteristic(this.platform.Characteristic.SupportedVideoStreamConfiguration)
95
+ .onSet(this.SupportedVideoStreamConfigurationSet.bind(this));
71
96
 
72
97
  // Update Homekit
73
98
  this.updateHomeKitCharacteristics();
@@ -108,14 +133,7 @@ export class IndoorCam {
108
133
  }
109
134
 
110
135
  parseStatus() {
111
- switch (this.deviceStatus.body.power) {
112
- case 'on':
113
- this.On = true;
114
- break;
115
- default:
116
- this.On = false;
117
- }
118
- this.platform.debug(`Indoor Cam ${this.accessory.displayName} On: ${this.On}`);
136
+ this.platform.debug(`Indoor Cam ${this.accessory.displayName} SelectedRTPStreamConfiguration: ${this.SelectedRTPStreamConfiguration}`);
119
137
  }
120
138
 
121
139
 
@@ -146,45 +164,37 @@ export class IndoorCam {
146
164
  * Camera - "command" "turnOn" "default" = set to ON state
147
165
  */
148
166
  async pushChanges() {
149
- const payload = {
150
- commandType: 'command',
151
- parameter: 'default',
152
- } as payload;
153
-
154
- if (this.On) {
155
- payload.command = 'turnOn';
167
+ if (!this.Active) {
168
+ const payload = {
169
+ commandType: 'command',
170
+ parameter: 'default',
171
+ command: 'turnOn',
172
+ } as payload;
173
+
174
+ this.platform.log.info(`Indoor Cam: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
175
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
176
+
177
+ // Make the API request
178
+ const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
179
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
180
+ this.statusCode(push);
181
+ this.refreshStatus();
156
182
  } else {
157
- payload.command = 'turnOff';
183
+ this.platform.device(`Indoor Cam: ${this.accessory.displayName} No pushChanges. Active: ${this.Active}`);
158
184
  }
159
-
160
- this.platform.log.info(`Indoor Cam: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
161
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
162
-
163
- // Make the API request
164
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
165
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
166
- this.statusCode(push);
167
- this.refreshStatus();
168
185
  }
169
186
 
170
187
  updateHomeKitCharacteristics() {
171
- if (this.On === undefined) {
172
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${this.On}`);
188
+ if (this.SelectedRTPStreamConfiguration === undefined) {
189
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${this.SelectedRTPStreamConfiguration}`);
173
190
  } else {
174
- this.service.updateCharacteristic(this.platform.Characteristic.On, this.On);
175
- this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
176
- }
177
- if (this.OutletInUse === undefined) {
178
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} OutletInUse: ${this.OutletInUse}`);
179
- } else {
180
- this.service.updateCharacteristic(this.platform.Characteristic.OutletInUse, this.OutletInUse);
181
- this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic OutletInUse: ${this.OutletInUse}`);
191
+ this.service.updateCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration, this.SelectedRTPStreamConfiguration);
192
+ this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic On: ${this.SelectedRTPStreamConfiguration}`);
182
193
  }
183
194
  }
184
195
 
185
196
  public apiError(e: any) {
186
- this.service.updateCharacteristic(this.platform.Characteristic.On, e);
187
- this.service.updateCharacteristic(this.platform.Characteristic.OutletInUse, e);
197
+ this.service.updateCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration, e);
188
198
  }
189
199
 
190
200
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
@@ -202,7 +212,7 @@ export class IndoorCam {
202
212
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device is offline.`);
203
213
  break;
204
214
  case 171:
205
- this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline.`);
215
+ this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
206
216
  break;
207
217
  case 190:
208
218
  this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -216,15 +226,73 @@ export class IndoorCam {
216
226
  }
217
227
  }
218
228
 
229
+ /**
230
+ * Handle requests to set the value of the "Active" characteristic
231
+ */
232
+ ActiveSet(value: CharacteristicValue) {
233
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} Active: ${value}`);
234
+
235
+ this.Active = value;
236
+ this.doCameraUpdate.next();
237
+ }
238
+
239
+ /**
240
+ * Handle requests to set the value of the "SelectedRTPStreamConfiguration" characteristic
241
+ */
242
+ SelectedRTPStreamConfigurationSet(value: CharacteristicValue) {
243
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SelectedRTPStreamConfiguration: ${value}`);
244
+
245
+ this.SelectedRTPStreamConfiguration = value;
246
+ this.doCameraUpdate.next();
247
+ }
248
+
219
249
  /**
220
250
  * Handle requests to set the value of the "On" characteristic
221
251
  */
222
- OnSet(value: CharacteristicValue) {
223
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${value}`);
252
+ SetupEndpointsSet(value: CharacteristicValue) {
253
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SetupEndpoints: ${value}`);
224
254
 
225
- this.On = value;
255
+ this.SetupEndpoints = value;
226
256
  this.doCameraUpdate.next();
227
257
  }
228
258
 
259
+ /**
260
+ * Handle requests to set the value of the "On" characteristic
261
+ */
262
+ SupportedAudioStreamConfigurationSet(value: CharacteristicValue) {
263
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedAudioStreamConfiguration: ${value}`);
264
+
265
+ this.SupportedAudioStreamConfiguration = value;
266
+ this.doCameraUpdate.next();
267
+ }
268
+
269
+ /**
270
+ * Handle requests to set the value of the "On" characteristic
271
+ */
272
+ SupportedRTPConfigurationSet(value: CharacteristicValue) {
273
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedRTPConfiguration: ${value}`);
274
+
275
+ this.SupportedRTPConfiguration = value;
276
+ this.doCameraUpdate.next();
277
+ }
229
278
 
279
+ /**
280
+ * Handle requests to set the value of the "On" characteristic
281
+ */
282
+ StreamingStatusSet(value: CharacteristicValue) {
283
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} StreamingStatus: ${value}`);
284
+
285
+ this.StreamingStatus = value;
286
+ this.doCameraUpdate.next();
287
+ }
288
+
289
+ /**
290
+ * Handle requests to set the value of the "On" characteristic
291
+ */
292
+ SupportedVideoStreamConfigurationSet(value: CharacteristicValue) {
293
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedVideoStreamConfiguration: ${value}`);
294
+
295
+ this.SupportedVideoStreamConfiguration = value;
296
+ this.doCameraUpdate.next();
297
+ }
230
298
  }
@@ -190,7 +190,7 @@ export class Plug {
190
190
  this.platform.log.error(`Plug: ${this.accessory.displayName} Device is offline.`);
191
191
  break;
192
192
  case 171:
193
- this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline.`);
193
+ this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
194
194
  break;
195
195
  case 190:
196
196
  this.platform.log.error(`Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -379,7 +379,7 @@ export class AirConditioner {
379
379
  this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Device is offline.`);
380
380
  break;
381
381
  case 171:
382
- this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Hub Device is offline.`);
382
+ this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
383
383
  break;
384
384
  case 190:
385
385
  this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Device internal error due to device states not synchronized`
@@ -239,7 +239,7 @@ export class AirPurifier {
239
239
  this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Device is offline.`);
240
240
  break;
241
241
  case 171:
242
- this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Hub Device is offline.`);
242
+ this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
243
243
  break;
244
244
  case 190:
245
245
  this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Device internal error due to device states not synchronized`
@@ -139,7 +139,7 @@ export class Camera {
139
139
  this.platform.log.error(`Camera: ${this.accessory.displayName} Device is offline.`);
140
140
  break;
141
141
  case 171:
142
- this.platform.log.error(`Camera: ${this.accessory.displayName} Hub Device is offline.`);
142
+ this.platform.log.error(`Camera: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
143
143
  break;
144
144
  case 190:
145
145
  this.platform.log.error(`Camera: ${this.accessory.displayName} Device internal error due to device states not synchronized`
@@ -261,7 +261,7 @@ export class Fan {
261
261
  this.platform.log.error(`Fan: ${this.accessory.displayName} Device is offline.`);
262
262
  break;
263
263
  case 171:
264
- this.platform.log.error(`Fan: ${this.accessory.displayName} Hub Device is offline.`);
264
+ this.platform.log.error(`Fan: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
265
265
  break;
266
266
  case 190:
267
267
  this.platform.log.error(`Fan: ${this.accessory.displayName} Device internal error due to device states not synchronized`
@@ -173,7 +173,7 @@ export class Light {
173
173
  this.platform.log.error(`Light: ${this.accessory.displayName} Device is offline.`);
174
174
  break;
175
175
  case 171:
176
- this.platform.log.error(`Light: ${this.accessory.displayName} Hub Device is offline.`);
176
+ this.platform.log.error(`Light: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
177
177
  break;
178
178
  case 190:
179
179
  this.platform.log.error(`Light: ${this.accessory.displayName} Device internal error due to device states not synchronized`
@@ -160,7 +160,7 @@ export class Others {
160
160
  this.platform.log.error(`Other: ${this.accessory.displayName} Device is offline.`);
161
161
  break;
162
162
  case 171:
163
- this.platform.log.error(`Other: ${this.accessory.displayName} Hub Device is offline.`);
163
+ this.platform.log.error(`Other: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
164
164
  break;
165
165
  case 190:
166
166
  this.platform.log.error(`Other: ${this.accessory.displayName} Device internal error due to device states not synchronized`
@@ -377,7 +377,7 @@ export class TV {
377
377
  this.platform.log.error(`${this.device.remoteType}: ${this.accessory.displayName} Device is offline.`);
378
378
  break;
379
379
  case 171:
380
- this.platform.log.error(`${this.device.remoteType}: ${this.accessory.displayName} Hub Device is offline.`);
380
+ this.platform.log.error(`${this.device.remoteType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
381
381
  break;
382
382
  case 190:
383
383
  this.platform.log.error(`${this.device.remoteType}: `
@@ -139,7 +139,7 @@ export class VacuumCleaner {
139
139
  this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Device is offline.`);
140
140
  break;
141
141
  case 171:
142
- this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Hub Device is offline.`);
142
+ this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
143
143
  break;
144
144
  case 190:
145
145
  this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Device internal error due to device states not synchronized`
@@ -153,7 +153,7 @@ export class WaterHeater {
153
153
  this.platform.log.error(`Water Heater: ${this.accessory.displayName} Device is offline.`);
154
154
  break;
155
155
  case 171:
156
- this.platform.log.error(`Water Heater: ${this.accessory.displayName} Hub Device is offline.`);
156
+ this.platform.log.error(`Water Heater: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
157
157
  break;
158
158
  case 190:
159
159
  this.platform.log.error(`Water Heater: ${this.accessory.displayName} Device internal error due to device states not synchronized`