@switchbot/homebridge-switchbot 1.1.1-beta.8 → 1.2.1-beta.1

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 (104) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/README.md +67 -28
  3. package/config.schema.json +46 -43
  4. package/dist/devices/bots.d.ts +2 -0
  5. package/dist/devices/bots.d.ts.map +1 -1
  6. package/dist/devices/bots.js +91 -39
  7. package/dist/devices/bots.js.map +1 -1
  8. package/dist/devices/colorbulb.d.ts +19 -3
  9. package/dist/devices/colorbulb.d.ts.map +1 -1
  10. package/dist/devices/colorbulb.js +190 -31
  11. package/dist/devices/colorbulb.js.map +1 -1
  12. package/dist/devices/contact.d.ts +2 -0
  13. package/dist/devices/contact.d.ts.map +1 -1
  14. package/dist/devices/contact.js +22 -5
  15. package/dist/devices/contact.js.map +1 -1
  16. package/dist/devices/curtains.d.ts +7 -5
  17. package/dist/devices/curtains.d.ts.map +1 -1
  18. package/dist/devices/curtains.js +82 -32
  19. package/dist/devices/curtains.js.map +1 -1
  20. package/dist/devices/humidifiers.d.ts +2 -0
  21. package/dist/devices/humidifiers.d.ts.map +1 -1
  22. package/dist/devices/humidifiers.js +84 -27
  23. package/dist/devices/humidifiers.js.map +1 -1
  24. package/dist/devices/indoorcam.d.ts +2 -0
  25. package/dist/devices/indoorcam.d.ts.map +1 -1
  26. package/dist/devices/indoorcam.js +23 -7
  27. package/dist/devices/indoorcam.js.map +1 -1
  28. package/dist/devices/meters.d.ts +2 -0
  29. package/dist/devices/meters.d.ts.map +1 -1
  30. package/dist/devices/meters.js +21 -3
  31. package/dist/devices/meters.js.map +1 -1
  32. package/dist/devices/motion.d.ts +2 -0
  33. package/dist/devices/motion.d.ts.map +1 -1
  34. package/dist/devices/motion.js +21 -3
  35. package/dist/devices/motion.js.map +1 -1
  36. package/dist/devices/plugs.d.ts +2 -0
  37. package/dist/devices/plugs.d.ts.map +1 -1
  38. package/dist/devices/plugs.js +23 -7
  39. package/dist/devices/plugs.js.map +1 -1
  40. package/dist/irdevices/airconditioners.d.ts +2 -0
  41. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  42. package/dist/irdevices/airconditioners.js +14 -5
  43. package/dist/irdevices/airconditioners.js.map +1 -1
  44. package/dist/irdevices/airpurifiers.d.ts +2 -0
  45. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  46. package/dist/irdevices/airpurifiers.js +14 -5
  47. package/dist/irdevices/airpurifiers.js.map +1 -1
  48. package/dist/irdevices/cameras.d.ts +2 -0
  49. package/dist/irdevices/cameras.d.ts.map +1 -1
  50. package/dist/irdevices/cameras.js +14 -5
  51. package/dist/irdevices/cameras.js.map +1 -1
  52. package/dist/irdevices/fans.d.ts +2 -0
  53. package/dist/irdevices/fans.d.ts.map +1 -1
  54. package/dist/irdevices/fans.js +13 -5
  55. package/dist/irdevices/fans.js.map +1 -1
  56. package/dist/irdevices/lights.d.ts +2 -0
  57. package/dist/irdevices/lights.d.ts.map +1 -1
  58. package/dist/irdevices/lights.js +14 -5
  59. package/dist/irdevices/lights.js.map +1 -1
  60. package/dist/irdevices/others.d.ts +2 -0
  61. package/dist/irdevices/others.d.ts.map +1 -1
  62. package/dist/irdevices/others.js +20 -11
  63. package/dist/irdevices/others.js.map +1 -1
  64. package/dist/irdevices/tvs.d.ts +2 -0
  65. package/dist/irdevices/tvs.d.ts.map +1 -1
  66. package/dist/irdevices/tvs.js +14 -4
  67. package/dist/irdevices/tvs.js.map +1 -1
  68. package/dist/irdevices/vacuumcleaners.d.ts +2 -0
  69. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  70. package/dist/irdevices/vacuumcleaners.js +14 -5
  71. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  72. package/dist/irdevices/waterheaters.d.ts +2 -0
  73. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  74. package/dist/irdevices/waterheaters.js +14 -5
  75. package/dist/irdevices/waterheaters.js.map +1 -1
  76. package/dist/platform.d.ts +1 -0
  77. package/dist/platform.d.ts.map +1 -1
  78. package/dist/platform.js +35 -26
  79. package/dist/platform.js.map +1 -1
  80. package/dist/settings.d.ts +4 -0
  81. package/dist/settings.d.ts.map +1 -1
  82. package/dist/settings.js +557 -1
  83. package/dist/settings.js.map +1 -1
  84. package/package.json +7 -7
  85. package/src/devices/bots.ts +92 -40
  86. package/src/devices/colorbulb.ts +218 -33
  87. package/src/devices/contact.ts +23 -5
  88. package/src/devices/curtains.ts +90 -39
  89. package/src/devices/humidifiers.ts +85 -29
  90. package/src/devices/indoorcam.ts +24 -7
  91. package/src/devices/meters.ts +22 -3
  92. package/src/devices/motion.ts +22 -3
  93. package/src/devices/plugs.ts +24 -7
  94. package/src/irdevices/airconditioners.ts +15 -5
  95. package/src/irdevices/airpurifiers.ts +15 -5
  96. package/src/irdevices/cameras.ts +15 -5
  97. package/src/irdevices/fans.ts +13 -5
  98. package/src/irdevices/lights.ts +15 -5
  99. package/src/irdevices/others.ts +21 -11
  100. package/src/irdevices/tvs.ts +15 -4
  101. package/src/irdevices/vacuumcleaners.ts +15 -5
  102. package/src/irdevices/waterheaters.ts +15 -5
  103. package/src/platform.ts +36 -26
  104. package/src/settings.ts +557 -1
