@homebridge-plugins/homebridge-meross 10.8.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +1346 -0
  2. package/LICENSE +21 -0
  3. package/README.md +68 -0
  4. package/config.schema.json +2066 -0
  5. package/eslint.config.js +49 -0
  6. package/lib/connection/http.js +345 -0
  7. package/lib/connection/mqtt.js +174 -0
  8. package/lib/device/baby.js +532 -0
  9. package/lib/device/cooler-single.js +447 -0
  10. package/lib/device/diffuser.js +730 -0
  11. package/lib/device/fan.js +530 -0
  12. package/lib/device/garage-main.js +225 -0
  13. package/lib/device/garage-single.js +495 -0
  14. package/lib/device/garage-sub.js +376 -0
  15. package/lib/device/heater-single.js +445 -0
  16. package/lib/device/hub-contact.js +56 -0
  17. package/lib/device/hub-leak.js +86 -0
  18. package/lib/device/hub-main.js +403 -0
  19. package/lib/device/hub-sensor.js +115 -0
  20. package/lib/device/hub-smoke.js +40 -0
  21. package/lib/device/hub-valve.js +377 -0
  22. package/lib/device/humidifier.js +521 -0
  23. package/lib/device/index.js +63 -0
  24. package/lib/device/light-cct.js +474 -0
  25. package/lib/device/light-dimmer.js +312 -0
  26. package/lib/device/light-rgb.js +528 -0
  27. package/lib/device/outlet-multi.js +383 -0
  28. package/lib/device/outlet-single.js +405 -0
  29. package/lib/device/power-strip.js +282 -0
  30. package/lib/device/purifier-single.js +372 -0
  31. package/lib/device/purifier.js +403 -0
  32. package/lib/device/roller-location.js +317 -0
  33. package/lib/device/roller.js +234 -0
  34. package/lib/device/sensor-presence.js +201 -0
  35. package/lib/device/switch-multi.js +403 -0
  36. package/lib/device/switch-single.js +371 -0
  37. package/lib/device/template.js +177 -0
  38. package/lib/device/thermostat.js +493 -0
  39. package/lib/fakegato/LICENSE +21 -0
  40. package/lib/fakegato/fakegato-history.js +814 -0
  41. package/lib/fakegato/fakegato-storage.js +108 -0
  42. package/lib/fakegato/fakegato-timer.js +125 -0
  43. package/lib/fakegato/uuid.js +27 -0
  44. package/lib/homebridge-ui/public/index.html +316 -0
  45. package/lib/homebridge-ui/server.js +10 -0
  46. package/lib/index.js +8 -0
  47. package/lib/platform.js +1256 -0
  48. package/lib/utils/colour.js +581 -0
  49. package/lib/utils/constants.js +377 -0
  50. package/lib/utils/custom-chars.js +165 -0
  51. package/lib/utils/eve-chars.js +130 -0
  52. package/lib/utils/functions.js +39 -0
  53. package/lib/utils/lang-en.js +114 -0
  54. package/package.json +70 -0
