@homebridge-plugins/homebridge-ewelink 12.7.0 → 12.7.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -3
- package/README.md +3 -5
- package/lib/device/air-conditioner.js +512 -0
- package/lib/device/index.js +4 -0
- package/lib/device/virtual.js +270 -0
- package/lib/platform.js +20 -0
- package/lib/utils/constants.js +3 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
All notable changes to homebridge-ewelink will be documented in this file.
|
|
3
|
+
All notable changes to `@homebridge-plugins/homebridge-ewelink` will be documented in this file.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## v12.8.0 (2025-12-05)
|
|
6
|
+
|
|
7
|
+
### Changes
|
|
8
|
+
|
|
9
|
+
- feat: add support for Virtual Switch (UIID 264) and Virtual Button (UIID 265)
|
|
10
|
+
- support more devices
|
|
11
|
+
- update readme badges (use `shields.io`)
|
|
12
|
+
- update workflows and npm publish via oidc
|
|
13
|
+
- updated dependencies
|
|
14
|
+
|
|
15
|
+
## v12.7.0 (2025-09-19)
|
|
16
|
+
|
|
17
|
+
### Changes
|
|
6
18
|
|
|
7
19
|
- dependency updates
|
|
8
20
|
- added new devices
|
|
9
21
|
|
|
10
22
|
## v12.6.2 (2025-07-24)
|
|
11
23
|
|
|
12
|
-
###
|
|
24
|
+
### Changes
|
|
13
25
|
|
|
14
26
|
- dependency updates
|
|
15
27
|
|
package/README.md
CHANGED
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
Homebridge plugin to integrate eWeLink devices into HomeKit
|
|
9
9
|
|
|
10
10
|
[](https://www.npmjs.com/package/@homebridge-plugins/homebridge-ewelink)
|
|
11
|
-
[](https://github.com/homebridge-plugins/homebridge-ewelink/wiki/Beta-Version)
|
|
12
|
-
|
|
13
|
-
[](https://plugins.hoobs.org/plugin/homebridge-ewelink)
|
|
15
|
-
|
|
11
|
+
[](https://github.com/homebridge-plugins/homebridge-ewelink/wiki/Beta-Version)<br>
|
|
12
|
+
[](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
|
|
13
|
+
[](https://plugins.hoobs.org/plugin/homebridge-ewelink)<br>
|
|
16
14
|
[](https://www.npmjs.com/package/@homebridge-plugins/homebridge-ewelink)
|
|
17
15
|
[](https://discord.com/channels/432663330281226270/742733745743855627)
|
|
18
16
|
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import platformConsts from '../utils/constants.js'
|
|
2
|
+
import { hasProperty, parseError } 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.hapServ = platform.api.hap.Service
|
|
9
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
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.tempOffset = deviceConf.offset || platformConsts.defaultValues.offset
|
|
24
|
+
this.tempOffsetFactor = deviceConf.offsetFactor
|
|
25
|
+
|
|
26
|
+
// Set the correct logging variables for this accessory
|
|
27
|
+
switch (deviceConf.overrideLogging) {
|
|
28
|
+
case 'standard':
|
|
29
|
+
this.enableLogging = true
|
|
30
|
+
this.enableDebugLogging = false
|
|
31
|
+
break
|
|
32
|
+
case 'debug':
|
|
33
|
+
this.enableLogging = true
|
|
34
|
+
this.enableDebugLogging = true
|
|
35
|
+
break
|
|
36
|
+
case 'disable':
|
|
37
|
+
this.enableLogging = false
|
|
38
|
+
this.enableDebugLogging = false
|
|
39
|
+
break
|
|
40
|
+
default:
|
|
41
|
+
this.enableLogging = !platform.config.disableDeviceLogging
|
|
42
|
+
this.enableDebugLogging = platform.config.debug
|
|
43
|
+
break
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Add the heater cooler service if it doesn't already exist
|
|
47
|
+
this.service = this.accessory.getService(this.hapServ.HeaterCooler)
|
|
48
|
+
|| this.accessory.addService(this.hapServ.HeaterCooler)
|
|
49
|
+
|
|
50
|
+
// Set custom properties of the current temperature characteristic
|
|
51
|
+
this.service.getCharacteristic(this.hapChar.CurrentTemperature).setProps({
|
|
52
|
+
minStep: 0.1,
|
|
53
|
+
})
|
|
54
|
+
this.cacheTemp = this.service.getCharacteristic(this.hapChar.CurrentTemperature).value
|
|
55
|
+
|
|
56
|
+
// Add the set handler to the active characteristic
|
|
57
|
+
this.service
|
|
58
|
+
.getCharacteristic(this.hapChar.Active)
|
|
59
|
+
.onSet(async value => this.internalActiveUpdate(value))
|
|
60
|
+
|
|
61
|
+
// Add the set handler to the target heater cooler state characteristic
|
|
62
|
+
this.service
|
|
63
|
+
.getCharacteristic(this.hapChar.TargetHeaterCoolerState)
|
|
64
|
+
.setProps({
|
|
65
|
+
minValue: 0,
|
|
66
|
+
maxValue: 2,
|
|
67
|
+
validValues: [0, 1, 2], // Auto, Heat, Cool
|
|
68
|
+
})
|
|
69
|
+
.onSet(async value => this.internalModeUpdate(value))
|
|
70
|
+
|
|
71
|
+
// Add the set handler to the cooling threshold temperature characteristic
|
|
72
|
+
this.service
|
|
73
|
+
.getCharacteristic(this.hapChar.CoolingThresholdTemperature)
|
|
74
|
+
.setProps({
|
|
75
|
+
minValue: 16,
|
|
76
|
+
maxValue: 32,
|
|
77
|
+
minStep: 1,
|
|
78
|
+
})
|
|
79
|
+
.onSet(async value => this.internalTempUpdate(value, 'cool'))
|
|
80
|
+
|
|
81
|
+
// Add the set handler to the heating threshold temperature characteristic
|
|
82
|
+
this.service
|
|
83
|
+
.getCharacteristic(this.hapChar.HeatingThresholdTemperature)
|
|
84
|
+
.setProps({
|
|
85
|
+
minValue: 16,
|
|
86
|
+
maxValue: 32,
|
|
87
|
+
minStep: 1,
|
|
88
|
+
})
|
|
89
|
+
.onSet(async value => this.internalTempUpdate(value, 'heat'))
|
|
90
|
+
|
|
91
|
+
// Add the set handler to the rotation speed characteristic (for fan speed)
|
|
92
|
+
this.service
|
|
93
|
+
.getCharacteristic(this.hapChar.RotationSpeed)
|
|
94
|
+
.setProps({
|
|
95
|
+
minValue: 0,
|
|
96
|
+
maxValue: 100,
|
|
97
|
+
minStep: 25,
|
|
98
|
+
})
|
|
99
|
+
.onSet(async value => this.internalSpeedUpdate(value))
|
|
100
|
+
|
|
101
|
+
// Add the get handlers only if the user hasn't disabled the disableNoResponse setting
|
|
102
|
+
if (!platform.config.disableNoResponse) {
|
|
103
|
+
this.service.getCharacteristic(this.hapChar.Active).onGet(() => {
|
|
104
|
+
if (!this.isOnline) {
|
|
105
|
+
throw new this.hapErr(-70402)
|
|
106
|
+
}
|
|
107
|
+
return this.service.getCharacteristic(this.hapChar.Active).value
|
|
108
|
+
})
|
|
109
|
+
this.service.getCharacteristic(this.hapChar.TargetHeaterCoolerState).onGet(() => {
|
|
110
|
+
if (!this.isOnline) {
|
|
111
|
+
throw new this.hapErr(-70402)
|
|
112
|
+
}
|
|
113
|
+
return this.service.getCharacteristic(this.hapChar.TargetHeaterCoolerState).value
|
|
114
|
+
})
|
|
115
|
+
this.service.getCharacteristic(this.hapChar.CurrentHeaterCoolerState).onGet(() => {
|
|
116
|
+
if (!this.isOnline) {
|
|
117
|
+
throw new this.hapErr(-70402)
|
|
118
|
+
}
|
|
119
|
+
return this.service.getCharacteristic(this.hapChar.CurrentHeaterCoolerState).value
|
|
120
|
+
})
|
|
121
|
+
this.service.getCharacteristic(this.hapChar.CurrentTemperature).onGet(() => {
|
|
122
|
+
if (!this.isOnline) {
|
|
123
|
+
throw new this.hapErr(-70402)
|
|
124
|
+
}
|
|
125
|
+
return this.service.getCharacteristic(this.hapChar.CurrentTemperature).value
|
|
126
|
+
})
|
|
127
|
+
this.service.getCharacteristic(this.hapChar.CoolingThresholdTemperature).onGet(() => {
|
|
128
|
+
if (!this.isOnline) {
|
|
129
|
+
throw new this.hapErr(-70402)
|
|
130
|
+
}
|
|
131
|
+
return this.service.getCharacteristic(this.hapChar.CoolingThresholdTemperature).value
|
|
132
|
+
})
|
|
133
|
+
this.service.getCharacteristic(this.hapChar.HeatingThresholdTemperature).onGet(() => {
|
|
134
|
+
if (!this.isOnline) {
|
|
135
|
+
throw new this.hapErr(-70402)
|
|
136
|
+
}
|
|
137
|
+
return this.service.getCharacteristic(this.hapChar.HeatingThresholdTemperature).value
|
|
138
|
+
})
|
|
139
|
+
this.service.getCharacteristic(this.hapChar.RotationSpeed).onGet(() => {
|
|
140
|
+
if (!this.isOnline) {
|
|
141
|
+
throw new this.hapErr(-70402)
|
|
142
|
+
}
|
|
143
|
+
return this.service.getCharacteristic(this.hapChar.RotationSpeed).value
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Initialise these caches now since they aren't determined by the initial externalUpdate()
|
|
148
|
+
this.cacheTarg = this.service.getCharacteristic(this.hapChar.CoolingThresholdTemperature).value
|
|
149
|
+
this.cacheMode = 'cool'
|
|
150
|
+
this.cacheSpeed = 50
|
|
151
|
+
|
|
152
|
+
// Pass the accessory to Fakegato to set up with Eve
|
|
153
|
+
this.accessory.eveService = new platform.eveService('custom', this.accessory, {
|
|
154
|
+
log: () => {},
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Output the customised options to the log
|
|
158
|
+
const normalLogging = this.enableLogging ? 'standard' : 'disable'
|
|
159
|
+
const opts = JSON.stringify({
|
|
160
|
+
logging: this.enableDebugLogging ? 'debug' : normalLogging,
|
|
161
|
+
offset: this.tempOffset,
|
|
162
|
+
offsetFactor: this.tempOffsetFactor,
|
|
163
|
+
})
|
|
164
|
+
this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async internalActiveUpdate(value) {
|
|
168
|
+
try {
|
|
169
|
+
const newValue = value === 1 ? 'on' : 'off'
|
|
170
|
+
|
|
171
|
+
// Don't continue if the value is the same as before
|
|
172
|
+
const prevState = this.service.getCharacteristic(this.hapChar.Active).value === 1 ? 'on' : 'off'
|
|
173
|
+
if (prevState === newValue) {
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Send the request to the platform sender function
|
|
178
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
179
|
+
power: newValue,
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
// Update the current state characteristic
|
|
183
|
+
this.service.updateCharacteristic(
|
|
184
|
+
this.hapChar.CurrentHeaterCoolerState,
|
|
185
|
+
value === 1
|
|
186
|
+
? (this.cacheMode === 'heat'
|
|
187
|
+
? this.hapChar.CurrentHeaterCoolerState.HEATING
|
|
188
|
+
: this.hapChar.CurrentHeaterCoolerState.COOLING)
|
|
189
|
+
: this.hapChar.CurrentHeaterCoolerState.INACTIVE,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
// Cache the new state and log if appropriate
|
|
193
|
+
if (this.enableLogging) {
|
|
194
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, newValue)
|
|
195
|
+
}
|
|
196
|
+
} catch (err) {
|
|
197
|
+
// Catch any errors during the process
|
|
198
|
+
const eText = parseError(err)
|
|
199
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.cantCtl, eText)
|
|
200
|
+
|
|
201
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
202
|
+
const prevStateValue = this.service.getCharacteristic(this.hapChar.Active).value
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
this.service.updateCharacteristic(this.hapChar.Active, prevStateValue)
|
|
205
|
+
}, 2000)
|
|
206
|
+
throw new this.hapErr(-70402)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async internalModeUpdate(value) {
|
|
211
|
+
try {
|
|
212
|
+
let newMode
|
|
213
|
+
switch (value) {
|
|
214
|
+
case 0: // Auto
|
|
215
|
+
newMode = 'auto'
|
|
216
|
+
break
|
|
217
|
+
case 1: // Heat
|
|
218
|
+
newMode = 'heat'
|
|
219
|
+
break
|
|
220
|
+
case 2: // Cool
|
|
221
|
+
newMode = 'cool'
|
|
222
|
+
break
|
|
223
|
+
default:
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Don't continue if the value is the same as before
|
|
228
|
+
if (this.cacheMode === newMode) {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Send the request to the platform sender function
|
|
233
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
234
|
+
mode: newMode,
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
// Update the current state characteristic if device is on
|
|
238
|
+
if (this.service.getCharacteristic(this.hapChar.Active).value === 1) {
|
|
239
|
+
this.service.updateCharacteristic(
|
|
240
|
+
this.hapChar.CurrentHeaterCoolerState,
|
|
241
|
+
value === 1
|
|
242
|
+
? this.hapChar.CurrentHeaterCoolerState.HEATING
|
|
243
|
+
: value === 2
|
|
244
|
+
? this.hapChar.CurrentHeaterCoolerState.COOLING
|
|
245
|
+
: this.hapChar.CurrentHeaterCoolerState.IDLE,
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Cache the new mode and log if appropriate
|
|
250
|
+
this.cacheMode = newMode
|
|
251
|
+
if (this.enableLogging) {
|
|
252
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curMode, newMode)
|
|
253
|
+
}
|
|
254
|
+
} catch (err) {
|
|
255
|
+
// Catch any errors during the process
|
|
256
|
+
const eText = parseError(err)
|
|
257
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.cantCtl, eText)
|
|
258
|
+
|
|
259
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
260
|
+
setTimeout(() => {
|
|
261
|
+
const prevValue = this.cacheMode === 'heat' ? 1 : this.cacheMode === 'cool' ? 2 : 0
|
|
262
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, prevValue)
|
|
263
|
+
}, 2000)
|
|
264
|
+
throw new this.hapErr(-70402)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async internalTempUpdate(value, mode) {
|
|
269
|
+
try {
|
|
270
|
+
// Only update if this is the active mode or auto mode
|
|
271
|
+
if (this.cacheMode !== mode && this.cacheMode !== 'auto') {
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Don't continue if the value is the same as before
|
|
276
|
+
if (this.cacheTarg === value) {
|
|
277
|
+
return
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Send the request to the platform sender function
|
|
281
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
282
|
+
temperature: value,
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
// Cache the new target temperature and log if appropriate
|
|
286
|
+
this.cacheTarg = value
|
|
287
|
+
if (this.enableLogging) {
|
|
288
|
+
this.log('[%s] %s [%s°C].', this.name, this.lang.tarTemp, value)
|
|
289
|
+
}
|
|
290
|
+
} catch (err) {
|
|
291
|
+
// Catch any errors during the process
|
|
292
|
+
const eText = parseError(err)
|
|
293
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.cantCtl, eText)
|
|
294
|
+
|
|
295
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
296
|
+
setTimeout(() => {
|
|
297
|
+
if (mode === 'cool') {
|
|
298
|
+
this.service.updateCharacteristic(this.hapChar.CoolingThresholdTemperature, this.cacheTarg)
|
|
299
|
+
} else {
|
|
300
|
+
this.service.updateCharacteristic(this.hapChar.HeatingThresholdTemperature, this.cacheTarg)
|
|
301
|
+
}
|
|
302
|
+
}, 2000)
|
|
303
|
+
throw new this.hapErr(-70402)
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async internalSpeedUpdate(value) {
|
|
308
|
+
try {
|
|
309
|
+
// Map HomeKit 0-100 to eWeLink wind speed values
|
|
310
|
+
// Assuming 101 = low, 102 = medium, 103 = high
|
|
311
|
+
let windSpeed
|
|
312
|
+
if (value === 0) {
|
|
313
|
+
windSpeed = 0
|
|
314
|
+
} else if (value <= 33) {
|
|
315
|
+
windSpeed = 101
|
|
316
|
+
} else if (value <= 66) {
|
|
317
|
+
windSpeed = 102
|
|
318
|
+
} else {
|
|
319
|
+
windSpeed = 103
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Don't continue if the value is the same as before
|
|
323
|
+
if (this.cacheSpeed === windSpeed) {
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Send the request to the platform sender function
|
|
328
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
329
|
+
wind_speed: windSpeed,
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
// Cache the new speed and log if appropriate
|
|
333
|
+
this.cacheSpeed = windSpeed
|
|
334
|
+
if (this.enableLogging) {
|
|
335
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curSpeed, value)
|
|
336
|
+
}
|
|
337
|
+
} catch (err) {
|
|
338
|
+
// Catch any errors during the process
|
|
339
|
+
const eText = parseError(err)
|
|
340
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.cantCtl, eText)
|
|
341
|
+
|
|
342
|
+
// Map cached speed back to HomeKit value
|
|
343
|
+
let prevValue = 50
|
|
344
|
+
if (this.cacheSpeed === 101) {
|
|
345
|
+
prevValue = 25
|
|
346
|
+
} else if (this.cacheSpeed === 102) {
|
|
347
|
+
prevValue = 50
|
|
348
|
+
} else if (this.cacheSpeed === 103) {
|
|
349
|
+
prevValue = 75
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
353
|
+
setTimeout(() => {
|
|
354
|
+
this.service.updateCharacteristic(this.hapChar.RotationSpeed, prevValue)
|
|
355
|
+
}, 2000)
|
|
356
|
+
throw new this.hapErr(-70402)
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async externalUpdate(params) {
|
|
361
|
+
try {
|
|
362
|
+
// Check to see if the provided params are valid for this model
|
|
363
|
+
if (
|
|
364
|
+
!hasProperty(params, 'power')
|
|
365
|
+
&& !hasProperty(params, 'mode')
|
|
366
|
+
&& !hasProperty(params, 'temperature')
|
|
367
|
+
&& !hasProperty(params, 'indoor_temperature')
|
|
368
|
+
&& !hasProperty(params, 'wind_speed')
|
|
369
|
+
) {
|
|
370
|
+
throw new Error(this.lang.paramsNotRecd)
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Update the active characteristic
|
|
374
|
+
if (hasProperty(params, 'power')) {
|
|
375
|
+
const newState = params.power === 'on' ? 1 : 0
|
|
376
|
+
this.service.updateCharacteristic(this.hapChar.Active, newState)
|
|
377
|
+
|
|
378
|
+
// Update the current state
|
|
379
|
+
this.service.updateCharacteristic(
|
|
380
|
+
this.hapChar.CurrentHeaterCoolerState,
|
|
381
|
+
newState === 1
|
|
382
|
+
? (this.cacheMode === 'heat'
|
|
383
|
+
? this.hapChar.CurrentHeaterCoolerState.HEATING
|
|
384
|
+
: this.hapChar.CurrentHeaterCoolerState.COOLING)
|
|
385
|
+
: this.hapChar.CurrentHeaterCoolerState.INACTIVE,
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
// Log the change if appropriate
|
|
389
|
+
if (params.updateSource && this.enableLogging) {
|
|
390
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, params.power)
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Update the mode characteristic
|
|
395
|
+
if (hasProperty(params, 'mode')) {
|
|
396
|
+
let targetState
|
|
397
|
+
switch (params.mode) {
|
|
398
|
+
case 'auto':
|
|
399
|
+
targetState = 0
|
|
400
|
+
break
|
|
401
|
+
case 'heat':
|
|
402
|
+
targetState = 1
|
|
403
|
+
break
|
|
404
|
+
case 'cool':
|
|
405
|
+
targetState = 2
|
|
406
|
+
break
|
|
407
|
+
default:
|
|
408
|
+
return
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
this.cacheMode = params.mode
|
|
412
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, targetState)
|
|
413
|
+
|
|
414
|
+
// Update current state if device is on
|
|
415
|
+
if (this.service.getCharacteristic(this.hapChar.Active).value === 1) {
|
|
416
|
+
this.service.updateCharacteristic(
|
|
417
|
+
this.hapChar.CurrentHeaterCoolerState,
|
|
418
|
+
targetState === 1
|
|
419
|
+
? this.hapChar.CurrentHeaterCoolerState.HEATING
|
|
420
|
+
: targetState === 2
|
|
421
|
+
? this.hapChar.CurrentHeaterCoolerState.COOLING
|
|
422
|
+
: this.hapChar.CurrentHeaterCoolerState.IDLE,
|
|
423
|
+
)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Log the change if appropriate
|
|
427
|
+
if (params.updateSource && this.enableLogging) {
|
|
428
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curMode, params.mode)
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Update the target temperature
|
|
433
|
+
if (hasProperty(params, 'temperature')) {
|
|
434
|
+
this.cacheTarg = params.temperature
|
|
435
|
+
this.service.updateCharacteristic(this.hapChar.CoolingThresholdTemperature, params.temperature)
|
|
436
|
+
this.service.updateCharacteristic(this.hapChar.HeatingThresholdTemperature, params.temperature)
|
|
437
|
+
|
|
438
|
+
// Log the change if appropriate
|
|
439
|
+
if (params.updateSource && this.enableLogging) {
|
|
440
|
+
this.log('[%s] %s [%s°C].', this.name, this.lang.tarTemp, params.temperature)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Update the current temperature
|
|
445
|
+
if (hasProperty(params, 'indoor_temperature')) {
|
|
446
|
+
let newTemp = Number(params.indoor_temperature)
|
|
447
|
+
|
|
448
|
+
// Apply any configured offset
|
|
449
|
+
if (this.tempOffsetFactor) {
|
|
450
|
+
newTemp *= this.tempOffsetFactor
|
|
451
|
+
}
|
|
452
|
+
newTemp += this.tempOffset
|
|
453
|
+
newTemp = Math.round(newTemp * 10) / 10
|
|
454
|
+
|
|
455
|
+
this.cacheTemp = newTemp
|
|
456
|
+
this.service.updateCharacteristic(this.hapChar.CurrentTemperature, newTemp)
|
|
457
|
+
this.accessory.eveService.addEntry({
|
|
458
|
+
time: Math.round(Date.now() / 1000),
|
|
459
|
+
temp: newTemp,
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
// Log the change if appropriate
|
|
463
|
+
if (params.updateSource && this.enableLogging) {
|
|
464
|
+
this.log('[%s] %s [%s°C].', this.name, this.lang.curTemp, newTemp)
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Update the fan speed
|
|
469
|
+
if (hasProperty(params, 'wind_speed')) {
|
|
470
|
+
// Map eWeLink wind speed to HomeKit rotation speed
|
|
471
|
+
let rotationSpeed = 50
|
|
472
|
+
if (params.wind_speed === 0) {
|
|
473
|
+
rotationSpeed = 0
|
|
474
|
+
} else if (params.wind_speed === 101) {
|
|
475
|
+
rotationSpeed = 25
|
|
476
|
+
} else if (params.wind_speed === 102) {
|
|
477
|
+
rotationSpeed = 50
|
|
478
|
+
} else if (params.wind_speed === 103) {
|
|
479
|
+
rotationSpeed = 75
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
this.cacheSpeed = params.wind_speed
|
|
483
|
+
this.service.updateCharacteristic(this.hapChar.RotationSpeed, rotationSpeed)
|
|
484
|
+
|
|
485
|
+
// Log the change if appropriate
|
|
486
|
+
if (params.updateSource && this.enableLogging) {
|
|
487
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curSpeed, rotationSpeed)
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
} catch (err) {
|
|
491
|
+
// Catch any errors during the process
|
|
492
|
+
const eText = parseError(err)
|
|
493
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.cantUpd, eText)
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
async currentState() {
|
|
498
|
+
const toReturn = {}
|
|
499
|
+
toReturn.services = ['heater-cooler']
|
|
500
|
+
toReturn.heater_cooler = {
|
|
501
|
+
state: this.service.getCharacteristic(this.hapChar.Active).value === 1 ? 'on' : 'off',
|
|
502
|
+
mode: this.cacheMode,
|
|
503
|
+
target_temp: this.cacheTarg,
|
|
504
|
+
current_temp: this.cacheTemp,
|
|
505
|
+
}
|
|
506
|
+
return toReturn
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
markStatus(isOnline) {
|
|
510
|
+
this.isOnline = isOnline
|
|
511
|
+
}
|
|
512
|
+
}
|
package/lib/device/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import deviceAirConditioner from './air-conditioner.js'
|
|
1
2
|
import deviceCurtain from './curtain.js'
|
|
2
3
|
import deviceDiffuser from './diffuser.js'
|
|
3
4
|
import deviceFan from './fan.js'
|
|
@@ -26,9 +27,11 @@ import deviceSwitchSingleInched from './switch-single-inched.js'
|
|
|
26
27
|
import deviceSwitchSingle from './switch-single.js'
|
|
27
28
|
import deviceTemplate from './template.js'
|
|
28
29
|
import deviceThermostat from './thermostat.js'
|
|
30
|
+
import deviceVirtual from './virtual.js'
|
|
29
31
|
import zb from './zigbee/index.js'
|
|
30
32
|
|
|
31
33
|
export default {
|
|
34
|
+
deviceAirConditioner,
|
|
32
35
|
deviceCurtain,
|
|
33
36
|
deviceDiffuser,
|
|
34
37
|
deviceFan,
|
|
@@ -56,6 +59,7 @@ export default {
|
|
|
56
59
|
deviceSwitchSingleInched,
|
|
57
60
|
deviceTemplate,
|
|
58
61
|
deviceThermostat,
|
|
62
|
+
deviceVirtual,
|
|
59
63
|
sim,
|
|
60
64
|
zb,
|
|
61
65
|
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { hasProperty, parseError } from '../utils/functions.js'
|
|
2
|
+
|
|
3
|
+
export default class {
|
|
4
|
+
constructor(platform, accessory) {
|
|
5
|
+
// Set up variables from the platform
|
|
6
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
7
|
+
this.hapServ = platform.api.hap.Service
|
|
8
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
9
|
+
this.lang = platform.lang
|
|
10
|
+
this.log = platform.log
|
|
11
|
+
this.platform = platform
|
|
12
|
+
|
|
13
|
+
// Set up variables from the accessory
|
|
14
|
+
this.name = accessory.displayName
|
|
15
|
+
this.accessory = accessory
|
|
16
|
+
|
|
17
|
+
// Initially set the online flag as true (to be then updated as false if necessary)
|
|
18
|
+
this.isOnline = true
|
|
19
|
+
|
|
20
|
+
// Set up custom variables for this device type
|
|
21
|
+
const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
|
|
22
|
+
|
|
23
|
+
// Set the correct logging variables for this accessory
|
|
24
|
+
switch (deviceConf.overrideLogging) {
|
|
25
|
+
case 'standard':
|
|
26
|
+
this.enableLogging = true
|
|
27
|
+
this.enableDebugLogging = false
|
|
28
|
+
break
|
|
29
|
+
case 'debug':
|
|
30
|
+
this.enableLogging = true
|
|
31
|
+
this.enableDebugLogging = true
|
|
32
|
+
break
|
|
33
|
+
case 'disable':
|
|
34
|
+
this.enableLogging = false
|
|
35
|
+
this.enableDebugLogging = false
|
|
36
|
+
break
|
|
37
|
+
default:
|
|
38
|
+
this.enableLogging = !platform.config.disableDeviceLogging
|
|
39
|
+
this.enableDebugLogging = platform.config.debug
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check device params to determine if it's a button or switch
|
|
44
|
+
this.isButton = hasProperty(accessory.context.eweParams, 'key')
|
|
45
|
+
|
|
46
|
+
if (this.isButton) {
|
|
47
|
+
// Virtual Button - use StatelessProgrammableSwitch
|
|
48
|
+
this.service = this.accessory.getService(this.hapServ.StatelessProgrammableSwitch)
|
|
49
|
+
|| this.accessory.addService(this.hapServ.StatelessProgrammableSwitch)
|
|
50
|
+
|
|
51
|
+
// Set up the button with single, double, and long press
|
|
52
|
+
this.service.getCharacteristic(this.hapChar.ProgrammableSwitchEvent).setProps({
|
|
53
|
+
minValue: 0,
|
|
54
|
+
maxValue: 2,
|
|
55
|
+
validValues: [0, 1, 2], // Single, Double, Long press
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
// Remove switch service if it exists from previous setup
|
|
59
|
+
if (this.accessory.getService(this.hapServ.Switch)) {
|
|
60
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Switch))
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
// Virtual Switch - use standard Switch service
|
|
64
|
+
this.service = this.accessory.getService(this.hapServ.Switch)
|
|
65
|
+
|| this.accessory.addService(this.hapServ.Switch)
|
|
66
|
+
|
|
67
|
+
// Add the set handler to the switch on/off characteristic
|
|
68
|
+
this.service
|
|
69
|
+
.getCharacteristic(this.hapChar.On)
|
|
70
|
+
.onSet(async value => this.internalStateUpdate(value))
|
|
71
|
+
|
|
72
|
+
// Add the get handler only if the user hasn't disabled the disableNoResponse setting
|
|
73
|
+
if (!platform.config.disableNoResponse) {
|
|
74
|
+
this.service.getCharacteristic(this.hapChar.On).onGet(() => {
|
|
75
|
+
if (!this.isOnline) {
|
|
76
|
+
throw new this.hapErr(-70402)
|
|
77
|
+
}
|
|
78
|
+
return this.service.getCharacteristic(this.hapChar.On).value
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Remove button service if it exists from previous setup
|
|
83
|
+
if (this.accessory.getService(this.hapServ.StatelessProgrammableSwitch)) {
|
|
84
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.StatelessProgrammableSwitch))
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Pass the accessory to Fakegato to set up with Eve
|
|
89
|
+
this.accessory.eveService = new platform.eveService('switch', this.accessory, {
|
|
90
|
+
log: () => {},
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
// Output the customised options to the log
|
|
94
|
+
const normalLogging = this.enableLogging ? 'standard' : 'disable'
|
|
95
|
+
const opts = JSON.stringify({
|
|
96
|
+
logging: this.enableDebugLogging ? 'debug' : normalLogging,
|
|
97
|
+
type: this.isButton ? 'button' : 'switch',
|
|
98
|
+
})
|
|
99
|
+
this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async internalStateUpdate(value) {
|
|
103
|
+
try {
|
|
104
|
+
// This is only for virtual switches, not buttons
|
|
105
|
+
if (this.isButton) {
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const newValue = value ? 'on' : 'off'
|
|
110
|
+
|
|
111
|
+
// Don't continue if the value is the same as before
|
|
112
|
+
const prevState = this.service.getCharacteristic(this.hapChar.On).value
|
|
113
|
+
if (prevState === value) {
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Send the request to the platform sender function
|
|
118
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
119
|
+
switches: [
|
|
120
|
+
{
|
|
121
|
+
outlet: 0,
|
|
122
|
+
switch: newValue,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Cache the new state and log if appropriate
|
|
128
|
+
if (this.enableLogging) {
|
|
129
|
+
this.accessory.eveService.addEntry({
|
|
130
|
+
time: Math.round(Date.now() / 1000),
|
|
131
|
+
status: value ? 1 : 0,
|
|
132
|
+
})
|
|
133
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, newValue)
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
// Catch any errors during the process
|
|
137
|
+
const eText = parseError(err)
|
|
138
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.cantCtl, eText)
|
|
139
|
+
|
|
140
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
141
|
+
setTimeout(() => {
|
|
142
|
+
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
143
|
+
}, 2000)
|
|
144
|
+
throw new this.hapErr(-70402)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async externalUpdate(params) {
|
|
149
|
+
try {
|
|
150
|
+
if (this.isButton) {
|
|
151
|
+
// Handle button press events
|
|
152
|
+
if (hasProperty(params, 'key')) {
|
|
153
|
+
// Map key values to HomeKit button events
|
|
154
|
+
let buttonEvent
|
|
155
|
+
switch (params.key) {
|
|
156
|
+
case 0:
|
|
157
|
+
buttonEvent = this.hapChar.ProgrammableSwitchEvent.SINGLE_PRESS
|
|
158
|
+
break
|
|
159
|
+
case 1:
|
|
160
|
+
buttonEvent = this.hapChar.ProgrammableSwitchEvent.DOUBLE_PRESS
|
|
161
|
+
break
|
|
162
|
+
case 2:
|
|
163
|
+
buttonEvent = this.hapChar.ProgrammableSwitchEvent.LONG_PRESS
|
|
164
|
+
break
|
|
165
|
+
default:
|
|
166
|
+
// Unknown key value, default to single press
|
|
167
|
+
buttonEvent = this.hapChar.ProgrammableSwitchEvent.SINGLE_PRESS
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Update the button event characteristic
|
|
171
|
+
this.service.updateCharacteristic(this.hapChar.ProgrammableSwitchEvent, buttonEvent)
|
|
172
|
+
|
|
173
|
+
// Log the button press if appropriate
|
|
174
|
+
if (params.updateSource && this.enableLogging) {
|
|
175
|
+
const pressType = params.key === 0 ? 'single' : params.key === 1 ? 'double' : 'long'
|
|
176
|
+
this.log('[%s] %s [%s press].', this.name, this.lang.curState, pressType)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Handle trigger time if provided
|
|
181
|
+
if (hasProperty(params, 'trigTime')) {
|
|
182
|
+
this.lastTriggerTime = params.trigTime
|
|
183
|
+
if (this.enableDebugLogging) {
|
|
184
|
+
this.log('[%s] Button triggered at %s.', this.name, new Date(Number.parseInt(params.trigTime)).toLocaleString())
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
// Handle virtual switch updates
|
|
189
|
+
if (hasProperty(params, 'switches') && Array.isArray(params.switches)) {
|
|
190
|
+
params.switches.forEach((outlet) => {
|
|
191
|
+
// Check this is the primary outlet
|
|
192
|
+
if (outlet.outlet !== 0) {
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Check we have a valid switch value
|
|
197
|
+
if (!hasProperty(outlet, 'switch')) {
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const newState = outlet.switch === 'on'
|
|
202
|
+
const prevState = this.service.getCharacteristic(this.hapChar.On).value
|
|
203
|
+
if (prevState === newState) {
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
this.service.updateCharacteristic(this.hapChar.On, newState)
|
|
208
|
+
this.cacheState = outlet.switch
|
|
209
|
+
|
|
210
|
+
// Add Eve history entry
|
|
211
|
+
this.accessory.eveService.addEntry({
|
|
212
|
+
time: Math.round(Date.now() / 1000),
|
|
213
|
+
status: newState ? 1 : 0,
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// Log the change if appropriate
|
|
217
|
+
if (params.updateSource && this.enableLogging) {
|
|
218
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, outlet.switch)
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Also handle single switch param for compatibility
|
|
224
|
+
if (hasProperty(params, 'switch')) {
|
|
225
|
+
const newState = params.switch === 'on'
|
|
226
|
+
const prevState = this.service.getCharacteristic(this.hapChar.On).value
|
|
227
|
+
if (prevState !== newState) {
|
|
228
|
+
this.service.updateCharacteristic(this.hapChar.On, newState)
|
|
229
|
+
this.cacheState = params.switch
|
|
230
|
+
|
|
231
|
+
// Add Eve history entry
|
|
232
|
+
this.accessory.eveService.addEntry({
|
|
233
|
+
time: Math.round(Date.now() / 1000),
|
|
234
|
+
status: newState ? 1 : 0,
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
// Log the change if appropriate
|
|
238
|
+
if (params.updateSource && this.enableLogging) {
|
|
239
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, params.switch)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
} catch (err) {
|
|
245
|
+
// Catch any errors during the process
|
|
246
|
+
const eText = parseError(err)
|
|
247
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.cantUpd, eText)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async currentState() {
|
|
252
|
+
const toReturn = {}
|
|
253
|
+
if (this.isButton) {
|
|
254
|
+
toReturn.services = ['button']
|
|
255
|
+
toReturn.button = {
|
|
256
|
+
last_trigger: this.lastTriggerTime || 'none',
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
toReturn.services = ['switch']
|
|
260
|
+
toReturn.switch = {
|
|
261
|
+
state: this.cacheState || 'off',
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return toReturn
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
markStatus(isOnline) {
|
|
268
|
+
this.isOnline = isOnline
|
|
269
|
+
}
|
|
270
|
+
}
|
package/lib/platform.js
CHANGED
|
@@ -1106,6 +1106,26 @@ export default class {
|
|
|
1106
1106
|
this.applyAccessoryLogging(accessory)
|
|
1107
1107
|
accessory.control = new deviceTypes.deviceThermostat(this, accessory)
|
|
1108
1108
|
/** */
|
|
1109
|
+
} else if (platformConsts.devices.airConditioner.includes(uiid)) {
|
|
1110
|
+
/**
|
|
1111
|
+
***************
|
|
1112
|
+
AIR CONDITIONERS
|
|
1113
|
+
****************
|
|
1114
|
+
*/
|
|
1115
|
+
accessory = devicesInHB.get(uuid) || this.addAccessory(device, `${device.deviceid}SWX`)
|
|
1116
|
+
this.applyAccessoryLogging(accessory)
|
|
1117
|
+
accessory.control = new deviceTypes.deviceAirConditioner(this, accessory)
|
|
1118
|
+
/** */
|
|
1119
|
+
} else if (platformConsts.devices.virtual.includes(uiid)) {
|
|
1120
|
+
/**
|
|
1121
|
+
***************
|
|
1122
|
+
VIRTUAL DEVICES
|
|
1123
|
+
****************
|
|
1124
|
+
*/
|
|
1125
|
+
accessory = devicesInHB.get(uuid) || this.addAccessory(device, `${device.deviceid}SWX`)
|
|
1126
|
+
this.applyAccessoryLogging(accessory)
|
|
1127
|
+
accessory.control = new deviceTypes.deviceVirtual(this, accessory)
|
|
1128
|
+
/** */
|
|
1109
1129
|
} else if (
|
|
1110
1130
|
device.showAs === 'thermostat'
|
|
1111
1131
|
&& platformConsts.devices.sensorAmbient.includes(uiid)
|
package/lib/utils/constants.js
CHANGED
|
@@ -285,7 +285,7 @@ export default {
|
|
|
285
285
|
212,
|
|
286
286
|
],
|
|
287
287
|
switchSingle: [1, 6, 14, 24, 27, 225, 226, 1009, 1256, 7004, 7005, 7010, 7032],
|
|
288
|
-
switchSCM: [77, 78, 81, 107, 112, 138, 160, 191, 209],
|
|
288
|
+
switchSCM: [77, 78, 81, 107, 112, 138, 160, 191, 209, 264],
|
|
289
289
|
switchSCMPower: [182, 190],
|
|
290
290
|
switchSinglePower: [5, 32],
|
|
291
291
|
switchMulti: [
|
|
@@ -329,7 +329,9 @@ export default {
|
|
|
329
329
|
sensorAmbient: [15, 181],
|
|
330
330
|
sensorTempHumi: [18],
|
|
331
331
|
thermostat: [127],
|
|
332
|
+
airConditioner: [151],
|
|
332
333
|
panel: [133, 195],
|
|
334
|
+
virtual: [265],
|
|
333
335
|
fan: [34],
|
|
334
336
|
humidifier: [19],
|
|
335
337
|
diffuser: [25],
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"displayName": "Homebridge eWeLink",
|
|
4
4
|
"alias": "eWeLink",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "12.7.0",
|
|
6
|
+
"version": "12.7.1-beta.0",
|
|
7
7
|
"description": "Homebridge plugin to integrate eWeLink devices into HomeKit.",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "bwp91",
|
|
@@ -61,14 +61,14 @@
|
|
|
61
61
|
"lint:fix": "npm run lint -- --fix"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@homebridge/plugin-ui-utils": "^2.1.
|
|
65
|
-
"axios": "^1.
|
|
64
|
+
"@homebridge/plugin-ui-utils": "^2.1.2",
|
|
65
|
+
"axios": "^1.13.2",
|
|
66
66
|
"node-persist": "^4.0.4",
|
|
67
|
-
"p-queue": "^
|
|
67
|
+
"p-queue": "^9.0.1",
|
|
68
68
|
"websocket-as-promised": "^3.0.1",
|
|
69
69
|
"ws": "^8.18.3"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@antfu/eslint-config": "^
|
|
72
|
+
"@antfu/eslint-config": "^6.4.2"
|
|
73
73
|
}
|
|
74
74
|
}
|