homebridge-smartsystem 6.8.12 → 6.8.18
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/README.md +58 -165
- package/accessories/accessory.js +20 -4
- package/accessories/accessory.ts +19 -4
- package/accessories/bulb.js +0 -5
- package/accessories/bulb.ts +1 -5
- package/accessories/dimmer.js +11 -3
- package/accessories/dimmer.ts +11 -4
- package/accessories/door.js +1 -0
- package/accessories/door.ts +1 -1
- package/accessories/garagedoor.js +19 -9
- package/accessories/garagedoor.ts +21 -9
- package/accessories/lock.js +15 -7
- package/accessories/lock.ts +14 -7
- package/accessories/temperature.js +10 -2
- package/accessories/temperature.ts +9 -2
- package/accessories/windowcovering.js +31 -15
- package/accessories/windowcovering.ts +30 -18
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -315,6 +315,7 @@ Homebridge UI version
|
|
|
315
315
|
- 9: corrected reading the local config file + dump it in the logs
|
|
316
316
|
- 10: wrong default port for cloud server
|
|
317
317
|
- 11: use new DNS entries + exponential backoff for new connections, give up after 16 seconds.
|
|
318
|
+
- 12, 13: small changes for missing value for Target...
|
|
318
319
|
|
|
319
320
|
## Hardware
|
|
320
321
|
A Raspberry Pi that connects to a Duotecno IP Node
|
|
@@ -540,170 +541,62 @@ add a file called "ssh" to the boot partition of the sd card
|
|
|
540
541
|
touch /Volumes/boot/ssh
|
|
541
542
|
```
|
|
542
543
|
|
|
543
|
-
later: ssh pi@192.168.99.97 / pw=raspberry
|
|
544
544
|
|
|
545
|
-
or, if you can access a terminal:
|
|
546
|
-
sudo raspi-config
|
|
547
|
-
-> enable ssh
|
|
548
|
-
-> boot to cmdline
|
|
549
|
-
|
|
550
|
-
if you want a private key on the machine
|
|
551
|
-
```
|
|
552
|
-
mkdir ~/.ssh
|
|
553
|
-
chmod 755 ~/.ssh
|
|
554
|
-
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
|
|
555
|
-
chmod 644 ~/.ssh/authorized_keys
|
|
556
|
-
rm ~/id_rsa.pub
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
### other stuff
|
|
560
|
-
if needed a wifi connection can be made too, add a file "wpa_supplicant.conf" to the boot partition of the sd card
|
|
561
|
-
example content:
|
|
562
|
-
```
|
|
563
|
-
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
|
|
564
|
-
update_config=1
|
|
565
|
-
|
|
566
|
-
network={
|
|
567
|
-
ssid="MySSID"
|
|
568
|
-
psk="MyPassword"
|
|
569
|
-
}
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
### dns server
|
|
574
|
-
If you need a dns server:
|
|
575
|
-
```
|
|
576
|
-
sudo vi /etc/network/interfaces
|
|
577
|
-
```
|
|
578
|
-
Add at end: dns-nameservers 8.8.4.4 8.8.8.8
|
|
579
|
-
=> reboot
|
|
580
|
-
```
|
|
581
|
-
shutdown -r now
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
### nodejs (65Mb)
|
|
585
|
-
Depends on version of Raspberry:
|
|
586
|
-
```
|
|
587
|
-
uname -a => ARM7 of ARM8
|
|
588
|
-
```
|
|
589
|
-
|
|
590
|
-
### 1a - nodejs - ARM7
|
|
591
|
-
```
|
|
592
|
-
wget https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-armv7l.tar.xz
|
|
593
|
-
cd /opt
|
|
594
|
-
sudo tar -xJvf ~/node-v12.16.1-linux-armv7l.tar.xz
|
|
595
|
-
rm -f ~/node-v12.16.1-linux-armv7l.tar.xz
|
|
596
|
-
sudo ln -s /opt/node-v12.16.1-linux-armv7l /opt/node
|
|
597
|
-
sudo ln -s /opt/node/bin/node /usr/bin/node
|
|
598
|
-
sudo ln -s /opt/node/bin/npm /usr/bin/npm
|
|
599
|
-
sudo apt-get install -y git
|
|
600
|
-
cd ~
|
|
601
|
-
```
|
|
602
|
-
|
|
603
|
-
### 1b - nodejs - ARM8
|
|
604
|
-
```
|
|
605
|
-
sudo rm -f /opt/node
|
|
606
|
-
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
|
|
607
|
-
sudo apt-get install -y nodejs
|
|
608
|
-
sudo npm install -g npm
|
|
609
|
-
sudo apt-get install -y git
|
|
610
|
-
cd ~
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
## New v2.0 All in one script
|
|
614
|
-
```
|
|
615
|
-
## old systems remove
|
|
616
|
-
sudo npm -g remove pm2
|
|
617
|
-
sudo rm -f /usr/bin/pm2
|
|
618
|
-
|
|
619
|
-
sudo npm -g remove homebridge
|
|
620
|
-
sudo rm -f /usr/bin/homebridge
|
|
621
|
-
|
|
622
|
-
sudo npm -g remove mqtt
|
|
623
|
-
sudo rm -f /usr/bin/mqtt
|
|
624
|
-
|
|
625
|
-
## clean up
|
|
626
|
-
sudo apt autoremove
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
## start intstall: node, npm, git
|
|
630
|
-
cd ~
|
|
631
|
-
sudo rm -f /opt/node
|
|
632
|
-
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
|
|
633
|
-
sudo apt-get install -y nodejs
|
|
634
|
-
sudo npm install -g npm
|
|
635
|
-
sudo apt-get install -y git
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
### install: homebridge
|
|
639
|
-
sudo npm install -g --force --unsafe-perm homebridge
|
|
640
|
-
### install mqtt
|
|
641
|
-
sudo npm install -g --force mqtt
|
|
642
|
-
|
|
643
|
-
### install: smartsystem
|
|
644
|
-
rm -rf smartsocket
|
|
645
|
-
git clone https://github.com/jcoppieters/smartsocket.git
|
|
646
|
-
cd smartsocket
|
|
647
|
-
git checkout v2.0
|
|
648
|
-
npm install
|
|
649
|
-
|
|
650
|
-
### config smartsystem
|
|
651
|
-
rm -rf /home/pi/.homebridge
|
|
652
|
-
mkdir -p /home/pi/.homebridge
|
|
653
|
-
cp ~/smartsocket/config.homebridge.json ~/.homebridge/config.json
|
|
654
|
-
cd ~/smartsocket
|
|
655
|
-
sudo ln -sf /home/pi/smartsocket/ /usr/lib/node_modules/homebridge-system # install the plugin via a link
|
|
656
|
-
cd ~
|
|
657
|
-
|
|
658
|
-
### install pm2 - process mgr
|
|
659
|
-
sudo npm install -g --force pm2
|
|
660
|
-
|
|
661
|
-
### IF NEEDED COPY OLD configs
|
|
662
|
-
cp -v duotecno/*.json smartsocket/
|
|
663
|
-
|
|
664
|
-
### start the system and save for reboots
|
|
665
|
-
cd ~/smartsocket
|
|
666
|
-
pm2 start homebridge
|
|
667
|
-
pm2 save
|
|
668
|
-
pm2 startup | grep "sudo" | bash
|
|
669
545
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
546
|
+
## Install Shelly gen 1 plugin
|
|
547
|
+
|
|
548
|
+
sudo vi /var/lib/homebridge/node_modules/homebridge-shelly/util/custom-characteristics.js
|
|
549
|
+
perms: ["ev","pr"], //Perms.READ, Perms.NOTIFY],
|
|
550
|
+
|
|
551
|
+
sudo vi /var/lib/homebridge/node_modules/homebridge-shelly/accessories/lightbulbs.js
|
|
552
|
+
return 5; //Accessory.Categories.LIGHTBULB
|
|
553
|
+
|
|
554
|
+
sudo vi /var/lib/homebridge/node_modules/homebridge-shelly/accessories/switches.js
|
|
555
|
+
return 8; //Accessory.Categories.SWITCH
|
|
556
|
+
|
|
557
|
+
switches.js: return 8; //Accessory.Categories.SWITCH -> 8
|
|
558
|
+
lightbulbs.js: return 5; //Accessory.Categories.LIGHTBULB -> 5 (4x)
|
|
559
|
+
|
|
560
|
+
base.js: return Accessory.Categories.OTHER -> 1
|
|
561
|
+
doors.js: return Accessory.Categories.DOOR -> 12
|
|
562
|
+
garage-door-openers.js: return Accessory.Categories.GARAGE_DOOR_OPENER -> 4
|
|
563
|
+
outlets.js: return Accessory.Categories.OUTLET -> 7
|
|
564
|
+
sensors.js: return Accessory.Categories.SENSOR -> 10 (4x)
|
|
565
|
+
valves.js: return Accessory.Categories.FAUCET -> 29
|
|
566
|
+
window-coverings.js: return Accessory.Categories.WINDOW_COVERING -> 14
|
|
567
|
+
windows.js: return Accessory.Categories.WINDOW -> 13
|
|
568
|
+
|
|
569
|
+
## OR
|
|
570
|
+
sudo vi /usr/lib/node_modules/homebridge/node_modules/hap-nodejs/dist/lib/Accessory.js
|
|
571
|
+
|
|
572
|
+
add:
|
|
573
|
+
Accessory.Categories = {
|
|
574
|
+
OTHER: 1,
|
|
575
|
+
BRIDGE: 2,
|
|
576
|
+
FAN: 3,
|
|
577
|
+
GARAGE_DOOR_OPENER: 4,
|
|
578
|
+
LIGHTBULB: 5,
|
|
579
|
+
DOOR_LOCK: 6,
|
|
580
|
+
OUTLET: 7,
|
|
581
|
+
SWITCH: 8,
|
|
582
|
+
THERMOSTAT: 9,
|
|
583
|
+
SENSOR: 10,
|
|
584
|
+
SECURITY_SYSTEM: 11,
|
|
585
|
+
DOOR: 12,
|
|
586
|
+
WINDOW: 13,
|
|
587
|
+
WINDOW_COVERING: 14,
|
|
588
|
+
PROGRAMMABLE_SWITCH: 15,
|
|
589
|
+
RANGE_EXTENDER: 16,
|
|
590
|
+
IP_CAMERA: 17,
|
|
591
|
+
VIDEO_DOORBELL: 18,
|
|
592
|
+
AIR_PURIFIER: 19,
|
|
593
|
+
HEATER: 20,
|
|
594
|
+
AIR_CONDITIONER: 21,
|
|
595
|
+
HUMIDIFIER: 22,
|
|
596
|
+
DEHUMIDIFIER: 23,
|
|
597
|
+
SPRINKLER: 28,
|
|
598
|
+
FAUCET: 29,
|
|
599
|
+
SHOWER_HEAD: 30,
|
|
600
|
+
TELEVISION: 31,
|
|
601
|
+
TARGET_CONTROLLER: 32
|
|
602
|
+
};
|
package/accessories/accessory.js
CHANGED
|
@@ -49,8 +49,16 @@ class Accessory {
|
|
|
49
49
|
getState(next) {
|
|
50
50
|
if (this.unit) {
|
|
51
51
|
this.unit.reqState(unit => {
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
try {
|
|
53
|
+
if (!unit) {
|
|
54
|
+
return next(new Error("Unit state not available"));
|
|
55
|
+
}
|
|
56
|
+
next(null, unit.status);
|
|
57
|
+
(0, logger_1.log)("accessory", "getState was called for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.status);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
next(err);
|
|
61
|
+
}
|
|
54
62
|
}).catch(err => next(err));
|
|
55
63
|
}
|
|
56
64
|
else {
|
|
@@ -60,8 +68,16 @@ class Accessory {
|
|
|
60
68
|
getValue(next) {
|
|
61
69
|
if (this.unit) {
|
|
62
70
|
this.unit.reqState(unit => {
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
try {
|
|
72
|
+
if (!unit) {
|
|
73
|
+
return next(new Error("Unit state not available"));
|
|
74
|
+
}
|
|
75
|
+
next(null, unit.value);
|
|
76
|
+
(0, logger_1.log)("accessory", "getValue was called for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.value);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
next(err);
|
|
80
|
+
}
|
|
65
81
|
}).catch(err => next(err));
|
|
66
82
|
}
|
|
67
83
|
else {
|
package/accessories/accessory.ts
CHANGED
|
@@ -68,8 +68,15 @@ export class Accessory {
|
|
|
68
68
|
getState(next) {
|
|
69
69
|
if (this.unit) {
|
|
70
70
|
this.unit.reqState(unit => {
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
try {
|
|
72
|
+
if (!unit) {
|
|
73
|
+
return next(new Error("Unit state not available"));
|
|
74
|
+
}
|
|
75
|
+
next(null, unit.status);
|
|
76
|
+
log("accessory", "getState was called for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.status);
|
|
77
|
+
} catch(err) {
|
|
78
|
+
next(err);
|
|
79
|
+
}
|
|
73
80
|
}).catch(err => next(err));
|
|
74
81
|
} else {
|
|
75
82
|
next( new Error("accessory - getState needs to be overridden if no unit is provided.") );
|
|
@@ -79,14 +86,22 @@ export class Accessory {
|
|
|
79
86
|
getValue(next) {
|
|
80
87
|
if (this.unit) {
|
|
81
88
|
this.unit.reqState(unit => {
|
|
82
|
-
|
|
83
|
-
|
|
89
|
+
try {
|
|
90
|
+
if (!unit) {
|
|
91
|
+
return next(new Error("Unit state not available"));
|
|
92
|
+
}
|
|
93
|
+
next(null, unit.value);
|
|
94
|
+
log("accessory", "getValue was called for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.value);
|
|
95
|
+
} catch(err) {
|
|
96
|
+
next(err);
|
|
97
|
+
}
|
|
84
98
|
}).catch(err => next(err));
|
|
85
99
|
} else {
|
|
86
100
|
next( new Error("accessory - getState needs to be overridden if no unit is provided.") );
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
103
|
|
|
104
|
+
|
|
90
105
|
setState(value, next) {
|
|
91
106
|
if (this.unit)
|
|
92
107
|
this.unit.setState(value)
|
package/accessories/bulb.js
CHANGED
|
@@ -25,11 +25,6 @@ class Bulb extends accessory_1.Accessory {
|
|
|
25
25
|
.then(() => next())
|
|
26
26
|
.catch(err => next(err));
|
|
27
27
|
}
|
|
28
|
-
setBrightness(value, next) {
|
|
29
|
-
this.unit.setState(value)
|
|
30
|
-
.then(() => next())
|
|
31
|
-
.catch(err => next(err));
|
|
32
|
-
}
|
|
33
28
|
}
|
|
34
29
|
exports.Bulb = Bulb;
|
|
35
30
|
//# sourceMappingURL=bulb.js.map
|
package/accessories/bulb.ts
CHANGED
package/accessories/dimmer.js
CHANGED
|
@@ -30,12 +30,20 @@ class Dimmer extends accessory_1.Accessory {
|
|
|
30
30
|
getBrightness(next) {
|
|
31
31
|
if (this.unit) {
|
|
32
32
|
this.unit.reqState(unit => {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
try {
|
|
34
|
+
if (!unit) {
|
|
35
|
+
return next(new Error("Unit state not available"));
|
|
36
|
+
}
|
|
37
|
+
next(null, unit.value);
|
|
38
|
+
(0, logger_1.log)("accessory", "getBrightness was called for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.value);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
next(err);
|
|
42
|
+
}
|
|
35
43
|
}).catch(err => next(err));
|
|
36
44
|
}
|
|
37
45
|
else {
|
|
38
|
-
next(new Error("accessory -
|
|
46
|
+
next(new Error("accessory - getBrightness needs to be overridden if no unit is provided."));
|
|
39
47
|
}
|
|
40
48
|
}
|
|
41
49
|
setPower(powerOn, next) {
|
package/accessories/dimmer.ts
CHANGED
|
@@ -41,14 +41,21 @@ export class Dimmer extends Accessory {
|
|
|
41
41
|
getBrightness(next) {
|
|
42
42
|
if (this.unit) {
|
|
43
43
|
this.unit.reqState(unit => {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
try {
|
|
45
|
+
if (!unit) {
|
|
46
|
+
return next(new Error("Unit state not available"));
|
|
47
|
+
}
|
|
48
|
+
next(null, unit.value);
|
|
49
|
+
log("accessory", "getBrightness was called for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.value);
|
|
50
|
+
} catch(err) {
|
|
51
|
+
next(err);
|
|
52
|
+
}
|
|
46
53
|
}).catch(err => next(err));
|
|
47
54
|
} else {
|
|
48
|
-
next( new Error("accessory -
|
|
55
|
+
next( new Error("accessory - getBrightness needs to be overridden if no unit is provided.") );
|
|
49
56
|
}
|
|
50
57
|
}
|
|
51
|
-
|
|
58
|
+
|
|
52
59
|
setPower(powerOn, next) {
|
|
53
60
|
this.waitingSetPower = true;
|
|
54
61
|
log("accessory", "setPower: *** waiting *** " + powerOn);
|
package/accessories/door.js
CHANGED
|
@@ -49,6 +49,7 @@ const windowcovering_1 = require("./windowcovering");
|
|
|
49
49
|
class Door extends windowcovering_1.WindowCovering {
|
|
50
50
|
constructor(homebridge, unit) {
|
|
51
51
|
super(homebridge, unit);
|
|
52
|
+
this.targetState = this.homebridge.Characteristic.CurrentDoorState.OPEN;
|
|
52
53
|
}
|
|
53
54
|
getAccessoryServices() {
|
|
54
55
|
// DoorOpener needs authentication
|
package/accessories/door.ts
CHANGED
|
@@ -13,7 +13,7 @@ const accessory_1 = require("./accessory");
|
|
|
13
13
|
class GarageDoor extends accessory_1.Accessory {
|
|
14
14
|
constructor(homebridge, unit) {
|
|
15
15
|
super(homebridge, unit);
|
|
16
|
-
this.targetState = this.homebridge.Characteristic.
|
|
16
|
+
this.targetState = this.homebridge.Characteristic.TargetDoorState.CLOSED;
|
|
17
17
|
}
|
|
18
18
|
getAccessoryServices() {
|
|
19
19
|
// GarageDoorOpener needs authentication
|
|
@@ -39,13 +39,15 @@ class GarageDoor extends accessory_1.Accessory {
|
|
|
39
39
|
return this.homebridge.Characteristic.CurrentDoorState.OPENING;
|
|
40
40
|
else if (status == types_1.UnitState.kStopped)
|
|
41
41
|
return this.homebridge.Characteristic.CurrentDoorState.STOPPED;
|
|
42
|
-
else
|
|
43
|
-
|
|
42
|
+
else {
|
|
43
|
+
(0, logger_1.log)("accessory", `Unknown Door/UnitState ${status}, defaulting to STOPPED`);
|
|
44
|
+
return this.homebridge.Characteristic.CurrentDoorState.STOPPED;
|
|
45
|
+
}
|
|
44
46
|
}
|
|
45
47
|
HB2DT(state) {
|
|
46
|
-
if (state == this.homebridge.Characteristic.
|
|
48
|
+
if (state == this.homebridge.Characteristic.TargetDoorState.OPEN)
|
|
47
49
|
return types_1.UnitMotorCmd.kOpen;
|
|
48
|
-
else if (state == this.homebridge.Characteristic.
|
|
50
|
+
else if (state == this.homebridge.Characteristic.TargetDoorState.CLOSED)
|
|
49
51
|
return types_1.UnitMotorCmd.kClose;
|
|
50
52
|
else if (state == this.homebridge.Characteristic.CurrentDoorState.STOPPED)
|
|
51
53
|
return types_1.UnitMotorCmd.kStop;
|
|
@@ -56,7 +58,7 @@ class GarageDoor extends accessory_1.Accessory {
|
|
|
56
58
|
try {
|
|
57
59
|
this.unit.reqState(unit => {
|
|
58
60
|
const hb = this.DT2HB(unit.status);
|
|
59
|
-
(0, logger_1.log)("accessory", "Get
|
|
61
|
+
(0, logger_1.log)("accessory", "Get CurrentDoorState of " + this.name + " = " + unit.status + " -> " + hb);
|
|
60
62
|
next(null, hb);
|
|
61
63
|
});
|
|
62
64
|
}
|
|
@@ -86,9 +88,17 @@ class GarageDoor extends accessory_1.Accessory {
|
|
|
86
88
|
}
|
|
87
89
|
// in response to Duotecno status messages
|
|
88
90
|
updateState() {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
const current = this.DT2HB(this.unit.status);
|
|
92
|
+
const target = current === this.homebridge.Characteristic.CurrentDoorState.OPEN
|
|
93
|
+
? this.homebridge.Characteristic.TargetDoorState.OPEN
|
|
94
|
+
: this.homebridge.Characteristic.TargetDoorState.CLOSED;
|
|
95
|
+
(0, logger_1.log)("accessory", "Received updateState -> Homekit GarageDoor for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.status + " -> passing to HB (current/target): " + current + " / " + target);
|
|
96
|
+
this.me
|
|
97
|
+
.getCharacteristic(this.homebridge.Characteristic.CurrentDoorState)
|
|
98
|
+
.updateValue(current);
|
|
99
|
+
this.me
|
|
100
|
+
.getCharacteristic(this.homebridge.Characteristic.TargetDoorState)
|
|
101
|
+
.updateValue(target);
|
|
92
102
|
}
|
|
93
103
|
}
|
|
94
104
|
exports.GarageDoor = GarageDoor;
|
|
@@ -14,7 +14,7 @@ import { Accessory } from "./accessory";
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
export class GarageDoor extends Accessory {
|
|
17
|
-
targetState = this.homebridge.Characteristic.
|
|
17
|
+
targetState = this.homebridge.Characteristic.TargetDoorState.CLOSED;
|
|
18
18
|
|
|
19
19
|
constructor(homebridge: API, unit: Unit) {
|
|
20
20
|
super(homebridge, unit);
|
|
@@ -56,15 +56,17 @@ export class GarageDoor extends Accessory {
|
|
|
56
56
|
else if (status == UnitState.kStopped)
|
|
57
57
|
return this.homebridge.Characteristic.CurrentDoorState.STOPPED;
|
|
58
58
|
|
|
59
|
-
else
|
|
60
|
-
|
|
59
|
+
else {
|
|
60
|
+
log("accessory", `Unknown Door/UnitState ${status}, defaulting to STOPPED`);
|
|
61
|
+
return this.homebridge.Characteristic.CurrentDoorState.STOPPED;
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
HB2DT(state): UnitMotorCmd | null {
|
|
64
|
-
if (state == this.homebridge.Characteristic.
|
|
66
|
+
if (state == this.homebridge.Characteristic.TargetDoorState.OPEN)
|
|
65
67
|
return UnitMotorCmd.kOpen;
|
|
66
68
|
|
|
67
|
-
else if (state == this.homebridge.Characteristic.
|
|
69
|
+
else if (state == this.homebridge.Characteristic.TargetDoorState.CLOSED)
|
|
68
70
|
return UnitMotorCmd.kClose;
|
|
69
71
|
|
|
70
72
|
else if (state == this.homebridge.Characteristic.CurrentDoorState.STOPPED)
|
|
@@ -78,7 +80,7 @@ export class GarageDoor extends Accessory {
|
|
|
78
80
|
try {
|
|
79
81
|
this.unit.reqState(unit => {
|
|
80
82
|
const hb = this.DT2HB(unit.status);
|
|
81
|
-
log("accessory", "Get
|
|
83
|
+
log("accessory", "Get CurrentDoorState of " + this.name + " = " + unit.status + " -> " + hb);
|
|
82
84
|
next(null, hb);
|
|
83
85
|
});
|
|
84
86
|
|
|
@@ -114,9 +116,19 @@ export class GarageDoor extends Accessory {
|
|
|
114
116
|
|
|
115
117
|
// in response to Duotecno status messages
|
|
116
118
|
updateState() {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
const current = this.DT2HB(this.unit.status);
|
|
120
|
+
const target =
|
|
121
|
+
current === this.homebridge.Characteristic.CurrentDoorState.OPEN
|
|
122
|
+
? this.homebridge.Characteristic.TargetDoorState.OPEN
|
|
123
|
+
: this.homebridge.Characteristic.TargetDoorState.CLOSED;
|
|
124
|
+
|
|
125
|
+
log("accessory", "Received updateState -> Homekit GarageDoor for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.status + " -> passing to HB (current/target): " + current + " / " + target);
|
|
126
|
+
this.me
|
|
127
|
+
.getCharacteristic(this.homebridge.Characteristic.CurrentDoorState)
|
|
128
|
+
.updateValue(current);
|
|
129
|
+
this.me
|
|
130
|
+
.getCharacteristic(this.homebridge.Characteristic.TargetDoorState)
|
|
131
|
+
.updateValue(target);
|
|
120
132
|
}
|
|
121
133
|
|
|
122
134
|
}
|
package/accessories/lock.js
CHANGED
|
@@ -14,7 +14,7 @@ const accessory_1 = require("./accessory");
|
|
|
14
14
|
class Lock extends accessory_1.Accessory {
|
|
15
15
|
constructor(homebridge, unit) {
|
|
16
16
|
super(homebridge, unit);
|
|
17
|
-
this.targetState =
|
|
17
|
+
this.targetState = this.homebridge.Characteristic.CurrentDoorState.CLOSED; // locked
|
|
18
18
|
(0, logger_1.log)("accessory", "created Lock -> " + unit.getDescription());
|
|
19
19
|
// set default for Unlocked to Locked
|
|
20
20
|
if (this.unit.getType() === types_1.UnitExtendedType.kUnlocker)
|
|
@@ -47,10 +47,10 @@ class Lock extends accessory_1.Accessory {
|
|
|
47
47
|
// always set to "locked" after sending the request.
|
|
48
48
|
this.unit.resetTimer = setTimeout(() => {
|
|
49
49
|
(0, logger_1.log)("accessory", "Autolock for an unlocker after 2 secs of " + this.unit.getDescription());
|
|
50
|
-
this.targetState =
|
|
51
|
-
this.me.getCharacteristic(this.homebridge.Characteristic.LockTargetState).updateValue(
|
|
50
|
+
this.targetState = this.homebridge.Characteristic.CurrentDoorState.CLOSED;
|
|
51
|
+
this.me.getCharacteristic(this.homebridge.Characteristic.LockTargetState).updateValue(this.targetState);
|
|
52
52
|
this.unit.status = 1;
|
|
53
|
-
this.me.getCharacteristic(this.homebridge.Characteristic.LockCurrentState).updateValue(
|
|
53
|
+
this.me.getCharacteristic(this.homebridge.Characteristic.LockCurrentState).updateValue(this.targetState);
|
|
54
54
|
}, 2000);
|
|
55
55
|
}
|
|
56
56
|
next();
|
|
@@ -63,9 +63,17 @@ class Lock extends accessory_1.Accessory {
|
|
|
63
63
|
}
|
|
64
64
|
getCurrent(next) {
|
|
65
65
|
this.unit.reqState(unit => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
try {
|
|
67
|
+
if (!unit) {
|
|
68
|
+
return next(new Error("Unit state not available"));
|
|
69
|
+
}
|
|
70
|
+
(0, logger_1.log)("accessory", "HB getting current state of lock = " + this.unit.status + " of " + this.unit.getDescription());
|
|
71
|
+
next(null, !!this.unit.status);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
next(err);
|
|
75
|
+
}
|
|
76
|
+
}).catch(err => next(err));
|
|
69
77
|
}
|
|
70
78
|
// in response to Duotecno status messages
|
|
71
79
|
updateState() {
|
package/accessories/lock.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { Accessory } from "./accessory";
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
export class Lock extends Accessory {
|
|
18
|
-
targetState =
|
|
18
|
+
targetState = this.homebridge.Characteristic.CurrentDoorState.CLOSED; // locked
|
|
19
19
|
|
|
20
20
|
constructor(homebridge: API, unit: Unit) {
|
|
21
21
|
super(homebridge, unit);
|
|
@@ -62,10 +62,10 @@ export class Lock extends Accessory {
|
|
|
62
62
|
// always set to "locked" after sending the request.
|
|
63
63
|
this.unit.resetTimer = setTimeout(() => {
|
|
64
64
|
log("accessory", "Autolock for an unlocker after 2 secs of " + this.unit.getDescription())
|
|
65
|
-
this.targetState =
|
|
66
|
-
this.me.getCharacteristic(this.homebridge.Characteristic.LockTargetState).updateValue(
|
|
65
|
+
this.targetState = this.homebridge.Characteristic.CurrentDoorState.CLOSED;
|
|
66
|
+
this.me.getCharacteristic(this.homebridge.Characteristic.LockTargetState).updateValue(this.targetState);
|
|
67
67
|
this.unit.status = 1;
|
|
68
|
-
this.me.getCharacteristic(this.homebridge.Characteristic.LockCurrentState).updateValue(
|
|
68
|
+
this.me.getCharacteristic(this.homebridge.Characteristic.LockCurrentState).updateValue(this.targetState);
|
|
69
69
|
}, 2000);
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -81,9 +81,16 @@ export class Lock extends Accessory {
|
|
|
81
81
|
|
|
82
82
|
getCurrent(next) {
|
|
83
83
|
this.unit.reqState(unit => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
try {
|
|
85
|
+
if (!unit) {
|
|
86
|
+
return next(new Error("Unit state not available"));
|
|
87
|
+
}
|
|
88
|
+
log("accessory", "HB getting current state of lock = " + this.unit.status + " of " + this.unit.getDescription());
|
|
89
|
+
next(null, !!this.unit.status);
|
|
90
|
+
} catch(err) {
|
|
91
|
+
next(err);
|
|
92
|
+
}
|
|
93
|
+
}).catch(err => next(err));
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
|
|
@@ -23,8 +23,16 @@ class Temperature extends accessory_1.Accessory {
|
|
|
23
23
|
getTemperature(next) {
|
|
24
24
|
if (this.unit) {
|
|
25
25
|
this.unit.reqState(unit => {
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
try {
|
|
27
|
+
if (!unit) {
|
|
28
|
+
return next(new Error("Unit state not available"));
|
|
29
|
+
}
|
|
30
|
+
(0, logger_1.log)("accessory", "reqState/getTemperature returned a value for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.value);
|
|
31
|
+
next(null, unit.value / 10.0);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
next(err);
|
|
35
|
+
}
|
|
28
36
|
})
|
|
29
37
|
.catch(err => next(err));
|
|
30
38
|
}
|
|
@@ -31,8 +31,15 @@ export class Temperature extends Accessory {
|
|
|
31
31
|
getTemperature(next) {
|
|
32
32
|
if (this.unit) {
|
|
33
33
|
this.unit.reqState(unit => {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
try {
|
|
35
|
+
if (!unit) {
|
|
36
|
+
return next(new Error("Unit state not available"));
|
|
37
|
+
}
|
|
38
|
+
log("accessory", "reqState/getTemperature returned a value for " + this.unit.node.getName() + " - " + this.unit.getName() + " -> " + this.unit.value);
|
|
39
|
+
next(null, <number>unit.value / 10.0);
|
|
40
|
+
} catch(err) {
|
|
41
|
+
next(err);
|
|
42
|
+
}
|
|
36
43
|
})
|
|
37
44
|
.catch(err => next(err));
|
|
38
45
|
} else {
|
|
@@ -58,7 +58,7 @@ const logger_1 = require("../duotecno/logger");
|
|
|
58
58
|
class WindowCovering extends accessory_1.Accessory {
|
|
59
59
|
constructor(homebridge, unit) {
|
|
60
60
|
super(homebridge, unit);
|
|
61
|
-
this.targetState =
|
|
61
|
+
this.targetState = this.homebridge.Characteristic.CurrentDoorState.OPEN;
|
|
62
62
|
}
|
|
63
63
|
getAccessoryServices() {
|
|
64
64
|
const covering = this.makeService(this.homebridge.Service.WindowCovering);
|
|
@@ -93,13 +93,21 @@ class WindowCovering extends accessory_1.Accessory {
|
|
|
93
93
|
getCurrentPosition(next) {
|
|
94
94
|
(0, logger_1.log)("accessory", "get CurrentPosition was called of " + this.name);
|
|
95
95
|
this.unit.reqState(unit => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
try {
|
|
97
|
+
if (!unit) {
|
|
98
|
+
return next(new Error("Unit state not available"));
|
|
99
|
+
}
|
|
100
|
+
if (unit.status == types_1.UnitState.kOpen)
|
|
101
|
+
next(null, 100);
|
|
102
|
+
else if (unit.status == types_1.UnitState.kClosed)
|
|
103
|
+
next(null, 0);
|
|
104
|
+
else
|
|
105
|
+
next(null, 50);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
next(err);
|
|
109
|
+
}
|
|
110
|
+
}).catch(err => next(err));
|
|
103
111
|
}
|
|
104
112
|
setTargetPosition(value, next) {
|
|
105
113
|
// homekit is giving 0-100 for windows
|
|
@@ -123,13 +131,21 @@ class WindowCovering extends accessory_1.Accessory {
|
|
|
123
131
|
getTargetPosition(next) {
|
|
124
132
|
(0, logger_1.log)("accessory", "get Characteristic.TargetPosition was called");
|
|
125
133
|
this.unit.reqState(unit => {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
try {
|
|
135
|
+
if (!unit) {
|
|
136
|
+
return next(new Error("Unit state not available"));
|
|
137
|
+
}
|
|
138
|
+
if (this.unit.status == types_1.UnitState.kOpen)
|
|
139
|
+
next(null, 100);
|
|
140
|
+
else if (this.unit.status == types_1.UnitState.kClosed)
|
|
141
|
+
next(null, 0);
|
|
142
|
+
else
|
|
143
|
+
next(null, 50);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
next(err);
|
|
147
|
+
}
|
|
148
|
+
}).catch(err => next(err));
|
|
133
149
|
}
|
|
134
150
|
// called in response to Duotecno status update
|
|
135
151
|
updateState() {
|
|
@@ -58,12 +58,10 @@ import { API } from "homebridge";
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
export class WindowCovering extends Accessory {
|
|
61
|
-
targetState;
|
|
61
|
+
targetState = this.homebridge.Characteristic.CurrentDoorState.OPEN;
|
|
62
62
|
|
|
63
63
|
constructor(homebridge: API, unit: Unit) {
|
|
64
64
|
super(homebridge, unit);
|
|
65
|
-
this.targetState = 0; // down or closed by default ??
|
|
66
|
-
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
getAccessoryServices() {
|
|
@@ -112,15 +110,22 @@ export class WindowCovering extends Accessory {
|
|
|
112
110
|
|
|
113
111
|
getCurrentPosition(next) {
|
|
114
112
|
log("accessory", "get CurrentPosition was called of " + this.name);
|
|
115
|
-
|
|
113
|
+
|
|
116
114
|
this.unit.reqState(unit => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
try {
|
|
116
|
+
if (!unit) {
|
|
117
|
+
return next(new Error("Unit state not available"));
|
|
118
|
+
}
|
|
119
|
+
if (unit.status == UnitState.kOpen)
|
|
120
|
+
next(null, 100);
|
|
121
|
+
else if (unit.status == UnitState.kClosed)
|
|
122
|
+
next(null, 0);
|
|
123
|
+
else
|
|
124
|
+
next(null, 50);
|
|
125
|
+
} catch(err) {
|
|
126
|
+
next(err);
|
|
127
|
+
}
|
|
128
|
+
}).catch(err => next(err));
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
|
|
@@ -149,13 +154,20 @@ export class WindowCovering extends Accessory {
|
|
|
149
154
|
log("accessory", "get Characteristic.TargetPosition was called");
|
|
150
155
|
|
|
151
156
|
this.unit.reqState(unit => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
try {
|
|
158
|
+
if (!unit) {
|
|
159
|
+
return next(new Error("Unit state not available"));
|
|
160
|
+
}
|
|
161
|
+
if (this.unit.status == UnitState.kOpen)
|
|
162
|
+
next(null, 100);
|
|
163
|
+
else if (this.unit.status == UnitState.kClosed)
|
|
164
|
+
next(null, 0);
|
|
165
|
+
else
|
|
166
|
+
next(null, 50);
|
|
167
|
+
} catch(err) {
|
|
168
|
+
next(err);
|
|
169
|
+
}
|
|
170
|
+
}).catch(err => next(err));
|
|
159
171
|
}
|
|
160
172
|
|
|
161
173
|
// called in response to Duotecno status update
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-smartsystem",
|
|
3
3
|
"displayname": "Duotecno Bridge",
|
|
4
|
-
"version": "6.8.
|
|
4
|
+
"version": "6.8.18",
|
|
5
5
|
"description": "SmartServer (Proxy TCP sockets to the cloud, Smappee MQTT, Duotecno IP Nodes, Homekit interface)",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"author": "Johan Coppieters",
|
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"start": "DEBUG=* homebridge -D -P '/Users/johan/Development/duotecno/smartsocket'",
|
|
12
12
|
"watch": "npx tsc --build . --watch",
|
|
13
|
-
"
|
|
13
|
+
"build": "npx tsc --build",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"publish": "npm publish",
|
|
16
|
+
"version:patch": "npm version patch && npm publish",
|
|
17
|
+
"version:minor": "npm version minor && npm publish"
|
|
14
18
|
},
|
|
15
19
|
"engines": {
|
|
16
20
|
"node": "^18.20.4 || ^20.15.1 || ^22",
|