@@ -0,0 +1,371 @@
1
+ import PQueue from 'p-queue'
2
+ import { TimeoutError } from 'p-timeout'
3
+
4
+ import mqttClient from '../connection/mqtt.js'
5
+ import platformConsts from '../utils/constants.js'
6
+ import { hasProperty, parseError } from '../utils/functions.js'
7
+ import platformLang from '../utils/lang-en.js'
8
+
9
+ export default class {
10
+ constructor(platform, accessory) {
11
+ // Set up variables from the platform
12
+ this.eveChar = platform.eveChar
13
+ this.hapChar = platform.api.hap.Characteristic
14
+ this.hapErr = platform.api.hap.HapStatusError
15
+ this.hapServ = platform.api.hap.Service
16
+ this.platform = platform
17
+
18
+ // Set up variables from the accessory
19
+ this.accessory = accessory
20
+ this.inUsePowerThreshold = this.accessory.context.options.inUsePowerThreshold
21
+ || platformConsts.defaultValues.inUsePowerThreshold
22
+ this.name = accessory.displayName
23
+ const cloudRefreshRate = hasProperty(platform.config, 'cloudRefreshRate')
24
+ ? platform.config.cloudRefreshRate
25
+ : platformConsts.defaultValues.cloudRefreshRate
26
+ const localRefreshRate = hasProperty(platform.config, 'refreshRate')
27
+ ? platform.config.refreshRate
28
+ : platformConsts.defaultValues.refreshRate
29
+ this.pollInterval = accessory.context.connection === 'local'
30
+ ? localRefreshRate
31
+ : cloudRefreshRate;
32
+
33
+ // If the accessory has any old services then remove them
34
+ ['Outlet', 'HeaterCooler', 'AirPurifier'].forEach((service) => {
35
+ if (this.accessory.getService(this.hapServ[service])) {
36
+ this.accessory.removeService(this.accessory.getService(this.hapServ[service]))
37
+ }
38
+ })
39
+
40
+ // Add the switch service if it doesn't already exist
41
+ this.service = this.accessory.getService(this.hapServ.Switch)
42
+ || this.accessory.addService(this.hapServ.Switch)
43
+
44
+ // Add the set handler to the switch on/off characteristic
45
+ this.service
46
+ .getCharacteristic(this.hapChar.On)
47
+ .onSet(async value => this.internalStateUpdate(value))
48
+ this.cacheState = this.service.getCharacteristic(this.hapChar.On).value
49
+
50
+ // Pass the accessory to Fakegato to set up with Eve
51
+ this.accessory.eveService = new platform.eveService('switch', this.accessory, { log: () => {} })
52
+
53
+ // Create the queue used for sending device requests
54
+ this.updateInProgress = false
55
+ this.queue = new PQueue({
56
+ concurrency: 1,
57
+ interval: 250,
58
+ intervalCap: 1,
59
+ timeout: 10000,
60
+ throwOnTimeout: true,
61
+ })
62
+ this.queue.on('idle', () => {
63
+ this.updateInProgress = false
64
+ })
65
+
66
+ // Set up the mqtt client for cloud devices to send and receive device updates
67
+ if (accessory.context.connection !== 'local') {
68
+ this.accessory.mqtt = new mqttClient(platform, this.accessory)
69
+ this.accessory.mqtt.connect()
70
+ }
71
+
72
+ // Always request a device update on startup, then start the interval for polling
73
+ setTimeout(() => this.requestUpdate(true), 2000)
74
+ this.accessory.refreshInterval = setInterval(
75
+ () => this.requestUpdate(),
76
+ this.pollInterval * 1000,
77
+ )
78
+
79
+ // Test to see if the device supports power usage
80
+ setTimeout(() => this.setupPowerReadings(), 5000)
81
+
82
+ // Output the customised options to the log
83
+ const opts = JSON.stringify({
84
+ connection: this.accessory.context.connection,
85
+ inUsePowerThreshold: this.inUsePowerThreshold,
86
+ showAs: 'switch',
87
+ })
88
+ platform.log('[%s] %s %s.', this.name, platformLang.devInitOpts, opts)
89
+ }
90
+
91
+ async internalStateUpdate(value) {
92
+ try {
93
+ // Add the request to the queue so updates are sent apart
94
+ await this.queue.add(async () => {
95
+ // Don't continue if the state is the same as before
96
+ if (value === this.cacheState) {
97
+ return
98
+ }
99
+
100
+ // This flag stops the plugin from requesting updates while pending on others
101
+ this.updateInProgress = true
102
+
103
+ // The plugin should have determined if it's 'toggle' or 'togglex' on the first poll run
104
+ let namespace
105
+ let payload
106
+ if (this.isToggleX) {
107
+ namespace = 'Appliance.Control.ToggleX'
108
+ payload = {
109
+ togglex: {
110
+ onoff: value ? 1 : 0,
111
+ channel: 0,
112
+ },
113
+ }
114
+ } else {
115
+ namespace = 'Appliance.Control.Toggle'
116
+ payload = {
117
+ toggle: {
118
+ onoff: value ? 1 : 0,
119
+ },
120
+ }
121
+ }
122
+
123
+ // Use the platform function to send the update to the device
124
+ await this.platform.sendUpdate(this.accessory, {
125
+ namespace,
126
+ payload,
127
+ })
128
+
129
+ // Update the cache
130
+ this.cacheState = value
131
+
132
+ // Add the entry to eve history and log
133
+ this.accessory.eveService.addEntry({ status: value ? 1 : 0 })
134
+ this.accessory.log(`${platformLang.curState} [${value ? 'on' : 'off'}]`)
135
+ })
136
+ } catch (err) {
137
+ // Catch any errors whilst updating the device
138
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
139
+ this.accessory.logWarn(`${platformLang.sendFailed} ${eText}`)
140
+ setTimeout(() => {
141
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState)
142
+ }, 2000)
143
+ throw new this.hapErr(-70402)
144
+ }
145
+ }
146
+
147
+ async requestUpdate(firstRun = false) {
148
+ try {
149
+ // Don't continue if an update is currently being sent to the device
150
+ if (this.updateInProgress) {
151
+ return
152
+ }
153
+
154
+ // Add the request to the queue so updates are sent apart
155
+ await this.queue.add(async () => {
156
+ // This flag stops the plugin from requesting updates while pending on others
157
+ this.updateInProgress = true
158
+
159
+ // Send the request
160
+ const res = await this.platform.sendUpdate(this.accessory, {
161
+ namespace: 'Appliance.System.All',
162
+ payload: {},
163
+ })
164
+
165
+ // Log the received data
166
+ this.accessory.logDebug(`${platformLang.incPoll}: ${JSON.stringify(res.data)}`)
167
+
168
+ // Check the response is in a useful format
169
+ const data = res.data.payload
170
+ if (data.all) {
171
+ if (data.all.digest) {
172
+ if (data.all.digest.togglex && data.all.digest.togglex[0]) {
173
+ this.isToggleX = true
174
+ this.applyUpdate(data.all.digest.togglex[0])
175
+ } else if (data.all.digest.toggle) {
176
+ this.isToggleX = false
177
+ this.applyUpdate(data.all.digest.toggle)
178
+ }
179
+ }
180
+
181
+ // A flag to check if we need to update the accessory context
182
+ let needsUpdate = false
183
+
184
+ // Get the mac address and hardware version of the device
185
+ if (data.all.system) {
186
+ // Mac address and hardware don't change regularly so only get on first poll
187
+ if (firstRun && data.all.system.hardware) {
188
+ this.accessory.context.macAddress = data.all.system.hardware.macAddress.toUpperCase()
189
+ this.accessory.context.hardware = data.all.system.hardware.version
190
+ }
191
+
192
+ // Get the ip address and firmware of the device
193
+ if (data.all.system.firmware) {
194
+ // Check for an IP change each and every time the device is polled
195
+ if (this.accessory.context.ipAddress !== data.all.system.firmware.innerIp) {
196
+ this.accessory.context.ipAddress = data.all.system.firmware.innerIp
197
+ needsUpdate = true
198
+ }
199
+
200
+ // Firmware doesn't change regularly so only get on first poll
201
+ if (firstRun) {
202
+ this.accessory.context.firmware = data.all.system.firmware.version
203
+ }
204
+ }
205
+ }
206
+
207
+ // Get the cloud online status of the device
208
+ if (data.all.system.online) {
209
+ const isOnline = data.all.system.online.status === 1
210
+ if (this.accessory.context.isOnline !== isOnline) {
211
+ this.accessory.context.isOnline = isOnline
212
+ needsUpdate = true
213
+ }
214
+ }
215
+
216
+ // Update the accessory cache if anything has changed
217
+ if (needsUpdate || firstRun) {
218
+ this.platform.updateAccessory(this.accessory)
219
+ }
220
+ }
221
+ })
222
+ } catch (err) {
223
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
224
+ this.accessory.logDebugWarn(`${platformLang.reqFailed}: ${eText}`)
225
+
226
+ // Set the homebridge-ui status of the device to offline if local and error is timeout
227
+ if (
228
+ (this.accessory.context.isOnline || firstRun)
229
+ && ['EHOSTUNREACH', 'timed out'].some(el => eText.includes(el))
230
+ ) {
231
+ this.accessory.context.isOnline = false
232
+ this.platform.updateAccessory(this.accessory)
233
+ }
234
+ }
235
+ }
236
+
237
+ receiveUpdate(params) {
238
+ try {
239
+ // Log the received data
240
+ this.accessory.logDebug(`${platformLang.incMQTT}: ${JSON.stringify(params)}`)
241
+ if (params.payload) {
242
+ if (params.payload.togglex && params.payload.togglex[0]) {
243
+ this.applyUpdate(params.payload.togglex[0])
244
+ } else if (params.payload.toggle) {
245
+ this.applyUpdate(params.payload.toggle)
246
+ }
247
+ }
248
+ } catch (err) {
249
+ this.accessory.logWarn(`${platformLang.refFailed} ${parseError(err)}`)
250
+ }
251
+ }
252
+
253
+ applyUpdate(data) {
254
+ // Check the data is in a format which contains the value we need
255
+ if (hasProperty(data, 'onoff')) {
256
+ // newState is given as 0 or 1 -> convert to bool for HomeKit
257
+ const newState = data.onoff === 1
258
+
259
+ // Check against the cache and update HomeKit and the cache if needed
260
+ if (this.cacheState !== newState) {
261
+ this.service.updateCharacteristic(this.hapChar.On, newState)
262
+ this.cacheState = newState
263
+
264
+ // Add the entry to eve history and log
265
+ this.accessory.eveService.addEntry({ status: this.cacheState ? 1 : 0 })
266
+
267
+ this.accessory.log(`${platformLang.curState} [${newState ? 'on' : 'off'}]`)
268
+ }
269
+ }
270
+ if (hasProperty(data, 'power')) {
271
+ const newPower = data.power
272
+
273
+ // Check against the cache and update HomeKit and the cache if needed
274
+ let newInUse = this.cacheInUse
275
+ if (this.cachePower !== newPower) {
276
+ const scaledPower = Math.round(newPower / 10) / 100
277
+ newInUse = this.cacheState && scaledPower > this.inUsePowerThreshold
278
+ this.service.updateCharacteristic(this.eveChar.CurrentConsumption, scaledPower)
279
+ this.cachePower = newPower
280
+ this.accessory.logDebug(`${platformLang.curPower} [${scaledPower}W]`)
281
+ }
282
+ if (this.cacheInUse !== newInUse) {
283
+ this.cacheInUse = newInUse
284
+ this.service.updateCharacteristic(this.hapChar.OutletInUse, !!newInUse)
285
+ this.accessory.log(`${platformLang.curInUse} [${newInUse ? 'yes' : 'no'}]`)
286
+ }
287
+ }
288
+ if (hasProperty(data, 'voltage')) {
289
+ // newState is given as 0 or 1 -> convert to bool for HomeKit
290
+ const newVoltage = data.voltage
291
+
292
+ // Check against the cache and update HomeKit and the cache if needed
293
+ if (this.cacheVoltage !== newVoltage) {
294
+ const scaledVoltage = Math.round(newVoltage * 10) / 100
295
+ this.service.updateCharacteristic(this.eveChar.Voltage, scaledVoltage)
296
+ this.cacheVoltage = newVoltage
297
+ this.accessory.logDebug(`${platformLang.curVolt} [${scaledVoltage}V]`)
298
+ }
299
+ }
300
+ }
301
+
302
+ async setupPowerReadings() {
303
+ try {
304
+ // Add the request to the queue so updates are sent apart
305
+ await this.queue.add(async () => {
306
+ // This flag stops the plugin from requesting updates while pending on others
307
+ this.updateInProgress = true
308
+ // Send the request
309
+ const res = await this.platform.sendUpdate(this.accessory, {
310
+ namespace: 'Appliance.Control.Electricity',
311
+ payload: {},
312
+ })
313
+ // Check the response is in a useful format
314
+ if (!res.data.payload || !res.data.payload.electricity) {
315
+ throw new Error('no data on initial run')
316
+ }
317
+
318
+ // Set up the outlet in use and Eve characteristics
319
+ if (!this.service.testCharacteristic(this.hapChar.OutletInUse)) {
320
+ this.service.addCharacteristic(this.hapChar.OutletInUse)
321
+ }
322
+ this.cacheInUse = this.service.getCharacteristic(this.hapChar.OutletInUse).value
323
+ if (!this.service.testCharacteristic(this.eveChar.CurrentConsumption)) {
324
+ this.service.addCharacteristic(this.eveChar.CurrentConsumption)
325
+ }
326
+ if (!this.service.testCharacteristic(this.eveChar.Voltage)) {
327
+ this.service.addCharacteristic(this.eveChar.Voltage)
328
+ }
329
+
330
+ // Create the poll
331
+ this.requestPowerReadings()
332
+ this.accessory.powerInterval = setInterval(() => this.requestPowerReadings(), 60000)
333
+ })
334
+ } catch (err) {
335
+ const eText = err instanceof TimeoutError
336
+ ? platformLang.timeout
337
+ : parseError(err, ['no data on initial run'])
338
+ this.accessory.logDebug(`${platformLang.disablingPower} ${eText}`)
339
+ }
340
+ }
341
+
342
+ async requestPowerReadings() {
343
+ try {
344
+ // Add the request to the queue so updates are sent apart
345
+ await this.queue.add(async () => {
346
+ // This flag stops the plugin from requesting updates while pending on others
347
+ this.updateInProgress = true
348
+ // Send the request
349
+ const res = await this.platform.sendUpdate(this.accessory, {
350
+ namespace: 'Appliance.Control.Electricity',
351
+ payload: {},
352
+ })
353
+
354
+ // Log the received data
355
+ this.accessory.logDebug(`${platformLang.incPoll}: ${JSON.stringify(res.data)}`)
356
+
357
+ // Check the response is in a useful format
358
+ const data = res.data.payload
359
+ if (data && data.electricity) {
360
+ this.applyUpdate(data.electricity)
361
+ }
362
+ })
363
+ } catch (err) {
364
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
365
+ this.accessory.logDebugWarn(`${platformLang.powerFail} ${eText}`)
366
+
367
+ // Also don't increase the measured total consumption in case of any error
368
+ this.accessory.eveService.addEntry({ power: 0 })
369
+ }
370
+ }
371
+ }
@@ -0,0 +1,177 @@
1
+ import PQueue from 'p-queue'
2
+ import { TimeoutError } from 'p-timeout'
3
+
4
+ import mqttClient from '../connection/mqtt.js'
5
+ import platformConsts from '../utils/constants.js'
6
+ import { hasProperty, parseError } from '../utils/functions.js'
7
+ import platformLang from '../utils/lang-en.js'
8
+
9
+ export default class {
10
+ constructor(platform, accessory) {
11
+ // Set up variables from the platform
12
+ this.hapChar = platform.api.hap.Characteristic
13
+ this.hapErr = platform.api.hap.HapStatusError
14
+ this.hapServ = platform.api.hap.Service
15
+ this.platform = platform
16
+
17
+ // Set up variables from the accessory
18
+ this.accessory = accessory
19
+ this.name = accessory.displayName
20
+ const cloudRefreshRate = hasProperty(platform.config, 'cloudRefreshRate')
21
+ ? platform.config.cloudRefreshRate
22
+ : platformConsts.defaultValues.cloudRefreshRate
23
+ const localRefreshRate = hasProperty(platform.config, 'refreshRate')
24
+ ? platform.config.refreshRate
25
+ : platformConsts.defaultValues.refreshRate
26
+ this.pollInterval = accessory.context.connection === 'local'
27
+ ? localRefreshRate
28
+ : cloudRefreshRate
29
+
30
+ // Create the queue used for sending device requests
31
+ this.updateInProgress = false
32
+ this.queue = new PQueue({
33
+ concurrency: 1,
34
+ interval: 250,
35
+ intervalCap: 1,
36
+ timeout: 10000,
37
+ throwOnTimeout: true,
38
+ })
39
+ this.queue.on('idle', () => {
40
+ this.updateInProgress = false
41
+ })
42
+
43
+ // Set up the mqtt client for cloud devices to send and receive device updates
44
+ if (accessory.context.connection !== 'local') {
45
+ this.accessory.mqtt = new mqttClient(platform, this.accessory)
46
+ this.accessory.mqtt.connect()
47
+ }
48
+
49
+ // Always request a device update on startup, then start the interval for polling
50
+ setTimeout(() => this.requestUpdate(true), 2000)
51
+ this.accessory.refreshInterval = setInterval(
52
+ () => this.requestUpdate(),
53
+ this.pollInterval * 1000,
54
+ )
55
+
56
+ // Output the customised options to the log
57
+ const opts = JSON.stringify({
58
+ connection: this.accessory.context.connection,
59
+ })
60
+ platform.log('[%s] %s %s.', this.name, platformLang.devInitOpts, opts)
61
+ }
62
+
63
+ async requestUpdate(firstRun = false) {
64
+ try {
65
+ // Don't continue if an update is currently being sent to the device
66
+ if (this.updateInProgress) {
67
+ return
68
+ }
69
+
70
+ // Add the request to the queue so updates are sent apart
71
+ await this.queue.add(async () => {
72
+ // This flag stops the plugin from requesting updates while pending on others
73
+ this.updateInProgress = true
74
+
75
+ // Send the request
76
+ const res = await this.platform.sendUpdate(this.accessory, {
77
+ namespace: 'Appliance.System.All',
78
+ payload: {},
79
+ })
80
+
81
+ // Log the received data
82
+ this.accessory.logWarn(`${platformLang.incPoll}: ${JSON.stringify(res.data)}`)
83
+
84
+ // Check the response is in a useful format
85
+ const data = res.data.payload
86
+ if (data.all) {
87
+ /*
88
+ if (data.all.digest) {
89
+ if (data.all.digest.togglex && data.all.digest.togglex[0]) {
90
+ this.isToggleX = true
91
+ this.applyUpdate(data.all.digest.togglex[0])
92
+ } else if (data.all.digest.toggle) {
93
+ this.isToggleX = false
94
+ this.applyUpdate(data.all.digest.toggle)
95
+ }
96
+ }
97
+ */
98
+
99
+ // A flag to check if we need to update the accessory context
100
+ let needsUpdate = false
101
+
102
+ // Get the mac address and hardware version of the device
103
+ if (data.all.system) {
104
+ // Mac address and hardware don't change regularly so only get on first poll
105
+ if (firstRun && data.all.system.hardware) {
106
+ this.accessory.context.macAddress = data.all.system.hardware.macAddress.toUpperCase()
107
+ this.accessory.context.hardware = data.all.system.hardware.version
108
+ }
109
+
110
+ // Get the ip address and firmware of the device
111
+ if (data.all.system.firmware) {
112
+ // Check for an IP change each and every time the device is polled
113
+ if (this.accessory.context.ipAddress !== data.all.system.firmware.innerIp) {
114
+ this.accessory.context.ipAddress = data.all.system.firmware.innerIp
115
+ needsUpdate = true
116
+ }
117
+
118
+ // Firmware doesn't change regularly so only get on first poll
119
+ if (firstRun) {
120
+ this.accessory.context.firmware = data.all.system.firmware.version
121
+ }
122
+ }
123
+ }
124
+
125
+ // Get the cloud online status of the device
126
+ if (data.all.system.online) {
127
+ const isOnline = data.all.system.online.status === 1
128
+ if (this.accessory.context.isOnline !== isOnline) {
129
+ this.accessory.context.isOnline = isOnline
130
+ needsUpdate = true
131
+ }
132
+ }
133
+
134
+ // Update the accessory cache if anything has changed
135
+ if (needsUpdate || firstRun) {
136
+ this.platform.updateAccessory(this.accessory)
137
+ }
138
+ }
139
+ })
140
+ } catch (err) {
141
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
142
+ this.accessory.logWarn(`${platformLang.reqFailed}: ${eText}`)
143
+
144
+ // Set the homebridge-ui status of the device to offline if local and error is timeout
145
+ if (
146
+ (this.accessory.context.isOnline || firstRun)
147
+ && ['EHOSTUNREACH', 'timed out'].some(el => eText.includes(el))
148
+ ) {
149
+ this.accessory.context.isOnline = false
150
+ this.platform.updateAccessory(this.accessory)
151
+ }
152
+ }
153
+ }
154
+
155
+ receiveUpdate(params) {
156
+ try {
157
+ // Log the received data
158
+ this.accessory.logWarn(`${platformLang.incMQTT}: ${JSON.stringify(params)}`)
159
+ if (params.payload) {
160
+ /*
161
+ if (params.payload.togglex && params.payload.togglex[0]) {
162
+ this.applyUpdate(params.payload.togglex[0])
163
+ } else if (params.payload.toggle) {
164
+ this.applyUpdate(params.payload.toggle)
165
+ }
166
+ */
167
+ }
168
+ } catch (err) {
169
+ this.accessory.logWarn(`${platformLang.refFailed} ${parseError(err)}`)
170
+ }
171
+ }
172
+
173
+ applyUpdate(data) {
174
+ // Logic here
175
+ this.accessory.log(data)
176
+ }
177
+ }