@switchbot/homebridge-switchbot 1.15.1-beta.6 → 1.15.1-beta.8

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/.prettierrc +1 -1
  2. package/dist/device/bot.d.ts +8 -7
  3. package/dist/device/bot.d.ts.map +1 -1
  4. package/dist/device/bot.js +83 -11
  5. package/dist/device/bot.js.map +1 -1
  6. package/dist/device/colorbulb.d.ts +8 -7
  7. package/dist/device/colorbulb.d.ts.map +1 -1
  8. package/dist/device/colorbulb.js +182 -23
  9. package/dist/device/colorbulb.js.map +1 -1
  10. package/dist/device/contact.d.ts +3 -3
  11. package/dist/device/contact.d.ts.map +1 -1
  12. package/dist/device/contact.js +50 -7
  13. package/dist/device/contact.js.map +1 -1
  14. package/dist/device/curtain.d.ts +9 -8
  15. package/dist/device/curtain.d.ts.map +1 -1
  16. package/dist/device/curtain.js +86 -14
  17. package/dist/device/curtain.js.map +1 -1
  18. package/dist/device/humidifier.d.ts +8 -7
  19. package/dist/device/humidifier.d.ts.map +1 -1
  20. package/dist/device/humidifier.js +152 -27
  21. package/dist/device/humidifier.js.map +1 -1
  22. package/dist/device/lock.d.ts +8 -7
  23. package/dist/device/lock.d.ts.map +1 -1
  24. package/dist/device/lock.js +84 -12
  25. package/dist/device/lock.js.map +1 -1
  26. package/dist/device/meter.d.ts +4 -4
  27. package/dist/device/meter.d.ts.map +1 -1
  28. package/dist/device/meter.js +51 -8
  29. package/dist/device/meter.js.map +1 -1
  30. package/dist/device/meterplus.d.ts +3 -3
  31. package/dist/device/meterplus.d.ts.map +1 -1
  32. package/dist/device/meterplus.js +49 -6
  33. package/dist/device/meterplus.js.map +1 -1
  34. package/dist/device/motion.d.ts +3 -3
  35. package/dist/device/motion.d.ts.map +1 -1
  36. package/dist/device/motion.js +49 -9
  37. package/dist/device/motion.js.map +1 -1
  38. package/dist/device/plug.d.ts +8 -7
  39. package/dist/device/plug.d.ts.map +1 -1
  40. package/dist/device/plug.js +83 -11
  41. package/dist/device/plug.js.map +1 -1
  42. package/dist/device/striplight.d.ts +8 -7
  43. package/dist/device/striplight.d.ts.map +1 -1
  44. package/dist/device/striplight.js +149 -19
  45. package/dist/device/striplight.js.map +1 -1
  46. package/dist/irdevice/airconditioner.d.ts +5 -4
  47. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  48. package/dist/irdevice/airconditioner.js +40 -6
  49. package/dist/irdevice/airconditioner.js.map +1 -1
  50. package/dist/irdevice/airpurifier.d.ts +5 -4
  51. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  52. package/dist/irdevice/airpurifier.js +40 -6
  53. package/dist/irdevice/airpurifier.js.map +1 -1
  54. package/dist/irdevice/camera.d.ts +5 -4
  55. package/dist/irdevice/camera.d.ts.map +1 -1
  56. package/dist/irdevice/camera.js +40 -6
  57. package/dist/irdevice/camera.js.map +1 -1
  58. package/dist/irdevice/fan.d.ts +7 -6
  59. package/dist/irdevice/fan.d.ts.map +1 -1
  60. package/dist/irdevice/fan.js +40 -6
  61. package/dist/irdevice/fan.js.map +1 -1
  62. package/dist/irdevice/light.d.ts +5 -4
  63. package/dist/irdevice/light.d.ts.map +1 -1
  64. package/dist/irdevice/light.js +40 -6
  65. package/dist/irdevice/light.js.map +1 -1
  66. package/dist/irdevice/other.d.ts +5 -4
  67. package/dist/irdevice/other.d.ts.map +1 -1
  68. package/dist/irdevice/other.js +40 -6
  69. package/dist/irdevice/other.js.map +1 -1
  70. package/dist/irdevice/tv.d.ts +7 -6
  71. package/dist/irdevice/tv.d.ts.map +1 -1
  72. package/dist/irdevice/tv.js +40 -6
  73. package/dist/irdevice/tv.js.map +1 -1
  74. package/dist/irdevice/vacuumcleaner.d.ts +5 -4
  75. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  76. package/dist/irdevice/vacuumcleaner.js +40 -6
  77. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  78. package/dist/irdevice/waterheater.d.ts +5 -4
  79. package/dist/irdevice/waterheater.d.ts.map +1 -1
  80. package/dist/irdevice/waterheater.js +40 -6
  81. package/dist/irdevice/waterheater.js.map +1 -1
  82. package/dist/platform.d.ts +3 -5
  83. package/dist/platform.d.ts.map +1 -1
  84. package/dist/platform.js +142 -92
  85. package/dist/platform.js.map +1 -1
  86. package/dist/settings.d.ts +2 -16
  87. package/dist/settings.d.ts.map +1 -1
  88. package/dist/settings.js +3 -3
  89. package/dist/settings.js.map +1 -1
  90. package/package.json +6 -7
  91. package/src/device/bot.ts +87 -15
  92. package/src/device/colorbulb.ts +186 -41
  93. package/src/device/contact.ts +49 -10
  94. package/src/device/curtain.ts +92 -19
  95. package/src/device/humidifier.ts +164 -30
  96. package/src/device/lock.ts +88 -16
  97. package/src/device/meter.ts +51 -12
  98. package/src/device/meterplus.ts +48 -9
  99. package/src/device/motion.ts +48 -12
  100. package/src/device/plug.ts +87 -15
  101. package/src/device/striplight.ts +161 -24
  102. package/src/irdevice/airconditioner.ts +43 -8
  103. package/src/irdevice/airpurifier.ts +43 -8
  104. package/src/irdevice/camera.ts +43 -8
  105. package/src/irdevice/fan.ts +44 -9
  106. package/src/irdevice/light.ts +43 -8
  107. package/src/irdevice/other.ts +43 -8
  108. package/src/irdevice/tv.ts +44 -9
  109. package/src/irdevice/vacuumcleaner.ts +43 -8
  110. package/src/irdevice/waterheater.ts +43 -8
  111. package/src/platform.ts +155 -105
  112. package/src/settings.ts +6 -10