@@ -31,6 +31,10 @@ export class Bot {
31
31
  state!: serviceData['state'];
32
32
  battery!: serviceData['battery'];
33
33
 
34
+ // Config
35
+ private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
36
+ private readonly debugDebug = this.platform.config.options?.debug === 'debug' || this.platform.debugMode;
37
+
34
38
  // Updates
35
39
  botUpdateInProgress!: boolean;
36
40
  doBotUpdate!: Subject<void>;
@@ -138,10 +142,15 @@ export class Bot {
138
142
  try {
139
143
  await this.pushChanges();
140
144
  } catch (e: any) {
141
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed to pushChanges,`
142
- + ` Error Message: ${JSON.stringify(e.message)}`);
143
- this.platform.debug(`Bot: ${this.accessory.displayName} Error: ${JSON.stringify(e)}`);
144
- this.apiError(e);
145
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges`);
146
+ if (this.deviceDebug) {
147
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges,`
148
+ + ` Error Message: ${JSON.stringify(e.message)}`);
149
+ }
150
+ if (this.debugDebug) {
151
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges,`
152
+ + ` Error: ${JSON.stringify(e)}`);
153
+ }
145
154
  }
146
155
  this.botUpdateInProgress = false;
147
156
  });
@@ -236,7 +245,15 @@ export class Bot {
236
245
  this.parseStatus();
237
246
  this.updateHomeKitCharacteristics();
238
247
  }).catch(async (e: any) => {
239
- this.platform.log.error(`Bot: ${this.accessory.displayName} BLE Connection failed refreshStatus, Error Message: ${JSON.stringify(e.message)}`);
248
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
249
+ if (this.deviceDebug) {
250
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
251
+ + ` Error Message: ${JSON.stringify(e.message)}`);
252
+ }
253
+ if (this.debugDebug) {
254
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
255
+ + ` Error: ${JSON.stringify(e)}`);
256
+ }
240
257
  if (this.platform.config.credentials?.openToken) {
241
258
  this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
242
259
  await this.openAPIRefreshStatus();
@@ -261,8 +278,15 @@ export class Bot {
261
278
  this.parseStatus();
262
279
  this.updateHomeKitCharacteristics();
263
280
  } catch (e: any) {
264
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed to refresh status, Error Message: ${JSON.stringify(e.message)}`);
265
- this.platform.debug(`Bot: ${this.accessory.displayName} Error: ${JSON.stringify(e)}`);
281
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
282
+ if (this.deviceDebug) {
283
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
284
+ + ` Error Message: ${JSON.stringify(e.message)}`);
285
+ }
286
+ if (this.debugDebug) {
287
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
288
+ + ` Error: ${JSON.stringify(e)}`);
289
+ }
266
290
  this.apiError(e);
267
291
  }
268
292
  }
@@ -295,7 +319,15 @@ export class Bot {
295
319
  }).then(() => {
296
320
  this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
297
321
  }).catch(async (e: any) => {
298
- this.platform.log.error(`Bot: ${this.accessory.displayName} BLE Connection failed pushChanges, Error Message: ${JSON.stringify(e.message)}`);
322
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
323
+ if (this.deviceDebug) {
324
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
325
+ + ` Error Message: ${JSON.stringify(e.message)}`);
326
+ }
327
+ if (this.debugDebug) {
328
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
329
+ + ` Error: ${JSON.stringify(e)}`);
330
+ }
299
331
  if (this.platform.config.credentials?.openToken) {
300
332
  this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
301
333
  await this.openAPIpushChanges();
@@ -303,20 +335,28 @@ export class Bot {
303
335
  });
304
336
  } else if (this.device.bot?.mode === 'switch') {
305
337
  this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
306
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list) => {
338
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
307
339
  this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.SwitchOn}`);
308
340
  return this.turnOnOff(device_list);
309
341
  }).then(() => {
310
342
  this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
311
343
  }).catch(async (e: any) => {
312
- this.platform.log.error(`Bot: ${this.accessory.displayName} BLE Connection failed pushChanges, Error Message: ${JSON.stringify(e.message)}`);
344
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
345
+ if (this.deviceDebug) {
346
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
347
+ + ` Error Message: ${JSON.stringify(e.message)}`);
348
+ }
349
+ if (this.debugDebug) {
350
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
351
+ + ` Error: ${JSON.stringify(e)}`);
352
+ }
313
353
  if (this.platform.config.credentials?.openToken) {
314
354
  this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
315
355
  await this.openAPIpushChanges();
316
356
  }
