@switchbot/homebridge-switchbot 1.15.1-beta.0 → 1.15.1-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug-report.yml +1 -0
- package/.github/ISSUE_TEMPLATE/feature-request.yml +1 -0
- package/.github/ISSUE_TEMPLATE/support-request.yml +1 -0
- package/.prettierrc +1 -1
- package/CHANGELOG.md +9 -0
- package/config.schema.json +11 -4
- package/dist/device/bot.d.ts +8 -7
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +104 -28
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +8 -7
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +223 -58
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +3 -3
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +54 -11
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +9 -8
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +102 -28
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +8 -7
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +187 -66
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +8 -7
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +98 -22
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +4 -4
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +55 -12
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +3 -3
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +53 -10
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +3 -3
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +53 -13
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +8 -7
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +100 -24
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +8 -7
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +186 -47
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -6
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +40 -6
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +7 -6
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +46 -11
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +7 -6
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +40 -6
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +8 -7
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +40 -6
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +7 -6
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +40 -6
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +7 -6
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +40 -6
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +8 -7
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +40 -6
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -6
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +40 -6
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +7 -6
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +40 -6
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +10 -6
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +211 -93
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +4 -21
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +3 -3
- package/dist/settings.js.map +1 -1
- package/package.json +12 -12
- package/src/device/bot.ts +104 -37
- package/src/device/colorbulb.ts +227 -95
- package/src/device/contact.ts +53 -14
- package/src/device/curtain.ts +105 -38
- package/src/device/humidifier.ts +189 -84
- package/src/device/lock.ts +97 -30
- package/src/device/meter.ts +55 -16
- package/src/device/meterplus.ts +52 -13
- package/src/device/motion.ts +52 -16
- package/src/device/plug.ts +101 -33
- package/src/device/striplight.ts +189 -68
- package/src/irdevice/airconditioner.ts +44 -9
- package/src/irdevice/airpurifier.ts +52 -17
- package/src/irdevice/camera.ts +46 -11
- package/src/irdevice/fan.ts +50 -15
- package/src/irdevice/light.ts +48 -13
- package/src/irdevice/other.ts +46 -11
- package/src/irdevice/tv.ts +56 -21
- package/src/irdevice/vacuumcleaner.ts +46 -11
- package/src/irdevice/waterheater.ts +46 -11
- package/src/platform.ts +232 -107
- package/src/settings.ts +4 -25
package/src/device/bot.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import
|
|
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 {
|
|
7
|
-
import { Context } from 'vm';
|
|
9
|
+
import { device, devicesConfig, deviceStatus, ad, serviceData, switchbot, 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;
|
|
@@ -415,7 +417,7 @@ export class Bot {
|
|
|
415
417
|
if (this.device.ble) {
|
|
416
418
|
this.SwitchToOpenAPI = false;
|
|
417
419
|
}
|
|
418
|
-
if (this.platform.config.credentials?.
|
|
420
|
+
if (this.platform.config.credentials?.token) {
|
|
419
421
|
this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
420
422
|
if (this.botMode === 'press') {
|
|
421
423
|
this.On = false;
|
|
@@ -510,7 +512,7 @@ export class Bot {
|
|
|
510
512
|
this.updateHomeKitCharacteristics();
|
|
511
513
|
} else {
|
|
512
514
|
this.errorLog(`Bot: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
|
|
513
|
-
if (this.platform.config.credentials?.
|
|
515
|
+
if (this.platform.config.credentials?.token) {
|
|
514
516
|
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
515
517
|
this.SwitchToOpenAPI = true;
|
|
516
518
|
await this.openAPIRefreshStatus();
|
|
@@ -524,7 +526,7 @@ export class Bot {
|
|
|
524
526
|
`Bot: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
525
527
|
);
|
|
526
528
|
}
|
|
527
|
-
if (this.platform.config.credentials?.
|
|
529
|
+
if (this.platform.config.credentials?.token) {
|
|
528
530
|
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
529
531
|
this.SwitchToOpenAPI = true;
|
|
530
532
|
await this.openAPIRefreshStatus();
|
|
@@ -552,14 +554,51 @@ export class Bot {
|
|
|
552
554
|
}
|
|
553
555
|
|
|
554
556
|
async openAPIRefreshStatus(): Promise<void> {
|
|
555
|
-
if (this.platform.config.credentials?.
|
|
557
|
+
if (this.platform.config.credentials?.token) {
|
|
556
558
|
this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI refreshStatus`);
|
|
557
559
|
try {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
this.
|
|
562
|
-
|
|
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')) {
|
|
@@ -639,7 +678,7 @@ export class Bot {
|
|
|
639
678
|
if (this.platform.debugMode) {
|
|
640
679
|
this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,` + ` Error: ${JSON.stringify(e)}`);
|
|
641
680
|
}
|
|
642
|
-
if (this.platform.config.credentials?.
|
|
681
|
+
if (this.platform.config.credentials?.token) {
|
|
643
682
|
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
644
683
|
await this.openAPIpushChanges();
|
|
645
684
|
}
|
|
@@ -668,7 +707,7 @@ export class Bot {
|
|
|
668
707
|
if (this.platform.debugMode) {
|
|
669
708
|
this.errorLog(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,` + ` Error: ${JSON.stringify(e)}`);
|
|
670
709
|
}
|
|
671
|
-
if (this.platform.config.credentials?.
|
|
710
|
+
if (this.platform.config.credentials?.token) {
|
|
672
711
|
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
673
712
|
await this.openAPIpushChanges();
|
|
674
713
|
}
|
|
@@ -696,40 +735,68 @@ export class Bot {
|
|
|
696
735
|
}
|
|
697
736
|
|
|
698
737
|
async openAPIpushChanges(): Promise<void> {
|
|
699
|
-
if (this.platform.config.credentials?.
|
|
738
|
+
if (this.platform.config.credentials?.token) {
|
|
700
739
|
try {
|
|
701
740
|
if (this.On !== this.OnCached || this.allowPush) {
|
|
702
741
|
this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
742
|
+
// Make Push On request to the API
|
|
743
|
+
const t = Date.now();
|
|
744
|
+
const nonce = 'requestID';
|
|
745
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
746
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
747
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
748
|
+
.digest();
|
|
749
|
+
const sign = signTerm.toString('base64');
|
|
750
|
+
this.debugLog(`Bot: ${this.accessory.displayName} sign: ${sign}`);
|
|
751
|
+
let command = '';
|
|
708
752
|
if (this.botMode === 'switch' && this.On) {
|
|
709
|
-
|
|
753
|
+
command = 'turnOn';
|
|
710
754
|
this.On = true;
|
|
711
755
|
this.debugLog(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
712
756
|
} else if (this.botMode === 'switch' && !this.On) {
|
|
713
|
-
|
|
757
|
+
command = 'turnOff';
|
|
714
758
|
this.On = false;
|
|
715
759
|
this.debugLog(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
|
|
716
760
|
} else if (this.botMode === 'press') {
|
|
717
|
-
|
|
761
|
+
command = 'press';
|
|
718
762
|
this.debugLog(`Bot: ${this.accessory.displayName} Press Mode`);
|
|
719
763
|
this.On = false;
|
|
720
764
|
} else {
|
|
721
765
|
throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
|
|
722
766
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
);
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
767
|
+
const body = JSON.stringify({
|
|
768
|
+
'command': `${command}`,
|
|
769
|
+
'parameter': 'default',
|
|
770
|
+
'commandType': 'command',
|
|
771
|
+
});
|
|
772
|
+
this.infoLog(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
773
|
+
const options = {
|
|
774
|
+
hostname: HostDomain,
|
|
775
|
+
port: 443,
|
|
776
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
777
|
+
method: 'POST',
|
|
778
|
+
headers: {
|
|
779
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
780
|
+
'sign': sign,
|
|
781
|
+
'nonce': nonce,
|
|
782
|
+
't': t,
|
|
783
|
+
'Content-Type': 'application/json',
|
|
784
|
+
'Content-Length': body.length,
|
|
785
|
+
},
|
|
786
|
+
};
|
|
787
|
+
const req = https.request(options, res => {
|
|
788
|
+
this.debugLog(`Bot: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
789
|
+
this.statusCode({ res });
|
|
790
|
+
res.on('data', d => {
|
|
791
|
+
this.debugLog(`Bot: ${this.accessory.displayName} d: ${d}`);
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
req.on('error', (e: any) => {
|
|
795
|
+
this.errorLog(`Bot: ${this.accessory.displayName} error message: ${e.message}`);
|
|
796
|
+
});
|
|
797
|
+
req.write(body);
|
|
798
|
+
req.end();
|
|
799
|
+
this.debugLog(`Bot: ${this.accessory.displayName} openAPIpushChanges: ${JSON.stringify(req)}`);
|
|
733
800
|
this.OnCached = this.On;
|
|
734
801
|
this.accessory.context.On = this.OnCached;
|
|
735
802
|
}
|
|
@@ -977,8 +1044,8 @@ export class Bot {
|
|
|
977
1044
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
978
1045
|
}
|
|
979
1046
|
|
|
980
|
-
async statusCode(
|
|
981
|
-
switch (
|
|
1047
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
1048
|
+
switch (res.statusCode) {
|
|
982
1049
|
case 151:
|
|
983
1050
|
this.errorLog(`Bot: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
984
1051
|
break;
|
|
@@ -999,7 +1066,7 @@ export class Bot {
|
|
|
999
1066
|
case 190:
|
|
1000
1067
|
this.errorLog(
|
|
1001
1068
|
`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
1002
|
-
` Or command: ${JSON.stringify(
|
|
1069
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
1003
1070
|
);
|
|
1004
1071
|
break;
|
|
1005
1072
|
case 100:
|
package/src/device/colorbulb.ts
CHANGED
|
@@ -1,23 +1,12 @@
|
|
|
1
|
-
import
|
|
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, 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;
|
|
@@ -378,7 +367,7 @@ export class ColorBulb {
|
|
|
378
367
|
`Color Bulb: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
379
368
|
);
|
|
380
369
|
}
|
|
381
|
-
if (this.platform.config.credentials?.
|
|
370
|
+
if (this.platform.config.credentials?.token) {
|
|
382
371
|
this.warnLog(`Color Bulb: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
383
372
|
this.SwitchToOpenAPI = true;
|
|
384
373
|
await this.openAPIRefreshStatus();
|
|
@@ -410,7 +399,7 @@ export class ColorBulb {
|
|
|
410
399
|
|
|
411
400
|
async BLEconnection(switchbot: any): Promise<void> {
|
|
412
401
|
this.errorLog(`Color Bulb: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
413
|
-
if (this.platform.config.credentials?.
|
|
402
|
+
if (this.platform.config.credentials?.token) {
|
|
414
403
|
this.warnLog(`Color Bulb: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
415
404
|
this.SwitchToOpenAPI = true;
|
|
416
405
|
await this.openAPIRefreshStatus();
|
|
@@ -419,15 +408,51 @@ export class ColorBulb {
|
|
|
419
408
|
|
|
420
409
|
private async openAPIRefreshStatus() {
|
|
421
410
|
try {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
this.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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')) {
|
|
@@ -453,38 +478,66 @@ export class ColorBulb {
|
|
|
453
478
|
async pushChanges(): Promise<void> {
|
|
454
479
|
try {
|
|
455
480
|
if (this.On !== this.OnCached) {
|
|
456
|
-
// Push On
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
481
|
+
// Make Push On request to the API
|
|
482
|
+
const t = Date.now();
|
|
483
|
+
const nonce = 'requestID';
|
|
484
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
485
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
486
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
487
|
+
.digest();
|
|
488
|
+
const sign = signTerm.toString('base64');
|
|
489
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
|
|
490
|
+
|
|
491
|
+
let command = '';
|
|
462
492
|
if (this.On) {
|
|
463
|
-
|
|
493
|
+
command = 'turnOn';
|
|
464
494
|
} else {
|
|
465
|
-
|
|
495
|
+
command = 'turnOff';
|
|
466
496
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
497
|
+
const body = JSON.stringify({
|
|
498
|
+
'command': `${command}`,
|
|
499
|
+
'parameter': 'default',
|
|
500
|
+
'commandType': 'command',
|
|
501
|
+
});
|
|
502
|
+
this.infoLog(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
503
|
+
const options = {
|
|
504
|
+
hostname: HostDomain,
|
|
505
|
+
port: 443,
|
|
506
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
507
|
+
method: 'POST',
|
|
508
|
+
headers: {
|
|
509
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
510
|
+
'sign': sign,
|
|
511
|
+
'nonce': nonce,
|
|
512
|
+
't': t,
|
|
513
|
+
'Content-Type': 'application/json',
|
|
514
|
+
'Content-Length': body.length,
|
|
515
|
+
},
|
|
516
|
+
};
|
|
517
|
+
const req = https.request(options, res => {
|
|
518
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
519
|
+
this.statusCode({ res });
|
|
520
|
+
res.on('data', d => {
|
|
521
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} d: ${d}`);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
req.on('error', (e: any) => {
|
|
525
|
+
this.errorLog(`Color Bulb: ${this.accessory.displayName} error message: ${e.message}`);
|
|
526
|
+
});
|
|
527
|
+
req.write(body);
|
|
528
|
+
req.end();
|
|
529
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(req)}`);
|
|
477
530
|
this.OnCached = this.On;
|
|
478
531
|
this.accessory.context.On = this.OnCached;
|
|
479
532
|
}
|
|
480
533
|
// Push Brightness Update
|
|
481
534
|
if (this.On) {
|
|
482
|
-
await this.pushBrightnessChanges();
|
|
535
|
+
//await this.pushBrightnessChanges();
|
|
483
536
|
}
|
|
484
537
|
|
|
485
538
|
// Push ColorTemperature Update
|
|
486
539
|
if (this.On) {
|
|
487
|
-
await this.pushColorTemperatureChanges();
|
|
540
|
+
//await this.pushColorTemperatureChanges();
|
|
488
541
|
}
|
|
489
542
|
|
|
490
543
|
// Push Hue & Saturation Update
|
|
@@ -511,21 +564,47 @@ export class ColorBulb {
|
|
|
511
564
|
const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
|
|
512
565
|
this.debugLog(`Color Bulb: ${this.accessory.displayName} rgb: ${JSON.stringify([red, green, blue])}`);
|
|
513
566
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
this.
|
|
567
|
+
// Make Push Hue/Saturation request to the API
|
|
568
|
+
const t = Date.now();
|
|
569
|
+
const nonce = 'requestID';
|
|
570
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
571
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
572
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
573
|
+
.digest();
|
|
574
|
+
const sign = signTerm.toString('base64');
|
|
575
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
|
|
576
|
+
const body = JSON.stringify({
|
|
577
|
+
'command': 'setColor',
|
|
578
|
+
'parameter': `${red}:${green}:${blue}`,
|
|
579
|
+
'commandType': 'command',
|
|
580
|
+
});
|
|
581
|
+
this.infoLog(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
582
|
+
const options = {
|
|
583
|
+
hostname: HostDomain,
|
|
584
|
+
port: 443,
|
|
585
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
586
|
+
method: 'POST',
|
|
587
|
+
headers: {
|
|
588
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
589
|
+
'sign': sign,
|
|
590
|
+
'nonce': nonce,
|
|
591
|
+
't': t,
|
|
592
|
+
'Content-Type': 'application/json',
|
|
593
|
+
'Content-Length': body.length,
|
|
594
|
+
},
|
|
595
|
+
};
|
|
596
|
+
const req = https.request(options, res => {
|
|
597
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
598
|
+
res.on('data', d => {
|
|
599
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} d: ${d}`);
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
req.on('error', (e: any) => {
|
|
603
|
+
this.errorLog(`Color Bulb: ${this.accessory.displayName} error message: ${e.message}`);
|
|
604
|
+
});
|
|
605
|
+
req.write(body);
|
|
606
|
+
req.end();
|
|
607
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} pushHueSaturationChanges: ${JSON.stringify(req)}`);
|
|
529
608
|
this.HueCached = this.Hue;
|
|
530
609
|
this.SaturationCached = this.Saturation;
|
|
531
610
|
} else {
|
|
@@ -551,21 +630,48 @@ export class ColorBulb {
|
|
|
551
630
|
const kelvin = Math.round(1000000 / Number(this.ColorTemperature));
|
|
552
631
|
this.cacheKelvin = kelvin;
|
|
553
632
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
633
|
+
// Make Push On request to the API
|
|
634
|
+
const t = Date.now();
|
|
635
|
+
const nonce = 'requestID';
|
|
636
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
637
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
638
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
639
|
+
.digest();
|
|
640
|
+
const sign = signTerm.toString('base64');
|
|
641
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
|
|
642
|
+
const body = JSON.stringify({
|
|
643
|
+
'command': 'setColorTemperature',
|
|
644
|
+
'parameter': `${kelvin}`,
|
|
645
|
+
'commandType': 'command',
|
|
646
|
+
});
|
|
647
|
+
this.infoLog(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
648
|
+
const options = {
|
|
649
|
+
hostname: HostDomain,
|
|
650
|
+
port: 443,
|
|
651
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
652
|
+
method: 'POST',
|
|
653
|
+
headers: {
|
|
654
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
655
|
+
'sign': sign,
|
|
656
|
+
'nonce': nonce,
|
|
657
|
+
't': t,
|
|
658
|
+
'Content-Type': 'application/json',
|
|
659
|
+
'Content-Length': body.length,
|
|
660
|
+
},
|
|
661
|
+
};
|
|
662
|
+
const req = https.request(options, res => {
|
|
663
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
664
|
+
res.on('data', d => {
|
|
665
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} d: ${d}`);
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
req.on('error', (e: any) => {
|
|
669
|
+
this.errorLog(`Color Bulb: ${this.accessory.displayName} error message: ${e.message}`);
|
|
670
|
+
});
|
|
671
|
+
req.write(body);
|
|
672
|
+
req.end();
|
|
564
673
|
|
|
565
|
-
|
|
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);
|
|
674
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} pushColorTemperatureChanges: ${JSON.stringify(req)}`);
|
|
569
675
|
this.ColorTemperatureCached = this.ColorTemperature;
|
|
570
676
|
} else {
|
|
571
677
|
this.debugLog(
|
|
@@ -587,21 +693,47 @@ export class ColorBulb {
|
|
|
587
693
|
async pushBrightnessChanges(): Promise<void> {
|
|
588
694
|
try {
|
|
589
695
|
if (this.Brightness !== this.BrightnessCached) {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
this.
|
|
696
|
+
// Make Push On request to the API
|
|
697
|
+
const t = Date.now();
|
|
698
|
+
const nonce = 'requestID';
|
|
699
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
700
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
701
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
702
|
+
.digest();
|
|
703
|
+
const sign = signTerm.toString('base64');
|
|
704
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} sign: ${sign}`);
|
|
705
|
+
const body = JSON.stringify({
|
|
706
|
+
'command': 'setBrightness',
|
|
707
|
+
'parameter': `${this.Brightness}`,
|
|
708
|
+
'commandType': 'command',
|
|
709
|
+
});
|
|
710
|
+
this.infoLog(`Color Bulb: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
711
|
+
const options = {
|
|
712
|
+
hostname: HostDomain,
|
|
713
|
+
port: 443,
|
|
714
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
715
|
+
method: 'POST',
|
|
716
|
+
headers: {
|
|
717
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
718
|
+
'sign': sign,
|
|
719
|
+
'nonce': nonce,
|
|
720
|
+
't': t,
|
|
721
|
+
'Content-Type': 'application/json',
|
|
722
|
+
'Content-Length': body.length,
|
|
723
|
+
},
|
|
724
|
+
};
|
|
725
|
+
const req = https.request(options, res => {
|
|
726
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
727
|
+
res.on('data', d => {
|
|
728
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} d: ${d}`);
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
req.on('error', (e: any) => {
|
|
732
|
+
this.errorLog(`Color Bulb: ${this.accessory.displayName} error message: ${e.message}`);
|
|
733
|
+
});
|
|
734
|
+
req.write(body);
|
|
735
|
+
req.end();
|
|
736
|
+
this.debugLog(`Color Bulb: ${this.accessory.displayName} pushBrightnessChanges: ${JSON.stringify(req)}`);
|
|
605
737
|
this.BrightnessCached = this.Brightness;
|
|
606
738
|
} else {
|
|
607
739
|
this.debugLog(
|
|
@@ -661,8 +793,8 @@ export class ColorBulb {
|
|
|
661
793
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
662
794
|
}
|
|
663
795
|
|
|
664
|
-
statusCode(
|
|
665
|
-
switch (
|
|
796
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
797
|
+
switch (res.statusCode) {
|
|
666
798
|
case 151:
|
|
667
799
|
this.errorLog(`Color Bulb: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
668
800
|
break;
|
|
@@ -683,7 +815,7 @@ export class ColorBulb {
|
|
|
683
815
|
case 190:
|
|
684
816
|
this.errorLog(
|
|
685
817
|
`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
686
|
-
` Or command: ${JSON.stringify(
|
|
818
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
687
819
|
);
|
|
688
820
|
break;
|
|
689
821
|
case 100:
|