@switchbot/homebridge-switchbot 2.0.0-beta.19 → 2.0.0-beta.20

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 (112) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/README.md +1 -2
  3. package/config.schema.json +51 -32
  4. package/dist/device/bot.d.ts +32 -29
  5. package/dist/device/bot.d.ts.map +1 -1
  6. package/dist/device/bot.js +549 -575
  7. package/dist/device/bot.js.map +1 -1
  8. package/dist/device/colorbulb.d.ts +33 -15
  9. package/dist/device/colorbulb.d.ts.map +1 -1
  10. package/dist/device/colorbulb.js +426 -341
  11. package/dist/device/colorbulb.js.map +1 -1
  12. package/dist/device/contact.d.ts +16 -9
  13. package/dist/device/contact.d.ts.map +1 -1
  14. package/dist/device/contact.js +246 -208
  15. package/dist/device/contact.js.map +1 -1
  16. package/dist/device/curtain.d.ts +21 -18
  17. package/dist/device/curtain.d.ts.map +1 -1
  18. package/dist/device/curtain.js +449 -449
  19. package/dist/device/curtain.js.map +1 -1
  20. package/dist/device/humidifier.d.ts +22 -20
  21. package/dist/device/humidifier.d.ts.map +1 -1
  22. package/dist/device/humidifier.js +346 -324
  23. package/dist/device/humidifier.js.map +1 -1
  24. package/dist/device/lock.d.ts +22 -10
  25. package/dist/device/lock.d.ts.map +1 -1
  26. package/dist/device/lock.js +257 -178
  27. package/dist/device/lock.js.map +1 -1
  28. package/dist/device/meter.d.ts +21 -14
  29. package/dist/device/meter.d.ts.map +1 -1
  30. package/dist/device/meter.js +287 -239
  31. package/dist/device/meter.js.map +1 -1
  32. package/dist/device/meterplus.d.ts +23 -10
  33. package/dist/device/meterplus.d.ts.map +1 -1
  34. package/dist/device/meterplus.js +308 -190
  35. package/dist/device/meterplus.js.map +1 -1
  36. package/dist/device/motion.d.ts +17 -10
  37. package/dist/device/motion.d.ts.map +1 -1
  38. package/dist/device/motion.js +225 -193
  39. package/dist/device/motion.js.map +1 -1
  40. package/dist/device/plug.d.ts +24 -17
  41. package/dist/device/plug.d.ts.map +1 -1
  42. package/dist/device/plug.js +270 -267
  43. package/dist/device/plug.js.map +1 -1
  44. package/dist/device/striplight.d.ts +36 -14
  45. package/dist/device/striplight.d.ts.map +1 -1
  46. package/dist/device/striplight.js +447 -299
  47. package/dist/device/striplight.js.map +1 -1
  48. package/dist/irdevice/airconditioner.d.ts +7 -14
  49. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  50. package/dist/irdevice/airconditioner.js +177 -169
  51. package/dist/irdevice/airconditioner.js.map +1 -1
  52. package/dist/irdevice/airpurifier.d.ts +3 -5
  53. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  54. package/dist/irdevice/airpurifier.js +72 -57
  55. package/dist/irdevice/airpurifier.js.map +1 -1
  56. package/dist/irdevice/camera.d.ts +3 -4
  57. package/dist/irdevice/camera.d.ts.map +1 -1
  58. package/dist/irdevice/camera.js +47 -33
  59. package/dist/irdevice/camera.js.map +1 -1
  60. package/dist/irdevice/fan.d.ts +3 -4
  61. package/dist/irdevice/fan.d.ts.map +1 -1
  62. package/dist/irdevice/fan.js +66 -48
  63. package/dist/irdevice/fan.js.map +1 -1
  64. package/dist/irdevice/light.d.ts +3 -4
  65. package/dist/irdevice/light.d.ts.map +1 -1
  66. package/dist/irdevice/light.js +48 -47
  67. package/dist/irdevice/light.js.map +1 -1
  68. package/dist/irdevice/other.d.ts +3 -4
  69. package/dist/irdevice/other.d.ts.map +1 -1
  70. package/dist/irdevice/other.js +47 -33
  71. package/dist/irdevice/other.js.map +1 -1
  72. package/dist/irdevice/tv.d.ts +10 -11
  73. package/dist/irdevice/tv.d.ts.map +1 -1
  74. package/dist/irdevice/tv.js +64 -48
  75. package/dist/irdevice/tv.js.map +1 -1
  76. package/dist/irdevice/vacuumcleaner.d.ts +7 -12
  77. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  78. package/dist/irdevice/vacuumcleaner.js +52 -41
  79. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  80. package/dist/irdevice/waterheater.d.ts +6 -11
  81. package/dist/irdevice/waterheater.d.ts.map +1 -1
  82. package/dist/irdevice/waterheater.js +52 -42
  83. package/dist/irdevice/waterheater.js.map +1 -1
  84. package/dist/platform.d.ts +0 -4
  85. package/dist/platform.d.ts.map +1 -1
  86. package/dist/platform.js +44 -66
  87. package/dist/platform.js.map +1 -1
  88. package/dist/settings.d.ts +3 -3
  89. package/dist/settings.d.ts.map +1 -1
  90. package/package.json +7 -6
  91. package/src/device/bot.ts +551 -589
  92. package/src/device/colorbulb.ts +441 -375
  93. package/src/device/contact.ts +249 -213
  94. package/src/device/curtain.ts +452 -461
  95. package/src/device/humidifier.ts +358 -365
  96. package/src/device/lock.ts +263 -179
  97. package/src/device/meter.ts +302 -253
  98. package/src/device/meterplus.ts +319 -194
  99. package/src/device/motion.ts +230 -199
  100. package/src/device/plug.ts +273 -274
  101. package/src/device/striplight.ts +460 -316
  102. package/src/irdevice/airconditioner.ts +181 -183
  103. package/src/irdevice/airpurifier.ts +70 -60
  104. package/src/irdevice/camera.ts +46 -36
  105. package/src/irdevice/fan.ts +64 -49
  106. package/src/irdevice/light.ts +47 -51
  107. package/src/irdevice/other.ts +46 -36
  108. package/src/irdevice/tv.ts +64 -51
  109. package/src/irdevice/vacuumcleaner.ts +52 -45
  110. package/src/irdevice/waterheater.ts +50 -45
  111. package/src/platform.ts +44 -68
  112. package/src/settings.ts +3 -3