317
357
  });
318
358
  } else {
319
- this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set.`);
359
+ this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
320
360
  }
321
361
  }
322
362
 
@@ -330,35 +370,47 @@ export class Bot {
330
370
 
331
371
  private async openAPIpushChanges() {
332
372
  if (this.platform.config.credentials?.openToken) {
333
- this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
334
- const payload = {
335
- commandType: 'command',
336
- parameter: 'default',
337
- } as payload;
338
-
339
- if (this.device.bot?.mode === 'switch' && this.SwitchOn) {
340
- payload.command = 'turnOn';
341
- this.SwitchOn = true;
342
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.SwitchOn}`);
343
- } else if (this.device.bot?.mode === 'switch' && !this.SwitchOn) {
344
- payload.command = 'turnOff';
345
- this.SwitchOn = false;
346
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.SwitchOn}`);
347
- } else if (this.device.bot?.mode === 'press') {
348
- payload.command = 'press';
349
- this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
350
- this.SwitchOn = false;
351
- } else {
352
- throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
353
- }
373
+ try {
374
+ this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
375
+ const payload = {
376
+ commandType: 'command',
377
+ parameter: 'default',
378
+ } as payload;
379
+
380
+ if (this.device.bot?.mode === 'switch' && this.SwitchOn) {
381
+ payload.command = 'turnOn';
382
+ this.SwitchOn = true;
383
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.SwitchOn}`);
384
+ } else if (this.device.bot?.mode === 'switch' && !this.SwitchOn) {
385
+ payload.command = 'turnOff';
386
+ this.SwitchOn = false;
387
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.SwitchOn}`);
388
+ } else if (this.device.bot?.mode === 'press') {
389
+ payload.command = 'press';
390
+ this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
391
+ this.SwitchOn = false;
392
+ } else {
393
+ throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
394
+ }
354
395
 
355
- this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
356
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
396
+ this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
397
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
357
398
 
358
- // Make the API request
359
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
360
- this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
361
- this.statusCode(push);
399
+ // Make the API request
400
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
401
+ this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
402
+ this.statusCode(push);
403
+ } catch (e: any) {
404
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
405
+ if (this.deviceDebug) {
406
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
407
+ + ` Error Message: ${JSON.stringify(e.message)}`);
408
+ }
409
+ if (this.debugDebug) {
410
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
411
+ + ` Error: ${JSON.stringify(e)}`);
412
+ }
413
+ }
362
414
  }
363
415
  }
364
416
 
@@ -422,8 +474,8 @@ export class Bot {
422
474
  this.platform.log.error(`Bot: ${this.accessory.displayName} Hub Device is offline.`);
423
475
  break;
424
476
  case 190:
425
- // eslint-disable-next-line max-len
426
- this.platform.log.error(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server. Or command fomrat is invalid.`);
477
+ this.platform.log.error(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
478
+ + ` Or command: ${JSON.stringify(push.data)} format is invalid`);
427
479
  break;
