homebridge-deconz 0.1.9 → 0.1.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/cli/deconz.js +1 -4
- package/homebridge-ui/public/index.old.html +3 -5
- package/lib/Deconz/Resource.js +97 -298
- package/lib/DeconzAccessory/Gateway.js +66 -21
- package/lib/DeconzAccessory/Light.js +11 -11
- package/lib/DeconzAccessory/Sensor.js +23 -18
- package/lib/DeconzAccessory/index.js +31 -38
- package/lib/DeconzService/AirQuality.js +60 -29
- package/lib/DeconzService/Consumption.js +5 -5
- package/lib/DeconzService/Humidity.js +3 -0
- package/lib/DeconzService/Label.js +103 -0
- package/lib/DeconzService/Light.js +76 -71
- package/lib/DeconzService/Outlet.js +1 -1
- package/lib/DeconzService/Power.js +6 -5
- package/lib/DeconzService/Status.js +25 -1
- package/lib/DeconzService/Switch.js +43 -78
- package/lib/DeconzService/index.js +1 -0
- package/package.json +5 -5
package/cli/deconz.js
CHANGED
@@ -514,10 +514,7 @@ class Main extends CommandLineTool {
|
|
514
514
|
|
515
515
|
this.bridgeid = this.gatewayConfig.bridgeid
|
516
516
|
if (this.clargs.options.apiKey == null) {
|
517
|
-
if (
|
518
|
-
this.gateways[this.bridgeid] != null &&
|
519
|
-
this.gateways[this.bridgeid].apiKey != null
|
520
|
-
) {
|
517
|
+
if (this.gateways[this.bridgeid]?.apiKey != null) {
|
521
518
|
this.clargs.options.apiKey = this.gateways[this.bridgeid].apiKey
|
522
519
|
} else if (process.env.DECONZ_API_KEY != null) {
|
523
520
|
this.clargs.options.apiKey = process.env.DECONZ_API_KEY
|
@@ -32,8 +32,7 @@ async function showFormPluginConfig () {
|
|
32
32
|
console.log('%s: cachedAccessories: %o', config.name, cachedAccessories)
|
33
33
|
const cachedGateways = cachedAccessories.filter((accessory) => {
|
34
34
|
return accessory.plugin === 'homebridge-deconz' &&
|
35
|
-
accessory.context
|
36
|
-
accessory.context.className === 'Gateway'
|
35
|
+
accessory.context?.className === 'Gateway'
|
37
36
|
})
|
38
37
|
const result = {}
|
39
38
|
for (const gateway of cachedGateways) {
|
@@ -207,8 +206,7 @@ async function showFormGateways (gateway) {
|
|
207
206
|
const cachedAccessories = await homebridge.getCachedAccessories()
|
208
207
|
const cachedGateways = cachedAccessories.filter((accessory) => {
|
209
208
|
return accessory.plugin === 'homebridge-deconz' &&
|
210
|
-
accessory.context
|
211
|
-
accessory.context.className === 'Gateway'
|
209
|
+
accessory.context?.className === 'Gateway'
|
212
210
|
})
|
213
211
|
const result = {}
|
214
212
|
for (const gateway of cachedGateways) {
|
@@ -249,7 +247,7 @@ async function showFormGateways (gateway) {
|
|
249
247
|
// layout: null,
|
250
248
|
// form: null
|
251
249
|
// }, {
|
252
|
-
// gateway: gateway
|
250
|
+
// gateway: gateway ?? gateways[0]
|
253
251
|
// }, 'Gateway Settings', 'Homebridge Settings')
|
254
252
|
const form = homebridge.createForm({
|
255
253
|
footerDisplay: 'For a detailed description, see the [wiki](https://github.com/ebaauw/homebridge-deconz/wiki/Configuration).',
|
package/lib/Deconz/Resource.js
CHANGED
@@ -5,13 +5,12 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const {
|
8
|
+
const { OptionParser } = require('homebridge-lib')
|
9
9
|
const Deconz = require('../Deconz')
|
10
10
|
const DeconzAccessory = require('../DeconzAccessory')
|
11
11
|
const DeconzService = require('../DeconzService')
|
12
12
|
|
13
13
|
const { toInstance, toInt, toObject, toString } = OptionParser
|
14
|
-
const { defaultGamut } = Colour
|
15
14
|
const { buttonEvent } = Deconz.ApiClient
|
16
15
|
const { SINGLE, DOUBLE, LONG } = DeconzService.Button
|
17
16
|
const rtypes = ['lights', 'sensors', 'groups']
|
@@ -30,51 +29,6 @@ const sensorsPrios = [
|
|
30
29
|
|
31
30
|
// =============================================================================
|
32
31
|
|
33
|
-
// See: http://www.developers.meethue.com/documentation/supported-lights
|
34
|
-
|
35
|
-
const hueGamutType = { // Color gamut per light model.
|
36
|
-
A: { // Color Lights
|
37
|
-
r: [0.7040, 0.2960],
|
38
|
-
g: [0.2151, 0.7106],
|
39
|
-
b: [0.1380, 0.0800]
|
40
|
-
},
|
41
|
-
B: { // Extended Color Lights
|
42
|
-
r: [0.6750, 0.3220],
|
43
|
-
g: [0.4090, 0.5180],
|
44
|
-
b: [0.1670, 0.0400]
|
45
|
-
},
|
46
|
-
C: { // next gen Extended Color Lights
|
47
|
-
r: [0.6920, 0.3080],
|
48
|
-
g: [0.1700, 0.7000],
|
49
|
-
b: [0.1530, 0.0480]
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
const hueGamutTypeByModel = {
|
54
|
-
LCT001: 'B', // Hue bulb A19
|
55
|
-
LCT002: 'B', // Hue Spot BR30
|
56
|
-
LCT003: 'B', // Hue Spot GU10
|
57
|
-
LCT007: 'B', // Hue bulb A19
|
58
|
-
LCT010: 'C', // Hue bulb A19
|
59
|
-
LCT011: 'C', // Hue BR30
|
60
|
-
LCT012: 'C', // Hue Color Candle
|
61
|
-
LCT014: 'C', // Hue bulb A19
|
62
|
-
LCT015: 'C', // Hue bulb A19
|
63
|
-
LCT016: 'C', // Hue bulb A19
|
64
|
-
LLC005: 'A', // Living Colors Gen3 Bloom, Aura
|
65
|
-
LLC006: 'A', // Living Colors Gen3 Iris
|
66
|
-
LLC007: 'A', // Living Colors Gen3 Bloom, Aura
|
67
|
-
LLC010: 'A', // Hue Living Colors Iris
|
68
|
-
LLC011: 'A', // Hue Living Colors Bloom
|
69
|
-
LLC012: 'A', // Hue Living Colors Bloom
|
70
|
-
LLC013: 'A', // Disney Living Colors
|
71
|
-
LLC014: 'A', // Living Colors Gen3 Bloom, Aura
|
72
|
-
LLC020: 'C', // Hue Go
|
73
|
-
LLM001: 'B', // Color Light Module
|
74
|
-
LST001: 'A', // Hue LightStrips
|
75
|
-
LST002: 'C' // Hue LightStrips Plus
|
76
|
-
}
|
77
|
-
|
78
32
|
const hueTapMap = {
|
79
33
|
34: 1002, // press 1
|
80
34
|
16: 2002, // press 2
|
@@ -99,9 +53,9 @@ class Resource {
|
|
99
53
|
toString('uniqueid', uniqueid, true)
|
100
54
|
const a = uniqueid.replace(/:/g, '').toUpperCase().split('-')
|
101
55
|
return {
|
102
|
-
mac: a
|
103
|
-
endpoint: a
|
104
|
-
cluster: a
|
56
|
+
mac: a?.[0],
|
57
|
+
endpoint: a?.[1],
|
58
|
+
cluster: a?.[2]
|
105
59
|
}
|
106
60
|
}
|
107
61
|
|
@@ -175,6 +129,11 @@ class Resource {
|
|
175
129
|
* @type {boolean}
|
176
130
|
*/
|
177
131
|
this.zigbee = true
|
132
|
+
} else if (this.isDeconzClip()) {
|
133
|
+
const a = body.uniqueid.split('-')
|
134
|
+
this.id = gateway.id + '-M' + a?.[0]
|
135
|
+
this.subtype = a?.[1]
|
136
|
+
this.zigbee = false
|
178
137
|
} else {
|
179
138
|
this.subtype = rtype[0].toUpperCase() + rid
|
180
139
|
this.id = gateway.id + '-' + this.subtype
|
@@ -211,60 +170,16 @@ class Resource {
|
|
211
170
|
? body.swversion == null ? '0.0.0' : body.swversion
|
212
171
|
: gateway.values.software
|
213
172
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
ctMax: (body.ctmax != null && body.ctmax !== 0 && body.ctmax !== 65535)
|
225
|
-
? body.ctmax
|
226
|
-
: 500,
|
227
|
-
ctMin: (body.ctmin != null && body.ctmin !== 0)
|
228
|
-
? body.ctmin
|
229
|
-
: 153,
|
230
|
-
xy: body.state.xy !== undefined,
|
231
|
-
gamut: defaultGamut,
|
232
|
-
alert: body.state.alert !== undefined,
|
233
|
-
colorLoop: body.state.effect !== undefined
|
234
|
-
}
|
235
|
-
if (body.capabilities != null) {
|
236
|
-
const cap = body.capabilities
|
237
|
-
if (cap.color != null) {
|
238
|
-
if (cap.color.ct != null) {
|
239
|
-
this.capabilities.ctMax = cap.color.ct.max
|
240
|
-
this.capabilities.ctMin = cap.color.ct.min
|
241
|
-
}
|
242
|
-
if (cap.color.effects != null && cap.color.effects.length > 2) {
|
243
|
-
this.capabilities.effects = cap.color.effects.slice(2).map((effect) => {
|
244
|
-
return effect[0].toUpperCase() + effect.slice(1)
|
245
|
-
})
|
246
|
-
}
|
247
|
-
if (cap.color.xy != null) {
|
248
|
-
this.capabilities.gamut = {
|
249
|
-
r: cap.color.xy.red,
|
250
|
-
g: cap.color.xy.green,
|
251
|
-
b: cap.color.xy.blue
|
252
|
-
}
|
253
|
-
}
|
254
|
-
}
|
255
|
-
}
|
256
|
-
break
|
257
|
-
}
|
258
|
-
case 'WarningDevice':
|
259
|
-
this.capabilities = {}
|
260
|
-
break
|
261
|
-
case 'WindowCovering':
|
262
|
-
this.capabilities = {}
|
263
|
-
break
|
264
|
-
default:
|
265
|
-
this.capabilities = {}
|
266
|
-
break
|
267
|
-
}
|
173
|
+
/** The name of the {@link DeconzService} subclass of the delegate of the
|
174
|
+
* corresponding HomeKit service, or `null` for unsupported and unknown
|
175
|
+
* resources.
|
176
|
+
*
|
177
|
+
* This is derived from the resource type and `type` in the resource body.
|
178
|
+
* @type {string}
|
179
|
+
*/
|
180
|
+
this.serviceName = this._serviceName
|
181
|
+
|
182
|
+
this.capabilities = {}
|
268
183
|
|
269
184
|
const f = 'patch' + this.serviceName
|
270
185
|
if (typeof this[f] === 'function') {
|
@@ -277,8 +192,12 @@ class Resource {
|
|
277
192
|
* @type {integer}
|
278
193
|
*/
|
279
194
|
get prio () {
|
280
|
-
if (this.rtype === 'groups')
|
281
|
-
|
195
|
+
if (this.rtype === 'groups') {
|
196
|
+
return -1
|
197
|
+
}
|
198
|
+
if (this.rtype === 'lights' || this.isDeconzClip()) {
|
199
|
+
return 0xFF - this.endpoint
|
200
|
+
}
|
282
201
|
return sensorsPrios.indexOf(this.serviceName)
|
283
202
|
}
|
284
203
|
|
@@ -289,14 +208,7 @@ class Resource {
|
|
289
208
|
*/
|
290
209
|
get rpath () { return '/' + this.rtype + '/' + this.rid }
|
291
210
|
|
292
|
-
|
293
|
-
* corresponding HomeKit service, or `null` for unsupported and unknown
|
294
|
-
* resources.
|
295
|
-
*
|
296
|
-
* This is derived from the resource type and `type` in the resource body.
|
297
|
-
* @type {string}
|
298
|
-
*/
|
299
|
-
get serviceName () {
|
211
|
+
get _serviceName () {
|
300
212
|
if (this.rtype === 'groups') {
|
301
213
|
return 'Light'
|
302
214
|
} else if (this.rtype === 'lights') {
|
@@ -314,11 +226,11 @@ class Resource {
|
|
314
226
|
// case 'Door Lock': return null
|
315
227
|
// case 'Door Lock Unit': return null
|
316
228
|
case 'Fan': return 'Light'
|
317
|
-
case 'On/Off light switch': return '
|
229
|
+
case 'On/Off light switch': return 'Switch'
|
318
230
|
case 'On/Off light': return 'Light'
|
319
|
-
case 'On/Off output': return '
|
320
|
-
case 'On/Off plug-in unit': return '
|
321
|
-
case 'Smart plug': return '
|
231
|
+
case 'On/Off output': return 'Outlet'
|
232
|
+
case 'On/Off plug-in unit': return 'Outlet'
|
233
|
+
case 'Smart plug': return 'Outlet'
|
322
234
|
case 'Configuration tool': return ''
|
323
235
|
case 'Range extender': return ''
|
324
236
|
case 'Warning device': return 'WarningDevice'
|
@@ -327,55 +239,34 @@ class Resource {
|
|
327
239
|
default: return null
|
328
240
|
}
|
329
241
|
} else { // (this.rtype === 'sensors')
|
330
|
-
|
331
|
-
|
332
|
-
case '
|
333
|
-
case '
|
334
|
-
case '
|
335
|
-
case '
|
336
|
-
case '
|
337
|
-
case '
|
338
|
-
case '
|
339
|
-
case 'ZHACarbonMonoxide':
|
340
|
-
case 'CLIPCarbonMonoxide': return 'CarbonMonoxide'
|
341
|
-
case 'ZHAConsumption':
|
342
|
-
case 'CLIPConsumption': return 'Consumption'
|
343
|
-
// case 'ZHADoorLock':
|
344
|
-
// case 'CLIPDoorLock': return null
|
242
|
+
const type = /^(CLIP|ZHA|ZGP)?([A-Za-z]*)$/.exec(this.body.type)?.[2]
|
243
|
+
switch (type) {
|
244
|
+
case 'AirPurifier': return 'AirPurifier'
|
245
|
+
case 'AirQuality': return 'AirQuality'
|
246
|
+
case 'Alarm': return 'Alarm'
|
247
|
+
case 'Battery': return 'Battery'
|
248
|
+
case 'CarbonMonoxide': return 'CarbonMonoxide'
|
249
|
+
case 'Consumption': return 'Consumption'
|
250
|
+
// case 'DoorLock': return null
|
345
251
|
case 'Daylight': return 'Daylight'
|
346
|
-
case '
|
347
|
-
case '
|
348
|
-
case '
|
349
|
-
case '
|
350
|
-
case '
|
351
|
-
case '
|
352
|
-
case '
|
353
|
-
case '
|
354
|
-
|
355
|
-
|
356
|
-
case '
|
357
|
-
case '
|
358
|
-
case '
|
359
|
-
case '
|
360
|
-
case '
|
361
|
-
case '
|
362
|
-
case '
|
363
|
-
case '
|
364
|
-
case 'ZHARelativeRotary': return 'Switch'
|
365
|
-
case 'ZHASpectral': return ''
|
366
|
-
case 'ZGPSwitch':
|
367
|
-
case 'ZHASwitch':
|
368
|
-
case 'CLIPSwitch': return 'Switch'
|
369
|
-
case 'ZHATemperature':
|
370
|
-
case 'CLIPTemperature': return 'Temperature'
|
371
|
-
case 'ZHAThermostat':
|
372
|
-
case 'CLIPThermostat': return 'Thermostat'
|
373
|
-
case 'ZHATime':
|
374
|
-
case 'CLIPTime': return ''
|
375
|
-
case 'ZHAVibration':
|
376
|
-
case 'CLIPVibration': return 'Motion'
|
377
|
-
case 'ZHAWater':
|
378
|
-
case 'CLIPWater': return 'Leak'
|
252
|
+
case 'Fire': return 'Smoke'
|
253
|
+
case 'GenericFlag': return 'Flag'
|
254
|
+
case 'GenericStatus': return 'Status'
|
255
|
+
case 'Humidity': return 'Humidity'
|
256
|
+
case 'LightLevel': return 'LightLevel'
|
257
|
+
case 'Moisture': return 'Humidity'
|
258
|
+
case 'OpenClose': return 'Contact'
|
259
|
+
case 'Power': return 'Power'
|
260
|
+
case 'Presence': return 'Motion'
|
261
|
+
case 'Pressure': return 'AirPressure'
|
262
|
+
case 'RelativeRotary': return 'Label'
|
263
|
+
case 'Spectral': return ''
|
264
|
+
case 'Switch': return 'Label'
|
265
|
+
case 'Temperature': return 'Temperature'
|
266
|
+
case 'Thermostat': return 'Thermostat'
|
267
|
+
case 'Time': return ''
|
268
|
+
case 'Vibration': return 'Motion'
|
269
|
+
case 'Water': return 'Leak'
|
379
270
|
default: return null
|
380
271
|
}
|
381
272
|
}
|
@@ -386,34 +277,7 @@ class Resource {
|
|
386
277
|
*/
|
387
278
|
patchLight (gateway) {
|
388
279
|
switch (this.manufacturer) {
|
389
|
-
case 'Busch-Jaeger':
|
390
|
-
// See: https://www.busch-jaeger.de/en/products/product-solutions/dimmer/busch-radio-controlled-dimmer-zigbee-light-link/
|
391
|
-
if (
|
392
|
-
this.model === 'RM01' && // 6715 U-500 with 6736-84.
|
393
|
-
this.capabilities.bri && this.body.type === 'On/Off light' // Issue #241
|
394
|
-
) {
|
395
|
-
gateway.vdebug(
|
396
|
-
'%s: ignoring state.bri for %s', this.rpath, this.body.type
|
397
|
-
)
|
398
|
-
this.capabilities.bri = false
|
399
|
-
}
|
400
|
-
break
|
401
|
-
case 'dresden elektronik':
|
402
|
-
// See: https://www.dresden-elektronik.de/funktechnik/solutions/wireless-light-control/wireless-ballasts/?L=1
|
403
|
-
this.capabilities.computesXy = true
|
404
|
-
break
|
405
|
-
case 'FeiBit':
|
406
|
-
if (this.model === 'FNB56-SKT1EHG1.2') { // issue #361
|
407
|
-
this.body.type = 'On/Off plug-in unit'
|
408
|
-
}
|
409
|
-
break
|
410
280
|
case 'GLEDOPTO':
|
411
|
-
// See: https://www.led-trading.de/zigbee-kompatibel-controller-led-lichtsteuerung
|
412
|
-
this.capabilities.gamut = {
|
413
|
-
r: [0.7006, 0.2993],
|
414
|
-
g: [0.1387, 0.8148],
|
415
|
-
b: [0.1510, 0.0227]
|
416
|
-
}
|
417
281
|
if (this.model === 'GLEDOPTO') { // Issue #244
|
418
282
|
if (
|
419
283
|
this.endpoint === '0A' &&
|
@@ -444,37 +308,6 @@ class Resource {
|
|
444
308
|
gateway.vdebug('%s: set model to %j', this.rpath, this.model)
|
445
309
|
}
|
446
310
|
break
|
447
|
-
case 'IKEA of Sweden':
|
448
|
-
// See: http://www.ikea.com/us/en/catalog/categories/departments/lighting/smart_lighting/
|
449
|
-
this.capabilities.gamut = defaultGamut // Issue #956
|
450
|
-
this.capabilities.noTransition = true
|
451
|
-
if (this.model === 'TRADFRI bulb E27 CWS 806lm') {
|
452
|
-
this.capabilities.computesXy = true
|
453
|
-
this.capabilities.gamut = {
|
454
|
-
r: [0.68, 0.31],
|
455
|
-
g: [0.11, 0.82],
|
456
|
-
b: [0.13, 0.04]
|
457
|
-
}
|
458
|
-
}
|
459
|
-
break
|
460
|
-
case 'innr':
|
461
|
-
// See: https://shop.innrlighting.com/en/shop
|
462
|
-
this.capabilities.gamut = { // Issue #152
|
463
|
-
r: [0.8817, 0.1033],
|
464
|
-
g: [0.2204, 0.7758],
|
465
|
-
b: [0.0551, 0.1940]
|
466
|
-
}
|
467
|
-
if (this.model === 'SP 120') { // smart plug
|
468
|
-
this.capabilities.bri = false
|
469
|
-
}
|
470
|
-
break
|
471
|
-
case 'LEDVANCE':
|
472
|
-
this.capabilities.gamut = {
|
473
|
-
r: [0.6972, 0.3027],
|
474
|
-
g: [0.1737, 0.6991],
|
475
|
-
b: [0.1227, 0.0959]
|
476
|
-
}
|
477
|
-
break
|
478
311
|
case 'LIDL Livarno Lux':
|
479
312
|
this.capabilities.ctMax = 454 // 2200 K
|
480
313
|
this.capabilities.ctMin = 153 // 6500 K
|
@@ -489,98 +322,53 @@ class Resource {
|
|
489
322
|
]
|
490
323
|
}
|
491
324
|
break
|
492
|
-
case 'MLI': // Issue #439
|
493
|
-
this.capabilities.gamut = {
|
494
|
-
r: [0.68, 0.31],
|
495
|
-
g: [0.11, 0.82],
|
496
|
-
b: [0.13, 0.04]
|
497
|
-
}
|
498
|
-
if (this.capabilities.colorLoop) {
|
499
|
-
this.capabilities.effects = [
|
500
|
-
'Sunset', 'Party', 'Worklight', 'Campfire', 'Romance', 'Nightlight'
|
501
|
-
]
|
502
|
-
}
|
503
|
-
break
|
504
|
-
case 'OSRAM':
|
505
|
-
this.capabilities.gamut = {
|
506
|
-
r: [0.6850, 0.3149],
|
507
|
-
g: [0.1780, 0.7253],
|
508
|
-
b: [0.1241, 0.0578]
|
509
|
-
}
|
510
|
-
break
|
511
|
-
case 'Philips':
|
512
|
-
case 'Signify Netherlands B.V.':
|
513
|
-
// See: http://www.developers.meethue.com/documentation/supported-lights
|
514
|
-
this.manufacturer = 'Signify Netherlands B.V.'
|
515
|
-
this.capabilities.breathe = true
|
516
|
-
this.capabilities.computesXy = true
|
517
|
-
if (this.body.capabilities == null) {
|
518
|
-
const gamut = hueGamutTypeByModel[this.model] || 'C'
|
519
|
-
this.capabilities.gamut = hueGamutType[gamut]
|
520
|
-
}
|
521
|
-
break
|
522
325
|
default:
|
523
326
|
break
|
524
327
|
}
|
525
328
|
}
|
526
329
|
|
330
|
+
/** Check whether resource is a CLIP sensor for Homebridge deCONZ.
|
331
|
+
* For these, we use the following conventions:
|
332
|
+
* - Use `uniqueid` to indicate device ID and subtype;
|
333
|
+
* - Use `swversion` to indicate readonly and range for `Flag` and `Status`.
|
334
|
+
*/
|
335
|
+
isDeconzClip () {
|
336
|
+
return this.rtype === 'sensors' &&
|
337
|
+
this.body.type.startsWith('CLIP') &&
|
338
|
+
this.body.modelid === this.body.type && (
|
339
|
+
this.body.manufacturername === 'homebridge-deconz' ||
|
340
|
+
this.body.manufacturername === 'homebridge-hue'
|
341
|
+
)
|
342
|
+
}
|
343
|
+
|
527
344
|
/** Patch a resource corresponding to a `Flag` service.
|
528
|
-
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
529
345
|
*/
|
530
|
-
patchFlag (
|
531
|
-
if (
|
532
|
-
this.body.manufacturername === 'homebridge-hue' &&
|
533
|
-
this.body.modelid === 'CLIPGenericFlag' &&
|
534
|
-
this.body.swversion === '0'
|
535
|
-
) {
|
346
|
+
patchFlag () {
|
347
|
+
if (this.isDeconzClip() && this.body.swversion === '0') {
|
536
348
|
this.capabilities.readonly = true
|
537
349
|
}
|
538
350
|
}
|
539
351
|
|
540
|
-
/** Patch a resource corresponding to a `
|
541
|
-
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
352
|
+
/** Patch a resource corresponding to a `Status` service.
|
542
353
|
*/
|
543
|
-
patchStatus (
|
544
|
-
if (
|
545
|
-
this.body.manufacturername === 'homebridge-hue' &&
|
546
|
-
this.body.modelid === 'CLIPGenericStatus'
|
547
|
-
) {
|
354
|
+
patchStatus () {
|
355
|
+
if (this.isDeconzClip()) {
|
548
356
|
const a = this.body.swversion.split(',')
|
549
357
|
const min = parseInt(a[0])
|
550
358
|
const max = parseInt(a[1])
|
551
|
-
const step = parseInt(a[2])
|
552
|
-
// Eve 3.1 displays the following controls, depending on the properties:
|
553
|
-
// 1. {minValue: 0, maxValue: 1, minStep: 1} switch
|
554
|
-
// 2. {minValue: a, maxValue: b, minStep: 1}, 1 < b - a <= 20 down|up
|
555
|
-
// 3. {minValue: a, maxValue: b}, (a, b) != (0, 1) slider
|
556
|
-
// 4. {minValue: a, maxValue: b, minStep: 1}, b - a > 20 slider
|
557
|
-
// Avoid the following bugs:
|
558
|
-
// 5. {minValue: 0, maxValue: 1} nothing
|
559
|
-
// 6. {minValue: a, maxValue: b, minStep: 1}, b - a = 1 switch*
|
560
|
-
// *) switch sends values 0 and 1 instead of a and b;
|
561
359
|
if (min === 0 && max === 0) {
|
562
360
|
this.capabilities.readonly = true
|
563
361
|
} else if (min >= -127 && max <= 127 && min < max) {
|
564
|
-
|
565
|
-
|
566
|
-
this.capabilities.props = { minValue: min, maxValue: max, minStep: 1 }
|
567
|
-
} else if (max - min === 1) {
|
568
|
-
// Workaround Eve bug (case 6 above).
|
569
|
-
this.capabilities.props = { minValue: min, maxValue: max }
|
570
|
-
} else if (step !== 1) {
|
571
|
-
// Default to slider for backwards compatibility.
|
572
|
-
this.capabilities.props = { minValue: min, maxValue: max }
|
573
|
-
} else {
|
574
|
-
this.capabilities.props = { minValue: min, maxValue: max, minStep: 1 }
|
575
|
-
}
|
362
|
+
this.capabilities.min = min
|
363
|
+
this.capabilities.max = max
|
576
364
|
}
|
577
365
|
}
|
578
366
|
}
|
579
367
|
|
580
|
-
/** Patch a resource corresponding to a `
|
368
|
+
/** Patch a resource corresponding to a `Label` service.
|
581
369
|
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
582
370
|
*/
|
583
|
-
|
371
|
+
patchLabel (gateway) {
|
584
372
|
const buttons = []
|
585
373
|
let dots = false
|
586
374
|
switch (this.manufacturer) {
|
@@ -671,6 +459,15 @@ class Resource {
|
|
671
459
|
buttons.push([3, 'Turn Left', SINGLE])
|
672
460
|
}
|
673
461
|
break
|
462
|
+
case 'SYMFONISK sound remote gen2':
|
463
|
+
buttons.push([1, 'Play', SINGLE])
|
464
|
+
buttons.push([2, 'Plus', SINGLE | LONG, true])
|
465
|
+
buttons.push([3, 'Minus', SINGLE | LONG, true])
|
466
|
+
buttons.push([4, 'Previous', SINGLE])
|
467
|
+
buttons.push([5, 'Next', SINGLE])
|
468
|
+
buttons.push([6, 'One Dot', SINGLE | DOUBLE | LONG])
|
469
|
+
buttons.push([7, 'Two Dots', SINGLE | DOUBLE | LONG])
|
470
|
+
break
|
674
471
|
case 'TRADFRI SHORTCUT Button':
|
675
472
|
buttons.push([1, 'Button', SINGLE | DOUBLE | LONG])
|
676
473
|
break
|
@@ -784,12 +581,16 @@ class Resource {
|
|
784
581
|
}
|
785
582
|
}
|
786
583
|
break
|
787
|
-
case 'lumi.sensor_86sw1': // Xiaomi wall switch (single button)
|
788
584
|
case 'lumi.ctrl_ln1.aq1':
|
585
|
+
case 'lumi.sensor_86sw1': // Xiaomi wall switch (single button).
|
586
|
+
case 'lumi.switch.l1aeu1': // Xiaomi Aqara H1, see #1149.
|
587
|
+
case 'lumi.switch.n1aeu1': // Xiaomi Aqara H1, see #1149.
|
789
588
|
buttons.push([1, 'Button', SINGLE | DOUBLE])
|
790
589
|
break
|
791
|
-
case 'lumi.sensor_86sw2': // Xiaomi wall switch (two buttons)
|
792
590
|
case 'lumi.ctrl_ln2.aq1':
|
591
|
+
case 'lumi.sensor_86sw2': // Xiaomi wall switch (two buttons).
|
592
|
+
case 'lumi.switch.l2aeu1': // Xiaomi Aqara H2, see #1149.
|
593
|
+
case 'lumi.switch.n2aeu1': // Xiaomi Aqara H2, see #1149.
|
793
594
|
buttons.push([1, 'Left', SINGLE | DOUBLE])
|
794
595
|
buttons.push([2, 'Right', SINGLE | DOUBLE])
|
795
596
|
buttons.push([3, 'Both', SINGLE | DOUBLE])
|
@@ -1255,9 +1056,8 @@ class Resource {
|
|
1255
1056
|
}
|
1256
1057
|
|
1257
1058
|
/** Patch a resource corresponding to a `Thermostat` service.
|
1258
|
-
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
1259
1059
|
*/
|
1260
|
-
patchThermostat (
|
1060
|
+
patchThermostat () {
|
1261
1061
|
if (this.manufacturer === 'ELKO' && this.model === 'Super TR') {
|
1262
1062
|
this.capabilities.heatValue = 'heat'
|
1263
1063
|
} else {
|
@@ -1266,9 +1066,8 @@ class Resource {
|
|
1266
1066
|
}
|
1267
1067
|
|
1268
1068
|
/** Patch a resource corresponding to a `WindowCovering` service.
|
1269
|
-
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
1270
1069
|
*/
|
1271
|
-
patchWindowCovering (
|
1070
|
+
patchWindowCovering () {
|
1272
1071
|
if (this.manufacturer === 'LUMI' && this.model === 'lumi.curtain.acn002') {
|
1273
1072
|
this.capabilities.maxSpeed = 2
|
1274
1073
|
this.capabilities.positionChange = true
|