@@ -48,7 +48,6 @@ export class ColorBulb {
48
48
  deviceLogging!: string;
49
49
  deviceRefreshRate!: number;
50
50
  adaptiveLightingShift?: number;
51
- OpenAPI?: boolean;
52
51
 
53
52
  // Adaptive Lighting
54
53
  AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
@@ -62,25 +61,18 @@ export class ColorBulb {
62
61
  colorBulbUpdateInProgress!: boolean;
63
62
  doColorBulbUpdate!: Subject<void>;
64
63
 
64
+ // Connection
65
+ private readonly BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
66
+ private readonly OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
67
+
65
68
  constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
66
69
  // default placeholders
67
70
  this.logs(device);
68
- this.openAPI();
69
71
  this.scan(device);
70
72
  this.refreshRate(device);
71
73
  this.adaptiveLighting(device);
72
74
  this.config(device);
73
- if (this.On === undefined) {
74
- this.On = false;
75
- } else {
76
- this.On = this.accessory.context.On;
77
- }
78
- this.Hue = 0;
79
- this.Brightness = 0;
80
- this.Saturation = 0;
81
- this.ColorTemperature = 140;
82
- this.minKelvin = 2000;
83
- this.maxKelvin = 9000;
75
+ this.context();
84
76
  // this is subject we use to track when we need to POST changes to the SwitchBot API
85
77
  this.doColorBulbUpdate = new Subject();
86
78
  this.colorBulbUpdateInProgress = false;
@@ -211,12 +203,9 @@ export class ColorBulb {
211
203
  try {
212
204
  await this.pushChanges();
213
205
  } catch (e: any) {
214
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges`);
215
- if (this.deviceLogging.includes('debug')) {
216
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges,`
217
- + ` Error Message: ${superStringify(e.message)}`);
218
- }
219
206
  this.apiError(e);
207
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
208
+ + ` Error Message: ${superStringify(e.message)}`);
220
209
  }
221
210
  this.colorBulbUpdateInProgress = false;
222
211
  // Refresh the status from the API
@@ -229,16 +218,23 @@ export class ColorBulb {
229
218
  });
230
219
  }
231
220
 