428
480
  case 100:
429
481
  this.platform.debug(`Bot: ${this.accessory.displayName} Command successfully sent.`);
@@ -2,7 +2,7 @@ import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
2
2
  import { SwitchBotPlatform } from '../platform';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { debounceTime, skipWhile, tap } from 'rxjs/operators';
5
- import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload } from '../settings';
5
+ import { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload, hs2rgb, rgb2hs } from '../settings';
6
6
  import { AxiosResponse } from 'axios';
7
7
 
8
8
  /**
@@ -16,7 +16,9 @@ export class ColorBulb {
16
16
 
17
17
  // Characteristic Values
18
18
  On!: CharacteristicValue;
19
+ Hue!: CharacteristicValue;
19
20
  Brightness!: CharacteristicValue;
21
+ Saturation!: CharacteristicValue;
20
22
  ColorTemperature!: CharacteristicValue;
21
23
 
22
24
  // OpenAPI Others
@@ -27,6 +29,8 @@ export class ColorBulb {
27
29
 
28
30
  // Config
29
31
  set_minStep?: number;
32
+ private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
33
+ private readonly debugDebug = this.platform.config.options?.debug === 'debug' || this.platform.debugMode;
30
34
 
31
35
  // Updates
32
36
  colorBulbUpdateInProgress!: boolean;
@@ -93,15 +97,38 @@ export class ColorBulb {
93
97
  // handle ColorTemperature events using the ColorTemperature characteristic
94
98
  this.service.getCharacteristic(this.platform.Characteristic.ColorTemperature)
95
99
  .setProps({
96
- minStep: this.minStep(),
100
+ minValue: 140,
101
+ maxValue: 500,
102
+ validValueRanges: [140, 500],
103
+ })
104
+ .onGet(() => {
105
+ return this.ColorTemperature;
106
+ })
107
+ .onSet(this.ColorTemperatureSet.bind(this));
108
+
109
+ // handle Hue events using the Hue characteristic
110
+ this.service.getCharacteristic(this.platform.Characteristic.Hue)
111
+ .setProps({
112
+ minValue: 0,
113
+ maxValue: 360,
114
+ validValueRanges: [0, 360],
115
+ })
116
+ .onGet(() => {
117
+ return this.Hue;
118
+ })
119
+ .onSet(this.HueSet.bind(this));
120
+
121
+ // handle Hue events using the Hue characteristic
122
+ this.service.getCharacteristic(this.platform.Characteristic.Saturation)
123
+ .setProps({
97
124
  minValue: 0,
98
125
  maxValue: 100,
99
126
  validValueRanges: [0, 100],
100
127
  })
101
128
  .onGet(() => {
102
- return this.ColorTemperature;
129
+ return this.Saturation;
103
130
  })
104
- .onSet(this.ColorTemperatureSet.bind(this));
131
+ .onSet(this.SaturationSet.bind(this));
105
132
 
106
133
  // Update Homekit
107
134
  this.updateHomeKitCharacteristics();
@@ -126,9 +153,15 @@ export class ColorBulb {
126
153
  try {
127
154
  await this.pushChanges();
128
155
  } catch (e: any) {
129
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed to pushChanges,`
130
- + ` Error Message: ${JSON.stringify(e.message)}`);
131
- this.platform.debug(`Color Bulb: ${this.accessory.displayName} Error: ${JSON.stringify(e)}`);
156
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges`);
157
+ if (this.deviceDebug) {
158
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges,`
159
+ + ` Error Message: ${JSON.stringify(e.message)}`);
160
+ }
161
+ if (this.debugDebug) {
162
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges,`
163
+ + ` Error: ${JSON.stringify(e)}`);
164
+ }
132
165
  this.apiError(e);
133
166
  }
134
167
  this.colorBulbUpdateInProgress = false;
@@ -152,9 +185,40 @@ export class ColorBulb {
152
185
  default:
153
186
  this.On = false;
154
187
  }
155
- this.platform.debug(`Color Bulb: ${this.accessory.displayName} On: ${this.On}`);
156
- this.deviceStatus.body.brightness = Number(this.Brightness);
157
- this.deviceStatus.body.colorTemperature = Number(this.ColorTemperature);
188
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} On: ${this.On}`);
189
+
190
+ // Brightness
191
+ this.Brightness = Number(this.deviceStatus.body.brightness);
192
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
193
+
194
+ // Color, Hue & Brightness
195
+ if (this.deviceStatus.body.color) {
196
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} color: ${JSON.stringify(this.deviceStatus.body.color)}`);
197
+ const [red, green, blue] = this.deviceStatus.body.color!.split(':');
198
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} red: ${JSON.stringify(red)}`);
199
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} green: ${JSON.stringify(green)}`);
200
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} blue: ${JSON.stringify(blue)}`);
201
+
202
+ const [hue, saturation] = rgb2hs(Number(red), Number(green), Number(blue));
203
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} hs: ${JSON.stringify(rgb2hs(Number(red), Number(green), Number(blue)))}`);
204
+
205
+ // Hue
206
+ this.Hue = hue;
207
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} Hue: ${this.Hue}`);
208
+
209
+ // Saturation
210
+ this.Saturation = saturation;
211
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} Saturation: ${this.Saturation}`);
212
+ }
213
+
214
+ // ColorTemperature
215
+ if (this.deviceStatus.body.colorTemperature) {
216
+ // Convert mired to kelvin to nearest 100 (Govee seems to need this)
217
+ const mired = Math.round(1000000 / this.deviceStatus.body.colorTemperature);
218
+
219
+ this.ColorTemperature = Number(mired);
220
+ this.platform.log.warn(`Color Bulb: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
221
+ }
158
222
  }
159
223
 
160
224
  async refreshStatus() {
@@ -164,37 +228,123 @@ export class ColorBulb {
164
228
  this.parseStatus();
165
229
  this.updateHomeKitCharacteristics();
166
230
  } catch (e: any) {
167
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed to refresh status, Error Message ${JSON.stringify(e.message)}`);
168
- this.platform.debug(`Color Bulb: ${this.accessory.displayName} Error: ${JSON.stringify(e)}`);
231
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
232
+ if (this.deviceDebug) {
233
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
234
+ + ` Error Message: ${JSON.stringify(e.message)}`);
235
+ }
236
+ if (this.debugDebug) {
237
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
238
+ + ` Error: ${JSON.stringify(e)}`);
239
+ }
169
240
  this.apiError(e);
170
241
  }
171
242
  }
172
243
 
173
244
  /**
174
245
  * Pushes the requested changes to the SwitchBot API
175
- * deviceType commandType Command command parameter Description
176
- * Color Bulb - "command" "turnOff" "default" = set to OFF state
177
- * Color Bulb - "command" "turnOn" "default" = set to ON state
246
+ * deviceType commandType Command command parameter Description
247
+ * Color Bulb - "command" "turnOff" "default" = set to OFF state
248
+ * Color Bulb - "command" "turnOn" "default" = set to ON state
249
+ * Color Bulb - "command" "toggle" "default" = toggle state
250
+ * Color Bulb - "command" "setBrightness" "{1-100}" = set brightness
251
+ * Color Bulb - "command" "setColor" "{0-255}:{0-255}:{0-255}" = set RGB color value
252
+ * Color Bulb - "command" "setColorTemperature" "{2700-6500}" = set color temperature
178
253
  */
