@switchbot/homebridge-switchbot 1.7.0 → 1.7.1-beta.3
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/CHANGELOG.md +15 -0
- package/config.schema.json +55 -0
- package/dist/devices/bots.d.ts +3 -0
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +100 -14
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/contact.d.ts +5 -0
- package/dist/devices/contact.d.ts.map +1 -1
- package/dist/devices/contact.js +80 -20
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts +5 -1
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +28 -3
- package/dist/devices/curtains.js.map +1 -1
- package/dist/devices/meters.d.ts +1 -0
- package/dist/devices/meters.d.ts.map +1 -1
- package/dist/devices/meters.js +8 -3
- package/dist/devices/meters.js.map +1 -1
- package/dist/devices/motion.d.ts +6 -1
- package/dist/devices/motion.d.ts.map +1 -1
- package/dist/devices/motion.js +98 -39
- package/dist/devices/motion.js.map +1 -1
- package/dist/settings.d.ts +8 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/package.json +71 -71
- package/src/devices/bots.ts +93 -7
- package/src/devices/contact.ts +82 -22
- package/src/devices/curtains.ts +31 -4
- package/src/devices/meters.ts +9 -3
- package/src/devices/motion.ts +106 -45
- package/src/settings.ts +9 -0
package/package.json
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/OpenWonderLabs/homebridge-switchbot/issues"
|
|
14
|
-
},
|
|
15
|
-
"engines": {
|
|
16
|
-
"homebridge": "^1.3.9",
|
|
17
|
-
"node": "^14.18.2 || ^16.13.1"
|
|
18
|
-
},
|
|
19
|
-
"main": "dist/index.js",
|
|
20
|
-
"scripts": {
|
|
21
|
-
"check": "npm install && npm outdated",
|
|
22
|
-
"update": "ncu -u && npm update && npm install",
|
|
23
|
-
"lint": "eslint src/**.ts",
|
|
24
|
-
"watch": "npm run build && npm link && nodemon",
|
|
25
|
-
"build": "rimraf ./dist && tsc",
|
|
26
|
-
"prepublishOnly": "npm run lint && npm run build"
|
|
27
|
-
},
|
|
28
|
-
"funding": [
|
|
29
|
-
{
|
|
30
|
-
"type": "Paypal",
|
|
31
|
-
"url": "https://paypal.me/donavanbecker"
|
|
2
|
+
"displayName": "Homebridge SwitchBot",
|
|
3
|
+
"name": "@switchbot/homebridge-switchbot",
|
|
4
|
+
"version": "1.7.1-beta.3",
|
|
5
|
+
"description": "The [Homebridge](https://homebridge.io) SwitchBot plugin allows you to access your [SwitchBot](https://www.switch-bot.com) device(s) from HomeKit.",
|
|
6
|
+
"author": "SwitchBot <support@wondertechlabs.com> (https://github.com/SwitchBot)",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git://github.com/OpenWonderLabs/homebridge-switchbot.git"
|
|
32
11
|
},
|
|
33
|
-
{
|
|
34
|
-
|
|
35
|
-
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/OpenWonderLabs/homebridge-switchbot/issues"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"homebridge": "^1.3.9",
|
|
17
|
+
"node": "^14.18.2 || ^16.13.1"
|
|
18
|
+
},
|
|
19
|
+
"main": "dist/index.js",
|
|
20
|
+
"scripts": {
|
|
21
|
+
"check": "npm install && npm outdated",
|
|
22
|
+
"update": "ncu -u && npm update && npm install",
|
|
23
|
+
"lint": "eslint src/**.ts",
|
|
24
|
+
"watch": "npm run build && npm link && nodemon",
|
|
25
|
+
"build": "rimraf ./dist && tsc",
|
|
26
|
+
"prepublishOnly": "npm run lint && npm run build"
|
|
27
|
+
},
|
|
28
|
+
"funding": [
|
|
29
|
+
{
|
|
30
|
+
"type": "Paypal",
|
|
31
|
+
"url": "https://paypal.me/donavanbecker"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"type": "GitHub",
|
|
35
|
+
"url": "https://github.com/sponsors/donavanbecker"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"homebridge-plugin",
|
|
43
|
+
"switchbot",
|
|
44
|
+
"humidifier",
|
|
45
|
+
"humidity",
|
|
46
|
+
"temperature",
|
|
47
|
+
"bot",
|
|
48
|
+
"curtains",
|
|
49
|
+
"windows",
|
|
50
|
+
"ble",
|
|
51
|
+
"ir"
|
|
52
|
+
],
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@homebridge/plugin-ui-utils": "^0.0.19",
|
|
55
|
+
"axios": "^0.24.0",
|
|
56
|
+
"rxjs": "^7.5.2"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/node": "^17.0.8",
|
|
60
|
+
"@typescript-eslint/eslint-plugin": "^5.9.1",
|
|
61
|
+
"@typescript-eslint/parser": "^5.9.1",
|
|
62
|
+
"eslint": "^8.6.0",
|
|
63
|
+
"homebridge": "^1.3.9",
|
|
64
|
+
"nodemon": "^2.0.15",
|
|
65
|
+
"npm-check-updates": "^12.1.0",
|
|
66
|
+
"rimraf": "^3.0.2",
|
|
67
|
+
"ts-node": "^10.4.0",
|
|
68
|
+
"typescript": "^4.5.4",
|
|
69
|
+
"typescript-axios-wb": "^1.0.3"
|
|
70
|
+
},
|
|
71
|
+
"optionalDependencies": {
|
|
72
|
+
"node-switchbot": "^1.1.2"
|
|
36
73
|
}
|
|
37
|
-
|
|
38
|
-
"publishConfig": {
|
|
39
|
-
"access": "public"
|
|
40
|
-
},
|
|
41
|
-
"keywords": [
|
|
42
|
-
"homebridge-plugin",
|
|
43
|
-
"switchbot",
|
|
44
|
-
"humidifier",
|
|
45
|
-
"humidity",
|
|
46
|
-
"temperature",
|
|
47
|
-
"bot",
|
|
48
|
-
"curtains",
|
|
49
|
-
"windows",
|
|
50
|
-
"ble",
|
|
51
|
-
"ir"
|
|
52
|
-
],
|
|
53
|
-
"dependencies": {
|
|
54
|
-
"@homebridge/plugin-ui-utils": "^0.0.19",
|
|
55
|
-
"axios": "^0.24.0",
|
|
56
|
-
"rxjs": "^7.5.1"
|
|
57
|
-
},
|
|
58
|
-
"devDependencies": {
|
|
59
|
-
"@types/node": "^17.0.8",
|
|
60
|
-
"@typescript-eslint/eslint-plugin": "^5.9.0",
|
|
61
|
-
"@typescript-eslint/parser": "^5.9.0",
|
|
62
|
-
"eslint": "^8.6.0",
|
|
63
|
-
"homebridge": "^1.3.9",
|
|
64
|
-
"nodemon": "^2.0.15",
|
|
65
|
-
"npm-check-updates": "^12.1.0",
|
|
66
|
-
"rimraf": "^3.0.2",
|
|
67
|
-
"ts-node": "^10.4.0",
|
|
68
|
-
"typescript": "^4.5.4",
|
|
69
|
-
"typescript-axios-wb": "^1.0.3"
|
|
70
|
-
},
|
|
71
|
-
"optionalDependencies": {
|
|
72
|
-
"node-switchbot": "^1.1.2"
|
|
73
|
-
}
|
|
74
|
-
}
|
|
74
|
+
}
|
package/src/devices/bots.ts
CHANGED
|
@@ -23,6 +23,7 @@ export class Bot {
|
|
|
23
23
|
private batteryService?: Service;
|
|
24
24
|
private garageDoorService?: Service;
|
|
25
25
|
private windowCoveringService?: Service;
|
|
26
|
+
private statefulProgrammableSwitchService?: Service;
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
// Characteristic Values
|
|
@@ -37,6 +38,7 @@ export class Bot {
|
|
|
37
38
|
// BLE Others
|
|
38
39
|
connected?: boolean;
|
|
39
40
|
switchbot!: switchbot;
|
|
41
|
+
SwitchToOpenAPI?: boolean;
|
|
40
42
|
serviceData!: serviceData;
|
|
41
43
|
mode!: serviceData['mode'];
|
|
42
44
|
state!: serviceData['state'];
|
|
@@ -110,6 +112,7 @@ export class Bot {
|
|
|
110
112
|
this.removeWindowService(accessory);
|
|
111
113
|
this.removeGarageDoorService(accessory);
|
|
112
114
|
this.removeWindowCoveringService(accessory);
|
|
115
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
113
116
|
|
|
114
117
|
// Add switchService
|
|
115
118
|
(this.switchService =
|
|
@@ -128,6 +131,7 @@ export class Bot {
|
|
|
128
131
|
this.removeSwitchService(accessory);
|
|
129
132
|
this.removeWindowService(accessory);
|
|
130
133
|
this.removeWindowCoveringService(accessory);
|
|
134
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
131
135
|
|
|
132
136
|
// Add switchService
|
|
133
137
|
(this.garageDoorService =
|
|
@@ -147,6 +151,7 @@ export class Bot {
|
|
|
147
151
|
this.removeWindowService(accessory);
|
|
148
152
|
this.removeGarageDoorService(accessory);
|
|
149
153
|
this.removeWindowCoveringService(accessory);
|
|
154
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
150
155
|
|
|
151
156
|
// Add switchService
|
|
152
157
|
(this.doorService =
|
|
@@ -172,6 +177,7 @@ export class Bot {
|
|
|
172
177
|
this.removeSwitchService(accessory);
|
|
173
178
|
this.removeGarageDoorService(accessory);
|
|
174
179
|
this.removeWindowCoveringService(accessory);
|
|
180
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
175
181
|
|
|
176
182
|
// Add switchService
|
|
177
183
|
(this.windowService =
|
|
@@ -197,6 +203,7 @@ export class Bot {
|
|
|
197
203
|
this.removeSwitchService(accessory);
|
|
198
204
|
this.removeWindowService(accessory);
|
|
199
205
|
this.removeGarageDoorService(accessory);
|
|
206
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
200
207
|
|
|
201
208
|
// Add switchService
|
|
202
209
|
(this.windowCoveringService =
|
|
@@ -222,6 +229,7 @@ export class Bot {
|
|
|
222
229
|
this.removeWindowService(accessory);
|
|
223
230
|
this.removeGarageDoorService(accessory);
|
|
224
231
|
this.removeWindowCoveringService(accessory);
|
|
232
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
225
233
|
|
|
226
234
|
// Add switchService
|
|
227
235
|
(this.lockService =
|
|
@@ -240,6 +248,7 @@ export class Bot {
|
|
|
240
248
|
this.removeWindowService(accessory);
|
|
241
249
|
this.removeGarageDoorService(accessory);
|
|
242
250
|
this.removeWindowCoveringService(accessory);
|
|
251
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
243
252
|
|
|
244
253
|
// Add switchService
|
|
245
254
|
(this.faucetService =
|
|
@@ -258,6 +267,7 @@ export class Bot {
|
|
|
258
267
|
this.removeWindowService(accessory);
|
|
259
268
|
this.removeGarageDoorService(accessory);
|
|
260
269
|
this.removeWindowCoveringService(accessory);
|
|
270
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
261
271
|
|
|
262
272
|
// Add switchService
|
|
263
273
|
(this.fanService =
|
|
@@ -267,6 +277,26 @@ export class Bot {
|
|
|
267
277
|
|
|
268
278
|
this.fanService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
269
279
|
this.fanService.getCharacteristic(this.platform.Characteristic.On).onSet(this.handleOnSet.bind(this));
|
|
280
|
+
} else if (device.bot?.deviceType === 'stateful') {
|
|
281
|
+
this.removeFanService(accessory);
|
|
282
|
+
this.removeLockService(accessory);
|
|
283
|
+
this.removeDoorService(accessory);
|
|
284
|
+
this.removeFaucetService(accessory);
|
|
285
|
+
this.removeOutletService(accessory);
|
|
286
|
+
this.removeSwitchService(accessory);
|
|
287
|
+
this.removeWindowService(accessory);
|
|
288
|
+
this.removeGarageDoorService(accessory);
|
|
289
|
+
this.removeWindowCoveringService(accessory);
|
|
290
|
+
|
|
291
|
+
// Add switchService
|
|
292
|
+
(this.statefulProgrammableSwitchService =
|
|
293
|
+
accessory.getService(this.platform.Service.StatefulProgrammableSwitch) ||
|
|
294
|
+
accessory.addService(this.platform.Service.StatefulProgrammableSwitch)), `${accessory.displayName} Stateful Programmable Switch`;
|
|
295
|
+
this.infoLog(`Bot: ${accessory.displayName} Displaying as Stateful Programmable Switch`);
|
|
296
|
+
|
|
297
|
+
this.statefulProgrammableSwitchService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
298
|
+
this.statefulProgrammableSwitchService.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState)
|
|
299
|
+
.onSet(this.handleOnSet.bind(this));
|
|
270
300
|
} else {
|
|
271
301
|
this.removeFanService(accessory);
|
|
272
302
|
this.removeLockService(accessory);
|
|
@@ -276,6 +306,7 @@ export class Bot {
|
|
|
276
306
|
this.removeWindowService(accessory);
|
|
277
307
|
this.removeGarageDoorService(accessory);
|
|
278
308
|
this.removeWindowCoveringService(accessory);
|
|
309
|
+
this.removeStatefulProgrammableSwitchService(accessory);
|
|
279
310
|
|
|
280
311
|
// Add outletService
|
|
281
312
|
(this.outletService =
|
|
@@ -287,12 +318,21 @@ export class Bot {
|
|
|
287
318
|
this.outletService.getCharacteristic(this.platform.Characteristic.On).onSet(this.handleOnSet.bind(this));
|
|
288
319
|
}
|
|
289
320
|
|
|
290
|
-
|
|
321
|
+
// Battery Service
|
|
322
|
+
if (!device.ble) {
|
|
323
|
+
this.debugLog(`Bot: ${accessory.displayName} Removing Battery Service`);
|
|
324
|
+
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
325
|
+
accessory.removeService(this.batteryService!);
|
|
326
|
+
} else if (!this.batteryService) {
|
|
327
|
+
this.debugLog(`Bot: ${accessory.displayName} Add Battery Service`);
|
|
291
328
|
(this.batteryService =
|
|
292
|
-
accessory.getService(this.platform.Service.Battery) ||
|
|
293
|
-
accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
329
|
+
this.accessory.getService(this.platform.Service.Battery) ||
|
|
330
|
+
this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
294
331
|
|
|
295
332
|
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
333
|
+
|
|
334
|
+
} else {
|
|
335
|
+
this.debugLog(`Bot: ${accessory.displayName} Battery Service Not Added`);
|
|
296
336
|
}
|
|
297
337
|
|
|
298
338
|
// Retrieve initial values and updateHomekit
|
|
@@ -408,6 +448,15 @@ export class Bot {
|
|
|
408
448
|
accessory.removeService(this.windowCoveringService!);
|
|
409
449
|
}
|
|
410
450
|
|
|
451
|
+
public removeStatefulProgrammableSwitchService(accessory: PlatformAccessory) {
|
|
452
|
+
// If statefulProgrammableSwitchService still pressent, then remove first
|
|
453
|
+
this.statefulProgrammableSwitchService = this.accessory.getService(this.platform.Service.StatefulProgrammableSwitch);
|
|
454
|
+
if (this.statefulProgrammableSwitchService) {
|
|
455
|
+
this.warnLog(`Bot: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
|
|
456
|
+
}
|
|
457
|
+
accessory.removeService(this.statefulProgrammableSwitchService!);
|
|
458
|
+
}
|
|
459
|
+
|
|
411
460
|
public removeSwitchService(accessory: PlatformAccessory) {
|
|
412
461
|
// If switchService still pressent, then remove first
|
|
413
462
|
this.switchService = this.accessory.getService(this.platform.Service.Switch);
|
|
@@ -484,10 +533,10 @@ export class Bot {
|
|
|
484
533
|
* Parse the device status from the SwitchBot api
|
|
485
534
|
*/
|
|
486
535
|
async parseStatus() {
|
|
487
|
-
if (this.device.ble) {
|
|
488
|
-
await this.BLEparseStatus();
|
|
489
|
-
} else {
|
|
536
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
490
537
|
await this.openAPIparseStatus();
|
|
538
|
+
} else {
|
|
539
|
+
await this.BLEparseStatus();
|
|
491
540
|
}
|
|
492
541
|
}
|
|
493
542
|
|
|
@@ -521,6 +570,9 @@ export class Bot {
|
|
|
521
570
|
}
|
|
522
571
|
|
|
523
572
|
private async openAPIparseStatus() {
|
|
573
|
+
if (this.device.ble) {
|
|
574
|
+
this.SwitchToOpenAPI = false;
|
|
575
|
+
}
|
|
524
576
|
if (this.platform.config.credentials?.openToken) {
|
|
525
577
|
this.debugLog(`Bot: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
526
578
|
if (this.botMode === 'press') {
|
|
@@ -528,7 +580,7 @@ export class Bot {
|
|
|
528
580
|
this.OnCached = this.On;
|
|
529
581
|
this.accessory.context.On = this.OnCached;
|
|
530
582
|
} else {
|
|
531
|
-
if (this.deviceStatus.body.power === 'on') {
|
|
583
|
+
/*if (this.deviceStatus.body.power === 'on') {
|
|
532
584
|
this.On = true;
|
|
533
585
|
this.OnCached = this.On;
|
|
534
586
|
this.accessory.context.On = this.OnCached;
|
|
@@ -536,6 +588,11 @@ export class Bot {
|
|
|
536
588
|
this.On = false;
|
|
537
589
|
this.OnCached = this.On;
|
|
538
590
|
this.accessory.context.On = this.OnCached;
|
|
591
|
+
}*/
|
|
592
|
+
this.OnCached = this.On;
|
|
593
|
+
this.accessory.context.On = this.OnCached;
|
|
594
|
+
if (this.On === undefined) {
|
|
595
|
+
this.On = false;
|
|
539
596
|
}
|
|
540
597
|
}
|
|
541
598
|
this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
|
|
@@ -620,6 +677,7 @@ export class Bot {
|
|
|
620
677
|
this.errorLog(`Bot: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
|
|
621
678
|
if (this.platform.config.credentials?.openToken) {
|
|
622
679
|
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
680
|
+
this.SwitchToOpenAPI = true;
|
|
623
681
|
await this.openAPIRefreshStatus();
|
|
624
682
|
}
|
|
625
683
|
}
|
|
@@ -635,6 +693,7 @@ export class Bot {
|
|
|
635
693
|
}
|
|
636
694
|
if (this.platform.config.credentials?.openToken) {
|
|
637
695
|
this.warnLog(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
696
|
+
this.SwitchToOpenAPI = true;
|
|
638
697
|
await this.openAPIRefreshStatus();
|
|
639
698
|
}
|
|
640
699
|
this.apiError(e);
|
|
@@ -952,6 +1011,23 @@ export class Bot {
|
|
|
952
1011
|
}
|
|
953
1012
|
}
|
|
954
1013
|
this.debugLog(`Bot: ${this.accessory.displayName} Fan On: ${this.On}`);
|
|
1014
|
+
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
1015
|
+
if (this.On === undefined) {
|
|
1016
|
+
this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
|
|
1017
|
+
} else {
|
|
1018
|
+
if (this.On) {
|
|
1019
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent,
|
|
1020
|
+
this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
|
|
1021
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, 1);
|
|
1022
|
+
this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1`);
|
|
1023
|
+
} else {
|
|
1024
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent,
|
|
1025
|
+
this.platform.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
|
|
1026
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, 0);
|
|
1027
|
+
this.debugLog(`Bot: ${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0`);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
this.debugLog(`Bot: ${this.accessory.displayName} StatefulProgrammableSwitch On: ${this.On}`);
|
|
955
1031
|
} else if (this.device.bot?.deviceType === 'switch') {
|
|
956
1032
|
if (this.On === undefined) {
|
|
957
1033
|
this.debugLog(`Bot: ${this.accessory.displayName} On: ${this.On}`);
|
|
@@ -1007,6 +1083,9 @@ export class Bot {
|
|
|
1007
1083
|
this.faucetService?.updateCharacteristic(this.platform.Characteristic.Active, e);
|
|
1008
1084
|
} else if (this.device.bot?.deviceType === 'fan') {
|
|
1009
1085
|
this.fanService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1086
|
+
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
1087
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent, e);
|
|
1088
|
+
this.statefulProgrammableSwitchService?.updateCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState, e);
|
|
1010
1089
|
} else if (this.device.bot?.deviceType === 'switch') {
|
|
1011
1090
|
this.switchService?.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1012
1091
|
} else {
|
|
@@ -1095,6 +1174,13 @@ export class Bot {
|
|
|
1095
1174
|
} else {
|
|
1096
1175
|
this.On = true;
|
|
1097
1176
|
}
|
|
1177
|
+
} else if (this.device.bot?.deviceType === 'stateful') {
|
|
1178
|
+
this.debugLog(`Bot: ${this.accessory.displayName} ProgrammableSwitchOutputState: ${value}`);
|
|
1179
|
+
if (value === 0) {
|
|
1180
|
+
this.On = false;
|
|
1181
|
+
} else {
|
|
1182
|
+
this.On = true;
|
|
1183
|
+
}
|
|
1098
1184
|
} else {
|
|
1099
1185
|
this.debugLog(`Bot: ${this.accessory.displayName} On: ${value}`);
|
|
1100
1186
|
this.On = value;
|
package/src/devices/contact.ts
CHANGED
|
@@ -29,6 +29,7 @@ export class Contact {
|
|
|
29
29
|
// BLE Others
|
|
30
30
|
connected?: boolean;
|
|
31
31
|
switchbot!: switchbot;
|
|
32
|
+
SwitchToOpenAPI!: boolean;
|
|
32
33
|
serviceData!: serviceData;
|
|
33
34
|
battery!: serviceData['battery'];
|
|
34
35
|
movement!: serviceData['movement'];
|
|
@@ -36,6 +37,8 @@ export class Contact {
|
|
|
36
37
|
lightLevel!: serviceData['lightLevel'];
|
|
37
38
|
|
|
38
39
|
// Config
|
|
40
|
+
set_minLux!: number;
|
|
41
|
+
set_maxLux!: number;
|
|
39
42
|
scanDuration!: number;
|
|
40
43
|
deviceLogging!: string;
|
|
41
44
|
deviceRefreshRate!: number;
|
|
@@ -57,8 +60,8 @@ export class Contact {
|
|
|
57
60
|
|
|
58
61
|
// Contact Config
|
|
59
62
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},`
|
|
60
|
-
+ ` hide_lightsensor: ${device.contact?.hide_lightsensor}, hide_motionsensor: ${device.contact?.hide_motionsensor}
|
|
61
|
-
|
|
63
|
+
+ ` hide_lightsensor: ${device.contact?.hide_lightsensor}, hide_motionsensor: ${device.contact?.hide_motionsensor},`
|
|
64
|
+
+ ` set_minLux: ${this.device.contact?.set_minLux}, set_maxLux: ${this.device.contact?.set_maxLux})`);
|
|
62
65
|
|
|
63
66
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
64
67
|
this.doContactUpdate = new Subject();
|
|
@@ -89,7 +92,7 @@ export class Contact {
|
|
|
89
92
|
this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
90
93
|
|
|
91
94
|
// each service must implement at-minimum the "required characteristics" for the given service type
|
|
92
|
-
// see https://developers.homebridge.io/#/service/
|
|
95
|
+
// see https://developers.homebridge.io/#/service/ContactSensor
|
|
93
96
|
|
|
94
97
|
// Motion Sensor Service
|
|
95
98
|
if (device.contact?.hide_motionsensor) {
|
|
@@ -125,12 +128,21 @@ export class Contact {
|
|
|
125
128
|
this.debugLog(`Contact Sensor: ${accessory.displayName} Light Sensor Service Not Added`);
|
|
126
129
|
}
|
|
127
130
|
|
|
128
|
-
|
|
131
|
+
// Battery Service
|
|
132
|
+
if (!device.ble) {
|
|
133
|
+
this.debugLog(`Contact Sensor: ${accessory.displayName} Removing Battery Service`);
|
|
134
|
+
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
135
|
+
accessory.removeService(this.batteryService!);
|
|
136
|
+
} else if (!this.batteryService) {
|
|
137
|
+
this.debugLog(`Contact Sensor: ${accessory.displayName} Add Battery Service`);
|
|
129
138
|
(this.batteryService =
|
|
130
|
-
accessory.getService(this.platform.Service.Battery) ||
|
|
131
|
-
accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
139
|
+
this.accessory.getService(this.platform.Service.Battery) ||
|
|
140
|
+
this.accessory.addService(this.platform.Service.Battery)), `${accessory.displayName} Battery`;
|
|
132
141
|
|
|
133
142
|
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
143
|
+
|
|
144
|
+
} else {
|
|
145
|
+
this.debugLog(`Contact Sensor: ${accessory.displayName} Battery Service Not Added`);
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
// Retrieve initial values and updateHomekit
|
|
@@ -191,23 +203,37 @@ export class Contact {
|
|
|
191
203
|
}
|
|
192
204
|
}
|
|
193
205
|
|
|
206
|
+
private minLux(): number {
|
|
207
|
+
if (this.device.contact?.set_minLux) {
|
|
208
|
+
this.set_minLux = this.device.contact!.set_minLux!;
|
|
209
|
+
} else {
|
|
210
|
+
this.set_minLux = 1;
|
|
211
|
+
}
|
|
212
|
+
return this.set_minLux;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private maxLux(): number {
|
|
216
|
+
if (this.device.contact?.set_maxLux) {
|
|
217
|
+
this.set_maxLux = this.device.contact!.set_maxLux!;
|
|
218
|
+
} else {
|
|
219
|
+
this.set_maxLux = 6001;
|
|
220
|
+
}
|
|
221
|
+
return this.set_maxLux;
|
|
222
|
+
}
|
|
223
|
+
|
|
194
224
|
/**
|
|
195
225
|
* Parse the device status from the SwitchBot api
|
|
196
226
|
*/
|
|
197
227
|
async parseStatus() {
|
|
198
|
-
if (this.device.ble) {
|
|
199
|
-
await this.BLEparseStatus();
|
|
200
|
-
} else {
|
|
228
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
201
229
|
await this.openAPIparseStatus();
|
|
230
|
+
} else {
|
|
231
|
+
await this.BLEparseStatus();
|
|
202
232
|
}
|
|
203
233
|
}
|
|
204
234
|
|
|
205
235
|
private async BLEparseStatus() {
|
|
206
236
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BLE parseStatus`);
|
|
207
|
-
if (this.device.contact?.hide_motionsensor) {
|
|
208
|
-
// Movement
|
|
209
|
-
this.MotionDetected = Boolean(this.movement);
|
|
210
|
-
}
|
|
211
237
|
// Door State
|
|
212
238
|
switch (this.doorState) {
|
|
213
239
|
case 'open':
|
|
@@ -221,31 +247,46 @@ export class Contact {
|
|
|
221
247
|
default:
|
|
222
248
|
this.errorLog(`Contact Sensor: ${this.accessory.displayName} timeout no closed, doorstate: ${this.doorState}`);
|
|
223
249
|
}
|
|
224
|
-
|
|
250
|
+
// Movement
|
|
251
|
+
if (!this.device.contact?.hide_motionsensor) {
|
|
252
|
+
this.MotionDetected = Boolean(this.movement);
|
|
253
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
254
|
+
}
|
|
255
|
+
// Light Level
|
|
256
|
+
if (!this.device.contact?.hide_lightsensor) {
|
|
257
|
+
this.set_minLux = this.minLux();
|
|
258
|
+
this.set_maxLux = this.maxLux();
|
|
225
259
|
switch (this.lightLevel) {
|
|
226
260
|
case 'dark':
|
|
227
261
|
case 0:
|
|
228
|
-
this.CurrentAmbientLightLevel =
|
|
262
|
+
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
229
263
|
break;
|
|
230
264
|
default:
|
|
231
|
-
this.CurrentAmbientLightLevel =
|
|
265
|
+
this.CurrentAmbientLightLevel = this.set_maxLux;
|
|
232
266
|
}
|
|
267
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} LightLevel: ${this.lightLevel},`
|
|
268
|
+
+ ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
233
269
|
}
|
|
234
270
|
// Battery
|
|
271
|
+
if (this.battery === undefined) {
|
|
272
|
+
this.battery === 100;
|
|
273
|
+
}
|
|
235
274
|
this.BatteryLevel = Number(this.battery);
|
|
236
275
|
if (this.BatteryLevel < 10) {
|
|
237
276
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
238
277
|
} else {
|
|
239
278
|
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
240
279
|
}
|
|
241
|
-
|
|
242
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}, MotionDetected: `
|
|
243
|
-
+ `${this.MotionDetected}, CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}, BatteryLevel: ${this.BatteryLevel}`);
|
|
280
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
|
|
244
281
|
}
|
|
245
282
|
|
|
246
283
|
private async openAPIparseStatus() {
|
|
284
|
+
if (this.device.ble) {
|
|
285
|
+
this.SwitchToOpenAPI = false;
|
|
286
|
+
}
|
|
247
287
|
if (this.platform.config.credentials?.openToken) {
|
|
248
288
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
289
|
+
// Contact State
|
|
249
290
|
if (this.deviceStatus.body.openState === 'open') {
|
|
250
291
|
this.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
|
|
251
292
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} ContactSensorState: ${this.ContactSensorState}`);
|
|
@@ -255,10 +296,27 @@ export class Contact {
|
|
|
255
296
|
} else {
|
|
256
297
|
this.debugLog(`Contact Sensor: ${this.accessory.displayName} openState: ${this.deviceStatus.body.openState}`);
|
|
257
298
|
}
|
|
258
|
-
|
|
259
|
-
|
|
299
|
+
// Motion State
|
|
300
|
+
if (!this.device.contact?.hide_motionsensor) {
|
|
301
|
+
if (typeof this.deviceStatus.body.moveDetected === 'boolean') {
|
|
302
|
+
this.MotionDetected = this.deviceStatus.body.moveDetected;
|
|
303
|
+
}
|
|
304
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
305
|
+
}
|
|
306
|
+
// Light Level
|
|
307
|
+
if (!this.device.contact?.hide_lightsensor) {
|
|
308
|
+
this.set_minLux = this.minLux();
|
|
309
|
+
this.set_maxLux = this.maxLux();
|
|
310
|
+
switch (this.deviceStatus.body.brightness) {
|
|
311
|
+
case 'dim':
|
|
312
|
+
this.CurrentAmbientLightLevel = this.set_minLux;
|
|
313
|
+
break;
|
|
314
|
+
case 'bright':
|
|
315
|
+
default:
|
|
316
|
+
this.CurrentAmbientLightLevel = this.set_maxLux;
|
|
317
|
+
}
|
|
318
|
+
this.debugLog(`Contact Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
260
319
|
}
|
|
261
|
-
this.debugLog(`Contact Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
262
320
|
}
|
|
263
321
|
}
|
|
264
322
|
|
|
@@ -353,6 +411,7 @@ export class Contact {
|
|
|
353
411
|
}
|
|
354
412
|
if (this.platform.config.credentials?.openToken) {
|
|
355
413
|
this.warnLog(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
414
|
+
this.SwitchToOpenAPI = true;
|
|
356
415
|
await this.openAPIRefreshStatus();
|
|
357
416
|
}
|
|
358
417
|
this.apiError(e);
|
|
@@ -366,6 +425,7 @@ export class Contact {
|
|
|
366
425
|
this.errorLog(`Contact Sensor: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
367
426
|
if (this.platform.config.credentials?.openToken) {
|
|
368
427
|
this.warnLog(`Contact Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
428
|
+
this.SwitchToOpenAPI = true;
|
|
369
429
|
await this.openAPIRefreshStatus();
|
|
370
430
|
}
|
|
371
431
|
}
|