221
+ /**
222
+ * Parse the device status from the SwitchBot api
223
+ */
232
224
  async parseStatus(): Promise<void> {
233
- if (this.SwitchToOpenAPI || !this.device.ble) {
225
+ /*if (this.BLE && !this.SwitchToOpenAPI) {
226
+ await this.BLEparseStatus();
227
+ } else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
228
+ this.SwitchToOpenAPI = false;
234
229
  await this.openAPIparseStatus();
235
230
  } else {
236
- await this.BLEparseStatus();
231
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
232
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
237
233
  }
238
234
  }
239
235
 
240
236
  async BLEparseStatus(): Promise<void> {
241
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE parseStatus`);
237
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
242
238
  // State
243
239
  switch (this.state) {
244
240
  case 'on':
@@ -251,6 +247,7 @@ export class ColorBulb {
251
247
  }
252
248
 
253
249
  async openAPIparseStatus() {
250
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
254
251
  switch (this.power) {
255
252
  case 'on':
256
253
  this.On = true;
@@ -297,16 +294,22 @@ export class ColorBulb {
297
294
  }
298
295
  }
299
296
 
297
+ /**
298
+ * Asks the SwitchBot API for the latest device information
299
+ */
300
300
  async refreshStatus(): Promise<void> {
301
- if (this.device.ble) {
301
+ /*if (this.BLE) {
302
302
  await this.BLERefreshStatus();
303
- } else {
303
+ } else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
304
304
  await this.openAPIRefreshStatus();
305
+ } else {
306
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
307
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
305
308
  }
306
309
  }
307
310
 
308
311
  async BLERefreshStatus(): Promise<void> {
309
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE refreshStatus`);
312
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
310
313
  const switchbot = await this.platform.connectBLE();
311
314
  // Convert to BLE Address
312
315
  this.device.bleMac = this.device
@@ -366,228 +369,232 @@ export class ColorBulb {
366
369
  this.parseStatus();
367
370
  this.updateHomeKitCharacteristics();
368
371
  } else {
369
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
370
- if (this.platform.config.credentials?.token) {
371
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
372
- this.SwitchToOpenAPI = true;
373
- await this.openAPIRefreshStatus();
374
- }
372
+ await this.BLEconnection(switchbot);
375
373
  }
376
374
  })
377
375
  .catch(async (e: any) => {
378
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
379
- if (this.deviceLogging.includes('debug')) {
380
- this.errorLog(
381
- `${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
382
- + ` Error Message: ${superStringify(e.message)}`,
383
- );
384
- }
385
- if (this.platform.config.credentials?.token) {
386
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
387
- this.SwitchToOpenAPI = true;
388
- await this.openAPIRefreshStatus();
389
- }
390
376
  this.apiError(e);
377
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
378
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
379
+ await this.BLEconnection(switchbot);
391
380
  });
392
381
  } else {
393
382
  await this.BLEconnection(switchbot);
394
383
  }
395
384
  }
396
385
 
397
- async getCustomBLEAddress(switchbot: any) {
398
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
399
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} customBLEaddress: ${this.device.customBLEaddress}`);
400
- (async () => {
401
- // Start to monitor advertisement packets
402
- await switchbot.startScan({
403
- model: 'u',
386
+ async openAPIRefreshStatus() {
387
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
388
+ try {
389
+ const t = Date.now();
390
+ const nonce = 'requestID';
391
+ const data = this.platform.config.credentials?.token + t + nonce;
392
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
393
+ const sign = signTerm.toString('base64');
394
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
395
+ const options = {
396
+ hostname: HostDomain,
397
+ port: 443,
398
+ path: `${DevicePath}/${this.device.deviceId}/status`,
399
+ method: 'GET',
400
+ headers: {
401
+ Authorization: this.platform.config.credentials?.token,
402
+ sign: sign,
403
+ nonce: nonce,
404
+ t: t,
405
+ 'Content-Type': 'application/json',
406
+ },
407
+ };
408
+ const req = https.request(options, (res) => {
409
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
410
+ this.statusCode({ res });
411
+ let rawData = '';
412
+ res.on('data', (d) => {
413
+ rawData += d;
414
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
404
415
  });
405
- // Set an event handler
406
- switchbot.onadvertisement = (ad: any) => {
407
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
408
- };
409
- await switchbot.wait(10000);
410
- // Stop to monitor
411
- switchbot.stopScan();
412
- })();
416
+ res.on('end', () => {
417
+ try {
418
+ this.deviceStatus = JSON.parse(rawData);
419
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
420
+ this.power = this.deviceStatus.body.power;
421
+ this.color = this.deviceStatus.body.color;
422
+ this.brightness = this.deviceStatus.body.brightness;
423
+ this.colorTemperature = this.deviceStatus.body.colorTemperature;
424
+ this.parseStatus();
425
+ this.updateHomeKitCharacteristics();
426
+ } catch (e: any) {
427
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
428
+ }
429
+ });
430
+ });
431
+ req.on('error', (e: any) => {
432
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
433
+ });
434
+ req.end();
435
+ } catch (e: any) {
436
+ this.apiError(e);
437
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
438
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
413
439
  }
414
440
  }
415
441
 
416
- async BLEconnection(switchbot: any): Promise<void> {
417
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
418
- if (this.platform.config.credentials?.token) {
419
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
420
- this.SwitchToOpenAPI = true;
421
- await this.openAPIRefreshStatus();
442
+ /**
443
+ * Pushes the requested changes to the SwitchBot API
444
+ * deviceType commandType Command command parameter Description
445
+ * Color Bulb - "command" "turnOff" "default" = set to OFF state
446
+ * Color Bulb - "command" "turnOn" "default" = set to ON state
447
+ * Color Bulb - "command" "toggle" "default" = toggle state
448
+ * Color Bulb - "command" "setBrightness" "{1-100}" = set brightness
449
+ * Color Bulb - "command" "setColor" "{0-255}:{0-255}:{0-255}" = set RGB color value
450
+ * Color Bulb - "command" "setColorTemperature" "{2700-6500}" = set color temperature
451
+ *
452
+ */
453
+ async pushChanges(): Promise<void> {
454
+ /*if (this.BLE) {
455
+ await this.BLERefreshStatus();
456
+ } else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
457
+ await this.openAPIpushChanges();
458
+ } else {
459
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
460
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
422
461
  }
462
+ interval(5000)
463
+ .pipe(take(1))
464
+ .subscribe(async () => {
465
+ await this.refreshStatus();
466
+ });
423
467
  }
424
468
 
425
- async openAPIRefreshStatus() {
426
- if (this.OpenAPI) {
427
- try {
469
+ async BLEpushChanges(): Promise<void> {
470
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
471
+ if (this.On !== this.accessory.context.On) {
472
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
473
+ const switchbot = await this.platform.connectBLE();
474
+ // Convert to BLE Address
475
+ this.device.bleMac = this.device
476
+ .deviceId!.match(/.{1,2}/g)!
477
+ .join(':')
478
+ .toLowerCase();
479
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
480
+ switchbot
481
+ .discover({
482
+ model: 'u',
483
+ id: this.device.bleMac,
484
+ })
485
+ .then((device_list: any) => {
486
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
487
+ return this.turnOnOff(device_list);
488
+ })
489
+ .then(() => {
490
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
491
+ this.On = false;
492
+ })
493
+ .catch(async (e: any) => {
494
+ this.apiError(e);
495
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
496
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
497
+ if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
498
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
499
+ await this.openAPIpushChanges();
500
+ }
501
+ });
502
+ } else {
503
+ this.debugLog(
504
+ `${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, `
505
+ +`OnCached: ${this.accessory.context.On}`,
506
+ );
507
+ }
508
+ }
509
+
510
+ async openAPIpushChanges(): Promise<void> {
511
+ try {
512
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
513
+ if (this.On !== this.accessory.context.On) {
514
+ // Make Push On request to the API
428
515
  const t = Date.now();
429
516
  const nonce = 'requestID';
430
517
  const data = this.platform.config.credentials?.token + t + nonce;
431
- const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
518
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
519
+ .update(Buffer.from(data, 'utf-8'))
520
+ .digest();
432
521
  const sign = signTerm.toString('base64');
433
522
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
523
+
524
+ let command = '';
525
+ if (this.On) {
526
+ command = 'turnOn';
527
+ } else {
528
+ command = 'turnOff';
529
+ }
530
+ const body = superStringify({
531
+ 'command': `${command}`,
532
+ 'parameter': 'default',
533
+ 'commandType': 'command',
534
+ });
535
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
434
536
  const options = {
435
537
  hostname: HostDomain,
436
538
  port: 443,
437
- path: `${DevicePath}/${this.device.deviceId}/status`,
438
- method: 'GET',
539
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
540
+ method: 'POST',
439
541
  headers: {
440
- Authorization: this.platform.config.credentials?.token,
441
- sign: sign,
442
- nonce: nonce,
443
- t: t,
542
+ 'Authorization': this.platform.config.credentials?.token,
543
+ 'sign': sign,
544
+ 'nonce': nonce,
545
+ 't': t,
444
546
  'Content-Type': 'application/json',
547
+ 'Content-Length': body.length,
445
548
  },
446
549
  };
447
- const req = https.request(options, (res) => {
448
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Refresh statusCode: ${res.statusCode}`);
449
- let rawData = '';
450
- res.on('data', (d) => {
451
- rawData += d;
550
+ const req = https.request(options, res => {
551
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
552
+ this.statusCode({ res });
553
+ res.on('data', d => {
452
554
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
453
555
  });
454
- res.on('end', () => {
455
- try {
456
- this.deviceStatus = JSON.parse(rawData);
457
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus: ${superStringify(this.deviceStatus)}`);
458
- this.power = this.deviceStatus.body.power;
459
- this.color = this.deviceStatus.body.color;
460
- this.brightness = this.deviceStatus.body.brightness;
461
- this.colorTemperature = this.deviceStatus.body.colorTemperature;
462
- this.parseStatus();
463
- this.updateHomeKitCharacteristics();
464
- } catch (e: any) {
465
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
466
- }
467
- });
468
556
  });
469
557
  req.on('error', (e: any) => {
470
558
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
471
559
  });
560
+ req.write(body);
472
561
  req.end();
473
- } catch (e: any) {
474
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
475
- if (this.deviceLogging.includes('debug')) {
476
- this.errorLog(
477
- `${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
478
- + ` Error Message: ${superStringify(e.message)}`,
479
- );
480
- }
481
- this.apiError(e);
562
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges: ${superStringify(req)}`);
563
+ } else {
564
+ this.debugLog(
565
+ `${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `On: ${this.On}, `
566
+ +`OnCached: ${this.accessory.context.On}`,
567
+ );
482
568
  }
483
- } else {
484
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI is disabled, commands will not be sent.`);
485
- }
486
- }
487
-
488
- /**
489
- * Pushes the requested changes to the SwitchBot API
490
- * deviceType commandType Command command parameter Description
491
- * Color Bulb - "command" "turnOff" "default" = set to OFF state
492
- * Color Bulb - "command" "turnOn" "default" = set to ON state
493
- * Color Bulb - "command" "toggle" "default" = toggle state
494
- * Color Bulb - "command" "setBrightness" "{1-100}" = set brightness
495
- * Color Bulb - "command" "setColor" "{0-255}:{0-255}:{0-255}" = set RGB color value
496
- * Color Bulb - "command" "setColorTemperature" "{2700-6500}" = set color temperature
497
- *
498
- */
499
- async pushChanges(): Promise<void> {
500
- if (this.OpenAPI) {
501
- try {
502
- if (this.On !== this.accessory.context.On) {
503
- // Make Push On request to the API
504
- const t = Date.now();
505
- const nonce = 'requestID';
506
- const data = this.platform.config.credentials?.token + t + nonce;
507
- const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
508
- .update(Buffer.from(data, 'utf-8'))
509
- .digest();
510
- const sign = signTerm.toString('base64');
511
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
512
-
513
- let command = '';
514
- if (this.On) {
515
- command = 'turnOn';
516
- } else {
517
- command = 'turnOff';
518
- }
519
- const body = superStringify({
520
- 'command': `${command}`,
521
- 'parameter': 'default',
522
- 'commandType': 'command',
523
- });
524
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
525
- const options = {
526
- hostname: HostDomain,
527
- port: 443,
528
- path: `${DevicePath}/${this.device.deviceId}/commands`,
529
- method: 'POST',
530
- headers: {
531
- 'Authorization': this.platform.config.credentials?.token,
532
- 'sign': sign,
533
- 'nonce': nonce,
534
- 't': t,
535
- 'Content-Type': 'application/json',
536
- 'Content-Length': body.length,
537
- },
538
- };
539
- const req = https.request(options, res => {
540
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
541
- this.statusCode({ res });
542
- res.on('data', d => {
543
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
544
- });
545
- });
546
- req.on('error', (e: any) => {
547
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
548
- });
549
- req.write(body);
550
- req.end();
551
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges: ${superStringify(req)}`);
552
- }
553
- // Push Brightness Update
554
- if (this.On) {
555
- await this.pushBrightnessChanges();
556
- }
557
-
558
- // Push ColorTemperature Update
559
- if (this.On) {
560
- await this.pushColorTemperatureChanges();
561
- }
562
-
563
- // Push Hue & Saturation Update
564
- if (this.On) {
565
- await this.pushHueSaturationChanges();
566
- }
567
- } catch (e: any) {
568
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
569
- if (this.deviceLogging.includes('debug')) {
570
- this.errorLog(
571
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
572
- + ` Error Message: ${superStringify(e.message)}`,
573
- );
574
- }
575
- this.apiError(e);
569
+ // Push Brightness Update
570
+ if (this.On) {
571
+ await this.pushBrightnessChanges();
576
572
  }
577
- } else {
578
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI is disabled, commands will not be sent.`);
573
+ // Push ColorTemperature Update
574
+ if (this.On) {
575
+ await this.pushColorTemperatureChanges();
576
+ }
577
+ // Push Hue & Saturation Update
578
+ if (this.On) {
579
+ await this.pushHueSaturationChanges();
580
+ }
581
+ } catch (e: any) {
582
+ this.apiError(e);
583
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
584
+ + ` Connection, Error Message: ${superStringify(e.message)}`,
585
+ );
579
586
  }
580
587
  }
581
588
 
582
589
  async pushHueSaturationChanges(): Promise<void> {
583
590
  try {
591
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges`);
584
592
  if (this.Hue !== this.accessory.context.Hue || this.Saturation !== this.accessory.context.Saturation) {
585
593
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${superStringify(this.Hue)}`);
586
594
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${superStringify(this.Saturation)}`);
587
595
 
588
596
  const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
589
597
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} rgb: ${superStringify([red, green, blue])}`);
590
-
591
598
  // Make Push Hue/Saturation request to the API
592
599
  const t = Date.now();
593
600
  const nonce = 'requestID';
@@ -618,7 +625,7 @@ export class ColorBulb {
618
625
  },
619
626
  };
620
627
  const req = https.request(options, res => {
621
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
628
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges statusCode: ${res.statusCode}`);
622
629
  res.on('data', d => {
623
630
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
624
631
  });
@@ -630,26 +637,19 @@ export class ColorBulb {
630
637
  req.end();
631
638
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges: ${superStringify(req)}`);
632
639
  } else {
633
- this.debugLog(
634
- `${this.device.deviceType}: ${this.accessory.displayName} No Changes.` +
635
- `Hue: ${this.Hue}, HueCached: ${this.accessory.context.Hue}, Saturation: ${this.Saturation},`
636
- +` SaturationCached: ${this.accessory.context.Saturation}`,
637
- );
640
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushHueSaturationChanges. Hue: ${this.Hue}, `
641
+ + `HueCached: ${this.accessory.context.Hue}, Saturation: ${this.Saturation}, SaturationCached: ${this.accessory.context.Saturation}`);
638
642
  }
639
643
  } catch (e: any) {
640
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
641
- if (this.deviceLogging.includes('debug')) {
642
- this.errorLog(
643
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
644
- + ` Error Message: ${superStringify(e.message)}`,
645
- );
646
- }
647
644
  this.apiError(e);
645
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushHueSaturationChanges with ${this.device.connectionType}`
646
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
648
647
  }
649
648
  }
650
649
 
651
650
  async pushColorTemperatureChanges(): Promise<void> {
652
651
  try {
652
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushColorTemperatureChanges`);
653
653
  if (this.ColorTemperature !== this.accessory.context.ColorTemperature) {
654
654
  const kelvin = Math.round(1000000 / Number(this.ColorTemperature));
655
655
  this.cacheKelvin = kelvin;
@@ -694,29 +694,22 @@ export class ColorBulb {
694
694
  });
695
695
  req.write(body);
696
696
  req.end();
697
-
698
697
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushColorTemperatureChanges: ${superStringify(req)}`);
699
698
  this.accessory.context.ColorTemperature = this.ColorTemperature;
700
699
  } else {
701
- this.debugLog(
702
- `${this.device.deviceType}: ${this.accessory.displayName} No Changes.` +
703
- `ColorTemperature: ${this.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`,
704
- );
700
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushColorTemperatureChanges.` +
701
+ `ColorTemperature: ${this.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`);
705
702
  }
706
703
  } catch (e: any) {
707
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
708
- if (this.deviceLogging.includes('debug')) {
709
- this.errorLog(
710
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
711
- + ` Error Message: ${superStringify(e.message)}`,
712
- );
713
- }
714
704
  this.apiError(e);
705
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushColorTemperatureChanges with ${this.device.connectionType}`
706
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
715
707
  }
716
708
  }
717
709
 
718
710
  async pushBrightnessChanges(): Promise<void> {
719
711
  try {
712
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges`);
720
713
  if (this.Brightness !== this.accessory.context.Brightness) {
721
714
  // Make Push On request to the API
722
715
  const t = Date.now();
@@ -748,7 +741,7 @@ export class ColorBulb {
748
741
  },
749
742
  };
750
743
  const req = https.request(options, res => {
751
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
744
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges statusCode: ${res.statusCode}`);
752
745
  res.on('data', d => {
753
746
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
754
747
  });
@@ -760,21 +753,83 @@ export class ColorBulb {
760
753
  req.end();
761
754
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges: ${superStringify(req)}`);
762
755
  } else {
763
- this.debugLog(
764
- `${this.device.deviceType}: ${this.accessory.displayName} No Changes.` + `Brightness: ${this.Brightness}, `
765
- +`BrightnessCached: ${this.accessory.context.Brightness}`,
766
- );
756
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushBrightnessChanges.` + `Brightness: ${this.Brightness}, `
757
+ +`BrightnessCached: ${this.accessory.context.Brightness}`);
767
758
  }
768
759
  } catch (e: any) {
769
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
770
- if (this.deviceLogging.includes('debug')) {
771
- this.errorLog(
772
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
773
- + ` Error Message: ${superStringify(e.message)}`,
774
- );
775
- }
776
760
  this.apiError(e);
761
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushBrightnessChanges with ${this.device.connectionType}`
762
+ + ` Connection, Error Message: ${superStringify(e.message)}`);
763
+ }
764
+ }
765
+
766
+ /**
767
+ * Handle requests to set the value of the "On" characteristic
768
+ */
769
+ async OnSet(value: CharacteristicValue): Promise<void> {
770
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
771
+
772
+ this.On = value;
773
+ this.doColorBulbUpdate.next();
774
+ }
775
+
776
+ /**
777
+ * Handle requests to set the value of the "Brightness" characteristic
778
+ */
779
+ async BrightnessSet(value: CharacteristicValue): Promise<void> {
780
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
781
+
782
+ this.Brightness = value;
783
+ this.doColorBulbUpdate.next();
784
+ }
785
+
786
+ /**
787
+ * Handle requests to set the value of the "ColorTemperature" characteristic
788
+ */
789
+ async ColorTemperatureSet(value: CharacteristicValue): Promise<void> {
790
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ColorTemperature: ${value}`);
791
+
792
+ // Convert mired to kelvin to nearest 100 (SwitchBot seems to need this)
793
+ const kelvin = Math.round(1000000 / Number(value) / 100) * 100;
794
+
795
+ // Check and increase/decrease kelvin to range of device
796
+ const k = Math.min(Math.max(kelvin, this.minKelvin), this.maxKelvin);
797
+
798
+ if (!this.accessory.context.On || this.cacheKelvin === k) {
799
+ return;
777
800
  }
801
+
802
+ // Updating the hue/sat to the corresponding values mimics native adaptive lighting
803
+ const hs = m2hs(value);
804
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, hs[0]);
805
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, hs[1]);
806
+
807
+ this.ColorTemperature = value;
808
+ this.doColorBulbUpdate.next();
809
+ }
810
+
811
+ /**
812
+ * Handle requests to set the value of the "Hue" characteristic
813
+ */
814
+ async HueSet(value: CharacteristicValue): Promise<void> {
815
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Hue: ${value}`);
816
+
817
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
818
+
819
+ this.Hue = value;
820
+ this.doColorBulbUpdate.next();
821
+ }
822
+
823
+ /**
824
+ * Handle requests to set the value of the "Saturation" characteristic
825
+ */
826
+ async SaturationSet(value: CharacteristicValue): Promise<void> {
827
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Saturation: ${value}`);
828
+
829
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
830
+
831
+ this.Saturation = value;
832
+ this.doColorBulbUpdate.next();
778
833
  }