179
254
  async pushChanges() {
180
- const payload = {
181
- commandType: 'command',
182
- parameter: 'default',
183
- } as payload;
184
-
185
- if (this.On) {
186
- payload.command = 'turnOn';
187
- } else {
188
- payload.command = 'turnOff';
189
- }
255
+ try {
256
+ // Push On Update
257
+ if (this.On) {
258
+ const payload = {
259
+ commandType: 'command',
260
+ parameter: 'default',
261
+ } as payload;
262
+
263
+ if (this.On) {
264
+ payload.command = 'turnOn';
265
+ } else {
266
+ payload.command = 'turnOff';
267
+ }
190
268
 
191
- this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
192
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
269
+ this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
270
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
271
+
272
+ // Make the API request
273
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
274
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
275
+ this.statusCode(push);
276
+ }
277
+
278
+ // Push Brightness Update
279
+ if (this.On) {
280
+ const payload = {
281
+ commandType: 'command',
282
+ command: 'setBrightness',
283
+ parameter: `{${this.Brightness}}`,
284
+ } as payload;
285
+
286
+ this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
287
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
288
+
289
+ // Make the API request
290
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
291
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
292
+ this.statusCode(push);
293
+ }
294
+
295
+ // Push ColorTemperature Update
296
+ if (this.On) {
297
+ const kelvin = Math.round(1000000 / Number(this.ColorTemperature));
298
+
299
+ const payload = {
300
+ commandType: 'command',
301
+ command: 'setColorTemperature',
302
+ parameter: `{${kelvin}}`,
303
+ } as payload;
304
+
305
+ this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
306
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
307
+
308
+ // Make the API request
309
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
310
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
311
+ this.statusCode(push);
312
+ }
313
+
314
+ // Push Hue & Saturation Update
315
+ if (this.On) {
316
+ this.platform.log.warn(JSON.stringify(this.Hue));
317
+ this.platform.log.warn(JSON.stringify(this.Saturation));
318
+
319
+ const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
320
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} rgb: ${JSON.stringify([red, green, blue])}`);
321
+
322
+ const payload = {
323
+ commandType: 'command',
324
+ command: 'setColor',
325
+ parameter: `{${red}}:{${green}}:{${blue}}`,
326
+ } as payload;
327
+
328
+ this.platform.log.info(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
329
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
330
+
331
+ // Make the API request
332
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
333
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
334
+ this.statusCode(push);
335
+ }
193
336
 
194
- // Make the API request
195
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
196
- this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
197
- this.statusCode(push);
337
+ } catch (e: any) {
338
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
339
+ if (this.deviceDebug) {
340
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
341
+ + ` Error Message: ${JSON.stringify(e.message)}`);
342
+ }
343
+ if (this.debugDebug) {
344
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
345
+ + ` Error: ${JSON.stringify(e)}`);
346
+ }
347
+ }
198
348
  }
199
349
 
200
350
  updateHomeKitCharacteristics() {
@@ -216,11 +366,25 @@ export class ColorBulb {
216
366
  this.service.updateCharacteristic(this.platform.Characteristic.Brightness, this.ColorTemperature);
217
367
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} updateCharacteristic ColorTemperature: ${this.ColorTemperature}`);
218
368
  }
