@homebridge-plugins/homebridge-wemo 7.0.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 +809 -0
- package/LICENSE +21 -0
- package/README.md +66 -0
- package/config.schema.json +814 -0
- package/eslint.config.js +50 -0
- package/lib/connection/http.js +174 -0
- package/lib/connection/upnp.js +155 -0
- package/lib/device/coffee.js +167 -0
- package/lib/device/crockpot.js +380 -0
- package/lib/device/dimmer.js +280 -0
- package/lib/device/heater.js +416 -0
- package/lib/device/humidifier.js +379 -0
- package/lib/device/index.js +39 -0
- package/lib/device/insight.js +353 -0
- package/lib/device/lightswitch.js +154 -0
- package/lib/device/link-bulb.js +467 -0
- package/lib/device/link-hub.js +63 -0
- package/lib/device/maker-garage.js +426 -0
- package/lib/device/maker-switch.js +202 -0
- package/lib/device/motion.js +148 -0
- package/lib/device/outlet.js +148 -0
- package/lib/device/purifier.js +468 -0
- package/lib/device/simulation/purifier-insight.js +357 -0
- package/lib/device/simulation/purifier.js +159 -0
- package/lib/device/simulation/switch-insight.js +315 -0
- package/lib/device/simulation/switch.js +154 -0
- package/lib/fakegato/LICENSE +21 -0
- package/lib/fakegato/fakegato-history.js +814 -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 +315 -0
- package/lib/homebridge-ui/server.js +10 -0
- package/lib/index.js +8 -0
- package/lib/platform.js +1423 -0
- package/lib/utils/colour.js +135 -0
- package/lib/utils/constants.js +129 -0
- package/lib/utils/eve-chars.js +130 -0
- package/lib/utils/functions.js +52 -0
- package/lib/utils/lang-en.js +125 -0
- package/package.json +70 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import platformConsts from '../../utils/constants.js'
|
|
2
|
+
import { hasProperty, parseError } from '../../utils/functions.js'
|
|
3
|
+
import platformLang from '../../utils/lang-en.js'
|
|
4
|
+
|
|
5
|
+
export default class {
|
|
6
|
+
constructor(platform, accessory) {
|
|
7
|
+
// Set up variables from the platform
|
|
8
|
+
this.eveChar = platform.eveChar
|
|
9
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
10
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
11
|
+
this.hapServ = platform.api.hap.Service
|
|
12
|
+
this.platform = platform
|
|
13
|
+
|
|
14
|
+
// Set up variables from the accessory
|
|
15
|
+
this.accessory = accessory
|
|
16
|
+
|
|
17
|
+
// Set up custom variables for this device type
|
|
18
|
+
const deviceConf = platform.deviceConf[accessory.context.serialNumber] || {}
|
|
19
|
+
this.showTodayTC = deviceConf.showTodayTC
|
|
20
|
+
this.wattDiff = deviceConf.wattDiff || platformConsts.defaultValues.wattDiff
|
|
21
|
+
this.timeDiff = deviceConf.timeDiff || platformConsts.defaultValues.timeDiff
|
|
22
|
+
if (this.timeDiff === 1) {
|
|
23
|
+
this.timeDiff = false
|
|
24
|
+
}
|
|
25
|
+
this.skipTimeDiff = false
|
|
26
|
+
|
|
27
|
+
if (!hasProperty(this.accessory.context, 'cacheLastWM')) {
|
|
28
|
+
this.accessory.context.cacheLastWM = 0
|
|
29
|
+
}
|
|
30
|
+
if (!hasProperty(this.accessory.context, 'cacheLastTC')) {
|
|
31
|
+
this.accessory.context.cacheLastTC = 0
|
|
32
|
+
}
|
|
33
|
+
if (!hasProperty(this.accessory.context, 'cacheTotalTC')) {
|
|
34
|
+
this.accessory.context.cacheTotalTC = 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// If the accessory has an outlet service then remove it
|
|
38
|
+
if (this.accessory.getService(this.hapServ.Outlet)) {
|
|
39
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Outlet))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// If the accessory has a switch service then remove it
|
|
43
|
+
if (this.accessory.getService(this.hapServ.Switch)) {
|
|
44
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Switch))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Add the purifier service if it doesn't already exist
|
|
48
|
+
this.service = this.accessory.getService(this.hapServ.AirPurifier)
|
|
49
|
+
|| this.accessory.addService(this.hapServ.AirPurifier)
|
|
50
|
+
|
|
51
|
+
// Add the Eve power characteristics
|
|
52
|
+
if (!this.service.testCharacteristic(this.eveChar.CurrentConsumption)) {
|
|
53
|
+
this.service.addCharacteristic(this.eveChar.CurrentConsumption)
|
|
54
|
+
}
|
|
55
|
+
if (!this.service.testCharacteristic(this.eveChar.TotalConsumption)) {
|
|
56
|
+
this.service.addCharacteristic(this.eveChar.TotalConsumption)
|
|
57
|
+
}
|
|
58
|
+
if (!this.service.testCharacteristic(this.eveChar.ResetTotal)) {
|
|
59
|
+
this.service.addCharacteristic(this.eveChar.ResetTotal)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Add the set handler to the purifier active characteristic
|
|
63
|
+
this.service
|
|
64
|
+
.getCharacteristic(this.hapChar.Active)
|
|
65
|
+
.removeOnSet()
|
|
66
|
+
.onSet(async value => this.internalStateUpdate(value))
|
|
67
|
+
|
|
68
|
+
// Add options to the purifier target state characteristic
|
|
69
|
+
this.service.getCharacteristic(this.hapChar.TargetAirPurifierState).setProps({
|
|
70
|
+
minValue: 1,
|
|
71
|
+
maxValue: 1,
|
|
72
|
+
validValues: [1],
|
|
73
|
+
})
|
|
74
|
+
this.service.updateCharacteristic(this.hapChar.TargetAirPurifierState, 1)
|
|
75
|
+
|
|
76
|
+
// Add the set handler to the switch reset (eve) characteristic
|
|
77
|
+
this.service.getCharacteristic(this.eveChar.ResetTotal).onSet(() => {
|
|
78
|
+
this.accessory.context.cacheLastWM = 0
|
|
79
|
+
this.accessory.context.cacheLastTC = 0
|
|
80
|
+
this.accessory.context.cacheTotalTC = 0
|
|
81
|
+
this.service.updateCharacteristic(this.eveChar.TotalConsumption, 0)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Pass the accessory to fakegato to set up the Eve info service
|
|
85
|
+
this.accessory.historyService = new platform.eveService('energy', this.accessory, {
|
|
86
|
+
log: () => {},
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Output the customised options to the log
|
|
90
|
+
const opts = JSON.stringify({
|
|
91
|
+
showAs: 'purifier',
|
|
92
|
+
showTodayTC: this.showTodayTC,
|
|
93
|
+
timeDiff: this.timeDiff,
|
|
94
|
+
wattDiff: this.wattDiff,
|
|
95
|
+
})
|
|
96
|
+
platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
|
|
97
|
+
|
|
98
|
+
// Request a device update immediately
|
|
99
|
+
this.requestDeviceUpdate()
|
|
100
|
+
|
|
101
|
+
// Start a polling interval if the user has disabled upnp
|
|
102
|
+
if (this.accessory.context.connection === 'http') {
|
|
103
|
+
this.pollingInterval = setInterval(
|
|
104
|
+
() => this.requestDeviceUpdate(),
|
|
105
|
+
platform.config.pollingInterval * 1000,
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
receiveDeviceUpdate(attribute) {
|
|
111
|
+
// Log the receiving update if debug is enabled
|
|
112
|
+
this.accessory.logDebug(`${platformLang.recUpd} [${attribute.name}: ${JSON.stringify(attribute.value)}]`)
|
|
113
|
+
|
|
114
|
+
// Let's see which attribute has been provided
|
|
115
|
+
switch (attribute.name) {
|
|
116
|
+
case 'BinaryState': {
|
|
117
|
+
// BinaryState is reported as 0=off, 1=on, 8=standby
|
|
118
|
+
// Send a HomeKit needed 1/0 argument (0=0, 1,8=1)
|
|
119
|
+
this.externalStateUpdate(attribute.value === 0 ? 0 : 1)
|
|
120
|
+
break
|
|
121
|
+
}
|
|
122
|
+
case 'InsightParams':
|
|
123
|
+
// Send the insight data straight to the function
|
|
124
|
+
this.externalInsightUpdate(
|
|
125
|
+
attribute.value.state,
|
|
126
|
+
attribute.value.power,
|
|
127
|
+
attribute.value.todayWm,
|
|
128
|
+
attribute.value.todayOnSeconds,
|
|
129
|
+
)
|
|
130
|
+
break
|
|
131
|
+
default:
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async sendDeviceUpdate(value) {
|
|
136
|
+
// Log the sending update if debug is enabled
|
|
137
|
+
this.accessory.logDebug(`${platformLang.senUpd} ${JSON.stringify(value)}`)
|
|
138
|
+
|
|
139
|
+
// Send the update
|
|
140
|
+
await this.platform.httpClient.sendDeviceUpdate(
|
|
141
|
+
this.accessory,
|
|
142
|
+
'urn:Belkin:service:basicevent:1',
|
|
143
|
+
'SetBinaryState',
|
|
144
|
+
value,
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async requestDeviceUpdate() {
|
|
149
|
+
try {
|
|
150
|
+
// Request the update
|
|
151
|
+
const data = await this.platform.httpClient.sendDeviceUpdate(
|
|
152
|
+
this.accessory,
|
|
153
|
+
'urn:Belkin:service:basicevent:1',
|
|
154
|
+
'GetBinaryState',
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
// Check for existence since BinaryState can be int 0
|
|
158
|
+
if (hasProperty(data, 'BinaryState')) {
|
|
159
|
+
this.receiveDeviceUpdate({
|
|
160
|
+
name: 'BinaryState',
|
|
161
|
+
value: Number.parseInt(data.BinaryState, 10),
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
} catch (err) {
|
|
165
|
+
const eText = parseError(err, [
|
|
166
|
+
platformLang.timeout,
|
|
167
|
+
platformLang.timeoutUnreach,
|
|
168
|
+
platformLang.noService,
|
|
169
|
+
])
|
|
170
|
+
this.accessory.logDebugWarn(`${platformLang.rduErr} ${eText}`)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async internalStateUpdate(value) {
|
|
175
|
+
try {
|
|
176
|
+
// Send the update
|
|
177
|
+
await this.sendDeviceUpdate({
|
|
178
|
+
BinaryState: value ? 1 : 0,
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Update the cache value
|
|
182
|
+
this.cacheState = value
|
|
183
|
+
|
|
184
|
+
// Log the change if appropriate
|
|
185
|
+
this.accessory.log(`${platformLang.curState} [${value ? platformLang.purifyYes : platformLang.purifyNo}]`)
|
|
186
|
+
|
|
187
|
+
// If turning the switch off then update the purifying state and current consumption
|
|
188
|
+
if (!value) {
|
|
189
|
+
// Update the HomeKit characteristics
|
|
190
|
+
this.service.updateCharacteristic(this.eveChar.CurrentConsumption, 0)
|
|
191
|
+
this.service.updateCharacteristic(this.hapChar.CurrentAirPurifierState, 0)
|
|
192
|
+
|
|
193
|
+
// Add an Eve entry for no power
|
|
194
|
+
this.accessory.historyService.addEntry({ power: 0 })
|
|
195
|
+
|
|
196
|
+
// Log the change if appropriate
|
|
197
|
+
this.accessory.log(`${platformLang.curCons} [0W]`)
|
|
198
|
+
} else {
|
|
199
|
+
// Set the current state to purifying
|
|
200
|
+
this.service.updateCharacteristic(this.hapChar.CurrentAirPurifierState, 2)
|
|
201
|
+
}
|
|
202
|
+
} catch (err) {
|
|
203
|
+
const eText = parseError(err, [platformLang.timeout, platformLang.timeoutUnreach])
|
|
204
|
+
this.accessory.logWarn(`${platformLang.cantCtl} ${eText}`)
|
|
205
|
+
|
|
206
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
207
|
+
setTimeout(() => {
|
|
208
|
+
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState)
|
|
209
|
+
}, 2000)
|
|
210
|
+
throw new this.hapErr(-70402)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
externalInsightUpdate(value, power, todayWm, todayOnSeconds) {
|
|
215
|
+
// Update whether the switch is ON (value=1) or OFF (value=0)
|
|
216
|
+
this.externalStateUpdate(value === 0 ? 0 : 1)
|
|
217
|
+
|
|
218
|
+
// Update whether the outlet-in-use is YES (value=1) or NO (value=0,8)
|
|
219
|
+
this.externalInUseUpdate(value === 1)
|
|
220
|
+
|
|
221
|
+
// Update the total consumption
|
|
222
|
+
this.externalTotalConsumptionUpdate(todayWm, todayOnSeconds)
|
|
223
|
+
|
|
224
|
+
// Update the current consumption
|
|
225
|
+
this.externalConsumptionUpdate(power)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
externalStateUpdate(value) {
|
|
229
|
+
try {
|
|
230
|
+
// Check to see if the cache value is different
|
|
231
|
+
if (value === this.cacheState) {
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Update the HomeKit characteristics
|
|
236
|
+
this.service.updateCharacteristic(this.hapChar.Active, value)
|
|
237
|
+
|
|
238
|
+
// Update the cache value
|
|
239
|
+
this.cacheState = value
|
|
240
|
+
|
|
241
|
+
// Log the change if appropriate
|
|
242
|
+
this.accessory.log(`${platformLang.curState} [${value ? platformLang.purifyYes : platformLang.purifyNo}]`)
|
|
243
|
+
|
|
244
|
+
// If the device has turned off then update the current consumption
|
|
245
|
+
if (!value) {
|
|
246
|
+
this.externalConsumptionUpdate(0)
|
|
247
|
+
}
|
|
248
|
+
} catch (err) {
|
|
249
|
+
// Catch any errors
|
|
250
|
+
this.accessory.logWarn(`${platformLang.cantUpd} ${parseError(err)}`)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
externalInUseUpdate(value) {
|
|
255
|
+
try {
|
|
256
|
+
// Check to see if the cache value is different
|
|
257
|
+
if (value === this.cacheInUse) {
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Update the HomeKit characteristic
|
|
262
|
+
this.service.updateCharacteristic(this.hapChar.CurrentAirPurifierState, value ? 2 : 1)
|
|
263
|
+
|
|
264
|
+
// Update the cache value
|
|
265
|
+
this.cacheInUse = value
|
|
266
|
+
|
|
267
|
+
// Log the change if appropriate
|
|
268
|
+
this.accessory.log(`${platformLang.curState} [${value ? platformLang.purifyYes : platformLang.purifyNo}]`)
|
|
269
|
+
} catch (err) {
|
|
270
|
+
// Catch any errors
|
|
271
|
+
this.accessory.logWarn(`${platformLang.cantUpd} ${parseError(err)}`)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
externalConsumptionUpdate(power) {
|
|
276
|
+
try {
|
|
277
|
+
// Divide by 1000 to get the power value in W
|
|
278
|
+
const powerInWatts = Math.round(power / 1000)
|
|
279
|
+
|
|
280
|
+
// Check to see if the cache value is different
|
|
281
|
+
if (powerInWatts === this.cachePowerInWatts) {
|
|
282
|
+
return
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Update the power in watts cache
|
|
286
|
+
this.cachePowerInWatts = powerInWatts
|
|
287
|
+
|
|
288
|
+
// Update the HomeKit characteristic
|
|
289
|
+
this.service.updateCharacteristic(this.eveChar.CurrentConsumption, this.cachePowerInWatts)
|
|
290
|
+
|
|
291
|
+
// Add the Eve wattage entry
|
|
292
|
+
this.accessory.historyService.addEntry({ power: this.cachePowerInWatts })
|
|
293
|
+
|
|
294
|
+
// Calculate a difference from the last reading
|
|
295
|
+
const diff = Math.abs(powerInWatts - this.cachePowerInWatts)
|
|
296
|
+
|
|
297
|
+
// Don't continue with logging if the user has set a timeout between entries or a min difference between entries
|
|
298
|
+
if (!this.skipTimeDiff && diff >= this.wattDiff) {
|
|
299
|
+
// Log the change if appropriate
|
|
300
|
+
this.accessory.log(`${platformLang.curCons} [${this.cachePowerInWatts}W]`)
|
|
301
|
+
|
|
302
|
+
// Set the time difference timeout if needed
|
|
303
|
+
if (this.timeDiff) {
|
|
304
|
+
this.skipTimeDiff = true
|
|
305
|
+
setTimeout(() => {
|
|
306
|
+
this.skipTimeDiff = false
|
|
307
|
+
}, this.timeDiff * 1000)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} catch (err) {
|
|
311
|
+
// Catch any errors
|
|
312
|
+
this.accessory.logWarn(`${platformLang.cantUpd} ${parseError(err)}`)
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
externalTotalConsumptionUpdate(todayWm, todayOnSeconds) {
|
|
317
|
+
try {
|
|
318
|
+
if (todayWm === this.accessory.context.cacheLastWM) {
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Update the cache last value
|
|
323
|
+
this.accessory.context.cacheLastWM = todayWm
|
|
324
|
+
|
|
325
|
+
// Convert to Wh (hours) from raw data of Wm (minutes)
|
|
326
|
+
const todayWh = Math.round(todayWm / 60000)
|
|
327
|
+
|
|
328
|
+
// Convert to kWh
|
|
329
|
+
const todaykWh = todayWh / 1000
|
|
330
|
+
|
|
331
|
+
// Convert to hours, minutes and seconds (HH:MM:SS)
|
|
332
|
+
const todayOnHours = new Date(todayOnSeconds * 1000).toISOString().substr(11, 8)
|
|
333
|
+
|
|
334
|
+
// Calculate the difference (ie extra usage from the last reading)
|
|
335
|
+
const difference = Math.max(todaykWh - this.accessory.context.cacheLastTC, 0)
|
|
336
|
+
|
|
337
|
+
// Update the caches
|
|
338
|
+
this.accessory.context.cacheTotalTC += difference
|
|
339
|
+
this.accessory.context.cacheLastTC = todaykWh
|
|
340
|
+
|
|
341
|
+
// Update the total consumption characteristic
|
|
342
|
+
this.service.updateCharacteristic(
|
|
343
|
+
this.eveChar.TotalConsumption,
|
|
344
|
+
this.showTodayTC ? todaykWh : this.accessory.context.cacheTotalTC,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
if (!this.skipTimeDiff) {
|
|
348
|
+
this.accessory.log(
|
|
349
|
+
`${platformLang.insOnTime} [${todayOnHours}] ${platformLang.insCons} [${todaykWh.toFixed(3)} kWh] ${platformLang.insTC} [${this.accessory.context.cacheTotalTC.toFixed(3)} kWh]`,
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
} catch (err) {
|
|
353
|
+
// Catch any errors
|
|
354
|
+
this.accessory.logWarn(`${platformLang.cantUpd} ${parseError(err)}`)
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { hasProperty, parseError } from '../../utils/functions.js'
|
|
2
|
+
import platformLang from '../../utils/lang-en.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.platform = platform
|
|
11
|
+
|
|
12
|
+
// Set up variables from the accessory
|
|
13
|
+
this.accessory = accessory
|
|
14
|
+
|
|
15
|
+
// If the accessory has an outlet service then remove it
|
|
16
|
+
if (this.accessory.getService(this.hapServ.Outlet)) {
|
|
17
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Outlet))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// If the accessory has a switch service then remove it
|
|
21
|
+
if (this.accessory.getService(this.hapServ.Switch)) {
|
|
22
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Switch))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Add the air purifier service if it doesn't already exist
|
|
26
|
+
this.service = this.accessory.getService(this.hapServ.AirPurifier)
|
|
27
|
+
|| this.accessory.addService(this.hapServ.AirPurifier)
|
|
28
|
+
|
|
29
|
+
// Add the set handler to the purifier active characteristic
|
|
30
|
+
this.service
|
|
31
|
+
.getCharacteristic(this.hapChar.Active)
|
|
32
|
+
.removeOnSet()
|
|
33
|
+
.onSet(async value => this.internalStateUpdate(value))
|
|
34
|
+
|
|
35
|
+
// Add options to the purifier target state characteristic
|
|
36
|
+
this.service.getCharacteristic(this.hapChar.TargetAirPurifierState).setProps({
|
|
37
|
+
minValue: 1,
|
|
38
|
+
maxValue: 1,
|
|
39
|
+
validValues: [1],
|
|
40
|
+
})
|
|
41
|
+
this.service.updateCharacteristic(this.hapChar.TargetAirPurifierState, 1)
|
|
42
|
+
|
|
43
|
+
// Output the customised options to the log
|
|
44
|
+
const opts = JSON.stringify({
|
|
45
|
+
showAs: 'purifier',
|
|
46
|
+
})
|
|
47
|
+
platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
|
|
48
|
+
|
|
49
|
+
// Request a device update immediately
|
|
50
|
+
this.requestDeviceUpdate()
|
|
51
|
+
|
|
52
|
+
// Start a polling interval if the user has disabled upnp
|
|
53
|
+
if (this.accessory.context.connection === 'http') {
|
|
54
|
+
this.pollingInterval = setInterval(
|
|
55
|
+
() => this.requestDeviceUpdate(),
|
|
56
|
+
platform.config.pollingInterval * 1000,
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
receiveDeviceUpdate(attribute) {
|
|
62
|
+
// Log the receiving update if debug is enabled
|
|
63
|
+
this.accessory.logDebug(`${platformLang.recUpd} [${attribute.name}: ${JSON.stringify(attribute.value)}]`)
|
|
64
|
+
|
|
65
|
+
// Send a HomeKit needed 1/0 argument
|
|
66
|
+
// attribute.value is 0 if and only if the switch is off
|
|
67
|
+
this.externalStateUpdate(attribute.value)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async sendDeviceUpdate(value) {
|
|
71
|
+
// Log the sending update if debug is enabled
|
|
72
|
+
this.accessory.logDebug(`${platformLang.senUpd} ${JSON.stringify(value)}`)
|
|
73
|
+
|
|
74
|
+
// Send the update
|
|
75
|
+
await this.platform.httpClient.sendDeviceUpdate(
|
|
76
|
+
this.accessory,
|
|
77
|
+
'urn:Belkin:service:basicevent:1',
|
|
78
|
+
'SetBinaryState',
|
|
79
|
+
value,
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async requestDeviceUpdate() {
|
|
84
|
+
try {
|
|
85
|
+
// Request the update
|
|
86
|
+
const data = await this.platform.httpClient.sendDeviceUpdate(
|
|
87
|
+
this.accessory,
|
|
88
|
+
'urn:Belkin:service:basicevent:1',
|
|
89
|
+
'GetBinaryState',
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
// Check for existence since BinaryState can be int 0
|
|
93
|
+
if (hasProperty(data, 'BinaryState')) {
|
|
94
|
+
// Send the data to the receiver function
|
|
95
|
+
this.receiveDeviceUpdate({
|
|
96
|
+
name: 'BinaryState',
|
|
97
|
+
value: Number.parseInt(data.BinaryState, 10),
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
} catch (err) {
|
|
101
|
+
const eText = parseError(err, [
|
|
102
|
+
platformLang.timeout,
|
|
103
|
+
platformLang.timeoutUnreach,
|
|
104
|
+
platformLang.noService,
|
|
105
|
+
])
|
|
106
|
+
this.accessory.logDebugWarn(`${platformLang.rduErr} ${eText}`)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async internalStateUpdate(value) {
|
|
111
|
+
try {
|
|
112
|
+
// Send the update
|
|
113
|
+
await this.sendDeviceUpdate({
|
|
114
|
+
BinaryState: value,
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// Update the HomeKit characteristic
|
|
118
|
+
this.service.updateCharacteristic(this.hapChar.CurrentAirPurifierState, value === 1 ? 2 : 0)
|
|
119
|
+
|
|
120
|
+
// Update the cache value
|
|
121
|
+
this.cacheState = value
|
|
122
|
+
|
|
123
|
+
// Log the change if appropriate
|
|
124
|
+
this.accessory.log(`${platformLang.curState} [${value === 1 ? platformLang.purifyYes : platformLang.purifyNo}]`)
|
|
125
|
+
} catch (err) {
|
|
126
|
+
// Catch any errors
|
|
127
|
+
const eText = parseError(err, [platformLang.timeout, platformLang.timeoutUnreach])
|
|
128
|
+
this.accessory.logWarn(`${platformLang.cantCtl} ${eText}`)
|
|
129
|
+
|
|
130
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState)
|
|
133
|
+
}, 2000)
|
|
134
|
+
throw new this.hapErr(-70402)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
externalStateUpdate(value) {
|
|
139
|
+
try {
|
|
140
|
+
// Check to see if the cache value is different
|
|
141
|
+
if (value === this.cacheState) {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Update the HomeKit characteristic
|
|
146
|
+
this.service.updateCharacteristic(this.hapChar.Active, value)
|
|
147
|
+
this.service.updateCharacteristic(this.hapChar.CurrentAirPurifierState, value === 1 ? 2 : 0)
|
|
148
|
+
|
|
149
|
+
// Update the cache value
|
|
150
|
+
this.cacheState = value
|
|
151
|
+
|
|
152
|
+
// Log the change if appropriate
|
|
153
|
+
this.accessory.log(`${platformLang.curState} [${value === 1 ? platformLang.purifyYes : platformLang.purifyNo}]`)
|
|
154
|
+
} catch (err) {
|
|
155
|
+
// Catch any errors
|
|
156
|
+
this.accessory.logWarn(`${platformLang.cantUpd} ${parseError(err)}`)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|