@homebridge-plugins/homebridge-ewelink 12.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +1363 -0
  2. package/LICENSE +21 -0
  3. package/README.md +68 -0
  4. package/config.schema.json +1757 -0
  5. package/eslint.config.js +15 -0
  6. package/lib/connection/api.js +508 -0
  7. package/lib/connection/http.js +304 -0
  8. package/lib/connection/lan.js +318 -0
  9. package/lib/connection/ws.js +414 -0
  10. package/lib/device/curtain.js +324 -0
  11. package/lib/device/diffuser.js +473 -0
  12. package/lib/device/fan.js +349 -0
  13. package/lib/device/group.js +106 -0
  14. package/lib/device/humidifier.js +199 -0
  15. package/lib/device/index.js +61 -0
  16. package/lib/device/light-cct.js +333 -0
  17. package/lib/device/light-dimmer.js +257 -0
  18. package/lib/device/light-rgb-cct.js +809 -0
  19. package/lib/device/light-rgb.js +272 -0
  20. package/lib/device/motor.js +363 -0
  21. package/lib/device/outlet-multi.js +417 -0
  22. package/lib/device/outlet-single-inched.js +409 -0
  23. package/lib/device/outlet-single.js +384 -0
  24. package/lib/device/panel.js +382 -0
  25. package/lib/device/rf-bridge.js +321 -0
  26. package/lib/device/rf-button.js +125 -0
  27. package/lib/device/rf-sensor.js +173 -0
  28. package/lib/device/sensor-ambient.js +311 -0
  29. package/lib/device/sensor-contact.js +140 -0
  30. package/lib/device/sensor-temp-humi.js +182 -0
  31. package/lib/device/simulation/blind.js +253 -0
  32. package/lib/device/simulation/cooler.js +312 -0
  33. package/lib/device/simulation/door.js +253 -0
  34. package/lib/device/simulation/doorbell.js +190 -0
  35. package/lib/device/simulation/garage-eachen.js +235 -0
  36. package/lib/device/simulation/garage-four.js +176 -0
  37. package/lib/device/simulation/garage-od-switch.js +36 -0
  38. package/lib/device/simulation/garage-one.js +395 -0
  39. package/lib/device/simulation/garage-two.js +394 -0
  40. package/lib/device/simulation/gate-one.js +327 -0
  41. package/lib/device/simulation/heater.js +389 -0
  42. package/lib/device/simulation/index.js +75 -0
  43. package/lib/device/simulation/light-fan.js +258 -0
  44. package/lib/device/simulation/lock-eachen.js +163 -0
  45. package/lib/device/simulation/lock-one.js +366 -0
  46. package/lib/device/simulation/p-button.js +223 -0
  47. package/lib/device/simulation/purifier.js +289 -0
  48. package/lib/device/simulation/rf-blind.js +192 -0
  49. package/lib/device/simulation/rf-door.js +180 -0
  50. package/lib/device/simulation/rf-window.js +180 -0
  51. package/lib/device/simulation/sensor-hidden.js +105 -0
  52. package/lib/device/simulation/sensor-leak.js +123 -0
  53. package/lib/device/simulation/sensor-visible.js +231 -0
  54. package/lib/device/simulation/sensor.js +300 -0
  55. package/lib/device/simulation/switch-valve.js +351 -0
  56. package/lib/device/simulation/tap-one.js +283 -0
  57. package/lib/device/simulation/tap-two.js +266 -0
  58. package/lib/device/simulation/th-cooler.js +443 -0
  59. package/lib/device/simulation/th-dehumidifier.js +424 -0
  60. package/lib/device/simulation/th-heater.js +449 -0
  61. package/lib/device/simulation/th-humidifier.js +424 -0
  62. package/lib/device/simulation/th-thermostat.js +611 -0
  63. package/lib/device/simulation/tv.js +252 -0
  64. package/lib/device/simulation/valve-four.js +232 -0
  65. package/lib/device/simulation/valve-one.js +345 -0
  66. package/lib/device/simulation/valve-two.js +340 -0
  67. package/lib/device/simulation/window.js +253 -0
  68. package/lib/device/switch-man.js +106 -0
  69. package/lib/device/switch-mate.js +82 -0
  70. package/lib/device/switch-multi.js +411 -0
  71. package/lib/device/switch-single-inched.js +332 -0
  72. package/lib/device/switch-single.js +307 -0
  73. package/lib/device/template.js +43 -0
  74. package/lib/device/thermostat.js +286 -0
  75. package/lib/device/zigbee/index.js +27 -0
  76. package/lib/device/zigbee/light-cct.js +263 -0
  77. package/lib/device/zigbee/light-dimmer.js +148 -0
  78. package/lib/device/zigbee/light-rgb-cct.js +400 -0
  79. package/lib/device/zigbee/motor.js +301 -0
  80. package/lib/device/zigbee/sensor-ambient.js +177 -0
  81. package/lib/device/zigbee/sensor-contact.js +137 -0
  82. package/lib/device/zigbee/sensor-leak.js +119 -0
  83. package/lib/device/zigbee/sensor-motion.js +119 -0
  84. package/lib/device/zigbee/sensor-occupancy.js +119 -0
  85. package/lib/device/zigbee/sensor-smoke.js +96 -0
  86. package/lib/device/zigbee/switch-stateless.js +104 -0
  87. package/lib/device/zigbee/thermostat.js +323 -0
  88. package/lib/fakegato/LICENSE +21 -0
  89. package/lib/fakegato/fakegato-history.js +813 -0
  90. package/lib/fakegato/fakegato-storage.js +108 -0
  91. package/lib/fakegato/fakegato-timer.js +125 -0
  92. package/lib/fakegato/uuid.js +27 -0
  93. package/lib/homebridge-ui/public/index.html +365 -0
  94. package/lib/homebridge-ui/server.js +46 -0
  95. package/lib/index.js +7 -0
  96. package/lib/node-dns-sd/LICENSE +21 -0
  97. package/lib/node-dns-sd/README.md +613 -0
  98. package/lib/node-dns-sd/lib/dns-sd-classes.json +6 -0
  99. package/lib/node-dns-sd/lib/dns-sd-composer.js +83 -0
  100. package/lib/node-dns-sd/lib/dns-sd-parser.js +344 -0
  101. package/lib/node-dns-sd/lib/dns-sd-types.json +52 -0
  102. package/lib/node-dns-sd/lib/dns-sd.js +580 -0
  103. package/lib/platform.js +2156 -0
  104. package/lib/utils/colour.js +552 -0
  105. package/lib/utils/constants.js +589 -0
  106. package/lib/utils/custom-chars.js +33 -0
  107. package/lib/utils/eve-chars.js +130 -0
  108. package/lib/utils/functions.js +42 -0
  109. package/lib/utils/lang-en.js +160 -0
  110. package/lib/utils/lang-fr.js +163 -0
  111. package/lib/utils/lang-th.js +160 -0
  112. package/lib/utils/lang.js +5 -0
  113. package/package.json +75 -0
