@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,252 @@
1
+ import platformConsts from '../../utils/constants.js'
2
+ import { hasProperty } from '../../utils/functions.js'
3
+
4
+ export default class {
5
+ constructor(platform, accessory) {
6
+ // Set up variables from the platform
7
+ this.eveChar = platform.eveChar
8
+ this.hapChar = platform.api.hap.Characteristic
9
+ this.hapErr = platform.api.hap.HapStatusError
10
+ this.hapServ = platform.api.hap.Service
11
+ this.lang = platform.lang
12
+ this.log = platform.log
13
+ this.platform = platform
14
+
15
+ // Set up variables from the accessory
16
+ this.name = accessory.displayName
17
+ this.accessory = accessory
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
+
25
+ // Set the correct logging variables for this accessory
26
+ switch (deviceConf.overrideLogging) {
27
+ case 'standard':
28
+ this.enableLogging = true
29
+ this.enableDebugLogging = false
30
+ break
31
+ case 'debug':
32
+ this.enableLogging = true
33
+ this.enableDebugLogging = true
34
+ break
35
+ case 'disable':
36
+ this.enableLogging = false
37
+ this.enableDebugLogging = false
38
+ break
39
+ default:
40
+ this.enableLogging = !platform.config.disableDeviceLogging
41
+ this.enableDebugLogging = platform.config.debug
42
+ break
43
+ }
44
+
45
+ // Add the tv service if it doesn't already exist
46
+ this.service = this.accessory.getService(this.hapServ.Television)
47
+ || this.accessory.addService(this.hapServ.Television)
48
+
49
+ // Set up the device type and power readings if necessary
50
+ if (platformConsts.devices.switchSingle.includes(this.accessory.context.eweUIID)) {
51
+ this.setup = 'switchSingle'
52
+ } else if (platformConsts.devices.switchSinglePower.includes(this.accessory.context.eweUIID)) {
53
+ this.setup = 'switchSingle'
54
+
55
+ // Add Eve power characteristics
56
+ this.powerReadings = true
57
+ if (!this.service.testCharacteristic(this.eveChar.CurrentConsumption)) {
58
+ this.service.addCharacteristic(this.eveChar.CurrentConsumption)
59
+ }
60
+ if (this.accessory.context.eweUIID === 32) {
61
+ if (!this.service.testCharacteristic(this.eveChar.ElectricCurrent)) {
62
+ this.service.addCharacteristic(this.eveChar.ElectricCurrent)
63
+ }
64
+ if (!this.service.testCharacteristic(this.eveChar.Voltage)) {
65
+ this.service.addCharacteristic(this.eveChar.Voltage)
66
+ }
67
+ }
68
+ } else if (platformConsts.devices.switchMulti.includes(this.accessory.context.eweUIID)) {
69
+ this.setup = 'switchMulti'
70
+ if (platformConsts.devices.switchMultiPower.includes(this.accessory.context.eweUIID)) {
71
+ // Add Eve power characteristics
72
+ this.powerReadings = true
73
+ if (!this.service.testCharacteristic(this.eveChar.CurrentConsumption)) {
74
+ this.service.addCharacteristic(this.eveChar.CurrentConsumption)
75
+ }
76
+ if (!this.service.testCharacteristic(this.eveChar.ElectricCurrent)) {
77
+ this.service.addCharacteristic(this.eveChar.ElectricCurrent)
78
+ }
79
+ if (!this.service.testCharacteristic(this.eveChar.Voltage)) {
80
+ this.service.addCharacteristic(this.eveChar.Voltage)
81
+ }
82
+ this.isDualR3 = true
83
+ }
84
+ } else if (platformConsts.devices.switchSCM.includes(this.accessory.context.eweUIID)) {
85
+ this.setup = 'switchMulti'
86
+ } else if (platformConsts.devices.switchSCMPower.includes(this.accessory.context.eweUIID)) {
87
+ // Could do power here
88
+ this.setup = 'switchMulti'
89
+ }
90
+
91
+ // Add the set handler to the tv active characteristic
92
+ this.service.getCharacteristic(this.hapChar.Active).onSet(async (value) => {
93
+ await this.internalUpdate(value)
94
+ })
95
+
96
+ // Add the get handlers only if the user hasn't disabled the disableNoResponse setting
97
+ if (!platform.config.disableNoResponse) {
98
+ this.service.getCharacteristic(this.hapChar.Active).onGet(() => {
99
+ if (!this.isOnline) {
100
+ throw new this.hapErr(-70402)
101
+ }
102
+ return this.service.getCharacteristic(this.hapChar.Active).value
103
+ })
104
+ }
105
+
106
+ // Set up an interval to get eWeLink to send power updates
107
+ if (
108
+ this.powerReadings
109
+ && (!this.isDualR3 || (this.isDualR3 && platform.config.mode !== 'lan'))
110
+ ) {
111
+ setTimeout(() => {
112
+ this.internalUIUpdate()
113
+ this.intervalPoll = setInterval(() => this.internalUIUpdate(), 120000)
114
+ }, 5000)
115
+
116
+ // Stop the intervals on Homebridge shutdown
117
+ platform.api.on('shutdown', () => clearInterval(this.intervalPoll))
118
+ }
119
+
120
+ // Output the customised options to the log
121
+ const normalLogging = this.enableLogging ? 'standard' : 'disable'
122
+ const opts = JSON.stringify({
123
+ logging: this.enableDebugLogging ? 'debug' : normalLogging,
124
+ showAs: 'audio/box/stick',
125
+ })
126
+ this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
127
+ }
128
+
129
+ async internalUpdate(value) {
130
+ try {
131
+ const params = {}
132
+ switch (this.setup) {
133
+ case 'switchSingle':
134
+ params.switch = value === 1 ? 'on' : 'off'
135
+ break
136
+ case 'switchMulti':
137
+ params.switches = [
138
+ {
139
+ switch: value === 1 ? 'on' : 'off',
140
+ outlet: 0,
141
+ },
142
+ ]
143
+ break
144
+ default:
145
+ return
146
+ }
147
+ await this.platform.sendDeviceUpdate(this.accessory, params)
148
+ this.cacheState = value === 1 ? 'on' : 'off'
149
+ if (this.enableLogging) {
150
+ this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
151
+ }
152
+ } catch (err) {
153
+ this.platform.deviceUpdateError(this.accessory, err, true)
154
+ setTimeout(() => {
155
+ this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
156
+ }, 2000)
157
+ throw new this.hapErr(-70402)
158
+ }
159
+ }
160
+
161
+ async internalUIUpdate() {
162
+ try {
163
+ // Skip polling if device isn't online
164
+ if (!this.isOnline) {
165
+ return
166
+ }
167
+
168
+ // Send the params to request the updates
169
+ if (this.isDualR3) {
170
+ await this.platform.sendDeviceUpdate(this.accessory, { uiActive: { outlet: 0, time: 120 } })
171
+ } else {
172
+ await this.platform.sendDeviceUpdate(this.accessory, { uiActive: 120 })
173
+ }
174
+ } catch (err) {
175
+ // Suppress errors here
176
+ }
177
+ }
178
+
179
+ async externalUpdate(params) {
180
+ try {
181
+ if (
182
+ (this.setup === 'switchMulti' && params.switches)
183
+ || (this.setup === 'switchSingle' && params.switch)
184
+ ) {
185
+ let newState
186
+ if (this.setup === 'switchMulti' && params.switches) {
187
+ newState = params.switches[0].switch
188
+ } else if (this.setup === 'switchSingle' && params.switch) {
189
+ newState = params.switch
190
+ }
191
+ if (newState && newState !== this.cacheState) {
192
+ this.cacheState = newState
193
+ this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
194
+ if (params.updateSource && this.enableLogging) {
195
+ this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
196
+ }
197
+ }
198
+ }
199
+
200
+ // Get the power readings given by certain devices
201
+ if (!this.powerReadings) {
202
+ return
203
+ }
204
+ let logger = false
205
+ let power
206
+ let voltage
207
+ let current
208
+ if (hasProperty(params, 'actPow_00')) {
209
+ power = Number.parseInt(params.actPow_00, 10) / 100
210
+ this.service.updateCharacteristic(this.eveChar.CurrentConsumption, power)
211
+ logger = true
212
+ } else if (hasProperty(params, 'power')) {
213
+ power = Number.parseFloat(params.power)
214
+ this.service.updateCharacteristic(this.eveChar.CurrentConsumption, power)
215
+ logger = true
216
+ }
217
+ if (hasProperty(params, 'voltage_00')) {
218
+ voltage = Number.parseInt(params.voltage_00, 10) / 100
219
+ this.service.updateCharacteristic(this.eveChar.Voltage, voltage)
220
+ logger = true
221
+ } else if (hasProperty(params, 'voltage')) {
222
+ voltage = Number.parseFloat(params.voltage)
223
+ this.service.updateCharacteristic(this.eveChar.Voltage, voltage)
224
+ logger = true
225
+ }
226
+ if (hasProperty(params, 'current_00')) {
227
+ current = Number.parseInt(params.current_00, 10) / 100
228
+ this.service.updateCharacteristic(this.eveChar.ElectricCurrent, current)
229
+ logger = true
230
+ } else if (hasProperty(params, 'current')) {
231
+ current = Number.parseFloat(params.current)
232
+ this.service.updateCharacteristic(this.eveChar.ElectricCurrent, current)
233
+ logger = true
234
+ }
235
+ if (params.updateSource && logger && this.enableLogging) {
236
+ this.log(
237
+ '[%s] %s%s%s.',
238
+ this.name,
239
+ power !== undefined ? `${this.lang.curPower} [${power}W]` : '',
240
+ voltage !== undefined ? ` ${this.lang.curVolt} [${voltage}V]` : '',
241
+ current !== undefined ? ` ${this.lang.curCurr} [${current}A]` : '',
242
+ )
243
+ }
244
+ } catch (err) {
245
+ this.platform.deviceUpdateError(this.accessory, err, false)
246
+ }
247
+ }
248
+
249
+ markStatus(isOnline) {
250
+ this.isOnline = isOnline
251
+ }
252
+ }
@@ -0,0 +1,232 @@
1
+ export default class {
2
+ constructor(platform, accessory) {
3
+ // Set up variables from the platform
4
+ this.hapChar = platform.api.hap.Characteristic
5
+ this.hapErr = platform.api.hap.HapStatusError
6
+ this.hapServ = platform.api.hap.Service
7
+ this.lang = platform.lang
8
+ this.log = platform.log
9
+ this.platform = platform
10
+
11
+ // Set up variables from the accessory
12
+ this.name = accessory.displayName
13
+ this.accessory = accessory
14
+
15
+ // Initially set the online flag as true (to be then updated as false if necessary)
16
+ this.isOnline = true
17
+
18
+ // Set up custom variables for this device type
19
+ const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
20
+ this.disableTimer = deviceConf.disableTimer
21
+
22
+ // Set the correct logging variables for this accessory
23
+ switch (deviceConf.overrideLogging) {
24
+ case 'standard':
25
+ this.enableLogging = true
26
+ this.enableDebugLogging = false
27
+ break
28
+ case 'debug':
29
+ this.enableLogging = true
30
+ this.enableDebugLogging = true
31
+ break
32
+ case 'disable':
33
+ this.enableLogging = false
34
+ this.enableDebugLogging = false
35
+ break
36
+ default:
37
+ this.enableLogging = !platform.config.disableDeviceLogging
38
+ this.enableDebugLogging = platform.config.debug
39
+ break
40
+ }
41
+
42
+ // We want four valve services for this accessory
43
+ ['A', 'B', 'C', 'D'].forEach((v) => {
44
+ // Add the valve service if it doesn't already exist
45
+ let valveService = this.accessory.getService(`Valve ${v}`)
46
+ if (!valveService) {
47
+ valveService = this.accessory.addService(
48
+ this.hapServ.Valve,
49
+ `Valve ${v}`,
50
+ `valve${v.toLowerCase()}`,
51
+ )
52
+ valveService.updateCharacteristic(this.hapChar.Active, 0)
53
+ valveService.updateCharacteristic(this.hapChar.InUse, 0)
54
+ if (!this.disableTimer) {
55
+ valveService.updateCharacteristic(this.hapChar.ValveType, 1)
56
+ valveService.updateCharacteristic(this.hapChar.SetDuration, 120)
57
+ valveService.addCharacteristic(this.hapChar.RemainingDuration)
58
+ }
59
+ }
60
+
61
+ // Add the set handler to the valve active characteristic
62
+ valveService
63
+ .getCharacteristic(this.hapChar.Active)
64
+ .onSet(async value => this.internalUpdate(`Valve ${v}`, value))
65
+
66
+ // Add the get handlers only if the user hasn't disabled the disableNoResponse setting
67
+ if (!platform.config.disableNoResponse) {
68
+ valveService.getCharacteristic(this.hapChar.Active).onGet(() => {
69
+ if (!this.isOnline) {
70
+ throw new this.hapErr(-70402)
71
+ }
72
+ return valveService.getCharacteristic(this.hapChar.Active).value
73
+ })
74
+ }
75
+
76
+ // Add the set handler to the valve set duration characteristic
77
+ if (this.disableTimer) {
78
+ if (valveService.testCharacteristic(this.hapChar.SetDuration)) {
79
+ valveService.removeCharacteristic(
80
+ valveService.getCharacteristic(this.hapChar.SetDuration),
81
+ )
82
+ }
83
+ if (valveService.testCharacteristic(this.hapChar.RemainingDuration)) {
84
+ valveService.removeCharacteristic(
85
+ valveService.getCharacteristic(this.hapChar.RemainingDuration),
86
+ )
87
+ }
88
+ } else {
89
+ valveService.getCharacteristic(this.hapChar.SetDuration).onSet((value) => {
90
+ // Check if the valve is currently active
91
+ if (valveService.getCharacteristic(this.hapChar.InUse).value === 1) {
92
+ // Update the remaining duration characteristic with the new value
93
+ valveService.updateCharacteristic(this.hapChar.RemainingDuration, value)
94
+
95
+ // Clear any existing active timers
96
+ clearTimeout(valveService.timer)
97
+
98
+ // Set a new active timer with the new time amount
99
+ valveService.timer = setTimeout(
100
+ () => valveService.setCharacteristic(this.hapChar.Active, 0),
101
+ value * 1000,
102
+ )
103
+ }
104
+ })
105
+ }
106
+ })
107
+
108
+ // Output the customised options to the log
109
+ const normalLogging = this.enableLogging ? 'standard' : 'disable'
110
+ const opts = JSON.stringify({
111
+ disableTimer: this.disableTimer,
112
+ logging: this.enableDebugLogging ? 'debug' : normalLogging,
113
+ showAs: 'valve_four',
114
+ })
115
+ this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
116
+ }
117
+
118
+ async internalUpdate(valve, value) {
119
+ try {
120
+ const params = {
121
+ switches: [],
122
+ }
123
+ const valveService = this.accessory.getService(valve)
124
+ switch (valve) {
125
+ case 'Valve A':
126
+ params.switches.push({ switch: value ? 'on' : 'off', outlet: 0 })
127
+ break
128
+ case 'Valve B':
129
+ params.switches.push({ switch: value ? 'on' : 'off', outlet: 1 })
130
+ break
131
+ case 'Valve C':
132
+ params.switches.push({ switch: value ? 'on' : 'off', outlet: 2 })
133
+ break
134
+ case 'Valve D':
135
+ params.switches.push({ switch: value ? 'on' : 'off', outlet: 3 })
136
+ break
137
+ default:
138
+ return
139
+ }
140
+ valveService.updateCharacteristic(this.hapChar.InUse, value)
141
+ switch (value) {
142
+ case 0:
143
+ if (!this.disableTimer) {
144
+ valveService.updateCharacteristic(this.hapChar.RemainingDuration, 0)
145
+ clearTimeout(this.accessory.getService(valve).timer)
146
+ }
147
+ if (this.enableLogging) {
148
+ this.log('[%s] [%s] %s [%s].', this.name, valve, this.lang.curState, this.lang.valveNo)
149
+ }
150
+ break
151
+ case 1: {
152
+ if (!this.disableTimer) {
153
+ const timer = valveService.getCharacteristic(this.hapChar.SetDuration).value
154
+ valveService.updateCharacteristic(this.hapChar.RemainingDuration, timer)
155
+ valveService.timer = setTimeout(() => {
156
+ valveService.setCharacteristic(this.hapChar.Active, 0)
157
+ }, timer * 1000)
158
+ }
159
+ if (this.enableLogging) {
160
+ this.log('[%s] [%s] %s [%s].', this.name, valve, this.lang.curState, this.lang.valveYes)
161
+ }
162
+
163
+ break
164
+ }
165
+ default:
166
+ return
167
+ }
168
+ await this.platform.sendDeviceUpdate(this.accessory, params)
169
+ } catch (err) {
170
+ this.platform.deviceUpdateError(this.accessory, err, true)
171
+ const valveService = this.accessory.getService(valve)
172
+ setTimeout(() => {
173
+ valveService.updateCharacteristic(this.hapChar.Active, value === 1 ? 0 : 1)
174
+ }, 2000)
175
+ throw new this.hapErr(-70402)
176
+ }
177
+ }
178
+
179
+ async externalUpdate(params) {
180
+ try {
181
+ if (!params.switches) {
182
+ return
183
+ }
184
+ ['A', 'B', 'C', 'D'].forEach((v, k) => {
185
+ const valveService = this.accessory.getService(`Valve ${v}`)
186
+ if (params.switches[k].switch === 'on') {
187
+ if (valveService.getCharacteristic(this.hapChar.Active).value === 0) {
188
+ valveService.updateCharacteristic(this.hapChar.Active, 1)
189
+ valveService.updateCharacteristic(this.hapChar.InUse, 1)
190
+ if (!this.disableTimer) {
191
+ const timer = valveService.getCharacteristic(this.hapChar.SetDuration).value
192
+ valveService.updateCharacteristic(this.hapChar.RemainingDuration, timer)
193
+ valveService.timer = setTimeout(() => {
194
+ valveService.setCharacteristic(this.hapChar.Active, 0)
195
+ }, timer * 1000)
196
+ }
197
+ if (params.updateSource && this.enableLogging) {
198
+ this.log(
199
+ '[%s] [Valve %s] %s [%s].',
200
+ this.name,
201
+ v,
202
+ this.lang.curState,
203
+ this.lang.valveYes,
204
+ )
205
+ }
206
+ }
207
+ } else if (valveService.getCharacteristic(this.hapChar.Active).value === 1) {
208
+ valveService.updateCharacteristic(this.hapChar.Active, 0)
209
+ valveService.updateCharacteristic(this.hapChar.InUse, 0)
210
+ if (!this.disableTimer) {
211
+ valveService.updateCharacteristic(this.hapChar.RemainingDuration, 0)
212
+ clearTimeout(valveService.timer)
213
+ } else if (params.updateSource && this.enableLogging) {
214
+ this.log(
215
+ '[%s] [Valve %s] %s [%s].',
216
+ this.name,
217
+ v,
218
+ this.lang.curState,
219
+ this.lang.valveNo,
220
+ )
221
+ }
222
+ }
223
+ })
224
+ } catch (err) {
225
+ this.platform.deviceUpdateError(this.accessory, err, false)
226
+ }
227
+ }
228
+
229
+ markStatus(isOnline) {
230
+ this.isOnline = isOnline
231
+ }
232
+ }