369
+ if (this.Hue === undefined) {
370
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} Hue: ${this.Hue}`);
371
+ } else {
372
+ this.service.updateCharacteristic(this.platform.Characteristic.Hue, this.Hue);
373
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} updateCharacteristic Hue: ${this.Hue}`);
374
+ }
375
+ if (this.Saturation === undefined) {
376
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} Saturation: ${this.Saturation}`);
377
+ } else {
378
+ this.service.updateCharacteristic(this.platform.Characteristic.Saturation, this.Saturation);
379
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} updateCharacteristic Saturation: ${this.Saturation}`);
380
+ }
219
381
  }
220
382
 
221
383
  public apiError(e: any) {
222
384
  this.service.updateCharacteristic(this.platform.Characteristic.On, e);
385
+ this.service.updateCharacteristic(this.platform.Characteristic.Hue, e);
223
386
  this.service.updateCharacteristic(this.platform.Characteristic.Brightness, e);
387
+ this.service.updateCharacteristic(this.platform.Characteristic.Saturation, e);
224
388
  this.service.updateCharacteristic(this.platform.Characteristic.ColorTemperature, e);
225
389
  }
226
390
 
@@ -242,8 +406,8 @@ export class ColorBulb {
242
406
  this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Hub Device is offline.`);
243
407
  break;
244
408
  case 190:
245
- // eslint-disable-next-line max-len
246
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server. Or command fomrat is invalid.`);
409
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
410
+ + ` Or command: ${JSON.stringify(push.data)} format is invalid`);
247
411
  break;