779
834
 
780
835
  async updateHomeKitCharacteristics(): Promise<void> {
@@ -795,7 +850,6 @@ export class ColorBulb {
795
850
  if (this.ColorTemperature === undefined) {
796
851
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
797
852
  } else {
798
-
799
853
  this.accessory.context.ColorTemperature = this.ColorTemperature;
800
854
  this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, this.ColorTemperature);
801
855
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ColorTemperature: ${this.ColorTemperature}`);
@@ -816,13 +870,100 @@ export class ColorBulb {
816
870
  }
817
871
  }
818
872
 
819
- apiError(e: any): void {
820
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.On, e);
821
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, e);
822
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Brightness, e);
823
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, e);
824
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, e);
825
- //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
873
+ async adaptiveLighting(device: device & devicesConfig): Promise<void> {
874
+ if (device.colorbulb?.adaptiveLightingShift) {
875
+ this.adaptiveLightingShift = device.colorbulb.adaptiveLightingShift;
876
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
877
+ } else {
878
+ this.adaptiveLightingShift = 0;
879
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
880
+ }
881
+ }
882
+
883
+ async getCustomBLEAddress(switchbot: any) {
884
+ if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
885
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} customBLEaddress: ${this.device.customBLEaddress}`);
886
+ (async () => {
887
+ // Start to monitor advertisement packets
888
+ await switchbot.startScan({
889
+ model: 'u',
890
+ });
891
+ // Set an event handler
892
+ switchbot.onadvertisement = (ad: any) => {
893
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
894
+ };
895
+ await switchbot.wait(10000);
896
+ // Stop to monitor
897
+ switchbot.stopScan();
898
+ })();
899
+ }
900
+ }
901
+
902
+ async BLEconnection(switchbot: any): Promise<void> {
903
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
904
+ if (this.platform.config.credentials?.token) {
905
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
906
+ this.SwitchToOpenAPI = true;
907
+ await this.openAPIRefreshStatus();
908
+ }
909
+ }
910
+
911
+ async turnOnOff(device_list: any): Promise<any> {
912
+ return await this.retry({
913
+ max: await this.maxRetry(),
914
+ fn: () => {
915
+ if (this.On) {
916
+ return device_list[0].turnOn({ id: this.device.bleMac });
917
+ } else {
918
+ return device_list[0].turnOff({ id: this.device.bleMac });
919
+ }
920
+ },
921
+ });
922
+ }
923
+
924
+ async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
925
+ return fn().catch(async (err: any) => {
926
+ if (max === 0) {
927
+ throw err;
928
+ }
929
+ this.infoLog(err);
930
+ this.infoLog('Retrying');
931
+ await this.switchbot.wait(1000);
932
+ return this.retry({ max: max - 1, fn });
933
+ });
934
+ }
935
+
936
+ async maxRetry(): Promise<number> {
937
+ let maxRetry: number;
938
+ if (this.device.bot?.maxRetry) {
939
+ maxRetry = this.device.bot?.maxRetry;
940
+ } else {
941
+ maxRetry = 5;
942
+ }
943
+ return maxRetry;
944
+ }
945
+
946
+ minStep(device: device & devicesConfig): number {
947
+ if (device.colorbulb?.set_minStep) {
948
+ this.set_minStep = device.colorbulb?.set_minStep;
949
+ } else {
950
+ this.set_minStep = 1;
951
+ }
952
+ return this.set_minStep;
953
+ }
954
+
955
+ async scan(device: device & devicesConfig): Promise<void> {
956
+ if (device.scanDuration) {
957
+ this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
958
+ if (this.BLE) {
959
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
960
+ }
961
+ } else {
962
+ this.scanDuration = this.accessory.context.scanDuration = 1;
963
+ if (this.BLE) {
964
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
965
+ }
966
+ }
826
967
  }
