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