@hoobs/hue
Version:
HOOBS plugin for Philips Hue and deCONZ
1,375 lines (1,357 loc) • 97.1 kB
JavaScript
// homebridge-hue/lib/HueSensor.js
// Copyright © 2016-2020 Erik Baauw. All rights reserved.
//
// Homebridge plugin for Philips Hue and/or deCONZ.
//
// HueSensor provides support for Philips Hue sensors.
'use strict'
const moment = require('moment')
// Link this module to HuePlatform.
module.exports = {
setHomebridge: setHomebridge,
HueSensor: HueSensor
}
function toInt (value, minValue, maxValue) {
const n = parseInt(value)
if (isNaN(n) || n < minValue) {
return minValue
}
if (n > maxValue) {
return maxValue
}
return n
}
const daylightEvents = {
100: { name: 'Solar Midnight', period: 'Night' },
110: { name: 'Astronomical Dawn', period: 'Astronomical Twilight' },
120: { name: 'Nautical Dawn', period: 'Nautical Twilight' },
130: { name: 'Dawn', period: 'Twilight' },
140: { name: 'Sunrise', period: 'Sunrise' },
150: { name: 'End Sunrise', period: 'Golden Hour' },
160: { name: 'End Golden Hour', period: 'Day' },
170: { name: 'Solar Noon', period: 'Day' },
180: { name: 'Start Golden Hour', period: 'Golden Hour' },
190: { name: 'Start Sunset', period: 'Sunset' },
200: { name: 'Sunset', period: 'Twilight' },
210: { name: 'Dusk', period: 'Nautical Twilight' },
220: { name: 'Nautical Dusk', period: 'Astronomical Twilight' },
230: { name: 'Astronomical Dusk', period: 'Night' }
}
const daylightPeriods = {
Night: { lightlevel: 0, daylight: false, dark: true },
'Astronomical Twilight': { lightlevel: 100, daylight: false, dark: true },
'Nautical Twilight': { lightlevel: 1000, daylight: false, dark: true },
Twilight: { lightlevel: 10000, daylight: false, dark: false },
Sunrise: { lightlevel: 15000, daylight: true, dark: false },
Sunset: { lightlevel: 20000, daylight: true, dark: false },
'Golden Hour': { lightlevel: 40000, daylight: true, dark: false },
Day: { lightlevel: 65535, daylight: true, dark: false }
}
// ===== Homebridge ============================================================
// Link this module to homebridge.
let Service
let Characteristic
let my
let eve
// let HistoryService
let SINGLE
let SINGLE_DOUBLE
let SINGLE_LONG
let SINGLE_DOUBLE_LONG
// let DOUBLE
let DOUBLE_LONG
let LONG
function setHomebridge (homebridge, _my, _eve) {
Service = homebridge.hap.Service
Characteristic = homebridge.hap.Characteristic
my = _my
eve = _eve
SINGLE = {
minValue: Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
maxValue: Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS
}
SINGLE_DOUBLE = {
minValue: Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
maxValue: Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS
}
SINGLE_LONG = {
minValue: Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
maxValue: Characteristic.ProgrammableSwitchEvent.LONG_PRESS,
validValues: [
Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
Characteristic.ProgrammableSwitchEvent.LONG_PRESS
]
}
SINGLE_DOUBLE_LONG = {
minValue: Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
maxValue: Characteristic.ProgrammableSwitchEvent.LONG_PRESS
}
// DOUBLE = {
// minValue: Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS,
// maxValue: Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS
// }
DOUBLE_LONG = {
minValue: Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS,
maxValue: Characteristic.ProgrammableSwitchEvent.LONG_PRESS
}
LONG = {
minValue: Characteristic.ProgrammableSwitchEvent.LONG_PRESS,
maxValue: Characteristic.ProgrammableSwitchEvent.LONG_PRESS
}
}
function hkLightLevel (v) {
let l = v ? Math.pow(10, (v - 1) / 10000) : 0.0001
l = Math.round(l * 10000) / 10000
return l > 100000 ? 100000 : l < 0.0001 ? 0.0001 : l
}
const PRESS = 0
const HOLD = 1
const SHORT_RELEASE = 2
const LONG_RELEASE = 3
const DOUBLE_PRESS = 4
const TRIPLE_PRESS = 5
const QUADRUPLE_PRESS = 6
const SHAKE = 7
const DROP = 8
// const TILT = 9
// As homebridge-hue polls the Hue bridge, not all dimmer switch buttonevents
// are received reliably. Consequently, we only issue one HomeKit change per
// Press/Hold/Release event series.
function hkZLLSwitchAction (value, oldValue, repeat = false) {
const button = Math.floor(value / 1000)
const oldButton = Math.floor(oldValue / 1000)
const event = value % 1000
const oldEvent = oldValue % 1000
switch (event) {
case PRESS:
// Wait for Hold or Release after press.
return null
case SHORT_RELEASE:
return Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS
case HOLD:
case LONG_RELEASE:
if (repeat) {
return Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS
}
if (button === oldButton && oldEvent === HOLD) {
// Already issued action on previous Hold.
return null
}
// falls through
case TRIPLE_PRESS:
case QUADRUPLE_PRESS:
return Characteristic.ProgrammableSwitchEvent.LONG_PRESS
case DOUBLE_PRESS:
case SHAKE:
case DROP:
return Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS
default:
return null
}
}
// ===== HueSensor =============================================================
function HueSensor (accessory, id, obj) {
this.accessory = accessory
this.id = id
this.obj = obj
this.bridge = this.accessory.bridge
this.log = this.accessory.log
this.serialNumber = this.accessory.serialNumber
this.name = this.obj.name
this.hk = {}
this.resource = '/sensors/' + id
this.serviceList = []
if (this.obj.type[0] === 'Z') {
// Zigbee sensor.
this.manufacturer = this.obj.manufacturername
this.model = this.obj.modelid
this.endpoint = this.obj.uniqueid.split('-')[1]
this.cluster = this.obj.uniqueid.split('-')[2]
this.subtype = this.endpoint + '-' + this.cluster
this.version = this.obj.swversion
} else {
// Hue bridge internal sensor.
this.manufacturer = this.bridge.manufacturername
if (this.accessory.isMulti) {
this.model = 'MultiCLIP'
this.subtype = this.id
} else if (
this.obj.manufacturername === 'homebridge-hue' &&
this.obj.modelid === this.obj.type &&
this.obj.uniqueid.split('-')[1] === this.id
) {
// Combine multiple CLIP sensors into one accessory.
this.model = 'MultiCLIP'
this.subtype = this.id
} else {
this.model = this.obj.type
}
this.version = this.bridge.version
}
this.infoService = this.accessory.getInfoService(this)
// See: http://www.developers.meethue.com/documentation/supported-sensors
let durationKey = 'duration'
switch (this.obj.type) {
case 'ZGPSwitch':
if (
this.obj.manufacturername === this.bridge.philips &&
this.obj.modelid === 'ZGPSWITCH'
) {
// 1.1 - Hue tap
this.createLabel(Characteristic.ServiceLabelNamespace.DOTS)
this.createButton(1, '1', SINGLE)
this.createButton(2, '2', SINGLE)
this.createButton(3, '3', SINGLE)
this.createButton(4, '4', SINGLE)
this.createButton(5, '1 and 2', SINGLE)
this.createButton(6, '3 and 4', SINGLE)
this.type = {
key: 'buttonevent',
homekitValue: function (v) {
return { 34: 1, 16: 2, 17: 3, 18: 4, 101: 5, 99: 6 }[v]
},
homekitAction: function () { return 0 }
}
} else if (
this.obj.manufacturername === 'PhilipsFoH' &&
this.obj.modelid === 'FOHSWITCH'
) {
// Friends of Hue switch
if (this.bridge.model === 'deCONZ') {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Top Left', SINGLE_LONG)
this.createButton(2, 'Bottom Left', SINGLE_LONG)
this.createButton(3, 'Top Right', SINGLE_LONG)
this.createButton(4, 'Bottom Right', SINGLE_LONG)
this.createButton(5, 'Top Both', SINGLE_LONG)
this.createButton(6, 'Bottom Both', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Top Left', SINGLE)
this.createButton(2, 'Bottom Left', SINGLE)
this.createButton(3, 'Top Right', SINGLE)
this.createButton(4, 'Bottom Right', SINGLE)
this.createButton(5, 'Top Both', SINGLE)
this.createButton(6, 'Bottom Both', SINGLE)
this.type = {
key: 'buttonevent',
homekitValue: function (v) {
return { 20: 1, 21: 2, 23: 3, 22: 4, 101: 5, 99: 6 }[v]
},
homekitAction: function () { return 0 }
}
}
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
break
case 'ZLLSwitch':
case 'ZHASwitch':
if (
this.obj.manufacturername === this.bridge.philips &&
(this.obj.modelid === 'RWL021' || this.obj.modelid === 'RWL020')
) {
// 1.2 - Hue wireless dimmer switch
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'On', SINGLE_LONG)
if (this.bridge.platform.config.hueDimmerRepeat) {
this.repeat = [2, 3]
this.createButton(2, 'Dim Up', SINGLE)
this.createButton(3, 'Dim Down', SINGLE)
} else {
this.createButton(2, 'Dim Up', SINGLE_LONG)
this.createButton(3, 'Dim Down', SINGLE_LONG)
}
this.createButton(4, 'Off', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === this.bridge.philips &&
this.obj.modelid === 'ROM001'
) {
// Hue smart button
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
if (this.bridge.platform.config.hueDimmerRepeat) {
this.repeat = [1]
this.createButton(1, 'Button', SINGLE)
} else {
this.createButton(1, 'Button', SINGLE_LONG)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'IKEA of Sweden' &&
this.obj.modelid === 'TRADFRI remote control'
) {
// Ikea Trådfri remote
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'On/Off', SINGLE)
this.createButton(2, 'Dim Up', SINGLE_LONG)
this.createButton(3, 'Dim Down', SINGLE_LONG)
this.createButton(4, 'Previous', SINGLE_LONG)
this.createButton(5, 'Next', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'IKEA of Sweden' &&
this.obj.modelid === 'TRADFRI wireless dimmer'
) {
// Ikea Trådfri dimmer
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'On', SINGLE)
this.createButton(2, 'Dim Up', SINGLE)
this.createButton(3, 'Dim Down', SINGLE)
this.createButton(4, 'Off', SINGLE)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'IKEA of Sweden' &&
this.obj.modelid === 'TRADFRI on/off switch'
) {
// Ikea Trådfri on/off switch
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'On', SINGLE_LONG)
this.createButton(2, 'Off', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'IKEA of Sweden' &&
this.obj.modelid === 'TRADFRI open/close remote'
) {
// Ikea Trådfri open/close remote
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Open', SINGLE_LONG)
this.createButton(2, 'Close', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'IKEA of Sweden' &&
this.obj.modelid === 'SYMFONISK Sound Controller'
) {
// Ikea Symfonisk sound controller
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Button', SINGLE_DOUBLE_LONG)
this.createButton(2, 'Turn Right', LONG)
this.createButton(3, 'Turn Left', LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'innr' &&
this.obj.modelid === 'RC 110'
) {
// innr RC 110 remote, exposed as multiple ZHASwitch resources
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
if (this.endpoint === '01') {
this.createButton(1, 'On/Off', SINGLE)
this.createButton(2, 'Dim Up', SINGLE_LONG)
this.createButton(3, 'Dim Down', SINGLE_LONG)
this.createButton(4, '1', SINGLE)
this.createButton(5, '2', SINGLE)
this.createButton(6, '3', SINGLE)
this.createButton(7, '4', SINGLE)
this.createButton(8, '5', SINGLE)
this.createButton(9, '6', SINGLE)
} else {
const light = parseInt(this.endpoint) - 2
const button = 7 + light * 3
this.createButton(button, `On/Off ${light}`, SINGLE)
this.createButton(button + 1, `Dim Up ${light}`, SINGLE_LONG)
this.createButton(button + 2, `Dim Down ${light}`, SINGLE_LONG)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'ubisys' &&
this.obj.modelid === 'S1 (5501)'
) {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, '1', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'ubisys' && (
this.obj.modelid === 'S1-R (5601)' ||
this.obj.modelid === 'S2 (5502)' ||
this.obj.modelid === 'S2-R (5602)' ||
this.obj.modelid === 'D1 (5503)' ||
this.obj.modelid === 'D1-R (5603)'
)
) {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, '1', SINGLE_LONG)
this.createButton(2, '2', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'ubisys' && (
this.obj.modelid === 'C4 (5504)' ||
this.obj.modelid === 'C4-R (5604)'
)
) {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, '1', SINGLE_LONG)
this.createButton(2, '2', SINGLE_LONG)
this.createButton(3, '3', SINGLE_LONG)
this.createButton(4, '4', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'dresden elektronik' &&
this.obj.modelid === 'Lighting Switch' && this.endpoint === '01'
) {
// dresden elektronik lighting switch
if (this.obj.mode !== 2) {
this.log.warn(
'%s: %s: warning: Lighting Switch mode %d instead of 2',
this.bridge.name, this.resource, this.obj.mode
)
}
this.createButton(1, 'Top Left', SINGLE_LONG)
this.createButton(2, 'Bottom Left', SINGLE_LONG)
this.createButton(3, 'Top Right', SINGLE_LONG)
this.createButton(4, 'Bottom Right', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'dresden elektronik' &&
this.obj.modelid === 'Scene Switch'
) {
// dresden elektronik scene switch
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'On', SINGLE_LONG)
this.createButton(2, 'Off', SINGLE_LONG)
this.createButton(3, 'Scene 1', SINGLE)
this.createButton(4, 'Scene 2', SINGLE)
this.createButton(5, 'Scene 3', SINGLE)
this.createButton(6, 'Scene 4', SINGLE)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'LUMI' &&
this.obj.modelid === 'lumi.sensor_86sw1'
) {
// Xiaomi wall switch (single button)
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Button', SINGLE_DOUBLE)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.sensor_switch' ||
this.obj.modelid === 'lumi.sensor_switch.aq2' ||
this.obj.modelid === 'lumi.sensor_switch.aq3'
)
) {
// Xiaomi Mi wireless switch
// Xiaomi Aqara smart wireless switch
// Xiaomi Aqara smart wireless switch with gyro
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Button', SINGLE_DOUBLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.sensor_86sw2' ||
this.obj.modelid === 'lumi.ctrl_ln2.aq1'
)
) {
// Xiaomi wall switch (two buttons)
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Left', SINGLE_DOUBLE)
this.createButton(2, 'Right', SINGLE_DOUBLE)
this.createButton(3, 'Both', SINGLE_DOUBLE)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.remote.b1acn01' ||
this.obj.modelid === 'lumi.remote.b186acn01'
)
) {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Left', SINGLE_DOUBLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'LUMI' &&
this.obj.modelid === 'lumi.remote.b286acn01'
) {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Left', SINGLE_DOUBLE_LONG)
this.createButton(2, 'Right', SINGLE_DOUBLE_LONG)
this.createButton(3, 'Both', SINGLE_DOUBLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'LUMI' &&
this.obj.modelid.startsWith('lumi.sensor_cube')
) {
// Xiaomi Mi smart cube
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
if (this.endpoint === '02') {
this.createButton(1, 'Side 1', SINGLE_DOUBLE_LONG)
this.createButton(2, 'Side 2', SINGLE_DOUBLE_LONG)
this.createButton(3, 'Side 3', SINGLE_DOUBLE_LONG)
this.createButton(4, 'Side 4', SINGLE_DOUBLE_LONG)
this.createButton(5, 'Side 5', SINGLE_DOUBLE_LONG)
this.createButton(6, 'Side 6', SINGLE_DOUBLE_LONG)
this.createButton(7, 'Cube', DOUBLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: function (v) {
if (v % 1000 === 0) {
return Characteristic.ProgrammableSwitchEvent.LONG_PRESS
} else if (v % 1000 === Math.floor(v / 1000) || v % 1000 === 8) {
return Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS
} else {
return Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS
}
}
}
} else if (this.endpoint === '03') {
this.createButton(8, 'Turn Right', SINGLE_DOUBLE_LONG)
this.createButton(9, 'Turn Left', SINGLE_DOUBLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return v > 0 ? 8 : 9 },
homekitAction: function (v) {
return Math.abs(v) < 4500
? Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS
: Math.abs(v) < 9000
? Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS
: Characteristic.ProgrammableSwitchEvent.LONG_PRESS
}
}
}
} else if (
this.obj.manufacturername === 'Insta' && (
this.obj.modelid === 'WS_3f_G_1' ||
this.obj.modelid === 'HS_4f_GJ_1' ||
this.obj.modelid === 'WS_4f_J_1'
)
) {
// Gira Light Link wall transmitter
// Gira/Jung Light Link hand transmitter
// Jung Light Link wall transmitter
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Off', SINGLE_DOUBLE_LONG)
this.createButton(2, 'On', SINGLE_DOUBLE_LONG)
this.createButton(3, 'Scene 1', SINGLE)
this.createButton(4, 'Scene 2', SINGLE)
this.createButton(5, 'Scene 3', SINGLE)
this.createButton(6, 'Scene 4', SINGLE)
if (this.obj.modelid !== 'WS_3f_G_1') {
this.createButton(7, 'Scene 5', SINGLE)
this.createButton(8, 'Scene 6', SINGLE)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'Busch-Jaeger' && (
this.obj.modelid === 'RM01' ||
this.obj.modelid === 'RB01'
)
) {
// Busch-Jaeger Light Link control element (mains-powered)
// Busch-Jaeger Light Link wall-mounted transmitter
// Exposed as multiple ZHASwitch resources?
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
if (this.endpoint === '0a') {
this.createButton(1, 'Button 1', SINGLE_LONG)
this.createButton(2, 'Button 2', SINGLE_LONG)
} else if (this.endpoint === '0b') {
this.createButton(3, 'Button 3', SINGLE_LONG)
this.createButton(4, 'Button 4', SINGLE_LONG)
} else if (this.endpoint === '0c') {
this.createButton(5, 'Button 5', SINGLE_LONG)
this.createButton(6, 'Button 6', SINGLE_LONG)
} else if (this.endpoint === '0d') {
this.createButton(7, 'Button 7', SINGLE_LONG)
this.createButton(8, 'Button 8', SINGLE_LONG)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'icasa' && (
this.obj.modelid === 'ICZB-KPD12' ||
this.obj.modelid === 'ICZB-KPD14S' ||
this.obj.modelid === 'ICZB-KPD18S'
)
) {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Off', SINGLE_LONG)
this.createButton(2, 'On', SINGLE_LONG)
if (this.obj.modelid !== 'ICZB-KPD12') {
this.createButton(3, 'S1', SINGLE)
this.createButton(4, 'S2', SINGLE)
if (this.obj.modelid === 'ICZB-KPD18S') {
this.createButton(5, 'S3', SINGLE)
this.createButton(6, 'S4', SINGLE)
this.createButton(7, 'S5', SINGLE)
this.createButton(8, 'S6', SINGLE)
}
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'Lutron' &&
this.obj.modelid === 'Z3-1BRL'
) {
// Lutron Aurora, see #522.
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
if (this.bridge.isHue) {
this.createButton(1, 'Button', SINGLE_LONG)
} else {
this.createButton(1, 'Button', SINGLE)
this.createButton(2, 'Turn Right', SINGLE)
this.createButton(3, 'Turn Left', SINGLE)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'Samjin' &&
this.obj.modelid === 'button'
) {
// Samsung SmartThings Button
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'Button', SINGLE_DOUBLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'Sunricher' &&
this.obj.modelid === 'ZG2833K8_EU05'
) {
// Sunricher 8-button remote, see #529.
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
if (this.endpoint === '01') {
this.createButton(1, 'On 1', SINGLE_LONG)
this.createButton(2, 'Off 1', SINGLE_LONG)
} else if (this.endpoint === '02') {
this.createButton(3, 'On 2', SINGLE_LONG)
this.createButton(4, 'Off 2', SINGLE_LONG)
} else if (this.endpoint === '03') {
this.createButton(5, 'On 3', SINGLE_LONG)
this.createButton(6, 'Off 3', SINGLE_LONG)
} else if (this.endpoint === '04') {
this.createButton(7, 'On 4', SINGLE_LONG)
this.createButton(8, 'Off 4', SINGLE_LONG)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'Sunricher' &&
this.obj.modelid === 'ZGRC-KEY-002'
) {
// Sunricher CCT remote, see #529.
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, 'On', SINGLE)
this.createButton(2, 'Off', SINGLE)
this.createButton(3, 'Dim', LONG)
this.createButton(4, 'C/W', SINGLE_LONG)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'Bitron Home' &&
this.obj.modelid === '902010/23'
) {
// Bitron remote, see #639.
this.createLabel(Characteristic.ServiceLabelNamespace.DOTS)
this.createButton(1, 'DimUp', SINGLE)
this.createButton(2, 'On', SINGLE)
this.createButton(3, 'Off', SINGLE)
this.createButton(4, 'DimDown', SINGLE)
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.remote.b286opcn01' ||
this.obj.modelid === 'lumi.remote.b486opcn01' ||
this.obj.modelid === 'lumi.remote.b686opcn01'
)
) {
// Xiaomi Aqara Opple, see #637.
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(1, '1', SINGLE_DOUBLE_LONG)
this.createButton(2, '2', SINGLE_DOUBLE_LONG)
if (this.obj.modelid !== 'lumi.remote.b286opcn01') {
this.createButton(3, '3', SINGLE_DOUBLE_LONG)
this.createButton(4, '4', SINGLE_DOUBLE_LONG)
}
if (this.obj.modelid === 'lumi.remote.b686opcn01') {
this.createButton(5, '5', SINGLE_DOUBLE_LONG)
this.createButton(6, '6', SINGLE_DOUBLE_LONG)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else if (
this.obj.manufacturername === 'icasa' &&
this.obj.modelid === 'ICZB-RM11S'
) {
// icasa remote, see deconz-rest-plugin#1978.
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
if (this.endpoint === '01') {
this.createButton(1, '1 Off', SINGLE_LONG)
this.createButton(2, '1 On', SINGLE_LONG)
this.createButton(9, 'S1', SINGLE)
this.createButton(10, 'S2', SINGLE)
} else if (this.endpoint === '02') {
this.createButton(3, '2 Off', SINGLE_LONG)
this.createButton(4, '2 On', SINGLE_LONG)
} else if (this.endpoint === '03') {
this.createButton(5, '3 Off', SINGLE_LONG)
this.createButton(6, '3 On', SINGLE_LONG)
} else if (this.endpoint === '04') {
this.createButton(7, '4 Off', SINGLE_LONG)
this.createButton(8, '4 On', SINGLE_LONG)
}
this.type = {
key: 'buttonevent',
homekitValue: function (v) { return Math.floor(v / 1000) },
homekitAction: hkZLLSwitchAction
}
} else {
this.log.warn(
'%s: %s: warning: ignoring unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
break
case 'ZLLRelativeRotary':
// Lutron Aurora, see #522.
if (
this.obj.manufacturername === 'Lutron' &&
this.obj.modelid === 'Z3-1BRL'
) {
this.createLabel(Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS)
this.createButton(2, 'Turn Right', SINGLE)
this.createButton(3, 'Turn Left', SINGLE)
this.type = {
key: 'expectedrotation',
homekitValue: function (v) { return v > 0 ? 2 : 3 },
homekitAction: function () {
return Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS
}
}
} else {
this.log.warn(
'%s: %s: warning: ignoring unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
break
case 'CLIPSwitch': // 2.1
// We'd need a way to specify the number of buttons, cf. max value for
// a CLIPGenericStatus sensor.
this.log.warn(
'%s: %s: warning: ignoring unsupported sensor type %s',
this.bridge.name, this.resource, this.obj.type
)
break
case 'ZLLPresence':
this.duration = 0
// falls through
case 'ZHAPresence':
if (
this.obj.manufacturername === this.bridge.philips &&
(this.obj.modelid === 'SML001' || this.obj.modelid === 'SML002')
) {
// 1.3 - Hue motion sensor
durationKey = 'delay'
} else if (
this.obj.manufacturername === 'IKEA of Sweden' &&
this.obj.modelid === 'TRADFRI motion sensor'
) {
// Ikea Trådfri motion sensor
this.obj.state.dark = false
} else if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.sensor_motion' ||
this.obj.modelid === 'lumi.sensor_motion.aq2'
)
) {
// Xiaomi motion sensor
// Xiaomi Aqara motion sensor
} else if (
this.obj.manufacturername === 'Heiman' &&
this.obj.modelid === 'PIR_TPV11'
) {
// Heiman motion sensor
} else if (
this.obj.manufacturername === 'SmartThings' &&
this.obj.modelid === 'tagv4'
) {
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPPresence': // 2.3
case 'Geofence': // Undocumented
this.service = new eve.Services.MotionSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.MotionDetected,
key: 'presence',
name: 'motion',
unit: '',
history: 'motion',
homekitValue: function (v) { return v ? 1 : 0 },
durationKey: durationKey,
sensitivitymax: this.obj.config.sensitivitymax
}
break
case 'ZLLTemperature':
case 'ZHATemperature':
if (
this.obj.manufacturername === this.bridge.philips &&
(this.obj.modelid === 'SML001' || this.obj.modelid === 'SML002')
) {
// 1.4 - Hue motion sensor
} else if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.weather' ||
this.obj.modelid === 'lumi.sensor_ht'
)
) {
// Xiaomi temperature/humidity sensor
// Xiaomi Aqara weather sensor
} else if (
this.obj.manufacturername === 'Heiman' &&
(this.obj.modelid === 'TH-H_V15' || this.obj.modelid === 'TH-T_V15')
) {
// Heiman temperature/humidity sensor
} else if (
this.obj.manufacturername === 'Samjin' &&
this.obj.modelid === 'button'
) {
// Samsung SmartThings Button temperature sensor
} else if (
this.obj.manufacturername === 'Samjin' &&
this.obj.modelid === 'multi'
) {
// Samsung SmartThings multipurpose sensor
} else if (
this.obj.manufacturername === 'Develco Products AS' && (
this.obj.modelid === 'SMSZB-120' ||
this.obj.modelid === 'HESZB-120'
)
) {
// Develco smoke sensor
// Develco heat sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPTemperature': // 2.4
this.service = new eve.Services.TemperatureSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.CurrentTemperature,
props: { minValue: -40.0, maxValue: 100.0 },
key: 'temperature',
name: 'temperature',
unit: '°C',
history: 'weather',
homekitValue: function (v) { return v ? Math.round(v / 10) / 10 : 0 }
}
break
case 'ZLLLightLevel': // 2.7 - Hue Motion Sensor
case 'ZHALightLevel':
if (
this.obj.manufacturername === this.bridge.philips &&
(this.obj.modelid === 'SML001' || this.obj.modelid === 'SML002')
) {
// 1.4 - Hue motion sensor
} else if (
this.obj.manufacturername === 'LUMI' &&
this.obj.modelid === 'lumi.sensor_motion.aq2'
) {
// Xiaomi Aqara motion sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPLightLevel': // 2.7
this.service = new Service.LightSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.CurrentAmbientLightLevel,
key: 'lightlevel',
name: 'light level',
unit: ' lux',
homekitValue: hkLightLevel
}
break
case 'ZHAOpenClose':
if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.sensor_magnet.aq2' ||
this.obj.modelid === 'lumi.sensor_magnet'
)
) {
// Xiaomi Aqara door/window sensor
// Xiaomi Mi door/window sensor
} else if (
this.obj.manufacturername === 'Heiman' &&
this.obj.modelid === 'DOOR_TPV13'
) {
// Heiman smart door sensor
} else if (
this.obj.manufacturername === 'Samjin' &&
this.obj.modelid === 'multi'
) {
// Samsung SmartThings multipurpose sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPOpenClose': // 2.2
this.service = new eve.Services.ContactSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.ContactSensorState,
key: 'open',
name: 'contact',
unit: '',
history: 'door',
homekitValue: function (v) { return v ? 1 : 0 }
}
break
case 'ZHAHumidity':
if (
this.obj.manufacturername === 'LUMI' && (
this.obj.modelid === 'lumi.weather' ||
this.obj.modelid === 'lumi.sensor_ht'
)
) {
// Xiaomi Aqara weather sensor
// Xiaomi Mi temperature/humidity sensor
} else if (
this.obj.manufacturername === 'Heiman' &&
(this.obj.modelid === 'TH-H_V15' || this.obj.modelid === 'TH-T_V15')
) {
// Heiman temperature/humidity sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPHumidity': // 2.5
this.service = new Service.HumiditySensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.CurrentRelativeHumidity,
key: 'humidity',
name: 'humidity',
unit: '%',
history: 'weather',
homekitValue: function (v) { return v ? Math.round(v / 100) : 0 }
}
break
case 'ZHAPressure':
if (
this.obj.manufacturername === 'LUMI' &&
this.obj.modelid === 'lumi.weather'
) {
// Xiaomi Aqara weather sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPPressure':
this.service = new eve.Services.AirPressureSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: eve.Characteristics.AirPressure,
key: 'pressure',
name: 'pressure',
unit: ' hPa',
history: 'weather',
homekitValue: function (v) { return v ? Math.round(v) : 0 }
}
this.service.updateCharacteristic(eve.Characteristics.Elevation, 0)
break
case 'ZHAAlarm':
if (
this.obj.manufacturername.toLowerCase() === 'heiman' &&
this.obj.modelid.startsWith('WarningDevice')
) {
// Heiman Siren
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPAlarm':
this.service = new my.Services.Resource(this.name, this.subtype)
this.service.addOptionalCharacteristic(my.Characteristics.Alarm)
this.serviceList.push(this.service)
this.type = {
Characteristic: my.Characteristics.Alarm,
key: 'alarm',
name: 'alarm',
homekitValue: function (v) { return v ? 1 : 0 }
}
break
case 'ZHACarbonMonoxide':
if (
this.obj.manufacturername === 'Heiman' &&
this.obj.modelid === 'CO_V16'
) {
// Heiman CO sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPCarbonMonoxide':
this.service = new Service.CarbonMonoxideSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.CarbonMonoxideDetected,
key: 'carbonmonoxide',
name: 'CO',
unit: '',
homekitValue: function (v) { return v ? 1 : 0 }
}
break
case 'ZHAFire':
if (
this.obj.manufacturername.toLowerCase() === 'heiman' && (
this.obj.modelid === 'SMOK_V16' ||
this.obj.modelid === 'GAS_V15' ||
this.obj.modelid === 'SmokeSensor-N-3.0' ||
this.obj.modelid === 'GASSensor-EM'
)
) {
// Heiman fire sensor
// Heiman gas sensor
} else if (
this.obj.manufacturername === 'Develco Products AS' && (
this.obj.modelid === 'SMSZB-120' ||
this.obj.modelid === 'HESZB-120'
)
) {
// Develco smoke sensor
// Develco heat sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPFire':
this.service = new Service.SmokeSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.SmokeDetected,
key: 'fire',
name: 'smoke',
unit: '',
homekitValue: function (v) { return v ? 1 : 0 }
}
break
case 'ZHAVibration':
if (
this.obj.manufacturername === 'LUMI' &&
this.obj.modelid === 'lumi.vibration.aq1'
) {
// Xiaomi vibration sensor
} else if (
this.obj.manufacturername === 'Samjin' &&
this.obj.modelid === 'multi'
) {
// Samsung SmartThings multipurpose sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPVibration':
this.service = new eve.Services.MotionSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.duration = 0
this.type = {
Characteristic: Characteristic.MotionDetected,
key: 'vibration',
name: 'motion',
unit: '',
history: 'motion',
homekitValue: function (v) { return v ? 1 : 0 },
sensitivitymax: this.obj.config.sensitivitymax
}
break
case 'ZHAWater':
if (
(
this.obj.manufacturername === 'LUMI' &&
this.obj.modelid === 'lumi.sensor_wleak.aq1'
) || (
this.obj.manufacturername === 'Heiman' &&
this.obj.modelid === 'WATER_TPV11'
)
) {
// Xiaomi Aqara flood sensor
// Heiman water sensor
} else {
this.log.warn(
'%s: %s: warning: unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
// falls through
case 'CLIPWater':
this.service = new Service.LeakSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.LeakDetected,
key: 'water',
name: 'leak',
unit: '',
homekitValue: function (v) { return v ? 1 : 0 }
}
break
case 'ZHAConsumption':
// falls through
case 'CLIPConsumption':
this.service = this.accessory.lightService == null
? new my.Services.Resource(this.name, this.subtype)
: this.accessory.lightService
this.serviceList.push(this.service)
this.service
.addOptionalCharacteristic(eve.Characteristics.TotalConsumption)
this.type = {
Characteristic: eve.Characteristics.TotalConsumption,
key: 'consumption',
name: 'total consumption',
unit: ' kWh',
history: 'energy',
homekitValue: function (v) { return v / 1000.0 }
}
break
case 'ZHAPower':
// falls through
case 'CLIPPower':
this.service = this.accessory.lightService == null
? new my.Services.Resource(this.name, this.subtype)
: this.accessory.lightService
this.serviceList.push(this.service)
this.service
.addOptionalCharacteristic(eve.Characteristics.CurrentConsumption)
this.type = {
Characteristic: eve.Characteristics.CurrentConsumption,
key: 'power',
name: 'current consumption',
unit: ' W',
history: 'energy',
homekitValue: function (v) { return v }
}
break
case 'ZHAThermostat':
// falls through
case 'CLIPThermostat':
this.service = new Service.Thermostat(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.CurrentTemperature,
// props: { minValue: -40.0, maxValue: 100.0 },
key: 'temperature',
name: 'temperature',
unit: '°C',
history: 'thermo',
homekitValue: function (v) { return v ? Math.round(v / 10) / 10 : 0 }
}
break
case 'Daylight':
if (
this.obj.manufacturername === this.bridge.philips &&
this.obj.modelid === 'PHDL00'
) {
// 2.6 - Built-in daylight sensor.
if (!this.obj.config.configured) {
this.log.warn(
'%s: %s: warning: %s sensor not configured',
this.bridge.name, this.resource, this.obj.type
)
}
this.manufacturer = this.obj.manufacturername
this.model = this.obj.modelid
this.service = new Service.LightSensor(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.CurrentAmbientLightLevel,
key: 'lightlevel',
name: 'light level',
unit: ' lux',
homekitValue: hkLightLevel
}
if (obj.state.status == null) {
// Hue bridge
obj.state.lightlevel = obj.state.daylight ? 65535 : 0
obj.state.dark = !obj.state.daylight
}
obj.config.reachable = obj.config.configured
} else {
this.log.warn(
'%s: %s: warning: ignoring unknown %s sensor %j',
this.bridge.name, this.resource, this.obj.type, this.obj
)
}
break
case 'ZHABattery':
case 'CLIPBattery':
this.service = this.accessory.getBatteryService(
this.obj.config.battery
)
// this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.BatteryLevel,
key: 'battery',
name: 'battery',
unit: '%',
homekitValue: function (v) { return toInt(v, 0, 100) }
}
break
case 'CLIPGenericFlag': // 2.8
this.service = new Service.Switch(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: Characteristic.On,
key: 'flag',
name: 'on',
unit: '',
homekitValue: function (v) { return v ? 1 : 0 },
bridgeValue: function (v) { return !!v },
setter: true
}
// Note that Eve handles a read-only switch correctly, but Home doesn't.
if (
this.obj.manufacturername === 'homebridge-hue' &&
this.obj.modelid === 'CLIPGenericFlag' &&
this.obj.swversion === '0'
) {
this.type.props = {
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
}
}
break
case 'CLIPGenericStatus': // 2.9
this.service = new my.Services.Status(this.name, this.subtype)
this.serviceList.push(this.service)
this.type = {
Characteristic: my.Characteristics.Status,
key: 'status',
name: 'status',