827
968
 
828
969
  async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
@@ -866,76 +1007,72 @@ export class ColorBulb {
866
1007
  if (this.device.offline) {
867
1008
  this.On = false;
868
1009
  this.lightBulbService.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
1010
+ await this.updateHomeKitCharacteristics();
869
1011
  }
870
1012
  }
871
1013
 
872
- /**
873
- * Handle requests to set the value of the "On" characteristic
874
- */
875
- async OnSet(value: CharacteristicValue): Promise<void> {
876
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${value}`);
877
-
878
- this.On = value;
879
- this.doColorBulbUpdate.next();
880
- }
881
-
882
- /**
883
- * Handle requests to set the value of the "Brightness" characteristic
884
- */
885
- async BrightnessSet(value: CharacteristicValue): Promise<void> {
886
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${value}`);
887
-
888
- this.Brightness = value;
889
- this.doColorBulbUpdate.next();
1014
+ apiError(e: any): void {
1015
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.On, e);
1016
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, e);
1017
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Brightness, e);
1018
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, e);
1019
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, e);
890
1020
  }
891
1021
 
892
- /**
893
- * Handle requests to set the value of the "ColorTemperature" characteristic
894
- */
895
- async ColorTemperatureSet(value: CharacteristicValue): Promise<void> {
896
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${value}`);
897
-
898
- // Convert mired to kelvin to nearest 100 (SwitchBot seems to need this)
899
- const kelvin = Math.round(1000000 / Number(value) / 100) * 100;
900
-
901
- // Check and increase/decrease kelvin to range of device
902
- const k = Math.min(Math.max(kelvin, this.minKelvin), this.maxKelvin);
903
-
904
- if (!this.accessory.context.On || this.cacheKelvin === k) {
905
- return;
1022
+ FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
1023
+ let FirmwareRevision: string;
1024
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
1025
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
1026
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
1027
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
1028
+ if (accessory.context.FirmwareRevision) {
1029
+ FirmwareRevision = accessory.context.FirmwareRevision;
1030
+ } else if (device.firmware) {
1031
+ FirmwareRevision = device.firmware;
1032
+ } else {
1033
+ FirmwareRevision = this.platform.version;
906
1034
  }
907
-
908
- // Updating the hue/sat to the corresponding values mimics native adaptive lighting
909
- const hs = m2hs(value);
910
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, hs[0]);
911
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, hs[1]);
912
-
913
- this.ColorTemperature = value;
914
- this.doColorBulbUpdate.next();
1035
+ return FirmwareRevision;
915
1036
  }
916
1037
 
917
- /**
918
- * Handle requests to set the value of the "Hue" characteristic
919
- */
920
- async HueSet(value: CharacteristicValue): Promise<void> {
921
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${value}`);
922
-
923
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
924
-
925
- this.Hue = value;
926
- this.doColorBulbUpdate.next();
1038
+ private context() {
1039
+ if (this.On === undefined) {
1040
+ this.On = false;
1041
+ } else {
1042
+ this.On = this.accessory.context.On;
1043
+ }
1044
+ if (this.Hue === undefined) {
1045
+ this.Hue = 0;
1046
+ } else {
1047
+ this.Hue = this.accessory.context.Hue;
1048
+ }
1049
+ if (this.Brightness === undefined) {
1050
+ this.Brightness = 0;
1051
+ } else {
1052
+ this.Brightness = this.accessory.context.Brightness;
1053
+ }
1054
+ if (this.Brightness === undefined) {
1055
+ this.Saturation = 0;
1056
+ } else {
1057
+ this.Saturation = this.accessory.context.Saturation;
1058
+ }
1059
+ if (this.ColorTemperature === undefined) {
1060
+ this.ColorTemperature = 140;
1061
+ } else {
1062
+ this.ColorTemperature = this.accessory.context.ColorTemperature;
1063
+ }
1064
+ this.minKelvin = 2000;
1065
+ this.maxKelvin = 9000;
927
1066
  }
