homebridge-deconz 1.1.2 → 1.2.2
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/lib/Deconz/Resource.js +60 -66
- package/lib/DeconzAccessory/Gateway.js +52 -7
- package/lib/DeconzPlatform.js +0 -5
- package/package.json +6 -6
package/lib/Deconz/Resource.js
CHANGED
@@ -49,6 +49,25 @@ const hueTapMap = {
|
|
49
49
|
99: 0 // release 3 and 4
|
50
50
|
}
|
51
51
|
|
52
|
+
const hkEvent = {
|
53
|
+
SINGLE: 0x01,
|
54
|
+
DOUBLE: 0x02,
|
55
|
+
LONG: 0x04
|
56
|
+
}
|
57
|
+
|
58
|
+
const buttonEventMap = {
|
59
|
+
0: 0, // PRESS
|
60
|
+
1: hkEvent.LONG, // HOLD
|
61
|
+
2: hkEvent.SINGLE, // SHORT_RELEASE
|
62
|
+
3: hkEvent.LONG, // LONG_RELEASE
|
63
|
+
4: hkEvent.DOUBLE, // DOUBLE_PRESS
|
64
|
+
5: hkEvent.LONG, // TRIPLE_PRESS
|
65
|
+
6: hkEvent.LONG, // QUADRUPLE_PRESS
|
66
|
+
7: hkEvent.LONG, // SHAKE
|
67
|
+
8: hkEvent.DOUBLE, // DROP
|
68
|
+
9: 0 // TILT
|
69
|
+
}
|
70
|
+
|
52
71
|
const ancillaryControlMap = {
|
53
72
|
disarmed: 1002,
|
54
73
|
already_disarmed: 1002,
|
@@ -437,6 +456,30 @@ class Resource {
|
|
437
456
|
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
438
457
|
*/
|
439
458
|
patchLabel (gateway) {
|
459
|
+
// FIX_ME: use introspect until buttons and events are reported as capability
|
460
|
+
if (this.body.introspect?.buttons != null) {
|
461
|
+
this.capabilities._introspect = true
|
462
|
+
this.capabilities._buttons = {}
|
463
|
+
let dots = 0
|
464
|
+
for (const button in this.body.introspect.buttons) {
|
465
|
+
const label = this.body.introspect.buttons[button].name
|
466
|
+
this.capabilities._buttons[button] = { label, events: 0 }
|
467
|
+
if (label.includes(' Dot')) {
|
468
|
+
dots++
|
469
|
+
}
|
470
|
+
}
|
471
|
+
this.capabilities._namespace = dots === this.body.introspect.buttons.length
|
472
|
+
? gateway.Characteristics.hap.ServiceLabelNamespace.DOTS
|
473
|
+
: gateway.Characteristics.hap.ServiceLabelNamespace.ARABIC_NUMERALS
|
474
|
+
for (const value in this.body.introspect.values) {
|
475
|
+
const button = Math.round(value / 1000)
|
476
|
+
const event = value % 1000
|
477
|
+
if (this.capabilities._buttons[button] != null) {
|
478
|
+
this.capabilities._buttons[button].events |= buttonEventMap[event]
|
479
|
+
}
|
480
|
+
}
|
481
|
+
}
|
482
|
+
// End FIX_ME
|
440
483
|
const buttons = []
|
441
484
|
let dots = false
|
442
485
|
switch (this.manufacturer) {
|
@@ -551,15 +594,11 @@ class Resource {
|
|
551
594
|
buttons.push([3, 'Previous', SINGLE | LONG])
|
552
595
|
buttons.push([4, 'Next', SINGLE | LONG])
|
553
596
|
break
|
554
|
-
case '
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
dots = true
|
560
|
-
buttons.push([1, '1', SINGLE | DOUBLE | LONG])
|
561
|
-
buttons.push([2, '2', SINGLE | DOUBLE | LONG])
|
562
|
-
break
|
597
|
+
// case 'SOMRIG shortcut button':
|
598
|
+
// dots = true
|
599
|
+
// buttons.push([1, '1', SINGLE | DOUBLE | LONG])
|
600
|
+
// buttons.push([2, '2', SINGLE | DOUBLE | LONG])
|
601
|
+
// break
|
563
602
|
case 'SYMFONISK Sound Controller':
|
564
603
|
if (this.cluster === '1000') {
|
565
604
|
buttons.push([1, 'Button', SINGLE | DOUBLE | LONG])
|
@@ -584,17 +623,6 @@ class Resource {
|
|
584
623
|
buttons.push([6, 'One Dot', SINGLE | DOUBLE | LONG])
|
585
624
|
buttons.push([7, 'Two Dots', SINGLE | DOUBLE | LONG])
|
586
625
|
break
|
587
|
-
case 'TRADFRI SHORTCUT Button':
|
588
|
-
buttons.push([1, 'Button', SINGLE | DOUBLE | LONG])
|
589
|
-
break
|
590
|
-
case 'TRADFRI on/off switch':
|
591
|
-
buttons.push([1, 'On', SINGLE | LONG])
|
592
|
-
buttons.push([2, 'Off', SINGLE | LONG])
|
593
|
-
break
|
594
|
-
case 'TRADFRI open/close remote':
|
595
|
-
buttons.push([1, 'Open', SINGLE | LONG])
|
596
|
-
buttons.push([2, 'Close', SINGLE | LONG])
|
597
|
-
break
|
598
626
|
case 'TRADFRI remote control':
|
599
627
|
buttons.push([1, 'Power', SINGLE])
|
600
628
|
buttons.push([2, 'Dim Up', SINGLE | LONG])
|
@@ -676,7 +704,6 @@ class Resource {
|
|
676
704
|
case 'lumi.remote.b186acn02':
|
677
705
|
buttons.push([1, 'Button', SINGLE | DOUBLE | LONG])
|
678
706
|
break
|
679
|
-
case 'lumi.remote.b28ac1':
|
680
707
|
case 'lumi.remote.b286acn01':
|
681
708
|
case 'lumi.remote.b286acn02':
|
682
709
|
buttons.push([1, 'Left', SINGLE | DOUBLE | LONG])
|
@@ -751,7 +778,7 @@ class Resource {
|
|
751
778
|
}
|
752
779
|
break
|
753
780
|
case 'lumi.sensor_switch': // Xiaomi Mi wireless switch
|
754
|
-
|
781
|
+
// fallthrough
|
755
782
|
case 'lumi.sensor_switch.aq3': // Xiaomi Aqara smart wireless switch with gyro
|
756
783
|
buttons.push([1, 'Button', SINGLE | DOUBLE | LONG])
|
757
784
|
break
|
@@ -822,11 +849,6 @@ class Resource {
|
|
822
849
|
break
|
823
850
|
case 'OSRAM':
|
824
851
|
switch (this.model) {
|
825
|
-
case 'Lightify Switch Mini':
|
826
|
-
buttons.push([1, 'Up', SINGLE | LONG])
|
827
|
-
buttons.push([2, 'Down', SINGLE | LONG])
|
828
|
-
buttons.push([3, 'Middle', SINGLE | LONG])
|
829
|
-
break
|
830
852
|
case 'Switch 4x EU-LIGHTIFY':
|
831
853
|
case 'Switch 4x-LIGHTIFY':
|
832
854
|
buttons.push([1, 'Top Left', SINGLE | LONG])
|
@@ -1037,18 +1059,6 @@ class Resource {
|
|
1037
1059
|
break
|
1038
1060
|
}
|
1039
1061
|
break
|
1040
|
-
case '_TZ3000_mh9px7cq':
|
1041
|
-
switch (this.model) {
|
1042
|
-
case 'TS0044':
|
1043
|
-
buttons.push([1, 'Button 1', SINGLE | DOUBLE | LONG])
|
1044
|
-
buttons.push([2, 'Button 2', SINGLE | DOUBLE | LONG])
|
1045
|
-
buttons.push([3, 'Button 3', SINGLE | DOUBLE | LONG])
|
1046
|
-
buttons.push([4, 'Button 4', SINGLE | DOUBLE | LONG])
|
1047
|
-
break
|
1048
|
-
default:
|
1049
|
-
break
|
1050
|
-
}
|
1051
|
-
break
|
1052
1062
|
case '_TZ3000_pzui3skt':
|
1053
1063
|
switch (this.model) {
|
1054
1064
|
case 'TS0041': // Tuya 1-button switch
|
@@ -1234,30 +1244,6 @@ class Resource {
|
|
1234
1244
|
break
|
1235
1245
|
}
|
1236
1246
|
break
|
1237
|
-
case 'ubisys':
|
1238
|
-
switch (this.model) {
|
1239
|
-
case 'C4 (5504)':
|
1240
|
-
case 'C4-R (5604)':
|
1241
|
-
buttons.push([1, '1', SINGLE | LONG])
|
1242
|
-
buttons.push([2, '2', SINGLE | LONG])
|
1243
|
-
buttons.push([3, '3', SINGLE | LONG])
|
1244
|
-
buttons.push([4, '4', SINGLE | LONG])
|
1245
|
-
break
|
1246
|
-
case 'D1 (5503)':
|
1247
|
-
case 'D1-R (5603)':
|
1248
|
-
case 'S1-R (5601)':
|
1249
|
-
case 'S2 (5502)':
|
1250
|
-
case 'S2-R (5602)':
|
1251
|
-
buttons.push([1, '1', SINGLE | LONG])
|
1252
|
-
buttons.push([2, '2', SINGLE | LONG])
|
1253
|
-
break
|
1254
|
-
case 'S1 (5501)':
|
1255
|
-
buttons.push([1, '1', SINGLE | LONG])
|
1256
|
-
break
|
1257
|
-
default:
|
1258
|
-
break
|
1259
|
-
}
|
1260
|
-
break
|
1261
1247
|
default:
|
1262
1248
|
if (this.body.type === 'ZHAAncillaryControl') {
|
1263
1249
|
buttons.push([1, 'Disarm', SINGLE])
|
@@ -1279,13 +1265,20 @@ class Resource {
|
|
1279
1265
|
for (const button of buttons) {
|
1280
1266
|
this.capabilities.buttons[button[0]] = {
|
1281
1267
|
label: button[1],
|
1282
|
-
events: button[2]
|
1283
|
-
|
1268
|
+
events: button[2]
|
1269
|
+
}
|
1270
|
+
if (button[3]) {
|
1271
|
+
this.capabilities.buttons[button[0]].hasRepeat = button[3]
|
1284
1272
|
}
|
1285
1273
|
}
|
1286
1274
|
this.capabilities.namespace = dots
|
1287
1275
|
? gateway.Characteristics.hap.ServiceLabelNamespace.DOTS
|
1288
1276
|
: gateway.Characteristics.hap.ServiceLabelNamespace.ARABIC_NUMERALS
|
1277
|
+
} else if (this.capabilities._buttons != null) {
|
1278
|
+
this.capabilities.buttons = this.capabilities._buttons
|
1279
|
+
this.capabilities.namespace = this.capabilities._namespace
|
1280
|
+
delete this.capabilities._buttons
|
1281
|
+
delete this.capabilities._namespace
|
1289
1282
|
}
|
1290
1283
|
}
|
1291
1284
|
|
@@ -1304,7 +1297,8 @@ class Resource {
|
|
1304
1297
|
patchThermostat () {
|
1305
1298
|
if (
|
1306
1299
|
(this.manufacturer === 'Danfoss' && ['eTRV0100', 'eTRV0103'].includes(this.model)) ||
|
1307
|
-
(this.manufacturer === 'ELKO' && this.model === 'Super TR')
|
1300
|
+
(this.manufacturer === 'ELKO' && this.model === 'Super TR') ||
|
1301
|
+
(this.manufacturer === 'LUMI' && this.model === 'lumi.airrtc.agl001')
|
1308
1302
|
) {
|
1309
1303
|
this.capabilities.heatValue = 'heat'
|
1310
1304
|
} else {
|
@@ -78,12 +78,12 @@ class Gateway extends AccessoryDelegate {
|
|
78
78
|
if (this.context.settingsById == null) {
|
79
79
|
this.context.settingsById = {}
|
80
80
|
}
|
81
|
-
if (this.context.fullState != null) {
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
}
|
81
|
+
// if (this.context.fullState != null) {
|
82
|
+
// this.analyseFullState(this.context.fullState, {
|
83
|
+
// analyseOnly: true,
|
84
|
+
// logUnsupported: true
|
85
|
+
// })
|
86
|
+
// }
|
87
87
|
|
88
88
|
this.addPropertyDelegate({
|
89
89
|
key: 'apiKey',
|
@@ -997,8 +997,22 @@ class Gateway extends AccessoryDelegate {
|
|
997
997
|
} catch (error) {
|
998
998
|
fullState.alarmsystems = {}
|
999
999
|
}
|
1000
|
+
// FIX_ME: use introspect until buttons and events are reported as capability
|
1001
|
+
fullState.introspectByRid = {}
|
1002
|
+
for (const rid in fullState.sensors) {
|
1003
|
+
const sensor = fullState.sensors[rid]
|
1004
|
+
if (sensor.type === 'ZHASwitch') {
|
1005
|
+
try {
|
1006
|
+
fullState.introspectByRid[rid] = await this.client.get(
|
1007
|
+
'/devices/' + sensor.uniqueid + '/state/buttonevent/introspect'
|
1008
|
+
)
|
1009
|
+
} catch (error) { }
|
1010
|
+
}
|
1011
|
+
}
|
1012
|
+
// End FIX_ME
|
1000
1013
|
this.context.fullState = fullState
|
1001
1014
|
this.pollFullState = false
|
1015
|
+
await this.analyseFullState(this.context.fullState, { logUnsupported: true })
|
1002
1016
|
} else {
|
1003
1017
|
const config = await this.client.get('/config')
|
1004
1018
|
if (config.bridgeid === this.id && config.UTC == null) {
|
@@ -1027,8 +1041,8 @@ class Gateway extends AccessoryDelegate {
|
|
1027
1041
|
if (this.values.exposeSchedules) {
|
1028
1042
|
this.context.fullState.schedules = await this.client.get('/schedules')
|
1029
1043
|
}
|
1044
|
+
await this.analyseFullState(this.context.fullState)
|
1030
1045
|
}
|
1031
|
-
await this.analyseFullState(this.context.fullState)
|
1032
1046
|
} catch (error) {
|
1033
1047
|
this.error('poll error: %s', error)
|
1034
1048
|
} finally {
|
@@ -1316,8 +1330,39 @@ class Gateway extends AccessoryDelegate {
|
|
1316
1330
|
const warn = (logUnsupported ? this.warn : this.vdebug).bind(this)
|
1317
1331
|
const debug = (logUnsupported ? this.debug : this.vdebug).bind(this)
|
1318
1332
|
|
1333
|
+
// FIX_ME: use introspect until buttons and events are reported as capability
|
1334
|
+
if (this.context.fullState.introspectByRid?.[rid] != null) {
|
1335
|
+
body.introspect = this.context.fullState.introspectByRid[rid]
|
1336
|
+
}
|
1337
|
+
// End FIX_ME
|
1319
1338
|
const resource = new Deconz.Resource(this, rtype, rid, body)
|
1320
1339
|
const { id, serviceName } = resource
|
1340
|
+
// FIX_ME: check introspect against whitelist
|
1341
|
+
if (logUnsupported && resource.body.type === 'ZHASwitch') {
|
1342
|
+
if (!resource.capabilities._introspect) {
|
1343
|
+
this.warn(
|
1344
|
+
'%s: /sensors/%d: %s by %s: no introspect',
|
1345
|
+
id, rid, resource.model, resource.manufacturer
|
1346
|
+
)
|
1347
|
+
}
|
1348
|
+
} else if (resource.capabilities._buttons != null) {
|
1349
|
+
if (
|
1350
|
+
JSON.stringify(resource.capabilities._buttons) !==
|
1351
|
+
JSON.stringify(resource.capabilities.buttons) ||
|
1352
|
+
resource.capabilities._namespace !== resource.capabilities.namespace
|
1353
|
+
) {
|
1354
|
+
this.debug(
|
1355
|
+
'%s: /sensors/%d: %s by %s: whitelist vs introspect mismatch: %j',
|
1356
|
+
id, rid, resource.model, resource.manufacturer, resource.capabilities
|
1357
|
+
)
|
1358
|
+
} else {
|
1359
|
+
this.warn(
|
1360
|
+
'%s: /sensors/%d: %s by %s: whitelist matches introspect',
|
1361
|
+
id, rid, resource.model, resource.manufacturer
|
1362
|
+
)
|
1363
|
+
}
|
1364
|
+
}
|
1365
|
+
// End FIX_ME
|
1321
1366
|
if (this.blacklist[rtype]?.[rid]) {
|
1322
1367
|
debug('%s: /%s/%d: ignoring blacklisted resource', id, rtype, rid)
|
1323
1368
|
return
|
package/lib/DeconzPlatform.js
CHANGED
@@ -253,11 +253,6 @@ class DeconzPlatform extends Platform {
|
|
253
253
|
) {
|
254
254
|
this.gatewayMap[id] = new DeconzAccessory.Gateway(this, context)
|
255
255
|
}
|
256
|
-
} else {
|
257
|
-
const gateway = this.gatewayMap[context.gid]
|
258
|
-
if (gateway != null) {
|
259
|
-
gateway.addAccessory(id)
|
260
|
-
}
|
261
256
|
}
|
262
257
|
} catch (error) { this.error(error) }
|
263
258
|
}
|
package/package.json
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
"ebaauw"
|
8
8
|
],
|
9
9
|
"license": "Apache-2.0",
|
10
|
-
"version": "1.
|
10
|
+
"version": "1.2.2",
|
11
11
|
"keywords": [
|
12
12
|
"homebridge-plugin",
|
13
13
|
"homekit",
|
@@ -26,13 +26,13 @@
|
|
26
26
|
"ui": "cli/ui.js"
|
27
27
|
},
|
28
28
|
"engines": {
|
29
|
-
"deCONZ": "2.
|
30
|
-
"homebridge": "^1.
|
31
|
-
"node": "^22||^20
|
29
|
+
"deCONZ": "2.30.2",
|
30
|
+
"homebridge": "^1.11.0||^2.0.0-beta",
|
31
|
+
"node": "^22||^20"
|
32
32
|
},
|
33
33
|
"dependencies": {
|
34
|
-
"hb-deconz-tools": "~2.0.
|
35
|
-
"homebridge-lib": "~7.1.
|
34
|
+
"hb-deconz-tools": "~2.0.14",
|
35
|
+
"homebridge-lib": "~7.1.7"
|
36
36
|
},
|
37
37
|
"scripts": {
|
38
38
|
"prepare": "standard && rm -rf out && jsdoc -c jsdoc.json",
|