248
412
  case 100:
249
413
  this.platform.debug(`Color Bulb: ${this.accessory.displayName} Command successfully sent.`);
@@ -282,4 +446,25 @@ export class ColorBulb {
282
446
  this.ColorTemperature = value;
283
447
  this.doColorBulbUpdate.next();
284
448
  }
449
+
450
+ /**
451
+ * Handle requests to set the value of the "Hue" characteristic
452
+ */
453
+ HueSet(value: CharacteristicValue) {
454
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} Hue: ${value}`);
455
+
456
+ this.Hue = value;
457
+ this.doColorBulbUpdate.next();
458
+ }
459
+
460
+ /**
461
+ * Handle requests to set the value of the "Saturation" characteristic
462
+ */
463
+ SaturationSet(value: CharacteristicValue) {
464
+ this.platform.debug(`Color Bulb: ${this.accessory.displayName} Saturation: ${value}`);
465
+
466
+ this.Saturation = value;
467
+ this.doColorBulbUpdate.next();
468
+ }
285
469
  }
470
+
@@ -34,6 +34,10 @@ export class Contact {
34
34
  doorState!: serviceData['doorState'];
35
35
  lightLevel!: serviceData['lightLevel'];
36
36
 
37
+ // Config
38
+ private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
39
+ private readonly debugDebug = this.platform.config.options?.debug === 'debug' || this.platform.debugMode;
40
+
37
41
  // Updates
38
42
  contactUbpdateInProgress!: boolean;
39
43
  doContactUpdate!: Subject<void>;
@@ -163,7 +167,7 @@ export class Contact {
163
167
  this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED;
164
168
  break;
165
169
  default:
166
- this.platform.log.error('timeout no closed');
170
+ this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} timeout no closed, doorstate: ${this.doorState}`);
167
171
  }
168
172
  if (this.device.contact?.hide_lightsensor) {// Light Level
169
173
  switch (this.lightLevel) {
@@ -256,7 +260,15 @@ export class Contact {
256
260
  this.parseStatus();
257
261
  this.updateHomeKitCharacteristics();
258
262
  }).catch(async (e: any) => {
259
- this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} BLE Connection failed, Error Message: ${JSON.stringify(e.message)}`);
263
+ this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
264
+ if (this.deviceDebug) {
265
+ this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
266
+ + ` Error Message: ${JSON.stringify(e.message)}`);
267
+ }
268
+ if (this.debugDebug) {
269
+ this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
270
+ + ` Error: ${JSON.stringify(e)}`);
271
+ }
260
272
  if (this.platform.config.credentials?.openToken) {
261
273
  this.platform.log.warn(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
262
274
  await this.openAPIRefreshStatus();
@@ -273,9 +285,15 @@ export class Contact {
273
285
  this.parseStatus();
274
286
  this.updateHomeKitCharacteristics();
275
287
  } catch (e: any) {
276
- this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed to refresh status.`
277
- + ` Error Message: ${JSON.stringify(e.message)}`);
278
- this.platform.debug(`Contact Sensor: ${this.accessory.displayName} Error: ${JSON.stringify(e)}`);
288
+ this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
289
+ if (this.deviceDebug) {
290
+ this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
291
+ + ` Error Message: ${JSON.stringify(e.message)}`);
292
+ }
293
+ if (this.debugDebug) {
294
+ this.platform.log.error(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
295
+ + ` Error: ${JSON.stringify(e)}`);
296
+ }
279
297
  this.apiError(e);
280
298
  }
281
299
  }