@@ -0,0 +1,382 @@
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.hapErr = platform.api.hap.HapStatusError
9
+ this.hapServ = platform.api.hap.Service
10
+ this.lang = platform.lang
11
+ this.log = platform.log
12
+ this.platform = platform
13
+
14
+ // Set up variables from the accessory
15
+ this.name = accessory.displayName
16
+ this.accessory = accessory
17
+ this.isProPanel = accessory.context.eweUIID === 195
18
+
19
+ // Initially set the online flag as true (to be then updated as false if necessary)
20
+ this.isOnline = true
21
+
22
+ // Set up custom variables for this device type
23
+ const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
24
+ this.tempOffset = deviceConf.offset || platformConsts.defaultValues.offset
25
+ this.tempOffsetFactor = deviceConf.offsetFactor
26
+
27
+ // Set the correct logging variables for this accessory
28
+ switch (deviceConf.overrideLogging) {
29
+ case 'standard':
30
+ this.enableLogging = true
31
+ this.enableDebugLogging = false
32
+ break
33
+ case 'debug':
34
+ this.enableLogging = true
35
+ this.enableDebugLogging = true
36
+ break
37
+ case 'disable':
38
+ this.enableLogging = false
39
+ this.enableDebugLogging = false
40
+ break
41
+ default:
42
+ this.enableLogging = !platform.config.disableDeviceLogging
43
+ this.enableDebugLogging = platform.config.debug
44
+ break
45
+ }
46
+
47
+ // Add the temperature sensor service if it doesn't already exist
48
+ this.tempService = this.accessory.getService(this.hapServ.TemperatureSensor)
49
+ || this.accessory.addService(this.hapServ.TemperatureSensor)
50
+
51
+ // Set custom properties of the current temperature characteristic
52
+ this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).setProps({
53
+ minStep: 0.1,
54
+ })
55
+ this.cacheTemp = this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).value
56
+ this.updateCache()
57
+
58
+ if (!this.isProPanel) {
59
+ // Add the outlet services if they don't already exist
60
+ this.service1 = this.accessory.getService('Channel 1')
61
+ || this.accessory.addService(this.hapServ.Switch, 'Channel 1', 'channel1')
62
+ this.service2 = this.accessory.getService('Channel 2')
63
+ || this.accessory.addService(this.hapServ.Switch, 'Channel 2', 'channel2')
64
+
65
+ // Add the set handler to the switch on/off characteristic
66
+ this.service1.getCharacteristic(this.hapChar.On).onSet(async (value) => {
67
+ await this.internalStateUpdate(this.service1, value)
68
+ })
69
+ this.cacheState1 = this.service1.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
70
+ this.service2.getCharacteristic(this.hapChar.On).onSet(async (value) => {
71
+ await this.internalStateUpdate(this.service2, value)
72
+ })
73
+ this.cacheState2 = this.service2.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
74
+
75
+ // Add the get handlers only if the user hasn't disabled the disableNoResponse setting
76
+ if (!platform.config.disableNoResponse) {
77
+ this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).onGet(() => {
78
+ if (!this.isOnline) {
79
+ throw new this.hapErr(-70402)
80
+ }
81
+ return this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).value
82
+ })
83
+ this.service1.getCharacteristic(this.hapChar.On).onGet(() => {
84
+ if (!this.isOnline) {
85
+ throw new this.hapErr(-70402)
86
+ }
87
+ return this.service1.getCharacteristic(this.hapChar.On).value
88
+ })
89
+ this.service2.getCharacteristic(this.hapChar.On).onGet(() => {
90
+ if (!this.isOnline) {
91
+ throw new this.hapErr(-70402)
92
+ }
93
+ return this.service1.getCharacteristic(this.hapChar.On).value
94
+ })
95
+ }
96
+ }
97
+
98
+ // Pass the accessory to Fakegato to set up with Eve
99
+ this.accessory.eveService = new platform.eveService('custom', this.accessory, {
100
+ log: () => {},
101
+ })
102
+
103
+ // Output the customised options to the log
104
+ const normalLogging = this.enableLogging ? 'standard' : 'disable'
105
+ const opts = JSON.stringify({
106
+ logging: this.enableDebugLogging ? 'debug' : normalLogging,
107
+ offset: this.tempOffset,
108
+ offsetFactor: this.tempOffsetFactor,
109
+ })
110
+ this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
111
+
112
+ /*
113
+ {
114
+ "bindInfos":{
115
+ "gaction":[
116
+ ""
117
+ ],
118
+ "scene":2
119
+ },
120
+ "version":8,
121
+ "pulses":[
122
+ {
123
+ "pulse":"off",
124
+ "width":1000,
125
+ "outlet":0
126
+ },
127
+ {
128
+ "pulse":"off",
129
+ "width":1000,
130
+ "outlet":1
131
+ }
132
+ ],
133
+ "switches":[
134
+ {
135
+ "switch":"off",
136
+ "outlet":0
137
+ },
138
+ {
139
+ "switch":"off",
140
+ "outlet":1
141
+ }
142
+ ],
143
+ "configure":[
144
+ {
145
+ "startup":"off",
146
+ "outlet":0
147
+ },
148
+ {
149
+ "startup":"off",
150
+ "outlet":1
151
+ }
152
+ ],
153
+ "lock":0,
154
+ "fwVersion":"1.0.2",
155
+ "temperature":24,
156
+ "humidity":50,
157
+ "tempUnit":0,
158
+ "HMI_outdoorTemp":{
159
+ "current":13,
160
+ "range":"-2,14"
161
+ },
162
+ "HMI_weather":1,
163
+ "cityId":"00000",
164
+ "dst":0,
165
+ "dstChange":"",
166
+ "geo":"",
167
+ "timeZone":1,
168
+ "HMI_dimEnable":0,
169
+ "HMI_resources":[
170
+ {
171
+ "ctype":"device",
172
+ "id":"100000000",
173
+ "uiid":6
174
+ },
175
+ {
176
+ "ctype":"device",
177
+ "id":"100000001",
178
+ "uiid":1
179
+ },
180
+ {
181
+ "ctype":"device",
182
+ "id":"100000002",
183
+ "uiid":6
184
+ },
185
+ {
186
+ "ctype":"idle"
187
+ },
188
+ {
189
+ "ctype":"idle"
190
+ },
191
+ {
192
+ "ctype":"idle"
193
+ },
194
+ {
195
+ "ctype":"idle"
196
+ },
197
+ {
198
+ "ctype":"idle"
199
+ }
200
+ ],
201
+ "HMI_ATCDevice":{
202
+ "ctype":"device",
203
+ "id":"100000000",
204
+ "outlet":0,
205
+ "etype":"hot"
206
+ },
207
+ "ctype":"device",
208
+ "id":"100000000",
209
+ "resourcetype":"ATC",
210
+ "ATCMode":1,
211
+ "ATCExpect0":23,
212
+ "ATCEnable":1,
213
+ "ATCExpect1":23
214
+ }
215
+ */
216
+ }
217
+
218
+ async internalStateUpdate(service, value) {
219
+ try {
220
+ const newValue = value ? 'on' : 'off'
221
+ const params = { switches: [] }
222
+ switch (service) {
223
+ case this.service1: {
224
+ if (newValue === this.cacheState1) {
225
+ return
226
+ }
227
+ params.switches.push({ outlet: 0, switch: value ? 'on' : 'off' })
228
+ break
229
+ }
230
+ case this.service2: {
231
+ if (newValue === this.cacheState2) {
232
+ return
233
+ }
234
+ params.switches.push({ outlet: 1, switch: value ? 'on' : 'off' })
235
+ break
236
+ }
237
+ default:
238
+ return
239
+ }
240
+ await this.platform.sendDeviceUpdate(this.accessory, params)
241
+ switch (service) {
242
+ case this.service1: {
243
+ this.cacheState1 = newValue
244
+ if (this.enableLogging) {
245
+ this.log(
246
+ '[%s] [%s] %s [%s].',
247
+ this.name,
248
+ service.displayName,
249
+ this.lang.curState,
250
+ this.cacheState1,
251
+ )
252
+ }
253
+ break
254
+ }
255
+ case this.service2: {
256
+ this.cacheState2 = newValue
257
+ if (this.enableLogging) {
258
+ this.log(
259
+ '[%s] [%s] %s [%s].',
260
+ this.name,
261
+ service.displayName,
262
+ this.lang.curState,
263
+ this.cacheState2,
264
+ )
265
+ }
266
+ break
267
+ }
268
+ default:
269
+ }
270
+ } catch (err) {
271
+ this.platform.deviceUpdateError(this.accessory, err, true)
272
+ setTimeout(() => {
273
+ service.updateCharacteristic(
274
+ this.hapChar.On,
275
+ service.getCharacteristic(this.hapChar.On).value,
276
+ )
277
+ }, 2000)
278
+ throw new this.hapErr(-70402)
279
+ }
280
+ }
281
+
282
+ async externalUpdate(params) {
283
+ try {
284
+ // Switches
285
+ if (params.switches && Array.isArray(params.switches)) {
286
+ params.switches.forEach((switchEntry) => {
287
+ const newValue = switchEntry.switch
288
+ switch (switchEntry.outlet) {
289
+ case 0: {
290
+ if (newValue !== this.cacheState1) {
291
+ this.cacheState1 = newValue
292
+ this.service1.updateCharacteristic(this.hapChar.On, this.cacheState1 === 'on')
293
+ if (params.updateSource && this.enableLogging) {
294
+ this.log(
295
+ '[%s] [%s] %s [%s].',
296
+ this.name,
297
+ this.service1.displayName,
298
+ this.lang.curState,
299
+ this.cacheState1,
300
+ )
301
+ }
302
+ }
303
+ break
304
+ }
305
+ case 1: {
306
+ if (newValue !== this.cacheState2) {
307
+ this.cacheState2 = newValue
308
+ this.service2.updateCharacteristic(this.hapChar.On, this.cacheState2 === 'on')
309
+ if (params.updateSource && this.enableLogging) {
310
+ this.log(
311
+ '[%s] [%s] %s [%s].',
312
+ this.name,
313
+ this.service2.displayName,
314
+ this.lang.curState,
315
+ this.cacheState2,
316
+ )
317
+ }
318
+ }
319
+ break
320
+ }
321
+ default:
322
+ }
323
+ })
324
+ }
325
+
326
+ // Current temperature
327
+ if (hasProperty(params, 'temperature')) {
328
+ let newTemp = Number(params.temperature)
329
+ if (this.tempOffsetFactor) {
330
+ newTemp *= this.tempOffset
331
+ } else {
332
+ newTemp += this.tempOffset
333
+ }
334
+ if (newTemp !== this.cacheTemp) {
335
+ this.cacheTemp = newTemp
336
+ this.tempService.updateCharacteristic(this.hapChar.CurrentTemperature, this.cacheTemp)
337
+ this.accessory.eveService.addEntry({ temp: this.cacheTemp })
338
+ if (params.updateSource && this.enableLogging) {
339
+ this.log('[%s] %s [%s°C].', this.name, this.lang.curTemp, this.cacheTemp)
340
+ }
341
+
342
+ // Update the cache file with the new temperature
343
+ this.updateCache()
344
+ }
345
+ }
346
+ } catch (err) {
347
+ this.platform.deviceUpdateError(this.accessory, err, false)
348
+ }
349
+ }
350
+
351
+ async updateCache() {
352
+ // Don't continue if the storage client hasn't initialised properly
353
+ if (!this.platform.storageClientData) {
354
+ return
355
+ }
356
+
357
+ // Attempt to save the new temperature to the cache
358
+ try {
359
+ await this.platform.storageData.setItem(
360
+ `${this.accessory.context.eweDeviceId}_temp`,
361
+ this.cacheTemp,
362
+ )
363
+ } catch (err) {
364
+ if (this.enableLogging) {
365
+ this.log.warn('[%s] %s %s.', this.name, this.lang.storageWriteErr, parseError(err))
366
+ }
367
+ }
368
+ }
369
+
370
+ currentState() {
371
+ const toReturn = {}
372
+ toReturn.services = ['temperature']
373
+ toReturn.temperature = {
374
+ current: this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).value,
375
+ }
376
+ return toReturn
377
+ }
378
+
379
+ markStatus(isOnline) {
380
+ this.isOnline = isOnline
381
+ }
382
+ }
@@ -0,0 +1,321 @@
1
+ import axios from 'axios'
2
+ import platformConsts from '../utils/constants.js'
3
+ import { hasProperty, parseError, sleep } from '../utils/functions.js'
4
+
5
+ export default class {
6
+ constructor(platform, accessory, devicesInHB) {
7
+ // Set up variables from the platform
8
+ this.devicesInHB = devicesInHB
9
+ this.disableDeviceLogging = platform.config.disableDeviceLogging
10
+ this.eveChar = platform.eveChar
11
+ this.hapChar = platform.api.hap.Characteristic
12
+ this.hapErr = platform.api.hap.HapStatusError
13
+ this.hapServ = platform.api.hap.Service
14
+ this.lang = platform.lang
15
+ this.log = platform.log
16
+ this.platform = platform
17
+
18
+ // Set up variables from the accessory
19
+ this.name = accessory.displayName
20
+ this.accessory = accessory
21
+
22
+ // Initially set the online flag as true (to be then updated as false if necessary)
23
+ this.isOnline = true
24
+
25
+ // Set up custom variables for this device type
26
+ const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
27
+ const { resetOnStartup } = deviceConf
28
+
29
+ // Set the correct logging variables for this accessory
30
+ switch (deviceConf.overrideLogging) {
31
+ case 'standard':
32
+ this.enableLogging = true
33
+ this.enableDebugLogging = false
34
+ break
35
+ case 'debug':
36
+ this.enableLogging = true
37
+ this.enableDebugLogging = true
38
+ break
39
+ case 'disable':
40
+ this.enableLogging = false
41
+ this.enableDebugLogging = false
42
+ break
43
+ default:
44
+ this.enableLogging = !platform.config.disableDeviceLogging
45
+ this.enableDebugLogging = platform.config.debug
46
+ break
47
+ }
48
+
49
+ // Output the customised options to the log
50
+ const normalLogging = this.enableLogging ? 'standard' : 'disable'
51
+ const opts = JSON.stringify({
52
+ logging: this.enableDebugLogging ? 'debug' : normalLogging,
53
+ resetOnStartup,
54
+ })
55
+ this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
56
+ }
57
+
58
+ async externalUpdate(params) {
59
+ try {
60
+ if (!hasProperty(params, 'updateSource')) {
61
+ return
62
+ }
63
+ const timeNow = new Date()
64
+ let subAccessory = false
65
+ let channel
66
+ if (
67
+ hasProperty(params, 'cmd')
68
+ && params.cmd === 'transmit'
69
+ && hasProperty(params, 'rfChl')
70
+ ) {
71
+ // RF Button
72
+ this.devicesInHB.forEach((acc) => {
73
+ if (
74
+ acc.context.eweDeviceId === this.accessory.context.eweDeviceId
75
+ && hasProperty(acc.context, 'buttons')
76
+ && hasProperty(acc.context.buttons, params.rfChl.toString())
77
+ ) {
78
+ subAccessory = acc
79
+ }
80
+ })
81
+ if (subAccessory) {
82
+ const deviceConf = this.platform.rfSubdevices[subAccessory.context.hbDeviceId]
83
+ let enableLogging
84
+ switch (deviceConf.overrideLogging) {
85
+ case 'standard':
86
+ case 'debug':
87
+ enableLogging = true
88
+ break
89
+ case 'disable':
90
+ enableLogging = false
91
+ break
92
+ default:
93
+ enableLogging = !this.disableDeviceLogging
94
+ break
95
+ }
96
+ const service = subAccessory.context.buttons[params.rfChl]
97
+ subAccessory.getService(service).updateCharacteristic(this.hapChar.On, true)
98
+ if (params.updateSource && enableLogging) {
99
+ this.log(
100
+ '[%s] %s [%s].',
101
+ subAccessory.displayName,
102
+ this.lang.curState,
103
+ this.lang.buttonTrig,
104
+ )
105
+ }
106
+ await sleep(3000)
107
+ subAccessory.getService(service).updateCharacteristic(this.hapChar.On, false)
108
+ } else {
109
+ throw new Error(this.lang.buttonNotFound)
110
+ }
111
+ } else if (
112
+ (hasProperty(params, 'cmd') && params.cmd === 'trigger')
113
+ || params.updateSource === 'LAN'
114
+ ) {
115
+ // RF Sensor
116
+ Object.keys(params)
117
+ .filter(name => /rfTrig/.test(name))
118
+ .forEach(async (chan) => {
119
+ try {
120
+ this.devicesInHB.forEach((acc) => {
121
+ if (
122
+ acc.context.eweDeviceId === this.accessory.context.eweDeviceId
123
+ && hasProperty(acc.context, 'buttons')
124
+ && hasProperty(acc.context.buttons, chan.split('g')[1].toString())
125
+ ) {
126
+ subAccessory = acc
127
+ channel = chan.split('g')[1].toString()
128
+ }
129
+ })
130
+ if (subAccessory) {
131
+ // Avoid duplicate triggers from LAN and WS
132
+ if (params[chan] === subAccessory.context.cacheLastAct) {
133
+ return
134
+ }
135
+ const deviceConf = this.platform.rfSubdevices[subAccessory.context.hbDeviceId] || {}
136
+ let enableLogging
137
+ switch (deviceConf.overrideLogging) {
138
+ case 'standard':
139
+ case 'debug':
140
+ enableLogging = true
141
+ break
142
+ case 'disable':
143
+ enableLogging = false
144
+ break
145
+ default:
146
+ enableLogging = !this.disableDeviceLogging
147
+ break
148
+ }
149
+ switch (subAccessory.context.subType) {
150
+ case 'blind':
151
+ case 'door':
152
+ case 'window':
153
+ // Simulations don't support external updates
154
+ return
155
+ case 'button':
156
+ case 'curtain': {
157
+ const service = subAccessory.context.buttons[channel]
158
+ subAccessory.getService(service).updateCharacteristic(this.hapChar.On, true)
159
+ this.log(
160
+ '[%s] %s [%s].',
161
+ subAccessory.displayName,
162
+ this.lang.curState,
163
+ this.lang.buttonTrig,
164
+ )
165
+ await sleep(3000)
166
+ subAccessory.getService(service).updateCharacteristic(this.hapChar.On, false)
167
+ return
168
+ }
169
+ default:
170
+ break
171
+ }
172
+ const sensorTimeLength = deviceConf.sensorTimeLength || platformConsts.defaultValues.sensorTimeLength
173
+ const sensorTimeDifference = deviceConf.sensorTimeDifference || platformConsts.defaultValues.sensorTimeDifference
174
+ subAccessory.context.cacheLastAct = params[chan]
175
+ const timeOfMotion = new Date(params[chan])
176
+ const diff = (timeNow.getTime() - timeOfMotion.getTime()) / 1000
177
+ let serv
178
+ let char
179
+ if (diff < sensorTimeDifference) {
180
+ switch (deviceConf.type) {
181
+ case 'water':
182
+ serv = this.hapServ.LeakSensor
183
+ char = this.hapChar.LeakDetected
184
+ break
185
+ case 'fire':
186
+ case 'smoke':
187
+ serv = this.hapServ.SmokeSensor
188
+ char = this.hapChar.SmokeDetected
189
+ break
190
+ case 'co':
191
+ serv = this.hapServ.CarbonMonoxideSensor
192
+ char = this.hapChar.CarbonMonoxideDetected
193
+ break
194
+ case 'co2':
195
+ serv = this.hapServ.CarbonDioxideSensor
196
+ char = this.hapChar.CarbonDioxideDetected
197
+ break
198
+ case 'contact': {
199
+ serv = this.hapServ.ContactSensor
200
+ char = this.hapChar.ContactSensorState
201
+ const initialTime = subAccessory.eveService.getInitialTime()
202
+ subAccessory
203
+ .getService(serv)
204
+ .updateCharacteristic(
205
+ this.eveChar.LastActivation,
206
+ Math.round(new Date().valueOf() / 1000) - initialTime,
207
+ )
208
+ break
209
+ }
210
+ case 'occupancy':
211
+ serv = this.hapServ.OccupancySensor
212
+ char = this.hapChar.OccupancyDetected
213
+ break
214
+ case 'p_button':
215
+ serv = this.hapServ.StatelessProgrammableSwitch
216
+ char = this.hapChar.ProgrammableSwitchEvent
217
+ break
218
+ case 'doorbell':
219
+ serv = this.hapServ.Doorbell
220
+ char = this.hapChar.ProgrammableSwitchEvent
221
+ break
222
+ default: {
223
+ serv = this.hapServ.MotionSensor
224
+ char = this.hapChar.MotionDetected
225
+ const initialTime = subAccessory.eveService.getInitialTime()
226
+ subAccessory
227
+ .getService(serv)
228
+ .updateCharacteristic(
229
+ this.eveChar.LastActivation,
230
+ Math.round(new Date().valueOf() / 1000) - initialTime,
231
+ )
232
+ break
233
+ }
234
+ }
235
+
236
+ // Call any webhook that is defined in the config
237
+ if (deviceConf.sensorWebHook) {
238
+ try {
239
+ await axios.get(deviceConf.sensorWebHook, {
240
+ timeout: 5000,
241
+ })
242
+ if (enableLogging) {
243
+ this.log(
244
+ '[%s] %s [GET %s].',
245
+ subAccessory.displayName,
246
+ 'http webhook request successful',
247
+ deviceConf.sensorWebHook,
248
+ )
249
+ }
250
+ } catch (e) {
251
+ if (enableLogging) {
252
+ this.log(
253
+ '[%s] %s %s.',
254
+ subAccessory.displayName,
255
+ 'http webhook request failed as',
256
+ e.message,
257
+ )
258
+ }
259
+ }
260
+ }
261
+
262
+ // Programmable button and doorbell activate differently
263
+ if (char === this.hapChar.ProgrammableSwitchEvent) {
264
+ subAccessory.getService(serv).updateCharacteristic(char, 0)
265
+ if (params.updateSource && enableLogging) {
266
+ this.log(
267
+ '[%s] %s [%s].',
268
+ subAccessory.displayName,
269
+ this.lang.curState,
270
+ this.lang.buttonSingle,
271
+ )
272
+ }
273
+ return
274
+ }
275
+ subAccessory.getService(serv).updateCharacteristic(char, 1)
276
+ subAccessory.eveService.addEntry({ status: 1 })
277
+ if (params.updateSource && enableLogging) {
278
+ this.log(
279
+ '[%s] %s [%s].',
280
+ subAccessory.displayName,
281
+ this.lang.curState,
282
+ this.lang.rfTrigYes,
283
+ )
284
+ }
285
+
286
+ const updateKey = Math.random()
287
+ .toString(36)
288
+ .substr(2, 8)
289
+ subAccessory.context.updateKey = updateKey
290
+ await sleep(sensorTimeLength * 1000)
291
+ if (updateKey !== subAccessory.context.updateKey) {
292
+ return
293
+ }
294
+ subAccessory.getService(serv).updateCharacteristic(char, 0)
295
+ subAccessory.eveService.addEntry({ status: 0 })
296
+ if (params.updateSource && enableLogging) {
297
+ this.log(
298
+ '[%s] %s [%s].',
299
+ subAccessory.displayName,
300
+ this.lang.curState,
301
+ this.lang.rfTrigNo,
302
+ )
303
+ }
304
+ }
305
+ } else {
306
+ throw new Error(`${this.lang.rfNotFound}[${chan}]`)
307
+ }
308
+ } catch (err) {
309
+ this.log.warn('[%s] %s %s.', this.name, this.lang.devNotRf, parseError(err))
310
+ }
311
+ })
312
+ }
313
+ } catch (err) {
314
+ this.platform.deviceUpdateError(this.accessory, err, false)
315
+ }
316
+ }
317
+
318
+ markStatus(isOnline) {
319
+ this.isOnline = isOnline
320
+ }
321
+ }