928
1067
 
929
- /**
930
- * Handle requests to set the value of the "Saturation" characteristic
931
- */
932
- async SaturationSet(value: CharacteristicValue): Promise<void> {
933
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${value}`);
934
-
935
- this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
936
-
937
- this.Saturation = value;
938
- this.doColorBulbUpdate.next();
1068
+ async refreshRate(device: device & devicesConfig): Promise<void> {
1069
+ if (device.refreshRate) {
1070
+ this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
1071
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
1072
+ } else if (this.platform.config.options!.refreshRate) {
1073
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
1074
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
1075
+ }
939
1076
  }
940
1077
 
941
1078
  async config(device: device & devicesConfig): Promise<void> {
@@ -943,11 +1080,8 @@ export class ColorBulb {
943
1080
  if (device.colorbulb) {
944
1081
  config = device.colorbulb;
945
1082
  }
946
- if (device.ble) {
947
- config['ble'] = device.ble;
948
- }
949
- if (device.openAPI !== undefined) {
950
- config['openAPI'] = device.openAPI;
1083
+ if (device.connectionType !== undefined) {
1084
+ config['connectionType'] = device.connectionType;
951
1085
  }
952
1086
  if (device.logging !== undefined) {
953
1087
  config['logging'] = device.logging;
@@ -966,39 +1100,6 @@ export class ColorBulb {
966
1100
  }
967
1101
  }
968
1102
 
969
- async refreshRate(device: device & devicesConfig): Promise<void> {
970
- if (device.refreshRate) {
971
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
972
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
973
- } else if (this.platform.config.options!.refreshRate) {
974
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
975
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
976
- }
977
- }
978
-
979
- async openAPI() {
980
- if (!this.device.openAPI) {
981
- this.OpenAPI = true;
982
- } else {
983
- this.OpenAPI = this.device.openAPI;
984
- }
985
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI: ${this.OpenAPI}`);
986
- }
987
-
988
- async scan(device: device & devicesConfig): Promise<void> {
989
- if (device.scanDuration) {
990
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
991
- if (device.ble) {
992
- this.debugLog(`Bot: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
993
- }
994
- } else {
995
- this.scanDuration = this.accessory.context.scanDuration = 1;
996
- if (this.device.ble) {
997
- this.debugLog(`Bot: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
998
- }
999
- }
1000
- }
1001
-
1002
1103
  async logs(device: device & devicesConfig): Promise<void> {
1003
1104
  if (this.platform.debugMode) {
1004
1105
  this.deviceLogging = this.accessory.context.logging = 'debugMode';
@@ -1015,41 +1116,6 @@ export class ColorBulb {
1015
1116
  }
1016
1117
  }
1017
1118
 
1018
- FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
1019
- let FirmwareRevision: string;
1020
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
1021
- + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
1022
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
1023
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
1024
- if (accessory.context.FirmwareRevision) {
1025
- FirmwareRevision = accessory.context.FirmwareRevision;
1026
- } else if (device.firmware) {
1027
- FirmwareRevision = device.firmware;
1028
- } else {
1029
- FirmwareRevision = this.platform.version;
1030
- }
1031
- return FirmwareRevision;
1032
- }
1033
-
1034
- async adaptiveLighting(device: device & devicesConfig): Promise<void> {
1035
- if (device.colorbulb?.adaptiveLightingShift) {
1036
- this.adaptiveLightingShift = device.colorbulb.adaptiveLightingShift;
1037
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
1038
- } else {
1039
- this.adaptiveLightingShift = 0;
1040
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
1041
- }
1042
- }
1043
-
1044
- minStep(device: device & devicesConfig): number {
1045
- if (device.colorbulb?.set_minStep) {
1046
- this.set_minStep = device.colorbulb?.set_minStep;
1047
- } else {
1048
- this.set_minStep = 1;
1049
- }
1050
- return this.set_minStep;
1051
- }
1052
-
1053
1119
  /**
1054
1120
  * Logging for Device
1055
1121
  */