package/src/device/bot.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { Context } from 'vm';
4
+ import { IncomingMessage } from 'http';
2
5
  import { interval, Subject } from 'rxjs';
3
6
  import { SwitchBotPlatform } from '../platform';
4
7
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
5
8
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
- import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, payload, deviceStatus } from '../settings';
7
- import { Context } from 'vm';
9
+ import { device, devicesConfig, deviceStatus, ad, serviceData, switchbot, payload, HostDomain, DevicePath } from '../settings';
8
10
 
9
11
  /**
10
12
  * Platform Accessory
@@ -33,7 +35,7 @@ export class Bot {
33
35
 
34
36
  // OpenAPI Others
35
37
  power: deviceStatus['power'];
36
- deviceStatus!: deviceStatusResponse;
38
+ deviceStatus!: any; //deviceStatusResponse;
37
39
 
38
40
  // BLE Others
39
41
  connected?: boolean;
@@ -555,11 +557,48 @@ export class Bot {
555
557
  if (this.platform.config.credentials?.token) {
556
558
  this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI refreshStatus`);
557
559
  try {
558
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
559
- this.debugLog(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
560
- this.power = this.deviceStatus.body.power;
561
- this.parseStatus();
562
- this.updateHomeKitCharacteristics();
560
+ const t = Date.now();
561
+ const nonce = 'requestID';
562
+ const data = this.platform.config.credentials?.token + t + nonce;
563
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
564
+ const sign = signTerm.toString('base64');
565
+ this.debugLog(`Bot: ${this.accessory.displayName} sign: ${sign}`);
566
+ const options = {
567
+ hostname: HostDomain,
568
+ port: 443,
569
+ path: `${DevicePath}/${this.device.deviceId}/status`,
570
+ method: 'GET',
571
+ headers: {
572
+ Authorization: this.platform.config.credentials?.token,
573
+ sign: sign,
574
+ nonce: nonce,
575
+ t: t,
576
+ 'Content-Type': 'application/json',
577
+ },
578
+ };
579
+ const req = https.request(options, (res) => {
580
+ this.debugLog(`Bot: ${this.accessory.displayName} Refresh statusCode: ${res.statusCode}`);
581
+ let rawData = '';
582
+ res.on('data', (d) => {
583
+ rawData += d;
584
+ this.debugLog(`d: ${d}`);
585
+ });
586
+ res.on('end', () => {
587
+ try {
588
+ this.deviceStatus = JSON.parse(rawData);
589
+ this.debugLog(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
590
+ this.power = this.deviceStatus.body.power;
591
+ this.parseStatus();
592
+ this.updateHomeKitCharacteristics();
593
+ } catch (e: any) {
594
+ this.errorLog(`Bot: ${this.accessory.displayName} error message: ${e.message}`);
595
+ }
596
+ });
597
+ });
598
+ req.on('error', (e: any) => {
599
+ this.errorLog(`Bot: ${this.accessory.displayName} error message: ${e.message}`);
600
+ });
601
+ req.end();
563
602
  } catch (e: any) {
564
603
  this.errorLog(`Bot: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
565
604
  if (this.deviceLogging.includes('debug')) {
@@ -727,9 +766,42 @@ export class Bot {
727
766
  );
728
767
 
729
768
  // Make the API request
730
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
731
- this.debugLog(`Bot: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
732
- this.statusCode(push);
769
+ const t = Date.now();
770
+ const nonce = 'requestID';
771
+ const data = this.platform.config.credentials?.token + t + nonce;
772
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
773
+ const sign = signTerm.toString('base64');
774
+ this.debugLog(`Bot: ${this.accessory.displayName} sign: ${sign}`);
775
+ const options = {
776
+ hostname: HostDomain,
777
+ port: 443,
778
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
779
+ method: 'POST',
780
+ headers: {
781
+ Authorization: this.platform.config.credentials?.token,
782
+ sign: sign,
783
+ nonce: nonce,
784
+ t: t,
785
+ 'Content-Type': 'application/json',
786
+ },
787
+ };
788
+
789
+ const req = https.request(options, (res) => {
790
+ this.debugLog(`Bot: ${this.accessory.displayName} Push statusCode: ${res.statusCode}`);
791
+ this.statusCode({ res });
792
+ res.on('data', (d) => {
793
+ this.debugLog(`d: ${d}`);
794
+ });
795
+ });
796
+
797
+ req.on('error', (error) => {
798
+ this.errorLog(`Bot: ${this.accessory.displayName} error: ${error}`);
799
+ });
800
+
801
+ req.write(payload);
802
+ req.end();
803
+
804
+ this.debugLog(`Bot: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
733
805
  this.OnCached = this.On;
734
806
  this.accessory.context.On = this.OnCached;
735
807
  }
@@ -977,8 +1049,8 @@ export class Bot {
977
1049
  //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
978
1050
  }
979
1051
 
980
- async statusCode(push: AxiosResponse<{ statusCode: number }>): Promise<void> {
981
- switch (push.data.statusCode) {
1052
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
1053
+ switch (res.statusCode) {
982
1054
  case 151:
983
1055
  this.errorLog(`Bot: ${this.accessory.displayName} Command not supported by this device type.`);
984
1056
  break;
@@ -999,7 +1071,7 @@ export class Bot {
999
1071
  case 190:
1000
1072
  this.errorLog(
1001
1073
  `Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
1002
- ` Or command: ${JSON.stringify(push.data)} format is invalid`,
1074
+ ` Or command: ${JSON.stringify(res)} format is invalid`,
1003
1075
  );
1004
1076
  break;
1005
1077
  case 100:
@@ -1,23 +1,12 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { Context } from 'vm';
4
+ import { IncomingMessage } from 'http';
2
5
  import { interval, Subject } from 'rxjs';
3
6
  import { SwitchBotPlatform } from '../platform';
4
7
  import { debounceTime, skipWhile, tap } from 'rxjs/operators';
5
8
  import { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
6
- import {
7
- DeviceURL,
8
- device,
9
- devicesConfig,
10
- switchbot,
11
- deviceStatusResponse,
12
- payload,
13
- hs2rgb,
14
- rgb2hs,
15
- m2hs,
16
- deviceStatus,
17
- serviceData,
18
- ad,
19
- } from '../settings';
20
- import { Context } from 'vm';
9
+ import { device, devicesConfig, deviceStatus, switchbot, payload, hs2rgb, rgb2hs, m2hs, serviceData, ad, HostDomain, DevicePath } from '../settings';
21
10
 
22
11
  /**
23
12
  * Platform Accessory
@@ -45,7 +34,7 @@ export class ColorBulb {
45
34
  color: deviceStatus['color'];
46
35
  brightness: deviceStatus['brightness'];
47
36
  colorTemperature?: deviceStatus['colorTemperature'];
48
- deviceStatus!: deviceStatusResponse;
37
+ deviceStatus!: any; //deviceStatusResponse;
49
38
 
50
39
  // BLE Others
51
40
  connected?: boolean;
@@ -419,15 +408,51 @@ export class ColorBulb {
419
408
 
420
409
  private async openAPIRefreshStatus() {
421
410
  try {
422
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
423
- this.debugLog(`Color Bulb: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
424
- this.power = this.deviceStatus.body.power;
425
- this.color = this.deviceStatus.body.color;
426
- this.brightness = this.deviceStatus.body.brightness;
427
- this.colorTemperature = this.deviceStatus.body.colorTemperature;
428
-
429
- this.parseStatus();
430
- this.updateHomeKitCharacteristics();
411
+ const t = Date.now();
412
+ const nonce = 'requestID';
413
+ const data = this.platform.config.credentials?.token + t + nonce;
414
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
415
+ const sign = signTerm.toString('base64');
416
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
417
+ const options = {
418
+ hostname: HostDomain,
419
+ port: 443,
420
+ path: `${DevicePath}/${this.device.deviceId}/status`,
421
+ method: 'GET',
422
+ headers: {
423
+ Authorization: this.platform.config.credentials?.token,
424
+ sign: sign,
425
+ nonce: nonce,
426
+ t: t,
427
+ 'Content-Type': 'application/json',
428
+ },
429
+ };
430
+ const req = https.request(options, (res) => {
431
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} Refresh statusCode: ${res.statusCode}`);
432
+ let rawData = '';
433
+ res.on('data', (d) => {
434
+ rawData += d;
435
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} d: ${d}`);
436
+ });
437
+ res.on('end', () => {
438
+ try {
439
+ this.deviceStatus = JSON.parse(rawData);
440
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
441
+ this.power = this.deviceStatus.body.power;
442
+ this.color = this.deviceStatus.body.color;
443
+ this.brightness = this.deviceStatus.body.brightness;
444
+ this.colorTemperature = this.deviceStatus.body.colorTemperature;
445
+ this.parseStatus();
446
+ this.updateHomeKitCharacteristics();
447
+ } catch (e: any) {
448
+ this.errorLog(`Color Bulb: ${this.accessory.displayName} error message: ${e.message}`);
449
+ }
450
+ });
451
+ });
452
+ req.on('error', (e: any) => {
453
+ this.errorLog(`Color Bulb: ${this.accessory.displayName} error message: ${e.message}`);
454
+ });
455
+ req.end();
431
456
  } catch (e: any) {
432
457
  this.errorLog(`Color Bulb: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
433
458
  if (this.deviceLogging.includes('debug')) {
@@ -471,9 +496,39 @@ export class ColorBulb {
471
496
  );
472
497
 
473
498
  // Make the API request
474
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
475
- this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
476
- this.statusCode(push);
499
+ const t = Date.now();
500
+ const nonce = 'requestID';
501
+ const data = this.platform.config.credentials?.token + t + nonce;
502
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
503
+ const sign = signTerm.toString('base64');
504
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
505
+ const options = {
506
+ hostname: HostDomain,
507
+ port: 443,
508
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
509
+ method: 'POST',
510
+ headers: {
511
+ Authorization: this.platform.config.credentials?.token,
512
+ sign: sign,
513
+ nonce: nonce,
514
+ t: t,
515
+ 'Content-Type': 'application/json',
516
+ },
517
+ };
518
+ const req = https.request(options, (res) => {
519
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
520
+ this.statusCode({ res });
521
+ res.on('data', (d) => {
522
+ this.debugLog(`d: ${d}`);
523
+ });
524
+ });
525
+ req.on('error', (error) => {
526
+ this.errorLog(`Color Bulb: ${this.accessory.displayName} error: ${error}`);
527
+ });
528
+ req.write(payload);
529
+ req.end();
530
+
531
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(req)}`);
477
532
  this.OnCached = this.On;
478
533
  this.accessory.context.On = this.OnCached;
479
534
  }
@@ -523,9 +578,39 @@ export class ColorBulb {
523
578
  );
524
579
 
525
580
  // Make the API request
526
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
527
- this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
528
- this.statusCode(push);
581
+ const t = Date.now();
582
+ const nonce = 'requestID';
583
+ const data = this.platform.config.credentials?.token + t + nonce;
584
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
585
+ const sign = signTerm.toString('base64');
586
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
587
+ const options = {
588
+ hostname: HostDomain,
589
+ port: 443,
590
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
591
+ method: 'POST',
592
+ headers: {
593
+ Authorization: this.platform.config.credentials?.token,
594
+ sign: sign,
595
+ nonce: nonce,
596
+ t: t,
597
+ 'Content-Type': 'application/json',
598
+ },
599
+ };
600
+ const req = https.request(options, (res) => {
601
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
602
+ this.statusCode({ res });
603
+ res.on('data', (d) => {
604
+ this.debugLog(`d: ${d}`);
605
+ });
606
+ });
607
+ req.on('error', (error) => {
608
+ this.errorLog(`Color Bulb: ${this.accessory.displayName} error: ${error}`);
609
+ });
610
+ req.write(payload);
611
+ req.end();
612
+
613
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(req)}`);
529
614
  this.HueCached = this.Hue;
530
615
  this.SaturationCached = this.Saturation;
531
616
  } else {
@@ -563,9 +648,39 @@ export class ColorBulb {
563
648
  );
564
649
 
565
650
  // Make the API request
566
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
567
- this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
568
- this.statusCode(push);
651
+ const t = Date.now();
652
+ const nonce = 'requestID';
653
+ const data = this.platform.config.credentials?.token + t + nonce;
654
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
655
+ const sign = signTerm.toString('base64');
656
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
657
+ const options = {
658
+ hostname: HostDomain,
659
+ port: 443,
660
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
661
+ method: 'POST',
662
+ headers: {
663
+ Authorization: this.platform.config.credentials?.token,
664
+ sign: sign,
665
+ nonce: nonce,
666
+ t: t,
667
+ 'Content-Type': 'application/json',
668
+ },
669
+ };
670
+ const req = https.request(options, (res) => {
671
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
672
+ this.statusCode({ res });
673
+ res.on('data', (d) => {
674
+ this.debugLog(`d: ${d}`);
675
+ });
676
+ });
677
+ req.on('error', (error) => {
678
+ this.errorLog(`Color Bulb: ${this.accessory.displayName} error: ${error}`);
679
+ });
680
+ req.write(payload);
681
+ req.end();
682
+
683
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(req)}`);
569
684
  this.ColorTemperatureCached = this.ColorTemperature;
570
685
  } else {
571
686
  this.debugLog(
@@ -599,9 +714,39 @@ export class ColorBulb {
599
714
  );
600
715
 
601
716
  // Make the API request
602
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
603
- this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
604
- this.statusCode(push);
717
+ const t = Date.now();
718
+ const nonce = 'requestID';
719
+ const data = this.platform.config.credentials?.token + t + nonce;
720
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
721
+ const sign = signTerm.toString('base64');
722
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
723
+ const options = {
724
+ hostname: HostDomain,
725
+ port: 443,
726
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
727
+ method: 'POST',
728
+ headers: {
729
+ Authorization: this.platform.config.credentials?.token,
730
+ sign: sign,
731
+ nonce: nonce,
732
+ t: t,
733
+ 'Content-Type': 'application/json',
734
+ },
735
+ };
736
+ const req = https.request(options, (res) => {
737
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
738
+ this.statusCode({ res });
739
+ res.on('data', (d) => {
740
+ this.debugLog(`d: ${d}`);
741
+ });
742
+ });
743
+ req.on('error', (error) => {
744
+ this.errorLog(`Color Bulb: ${this.accessory.displayName} error: ${error}`);
745
+ });
746
+ req.write(payload);
747
+ req.end();
748
+
749
+ this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(req)}`);
605
750
  this.BrightnessCached = this.Brightness;
606
751
  } else {
607
752
  this.debugLog(
@@ -661,8 +806,8 @@ export class ColorBulb {
661
806
  //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
662
807
  }
663
808
 
664
- statusCode(push: AxiosResponse<{ statusCode: number }>): void {
665
- switch (push.data.statusCode) {
809
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
810
+ switch (res.statusCode) {
666
811
  case 151:
667
812
  this.errorLog(`Color Bulb: ${this.accessory.displayName} Command not supported by this device type.`);
668
813
  break;
@@ -683,7 +828,7 @@ export class ColorBulb {
683
828
  case 190:
684
829
  this.errorLog(
685
830
  `Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
686
- ` Or command: ${JSON.stringify(push.data)} format is invalid`,
831
+ ` Or command: ${JSON.stringify(res)} format is invalid`,
687
832
  );
688
833
  break;
689
834
  case 100:
@@ -1,9 +1,11 @@
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { Context } from 'vm';
1
4
  import { interval, Subject } from 'rxjs';
2
5
  import { skipWhile } from 'rxjs/operators';
3
6
  import { SwitchBotPlatform } from '../platform';
4
7
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
5
- import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, deviceStatus, ad } from '../settings';
6
- import { Context } from 'vm';
8
+ import { device, devicesConfig, serviceData, switchbot, deviceStatus, ad, HostDomain, DevicePath } from '../settings';
7
9
 
8
10
  /**
9
11
  * Platform Accessory
@@ -28,7 +30,7 @@ export class Contact {
28
30
  openState: deviceStatus['openState'];
29
31
  moveDetected: deviceStatus['moveDetected'];
30
32
  brightness: deviceStatus['brightness'];
31
- deviceStatus!: deviceStatusResponse;
33
+ deviceStatus!: any; //deviceStatusResponse;
32
34
 
33
35
  // BLE Others
34
36
  connected?: boolean;
@@ -374,13 +376,50 @@ export class Contact {
374
376
  if (this.platform.config.credentials?.token) {
375
377
  this.debugLog(`Contact Sensor: ${this.accessory.displayName} OpenAPI refreshStatus`);
376
378
  try {
377
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
378
- this.debugLog(`Contact Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
379
- this.openState = this.deviceStatus.body.openState;
380
- this.moveDetected = this.deviceStatus.body.moveDetected;
381
- this.brightness = this.deviceStatus.body.brightness;
382
- this.parseStatus();
383
- this.updateHomeKitCharacteristics();
379
+ const t = Date.now();
380
+ const nonce = 'requestID';
381
+ const data = this.platform.config.credentials?.token + t + nonce;
382
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
383
+ const sign = signTerm.toString('base64');
384
+ this.debugLog(`Contact Sensor: ${this.accessory.displayName} sign: ${sign}`);
385
+ const options = {
386
+ hostname: HostDomain,
387
+ port: 443,
388
+ path: `${DevicePath}/${this.device.deviceId}/status`,
389
+ method: 'GET',
390
+ headers: {
391
+ Authorization: this.platform.config.credentials?.token,
392
+ sign: sign,
393
+ nonce: nonce,
394
+ t: t,
395
+ 'Content-Type': 'application/json',
396
+ },
397
+ };
398
+ const req = https.request(options, (res) => {
399
+ this.debugLog(`Contact Sensor: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
400
+ let rawData = '';
401
+ res.on('data', (d) => {
402
+ rawData += d;
403
+ this.debugLog(`Contact Sensor: ${this.accessory.displayName} d: ${d}`);
404
+ });
405
+ res.on('end', () => {
406
+ try {
407
+ this.deviceStatus = JSON.parse(rawData);
408
+ this.debugLog(`Contact Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
409
+ this.openState = this.deviceStatus.body.openState;
410
+ this.moveDetected = this.deviceStatus.body.moveDetected;
411
+ this.brightness = this.deviceStatus.body.brightness;
412
+ this.parseStatus();
413
+ this.updateHomeKitCharacteristics();
414
+ } catch (e: any) {
415
+ this.errorLog(`Contact Sensor: ${this.accessory.displayName} error message: ${e.message}`);
416
+ }
417
+ });
418
+ });
419
+ req.on('error', (e: any) => {
420
+ this.errorLog(`Contact Sensor: ${this.accessory.displayName} error message: ${e.message}`);
421
+ });
422
+ req.end();
384
423
  } catch (e: any) {
385
424
  this.errorLog(`Contact Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
386
425
  if (this.deviceLogging.includes('debug')) {
@@ -1,12 +1,14 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { Context } from 'vm';
4
+ import { MqttClient } from 'mqtt';
5
+ import { IncomingMessage } from 'http';
2
6
  import { interval, Subject } from 'rxjs';
7
+ import { connectAsync } from 'async-mqtt';
3
8
  import { SwitchBotPlatform } from '../platform';
4
9
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
5
10
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
- import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, payload, deviceStatus, ad } from '../settings';
7
- import { Context } from 'vm';
8
- import { MqttClient } from 'mqtt';
9
- import { connectAsync } from 'async-mqtt';
11
+ import { device, devicesConfig, serviceData, switchbot, payload, deviceStatus, ad, HostDomain, DevicePath } from '../settings';
10
12
 
11
13
  export class Curtain {
12
14
  // Services
@@ -23,7 +25,7 @@ export class Curtain {
23
25
  StatusLowBattery?: CharacteristicValue;
24
26
 
25
27
  // OpenAPI Others
26
- deviceStatus!: deviceStatusResponse;
28
+ deviceStatus!: any; //deviceStatusResponse;
27
29
  slidePosition: deviceStatus['slidePosition'];
28
30
  moving: deviceStatus['moving'];
29
31
  brightness: deviceStatus['brightness'];
@@ -532,13 +534,51 @@ export class Curtain {
532
534
  if (this.platform.config.credentials?.token) {
533
535
  this.debugLog(`Curtain: ${this.accessory.displayName} OpenAPI refreshStatus`);
534
536
  try {
535
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
536
- this.debugLog(`Curtain: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
537
- this.slidePosition = this.deviceStatus.body.slidePosition;
538
- this.moving = this.deviceStatus.body.moving;
539
- this.brightness = this.deviceStatus.body.brightness;
540
- this.parseStatus();
541
- this.updateHomeKitCharacteristics();
537
+ const t = Date.now();
538
+ const nonce = 'requestID';
539
+ const data = this.platform.config.credentials?.token + t + nonce;
540
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
541
+ const sign = signTerm.toString('base64');
542
+ this.debugLog(`Curtain: ${this.accessory.displayName} sign: ${sign}`);
543
+ const options = {
544
+ hostname: HostDomain,
545
+ port: 443,
546
+ path: `${DevicePath}/${this.device.deviceId}/status`,
547
+ method: 'GET',
548
+ headers: {
549
+ Authorization: this.platform.config.credentials?.token,
550
+ sign: sign,
551
+ nonce: nonce,
552
+ t: t,
553
+ 'Content-Type': 'application/json',
554
+ },
555
+ };
556
+ const req = https.request(options, (res) => {
557
+ this.debugLog(`Curtain: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
558
+ let rawData = '';
559
+ res.on('data', (d) => {
560
+ rawData += d;
561
+ this.debugLog(`Curtain: ${this.accessory.displayName} d: ${d}`);
562
+ });
563
+
564
+ res.on('end', () => {
565
+ try {
566
+ this.deviceStatus = JSON.parse(rawData);
567
+ this.debugLog(`Curtain: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
568
+ this.slidePosition = this.deviceStatus.body.slidePosition;
569
+ this.moving = this.deviceStatus.body.moving;
570
+ this.brightness = this.deviceStatus.body.brightness;
571
+ this.parseStatus();
572
+ this.updateHomeKitCharacteristics();
573
+ } catch (e: any) {
574
+ this.errorLog(`Curtain: ${this.accessory.displayName} error message: ${e.message}`);
575
+ }
576
+ });
577
+ });
578
+ req.on('error', (e: any) => {
579
+ this.errorLog(`Curtain: ${this.accessory.displayName} error message: ${e.message}`);
580
+ });
581
+ req.end();
542
582
  } catch (e: any) {
543
583
  this.errorLog(`Curtain: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
544
584
  if (this.deviceLogging.includes('debug')) {
@@ -667,9 +707,42 @@ export class Curtain {
667
707
  );
668
708
 
669
709
  // Make the API request
670
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId!}/commands`, payload);
671
- this.debugLog(`Curtain: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
672
- this.statusCode(push);
710
+ const t = Date.now();
711
+ const nonce = 'requestID';
712
+ const data = this.platform.config.credentials?.token + t + nonce;
713
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
714
+ const sign = signTerm.toString('base64');
715
+ this.debugLog(`Curtain: ${this.accessory.displayName} sign: ${sign}`);
716
+ const options = {
717
+ hostname: HostDomain,
718
+ port: 443,
719
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
720
+ method: 'POST',
721
+ headers: {
722
+ Authorization: this.platform.config.credentials?.token,
723
+ sign: sign,
724
+ nonce: nonce,
725
+ t: t,
726
+ 'Content-Type': 'application/json',
727
+ },
728
+ };
729
+
730
+ const req = https.request(options, (res) => {
731
+ this.debugLog(`Curtain: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
732
+ this.statusCode({ res });
733
+ res.on('data', (d) => {
734
+ this.debugLog(`Curtain: ${this.accessory.displayName} d: ${d}`);
735
+ });
736
+ });
737
+
738
+ req.on('error', (error) => {
739
+ this.errorLog(`Curtain: ${this.accessory.displayName} error: ${error}`);
740
+ });
741
+
742
+ req.write(payload);
743
+ req.end();
744
+
745
+ this.debugLog(`Curtain: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
673
746
  } else {
674
747
  this.debugLog(
675
748
  `Curtain: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.` +
@@ -752,8 +825,8 @@ export class Curtain {
752
825
  //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
753
826
  }
754
827
 
755
- async statusCode(push: AxiosResponse<{ statusCode: number }>): Promise<void> {
756
- switch (push.data.statusCode) {
828
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
829
+ switch (res.statusCode) {
757
830
  case 151:
758
831
  this.errorLog(`Curtain: ${this.accessory.displayName} Command not supported by this device type.`);
759
832
  break;
@@ -772,7 +845,7 @@ export class Curtain {
772
845
  case 190:
773
846
  this.errorLog(
774
847
  `Curtain: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
775
- ` Or command: ${JSON.stringify(push.data)} format is invalid`,
848
+ ` Or command: ${JSON.stringify(res)} format is invalid`,
776
849
  );
777
850
  break;
778
851
  case 100: