@switchbot/homebridge-switchbot 1.15.1-beta.1 → 1.15.1-beta.11
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/dist/device/bot.d.ts +8 -7
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +97 -21
- 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 +221 -56
- 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 +50 -7
- 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 +95 -21
- 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 +180 -59
- 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 +51 -8
- 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 +49 -6
- 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 +49 -9
- 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 +96 -20
- 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 +65 -28
- 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 +65 -28
- 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 +58 -22
- 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 +76 -40
- 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 +71 -35
- 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 +58 -22
- 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 +112 -76
- 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 +58 -22
- 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 +58 -22
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +3 -5
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +143 -87
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +2 -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 +10 -12
- package/src/device/bot.ts +97 -30
- package/src/device/colorbulb.ts +225 -93
- package/src/device/contact.ts +49 -10
- package/src/device/curtain.ts +98 -31
- package/src/device/humidifier.ts +182 -77
- package/src/device/lock.ts +97 -30
- package/src/device/meter.ts +51 -12
- package/src/device/meterplus.ts +48 -9
- package/src/device/motion.ts +48 -12
- package/src/device/plug.ts +97 -29
- package/src/device/striplight.ts +189 -68
- package/src/irdevice/airconditioner.ts +64 -34
- package/src/irdevice/airpurifier.ts +64 -36
- package/src/irdevice/camera.ts +57 -27
- package/src/irdevice/fan.ts +76 -46
- package/src/irdevice/light.ts +69 -39
- package/src/irdevice/other.ts +57 -27
- package/src/irdevice/tv.ts +112 -82
- package/src/irdevice/vacuumcleaner.ts +57 -27
- package/src/irdevice/waterheater.ts +57 -27
- package/src/platform.ts +157 -100
- package/src/settings.ts +2 -25
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;
|
|
@@ -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:
|
package/src/device/contact.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
this.
|
|
383
|
-
|
|
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')) {
|
package/src/device/curtain.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import
|
|
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 {
|
|
7
|
-
import { Context } from 'vm';
|
|
8
|
-
import { MqttClient } from 'mqtt';
|
|
9
|
-
import { connectAsync } from 'async-mqtt';
|
|
11
|
+
import { device, devicesConfig, serviceData, switchbot, 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
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
this.
|
|
541
|
-
|
|
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')) {
|
|
@@ -639,6 +679,15 @@ export class Curtain {
|
|
|
639
679
|
try {
|
|
640
680
|
this.debugLog(`Curtain: ${this.accessory.displayName} OpenAPI pushChanges`);
|
|
641
681
|
if (this.TargetPosition !== this.CurrentPosition) {
|
|
682
|
+
// Make Push On request to the API
|
|
683
|
+
const t = Date.now();
|
|
684
|
+
const nonce = 'requestID';
|
|
685
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
686
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
687
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
688
|
+
.digest();
|
|
689
|
+
const sign = signTerm.toString('base64');
|
|
690
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} sign: ${sign}`);
|
|
642
691
|
this.debugLog(`Pushing ${this.TargetPosition}`);
|
|
643
692
|
const adjustedTargetPosition = 100 - Number(this.TargetPosition);
|
|
644
693
|
if (this.TargetPosition > 50) {
|
|
@@ -655,21 +704,39 @@ export class Curtain {
|
|
|
655
704
|
}
|
|
656
705
|
this.debugLog(`${this.accessory.displayName} Mode: ${this.Mode}`);
|
|
657
706
|
const adjustedMode = this.setPositionMode || 'ff';
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
707
|
+
const body = JSON.stringify({
|
|
708
|
+
'command': 'setPosition',
|
|
709
|
+
'parameter': `0,${adjustedMode},${adjustedTargetPosition}`,
|
|
710
|
+
'commandType': 'command',
|
|
711
|
+
});
|
|
712
|
+
this.infoLog(`Curtain: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
713
|
+
const options = {
|
|
714
|
+
hostname: HostDomain,
|
|
715
|
+
port: 443,
|
|
716
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
717
|
+
method: 'POST',
|
|
718
|
+
headers: {
|
|
719
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
720
|
+
'sign': sign,
|
|
721
|
+
'nonce': nonce,
|
|
722
|
+
't': t,
|
|
723
|
+
'Content-Type': 'application/json',
|
|
724
|
+
'Content-Length': body.length,
|
|
725
|
+
},
|
|
726
|
+
};
|
|
727
|
+
const req = https.request(options, res => {
|
|
728
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
729
|
+
this.statusCode({ res });
|
|
730
|
+
res.on('data', d => {
|
|
731
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} d: ${d}`);
|
|
732
|
+
});
|
|
733
|
+
});
|
|
734
|
+
req.on('error', (e: any) => {
|
|
735
|
+
this.errorLog(`Curtain: ${this.accessory.displayName} error message: ${e.message}`);
|
|
736
|
+
});
|
|
737
|
+
req.write(body);
|
|
738
|
+
req.end();
|
|
739
|
+
this.debugLog(`Curtain: ${this.accessory.displayName} openAPIpushChanges: ${JSON.stringify(req)}`);
|
|
673
740
|
} else {
|
|
674
741
|
this.debugLog(
|
|
675
742
|
`Curtain: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.` +
|
|
@@ -752,8 +819,8 @@ export class Curtain {
|
|
|
752
819
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
753
820
|
}
|
|
754
821
|
|
|
755
|
-
async statusCode(
|
|
756
|
-
switch (
|
|
822
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
823
|
+
switch (res.statusCode) {
|
|
757
824
|
case 151:
|
|
758
825
|
this.errorLog(`Curtain: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
759
826
|
break;
|
|
@@ -772,7 +839,7 @@ export class Curtain {
|
|
|
772
839
|
case 190:
|
|
773
840
|
this.errorLog(
|
|
774
841
|
`Curtain: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
775
|
-
` Or command: ${JSON.stringify(
|
|
842
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
776
843
|
);
|
|
777
844
|
break;
|
|
778
845
|
case 100:
|