@homebridge-plugins/homebridge-ewelink 12.3.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 +1363 -0
- package/LICENSE +21 -0
- package/README.md +68 -0
- package/config.schema.json +1757 -0
- package/eslint.config.js +15 -0
- package/lib/connection/api.js +508 -0
- package/lib/connection/http.js +304 -0
- package/lib/connection/lan.js +318 -0
- package/lib/connection/ws.js +414 -0
- package/lib/device/curtain.js +324 -0
- package/lib/device/diffuser.js +473 -0
- package/lib/device/fan.js +349 -0
- package/lib/device/group.js +106 -0
- package/lib/device/humidifier.js +199 -0
- package/lib/device/index.js +61 -0
- package/lib/device/light-cct.js +333 -0
- package/lib/device/light-dimmer.js +257 -0
- package/lib/device/light-rgb-cct.js +809 -0
- package/lib/device/light-rgb.js +272 -0
- package/lib/device/motor.js +363 -0
- package/lib/device/outlet-multi.js +417 -0
- package/lib/device/outlet-single-inched.js +409 -0
- package/lib/device/outlet-single.js +384 -0
- package/lib/device/panel.js +382 -0
- package/lib/device/rf-bridge.js +321 -0
- package/lib/device/rf-button.js +125 -0
- package/lib/device/rf-sensor.js +173 -0
- package/lib/device/sensor-ambient.js +311 -0
- package/lib/device/sensor-contact.js +140 -0
- package/lib/device/sensor-temp-humi.js +182 -0
- package/lib/device/simulation/blind.js +253 -0
- package/lib/device/simulation/cooler.js +312 -0
- package/lib/device/simulation/door.js +253 -0
- package/lib/device/simulation/doorbell.js +190 -0
- package/lib/device/simulation/garage-eachen.js +235 -0
- package/lib/device/simulation/garage-four.js +176 -0
- package/lib/device/simulation/garage-od-switch.js +36 -0
- package/lib/device/simulation/garage-one.js +395 -0
- package/lib/device/simulation/garage-two.js +394 -0
- package/lib/device/simulation/gate-one.js +327 -0
- package/lib/device/simulation/heater.js +389 -0
- package/lib/device/simulation/index.js +75 -0
- package/lib/device/simulation/light-fan.js +258 -0
- package/lib/device/simulation/lock-eachen.js +163 -0
- package/lib/device/simulation/lock-one.js +366 -0
- package/lib/device/simulation/p-button.js +223 -0
- package/lib/device/simulation/purifier.js +289 -0
- package/lib/device/simulation/rf-blind.js +192 -0
- package/lib/device/simulation/rf-door.js +180 -0
- package/lib/device/simulation/rf-window.js +180 -0
- package/lib/device/simulation/sensor-hidden.js +105 -0
- package/lib/device/simulation/sensor-leak.js +123 -0
- package/lib/device/simulation/sensor-visible.js +231 -0
- package/lib/device/simulation/sensor.js +300 -0
- package/lib/device/simulation/switch-valve.js +351 -0
- package/lib/device/simulation/tap-one.js +283 -0
- package/lib/device/simulation/tap-two.js +266 -0
- package/lib/device/simulation/th-cooler.js +443 -0
- package/lib/device/simulation/th-dehumidifier.js +424 -0
- package/lib/device/simulation/th-heater.js +449 -0
- package/lib/device/simulation/th-humidifier.js +424 -0
- package/lib/device/simulation/th-thermostat.js +611 -0
- package/lib/device/simulation/tv.js +252 -0
- package/lib/device/simulation/valve-four.js +232 -0
- package/lib/device/simulation/valve-one.js +345 -0
- package/lib/device/simulation/valve-two.js +340 -0
- package/lib/device/simulation/window.js +253 -0
- package/lib/device/switch-man.js +106 -0
- package/lib/device/switch-mate.js +82 -0
- package/lib/device/switch-multi.js +411 -0
- package/lib/device/switch-single-inched.js +332 -0
- package/lib/device/switch-single.js +307 -0
- package/lib/device/template.js +43 -0
- package/lib/device/thermostat.js +286 -0
- package/lib/device/zigbee/index.js +27 -0
- package/lib/device/zigbee/light-cct.js +263 -0
- package/lib/device/zigbee/light-dimmer.js +148 -0
- package/lib/device/zigbee/light-rgb-cct.js +400 -0
- package/lib/device/zigbee/motor.js +301 -0
- package/lib/device/zigbee/sensor-ambient.js +177 -0
- package/lib/device/zigbee/sensor-contact.js +137 -0
- package/lib/device/zigbee/sensor-leak.js +119 -0
- package/lib/device/zigbee/sensor-motion.js +119 -0
- package/lib/device/zigbee/sensor-occupancy.js +119 -0
- package/lib/device/zigbee/sensor-smoke.js +96 -0
- package/lib/device/zigbee/switch-stateless.js +104 -0
- package/lib/device/zigbee/thermostat.js +323 -0
- package/lib/fakegato/LICENSE +21 -0
- package/lib/fakegato/fakegato-history.js +813 -0
- package/lib/fakegato/fakegato-storage.js +108 -0
- package/lib/fakegato/fakegato-timer.js +125 -0
- package/lib/fakegato/uuid.js +27 -0
- package/lib/homebridge-ui/public/index.html +365 -0
- package/lib/homebridge-ui/server.js +46 -0
- package/lib/index.js +7 -0
- package/lib/node-dns-sd/LICENSE +21 -0
- package/lib/node-dns-sd/README.md +613 -0
- package/lib/node-dns-sd/lib/dns-sd-classes.json +6 -0
- package/lib/node-dns-sd/lib/dns-sd-composer.js +83 -0
- package/lib/node-dns-sd/lib/dns-sd-parser.js +344 -0
- package/lib/node-dns-sd/lib/dns-sd-types.json +52 -0
- package/lib/node-dns-sd/lib/dns-sd.js +580 -0
- package/lib/platform.js +2156 -0
- package/lib/utils/colour.js +552 -0
- package/lib/utils/constants.js +589 -0
- package/lib/utils/custom-chars.js +33 -0
- package/lib/utils/eve-chars.js +130 -0
- package/lib/utils/functions.js +42 -0
- package/lib/utils/lang-en.js +160 -0
- package/lib/utils/lang-fr.js +163 -0
- package/lib/utils/lang-th.js +160 -0
- package/lib/utils/lang.js +5 -0
- package/package.json +75 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import deviceCurtain from './curtain.js'
|
|
2
|
+
import deviceDiffuser from './diffuser.js'
|
|
3
|
+
import deviceFan from './fan.js'
|
|
4
|
+
import deviceGroup from './group.js'
|
|
5
|
+
import deviceHumidifier from './humidifier.js'
|
|
6
|
+
import deviceLightCCT from './light-cct.js'
|
|
7
|
+
import deviceLightDimmer from './light-dimmer.js'
|
|
8
|
+
import deviceLightRGB from './light-rgb.js'
|
|
9
|
+
import deviceLightRGBCCT from './light-rgb-cct.js'
|
|
10
|
+
import deviceMotor from './motor.js'
|
|
11
|
+
import deviceOutletMulti from './outlet-multi.js'
|
|
12
|
+
import deviceOutletSingle from './outlet-single.js'
|
|
13
|
+
import deviceOutletSingleInched from './outlet-single-inched.js'
|
|
14
|
+
import devicePanel from './panel.js'
|
|
15
|
+
import deviceRfBridge from './rf-bridge.js'
|
|
16
|
+
import deviceRfButton from './rf-button.js'
|
|
17
|
+
import deviceRfSensor from './rf-sensor.js'
|
|
18
|
+
import deviceSensorAmbient from './sensor-ambient.js'
|
|
19
|
+
import deviceSensorContact from './sensor-contact.js'
|
|
20
|
+
import deviceSensorTempHumi from './sensor-temp-humi.js'
|
|
21
|
+
import sim from './simulation/index.js'
|
|
22
|
+
import deviceSwitchMan from './switch-man.js'
|
|
23
|
+
import deviceSwitchMate from './switch-mate.js'
|
|
24
|
+
import deviceSwitchMulti from './switch-multi.js'
|
|
25
|
+
import deviceSwitchSingle from './switch-single.js'
|
|
26
|
+
import deviceSwitchSingleInched from './switch-single-inched.js'
|
|
27
|
+
import deviceTemplate from './template.js'
|
|
28
|
+
import deviceThermostat from './thermostat.js'
|
|
29
|
+
import zb from './zigbee/index.js'
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
deviceCurtain,
|
|
33
|
+
deviceDiffuser,
|
|
34
|
+
deviceFan,
|
|
35
|
+
deviceGroup,
|
|
36
|
+
deviceHumidifier,
|
|
37
|
+
deviceLightCCT,
|
|
38
|
+
deviceLightDimmer,
|
|
39
|
+
deviceLightRGB,
|
|
40
|
+
deviceLightRGBCCT,
|
|
41
|
+
deviceMotor,
|
|
42
|
+
deviceOutletMulti,
|
|
43
|
+
deviceOutletSingle,
|
|
44
|
+
deviceOutletSingleInched,
|
|
45
|
+
devicePanel,
|
|
46
|
+
deviceRfBridge,
|
|
47
|
+
deviceRfButton,
|
|
48
|
+
deviceRfSensor,
|
|
49
|
+
deviceSensorAmbient,
|
|
50
|
+
deviceSensorContact,
|
|
51
|
+
deviceSensorTempHumi,
|
|
52
|
+
deviceSwitchMan,
|
|
53
|
+
deviceSwitchMate,
|
|
54
|
+
deviceSwitchMulti,
|
|
55
|
+
deviceSwitchSingle,
|
|
56
|
+
deviceSwitchSingleInched,
|
|
57
|
+
deviceTemplate,
|
|
58
|
+
deviceThermostat,
|
|
59
|
+
sim,
|
|
60
|
+
zb,
|
|
61
|
+
}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import platformConsts from '../utils/constants.js'
|
|
2
|
+
import { generateRandomString, hasProperty, sleep } from '../utils/functions.js'
|
|
3
|
+
|
|
4
|
+
export default class {
|
|
5
|
+
constructor(platform, accessory) {
|
|
6
|
+
// Set up variables from the platform
|
|
7
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
8
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
9
|
+
this.hapServ = platform.api.hap.Service
|
|
10
|
+
this.lang = platform.lang
|
|
11
|
+
this.log = platform.log
|
|
12
|
+
this.platform = platform
|
|
13
|
+
|
|
14
|
+
// Set up variables from the accessory
|
|
15
|
+
this.name = accessory.displayName
|
|
16
|
+
this.accessory = accessory
|
|
17
|
+
|
|
18
|
+
// Initially set the online flag as true (to be then updated as false if necessary)
|
|
19
|
+
this.isOnline = true
|
|
20
|
+
|
|
21
|
+
// Set up custom variables for this device type
|
|
22
|
+
const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
|
|
23
|
+
this.deviceModel = deviceConf.deviceModel || 'bulbB02FA60'
|
|
24
|
+
this.alShift = deviceConf.adaptiveLightingShift || platformConsts.defaultValues.adaptiveLightingShift
|
|
25
|
+
this.brightStep = deviceConf.brightnessStep
|
|
26
|
+
? Math.min(deviceConf.brightnessStep, 100)
|
|
27
|
+
: platformConsts.defaultValues.brightnessStep
|
|
28
|
+
this.offlineAsOff = deviceConf.offlineAsOff
|
|
29
|
+
|
|
30
|
+
// Set the correct logging variables for this accessory
|
|
31
|
+
switch (deviceConf.overrideLogging) {
|
|
32
|
+
case 'standard':
|
|
33
|
+
this.enableLogging = true
|
|
34
|
+
this.enableDebugLogging = false
|
|
35
|
+
break
|
|
36
|
+
case 'debug':
|
|
37
|
+
this.enableLogging = true
|
|
38
|
+
this.enableDebugLogging = true
|
|
39
|
+
break
|
|
40
|
+
case 'disable':
|
|
41
|
+
this.enableLogging = false
|
|
42
|
+
this.enableDebugLogging = false
|
|
43
|
+
break
|
|
44
|
+
default:
|
|
45
|
+
this.enableLogging = !platform.config.disableDeviceLogging
|
|
46
|
+
this.enableDebugLogging = platform.config.debug
|
|
47
|
+
break
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Different bulbs have different colour temperature ranges
|
|
51
|
+
switch (this.deviceModel) {
|
|
52
|
+
case 'bulbB02FST64':
|
|
53
|
+
this.minK = 1800
|
|
54
|
+
this.maxK = 5000
|
|
55
|
+
break
|
|
56
|
+
case 'bulbB02BA60':
|
|
57
|
+
this.minK = 2700
|
|
58
|
+
this.maxK = 6500
|
|
59
|
+
break
|
|
60
|
+
default:
|
|
61
|
+
this.minK = 2200
|
|
62
|
+
this.maxK = 6500
|
|
63
|
+
break
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Add the lightbulb service if it doesn't already exist
|
|
67
|
+
this.service = this.accessory.getService(this.hapServ.Lightbulb)
|
|
68
|
+
|| this.accessory.addService(this.hapServ.Lightbulb)
|
|
69
|
+
|
|
70
|
+
// If adaptive lighting has just been disabled then remove and re-add service to hide AL icon
|
|
71
|
+
if (this.alShift === -1 && this.accessory.context.adaptiveLighting) {
|
|
72
|
+
this.accessory.removeService(this.service)
|
|
73
|
+
this.service = this.accessory.addService(this.hapServ.Lightbulb)
|
|
74
|
+
this.accessory.context.adaptiveLighting = false
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Add the set handler to the lightbulb on/off characteristic
|
|
78
|
+
this.service
|
|
79
|
+
.getCharacteristic(this.hapChar.On)
|
|
80
|
+
.onSet(async value => this.internalStateUpdate(value))
|
|
81
|
+
|
|
82
|
+
// Add the set handler to the lightbulb brightness characteristic
|
|
83
|
+
this.service
|
|
84
|
+
.getCharacteristic(this.hapChar.Brightness)
|
|
85
|
+
.setProps({ minStep: this.brightStep })
|
|
86
|
+
.onSet(async value => this.internalBrightnessUpdate(value))
|
|
87
|
+
|
|
88
|
+
// Add the set handler to the lightbulb colour temperature characteristic
|
|
89
|
+
this.service
|
|
90
|
+
.getCharacteristic(this.hapChar.ColorTemperature)
|
|
91
|
+
.onSet(async value => this.internalCTUpdate(value))
|
|
92
|
+
|
|
93
|
+
// This is needed as sometimes we need to send the brightness with a cct update
|
|
94
|
+
this.cacheBright = this.service.getCharacteristic(this.hapChar.Brightness).value
|
|
95
|
+
|
|
96
|
+
// Set up the adaptive lighting controller if not disabled by user
|
|
97
|
+
if (this.alShift !== -1) {
|
|
98
|
+
this.accessory.alController = new platform.api.hap.AdaptiveLightingController(this.service, {
|
|
99
|
+
customTemperatureAdjustment: this.alShift,
|
|
100
|
+
})
|
|
101
|
+
this.accessory.configureController(this.accessory.alController)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Add the get handlers only if the user hasn't disabled the disableNoResponse setting
|
|
105
|
+
if (!platform.config.disableNoResponse) {
|
|
106
|
+
this.service.getCharacteristic(this.hapChar.On).onGet(() => {
|
|
107
|
+
if (!this.isOnline) {
|
|
108
|
+
throw new this.hapErr(-70402)
|
|
109
|
+
}
|
|
110
|
+
return this.service.getCharacteristic(this.hapChar.On).value
|
|
111
|
+
})
|
|
112
|
+
this.service.getCharacteristic(this.hapChar.Brightness).onGet(() => {
|
|
113
|
+
if (!this.isOnline) {
|
|
114
|
+
throw new this.hapErr(-70402)
|
|
115
|
+
}
|
|
116
|
+
return this.service.getCharacteristic(this.hapChar.Brightness).value
|
|
117
|
+
})
|
|
118
|
+
this.service.getCharacteristic(this.hapChar.ColorTemperature).onGet(() => {
|
|
119
|
+
if (!this.isOnline) {
|
|
120
|
+
throw new this.hapErr(-70402)
|
|
121
|
+
}
|
|
122
|
+
return this.service.getCharacteristic(this.hapChar.ColorTemperature).value
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Output the customised options to the log
|
|
127
|
+
const normalLogging = this.enableLogging ? 'standard' : 'disable'
|
|
128
|
+
const opts = JSON.stringify({
|
|
129
|
+
adaptiveLightingShift: this.alShift,
|
|
130
|
+
brightnessStep: this.brightStep,
|
|
131
|
+
deviceModel: this.deviceModel,
|
|
132
|
+
logging: this.enableDebugLogging ? 'debug' : normalLogging,
|
|
133
|
+
offlineAsOff: !!this.offlineAsOff,
|
|
134
|
+
})
|
|
135
|
+
this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async internalStateUpdate(value) {
|
|
139
|
+
try {
|
|
140
|
+
const newValue = value ? 'on' : 'off'
|
|
141
|
+
if (this.cacheState === newValue) {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
const timerKey = generateRandomString(5)
|
|
145
|
+
this.updateTimeout = timerKey
|
|
146
|
+
setTimeout(() => {
|
|
147
|
+
if (this.updateTimeout === timerKey) {
|
|
148
|
+
this.updateTimeout = false
|
|
149
|
+
}
|
|
150
|
+
}, 5000)
|
|
151
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
152
|
+
switch: newValue,
|
|
153
|
+
})
|
|
154
|
+
this.cacheState = newValue
|
|
155
|
+
if (this.enableLogging) {
|
|
156
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
|
|
157
|
+
}
|
|
158
|
+
} catch (err) {
|
|
159
|
+
this.platform.deviceUpdateError(this.accessory, err, true)
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
162
|
+
}, 2000)
|
|
163
|
+
throw new this.hapErr(-70402)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async internalBrightnessUpdate(value) {
|
|
168
|
+
try {
|
|
169
|
+
if (this.cacheBright === value) {
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
const updateKey = generateRandomString(5)
|
|
173
|
+
this.updateKeyBright = updateKey
|
|
174
|
+
await sleep(500)
|
|
175
|
+
if (updateKey !== this.updateKeyBright) {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
this.updateTimeout = updateKey
|
|
179
|
+
setTimeout(() => {
|
|
180
|
+
if (this.updateTimeout === updateKey) {
|
|
181
|
+
this.updateTimeout = false
|
|
182
|
+
}
|
|
183
|
+
}, 5000)
|
|
184
|
+
const params = {
|
|
185
|
+
white: {
|
|
186
|
+
br: value,
|
|
187
|
+
ct: this.cacheCT,
|
|
188
|
+
},
|
|
189
|
+
}
|
|
190
|
+
await this.platform.sendDeviceUpdate(this.accessory, params)
|
|
191
|
+
this.cacheBright = value
|
|
192
|
+
if (this.enableLogging) {
|
|
193
|
+
this.log('[%s] %s [%s%].', this.name, this.lang.curBright, this.cacheBright)
|
|
194
|
+
}
|
|
195
|
+
} catch (err) {
|
|
196
|
+
this.platform.deviceUpdateError(this.accessory, err, true)
|
|
197
|
+
setTimeout(() => {
|
|
198
|
+
this.service.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
|
|
199
|
+
}, 2000)
|
|
200
|
+
throw new this.hapErr(-70402)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async internalCTUpdate(value) {
|
|
205
|
+
try {
|
|
206
|
+
if (this.cacheMired === value) {
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
if (
|
|
210
|
+
this.accessory.alController
|
|
211
|
+
&& this.accessory.alController.isAdaptiveLightingActive()
|
|
212
|
+
&& (this.cacheState !== 'on' || !this.isOnline)
|
|
213
|
+
) {
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
const updateKey = generateRandomString(5)
|
|
217
|
+
this.updateKeyCT = updateKey
|
|
218
|
+
await sleep(400)
|
|
219
|
+
if (updateKey !== this.updateKeyCT) {
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
this.updateTimeout = updateKey
|
|
223
|
+
setTimeout(() => {
|
|
224
|
+
if (this.updateTimeout === updateKey) {
|
|
225
|
+
this.updateTimeout = false
|
|
226
|
+
}
|
|
227
|
+
}, 5000)
|
|
228
|
+
const kelvin = Math.round(1000000 / value)
|
|
229
|
+
const scaledK = Math.max(Math.min(kelvin, this.maxK), this.minK)
|
|
230
|
+
const scaledCT = Math.round(((scaledK - this.minK) / (this.maxK - this.minK)) * 255)
|
|
231
|
+
const params = {
|
|
232
|
+
white: {
|
|
233
|
+
br: this.cacheBright,
|
|
234
|
+
ct: scaledCT,
|
|
235
|
+
},
|
|
236
|
+
}
|
|
237
|
+
await this.platform.sendDeviceUpdate(this.accessory, params)
|
|
238
|
+
this.cacheMired = value
|
|
239
|
+
this.cacheCT = scaledCT
|
|
240
|
+
if (this.enableLogging) {
|
|
241
|
+
if (this.accessory.alController && this.accessory.alController.isAdaptiveLightingActive()) {
|
|
242
|
+
this.log('[%s] %s [%sK] %s.', this.name, this.lang.curColour, scaledK, this.lang.viaAL)
|
|
243
|
+
} else {
|
|
244
|
+
this.log('[%s] %s [%sK].', this.name, this.lang.curColour, scaledK)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
} catch (err) {
|
|
248
|
+
this.platform.deviceUpdateError(this.accessory, err, true)
|
|
249
|
+
setTimeout(() => {
|
|
250
|
+
this.service.updateCharacteristic(this.hapChar.ColorTemperature, this.cacheMired)
|
|
251
|
+
}, 2000)
|
|
252
|
+
throw new this.hapErr(-70402)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async externalUpdate(params) {
|
|
257
|
+
try {
|
|
258
|
+
if (this.updateTimeout) {
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
if (params.switch && params.switch !== this.cacheState) {
|
|
262
|
+
this.cacheState = params.switch
|
|
263
|
+
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
264
|
+
if (params.updateSource && this.enableLogging) {
|
|
265
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (params.white) {
|
|
269
|
+
if (hasProperty(params.white, 'br') && this.cacheBright !== params.white.br) {
|
|
270
|
+
this.cacheBright = params.white.br
|
|
271
|
+
this.service.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
|
|
272
|
+
if (params.updateSource && this.enableLogging) {
|
|
273
|
+
this.log('[%s] %s [%s%].', this.name, this.lang.curBright, this.cacheBright)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (hasProperty(params.white, 'ct') && this.cacheCT !== params.white.ct) {
|
|
277
|
+
const ctDiff = Math.abs(params.white.ct - this.cacheCT)
|
|
278
|
+
this.cacheCT = params.white.ct
|
|
279
|
+
const kelvin = (this.cacheCT / 255) * (this.maxK - this.minK) + this.minK
|
|
280
|
+
const scaledK = Math.round(kelvin)
|
|
281
|
+
this.cacheMired = Math.min(Math.max(Math.round(1000000 / scaledK), 140), 500)
|
|
282
|
+
this.service.updateCharacteristic(this.hapChar.ColorTemperature, this.cacheMired)
|
|
283
|
+
if (params.updateSource) {
|
|
284
|
+
if (this.enableLogging) {
|
|
285
|
+
this.log('[%s] %s [%sK].', this.name, this.lang.curColour, scaledK)
|
|
286
|
+
}
|
|
287
|
+
if (
|
|
288
|
+
this.accessory.alController
|
|
289
|
+
&& this.accessory.alController.isAdaptiveLightingActive()
|
|
290
|
+
&& ctDiff > 20
|
|
291
|
+
) {
|
|
292
|
+
// Look for a variation greater than twenty
|
|
293
|
+
this.accessory.alController.disableAdaptiveLighting()
|
|
294
|
+
if (this.enableLogging) {
|
|
295
|
+
this.log('[%s] %s.', this.name, this.lang.disabledAL)
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
} catch (err) {
|
|
302
|
+
this.platform.deviceUpdateError(this.accessory, err, false)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
markStatus(isOnline) {
|
|
307
|
+
this.isOnline = isOnline
|
|
308
|
+
|
|
309
|
+
// Show as off if offlineAsOff is enabled
|
|
310
|
+
if (this.offlineAsOff && !isOnline && this.cacheState !== 'off') {
|
|
311
|
+
this.service.updateCharacteristic(this.hapChar.On, false)
|
|
312
|
+
this.cacheState = 'off'
|
|
313
|
+
if (this.enableLogging) {
|
|
314
|
+
this.log('[%s] %s [%s - offline]', this.name, this.lang.curState, this.cacheState)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
currentState() {
|
|
320
|
+
const toReturn = {}
|
|
321
|
+
toReturn.services = ['light']
|
|
322
|
+
toReturn.light = {
|
|
323
|
+
state: this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off',
|
|
324
|
+
brightness: this.service.getCharacteristic(this.hapChar.Brightness).value,
|
|
325
|
+
colourtemperature: this.service.getCharacteristic(this.hapChar.ColorTemperature).value,
|
|
326
|
+
adaptivelighting:
|
|
327
|
+
this.accessory.alController && this.accessory.alController.isAdaptiveLightingActive()
|
|
328
|
+
? 'on'
|
|
329
|
+
: 'off',
|
|
330
|
+
}
|
|
331
|
+
return toReturn
|
|
332
|
+
}
|
|
333
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import platformConsts from '../utils/constants.js'
|
|
2
|
+
import { generateRandomString, hasProperty, sleep } from '../utils/functions.js'
|
|
3
|
+
|
|
4
|
+
export default class {
|
|
5
|
+
constructor(platform, accessory) {
|
|
6
|
+
// Set up variables from the platform
|
|
7
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
8
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
9
|
+
this.hapServ = platform.api.hap.Service
|
|
10
|
+
this.lang = platform.lang
|
|
11
|
+
this.log = platform.log
|
|
12
|
+
this.platform = platform
|
|
13
|
+
|
|
14
|
+
// Set up variables from the accessory
|
|
15
|
+
this.name = accessory.displayName
|
|
16
|
+
this.accessory = accessory
|
|
17
|
+
|
|
18
|
+
// Initially set the online flag as true (to be then updated as false if necessary)
|
|
19
|
+
this.isOnline = true
|
|
20
|
+
|
|
21
|
+
// Set up custom variables for this device type
|
|
22
|
+
const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
|
|
23
|
+
this.brightStep = deviceConf.brightnessStep
|
|
24
|
+
? Math.min(deviceConf.brightnessStep, 100)
|
|
25
|
+
: platformConsts.defaultValues.brightnessStep
|
|
26
|
+
this.offlineAsOff = deviceConf.offlineAsOff
|
|
27
|
+
|
|
28
|
+
// Set the correct logging variables for this accessory
|
|
29
|
+
switch (deviceConf.overrideLogging) {
|
|
30
|
+
case 'standard':
|
|
31
|
+
this.enableLogging = true
|
|
32
|
+
this.enableDebugLogging = false
|
|
33
|
+
break
|
|
34
|
+
case 'debug':
|
|
35
|
+
this.enableLogging = true
|
|
36
|
+
this.enableDebugLogging = true
|
|
37
|
+
break
|
|
38
|
+
case 'disable':
|
|
39
|
+
this.enableLogging = false
|
|
40
|
+
this.enableDebugLogging = false
|
|
41
|
+
break
|
|
42
|
+
default:
|
|
43
|
+
this.enableLogging = !platform.config.disableDeviceLogging
|
|
44
|
+
this.enableDebugLogging = platform.config.debug
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Remove any fan services from a similation
|
|
49
|
+
if (accessory.getService(this.hapServ.Fan)) {
|
|
50
|
+
accessory.removeService(accessory.getService(this.hapServ.Fan))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Add the lightbulb service if it doesn't already exist
|
|
54
|
+
this.service = this.accessory.getService(this.hapServ.Lightbulb)
|
|
55
|
+
|| this.accessory.addService(this.hapServ.Lightbulb)
|
|
56
|
+
|
|
57
|
+
// Add the set handler to the lightbulb on/off characteristic
|
|
58
|
+
this.service
|
|
59
|
+
.getCharacteristic(this.hapChar.On)
|
|
60
|
+
.onSet(async value => this.internalStateUpdate(value))
|
|
61
|
+
|
|
62
|
+
// Add the set handler to the lightbulb brightness characteristic
|
|
63
|
+
this.service
|
|
64
|
+
.getCharacteristic(this.hapChar.Brightness)
|
|
65
|
+
.setProps({ minStep: this.brightStep })
|
|
66
|
+
.onSet(async value => this.internalBrightnessUpdate(value))
|
|
67
|
+
|
|
68
|
+
// Add the get handlers only if the user hasn't disabled the disableNoResponse setting
|
|
69
|
+
if (!platform.config.disableNoResponse) {
|
|
70
|
+
this.service.getCharacteristic(this.hapChar.On).onGet(() => {
|
|
71
|
+
if (!this.isOnline) {
|
|
72
|
+
throw new this.hapErr(-70402)
|
|
73
|
+
}
|
|
74
|
+
return this.service.getCharacteristic(this.hapChar.On).value
|
|
75
|
+
})
|
|
76
|
+
this.service.getCharacteristic(this.hapChar.Brightness).onGet(() => {
|
|
77
|
+
if (!this.isOnline) {
|
|
78
|
+
throw new this.hapErr(-70402)
|
|
79
|
+
}
|
|
80
|
+
return this.service.getCharacteristic(this.hapChar.Brightness).value
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Output the customised options to the log
|
|
85
|
+
const normalLogging = this.enableLogging ? 'standard' : 'disable'
|
|
86
|
+
const opts = JSON.stringify({
|
|
87
|
+
brightnessStep: this.brightStep,
|
|
88
|
+
logging: this.enableDebugLogging ? 'debug' : normalLogging,
|
|
89
|
+
offlineAsOff: !!this.offlineAsOff,
|
|
90
|
+
})
|
|
91
|
+
this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async internalStateUpdate(value) {
|
|
95
|
+
try {
|
|
96
|
+
const newValue = value ? 'on' : 'off'
|
|
97
|
+
if (this.cacheState === newValue) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
const params = {}
|
|
101
|
+
switch (this.accessory.context.eweUIID) {
|
|
102
|
+
case 36:
|
|
103
|
+
case 44:
|
|
104
|
+
// KING-M4, D1
|
|
105
|
+
params.switch = newValue
|
|
106
|
+
break
|
|
107
|
+
case 57:
|
|
108
|
+
params.state = newValue
|
|
109
|
+
break
|
|
110
|
+
default:
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
await this.platform.sendDeviceUpdate(this.accessory, params)
|
|
114
|
+
this.cacheState = newValue
|
|
115
|
+
if (this.enableLogging) {
|
|
116
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
|
|
117
|
+
}
|
|
118
|
+
} catch (err) {
|
|
119
|
+
this.platform.deviceUpdateError(this.accessory, err, true)
|
|
120
|
+
setTimeout(() => {
|
|
121
|
+
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
122
|
+
}, 2000)
|
|
123
|
+
throw new this.hapErr(-70402)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async internalBrightnessUpdate(value) {
|
|
128
|
+
try {
|
|
129
|
+
if (this.cacheBright === value) {
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
const updateKey = generateRandomString(5)
|
|
133
|
+
this.updateKeyBright = updateKey
|
|
134
|
+
await sleep(500)
|
|
135
|
+
if (updateKey !== this.updateKeyBright) {
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
const params = {}
|
|
139
|
+
switch (this.accessory.context.eweUIID) {
|
|
140
|
+
case 36:
|
|
141
|
+
params.bright = Math.round((value * 9) / 10 + 10)
|
|
142
|
+
// KING-M4 eWeLink scale is 10-100 and HomeKit scale is 0-100
|
|
143
|
+
break
|
|
144
|
+
case 44:
|
|
145
|
+
params.brightness = value
|
|
146
|
+
// D1 eWeLink scale matches HomeKit scale of 0-100
|
|
147
|
+
params.mode = 0
|
|
148
|
+
break
|
|
149
|
+
case 57:
|
|
150
|
+
params.channel0 = Math.round((value * 23) / 10 + 25).toString()
|
|
151
|
+
// Device eWeLink scale is 25-255 and HomeKit scale is 0-100.
|
|
152
|
+
break
|
|
153
|
+
default:
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
await this.platform.sendDeviceUpdate(this.accessory, params)
|
|
157
|
+
this.cacheBright = value
|
|
158
|
+
if (this.enableLogging) {
|
|
159
|
+
this.log('[%s] %s [%s%].', this.name, this.lang.curBright, this.cacheBright)
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
this.platform.deviceUpdateError(this.accessory, err, true)
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
this.service.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
|
|
165
|
+
}, 2000)
|
|
166
|
+
throw new this.hapErr(-70402)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async externalUpdate(params) {
|
|
171
|
+
try {
|
|
172
|
+
if (this.accessory.context.eweUIID === 57) {
|
|
173
|
+
if (params.state && params.state !== this.cacheState) {
|
|
174
|
+
this.service.updateCharacteristic(this.hapChar.On, params.state === 'on')
|
|
175
|
+
this.cacheState = params.state
|
|
176
|
+
if (params.updateSource && this.enableLogging) {
|
|
177
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} else if (params.switch && params.switch !== this.cacheState) {
|
|
181
|
+
this.service.updateCharacteristic(this.hapChar.On, params.switch === 'on')
|
|
182
|
+
this.cacheState = params.switch
|
|
183
|
+
if (params.updateSource && this.enableLogging) {
|
|
184
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
switch (this.accessory.context.eweUIID) {
|
|
189
|
+
case 36:
|
|
190
|
+
// KING-M4 eWeLink scale is 10-100 and HomeKit scale is 0-100.
|
|
191
|
+
if (hasProperty(params, 'bright')) {
|
|
192
|
+
const nb = Math.round(((params.bright - 10) * 10) / 9)
|
|
193
|
+
if (nb !== this.cacheBright) {
|
|
194
|
+
this.service.updateCharacteristic(this.hapChar.Brightness, nb)
|
|
195
|
+
this.cacheBright = nb
|
|
196
|
+
if (params.updateSource && this.enableLogging) {
|
|
197
|
+
this.log('[%s] %s [%s%].', this.name, this.lang.curBright, nb)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
break
|
|
202
|
+
case 44:
|
|
203
|
+
// D1 eWeLink scale matches HomeKit scale of 0-100
|
|
204
|
+
if (hasProperty(params, 'brightness')) {
|
|
205
|
+
const nb = params.brightness
|
|
206
|
+
if (nb !== this.cacheBright) {
|
|
207
|
+
this.service.updateCharacteristic(this.hapChar.Brightness, nb)
|
|
208
|
+
this.cacheBright = nb
|
|
209
|
+
if (params.updateSource && this.enableLogging) {
|
|
210
|
+
this.log('[%s] %s [%s%].', this.name, this.lang.curBright, nb)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
break
|
|
215
|
+
case 57:
|
|
216
|
+
// Device eWeLink scale is 25-255 and HomeKit scale is 0-100.
|
|
217
|
+
if (hasProperty(params, 'channel0')) {
|
|
218
|
+
const nb = Math.round(((Number.parseInt(params.channel0, 10) - 25) * 10) / 23)
|
|
219
|
+
if (nb !== this.cacheBright) {
|
|
220
|
+
this.service.updateCharacteristic(this.hapChar.Brightness, nb)
|
|
221
|
+
this.cacheBright = nb
|
|
222
|
+
if (params.updateSource && this.enableLogging) {
|
|
223
|
+
this.log('[%s] %s [%s%].', this.name, this.lang.curBright, nb)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
break
|
|
228
|
+
default:
|
|
229
|
+
}
|
|
230
|
+
} catch (err) {
|
|
231
|
+
this.platform.deviceUpdateError(this.accessory, err, false)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
markStatus(isOnline) {
|
|
236
|
+
this.isOnline = isOnline
|
|
237
|
+
|
|
238
|
+
// Show as off if offlineAsOff is enabled
|
|
239
|
+
if (this.offlineAsOff && !isOnline && this.cacheState !== 'off') {
|
|
240
|
+
this.service.updateCharacteristic(this.hapChar.On, false)
|
|
241
|
+
this.cacheState = 'off'
|
|
242
|
+
if (this.enableLogging) {
|
|
243
|
+
this.log('[%s] %s [%s - offline]', this.name, this.lang.curState, this.cacheState)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
currentState() {
|
|
249
|
+
const toReturn = {}
|
|
250
|
+
toReturn.services = ['light']
|
|
251
|
+
toReturn.light = {
|
|
252
|
+
state: this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off',
|
|
253
|
+
brightness: this.service.getCharacteristic(this.hapChar.Brightness).value,
|
|
254
|
+
}
|
|
255
|
+
return toReturn
|
|
256
|
+
}
|
|
257
|
+
}
|