@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,258 @@
1
+ import platformConsts from '../../utils/constants.js'
2
+ import { generateRandomString, hasProperty, sleep } 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
+
18
+ // Initially set the online flag as true (to be then updated as false if necessary)
19
+ this.isOnline = true
20
+
21
+ // Set up custom variables for this device type
22
+ const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
23
+ this.brightStep = deviceConf.brightnessStep
24
+ ? Math.min(deviceConf.brightnessStep, 100)
25
+ : platformConsts.defaultValues.brightnessStep
26
+ this.offlineAsOff = deviceConf.offlineAsOff
27
+
28
+ // Set the correct logging variables for this accessory
29
+ switch (deviceConf.overrideLogging) {
30
+ case 'standard':
31
+ this.enableLogging = true
32
+ this.enableDebugLogging = false
33
+ break
34
+ case 'debug':
35
+ this.enableLogging = true
36
+ this.enableDebugLogging = true
37
+ break
38
+ case 'disable':
39
+ this.enableLogging = false
40
+ this.enableDebugLogging = false
41
+ break
42
+ default:
43
+ this.enableLogging = !platform.config.disableDeviceLogging
44
+ this.enableDebugLogging = platform.config.debug
45
+ break
46
+ }
47
+
48
+ // Remove any existing lightbulb services if found
49
+ if (accessory.getService(this.hapServ.Lightbulb)) {
50
+ accessory.removeService(accessory.getService(this.hapServ.Lightbulb))
51
+ }
52
+
53
+ // Add the fan service if it doesn't already exist
54
+ this.service = this.accessory.getService(this.hapServ.Fan)
55
+ || this.accessory.addService(this.hapServ.Fan)
56
+
57
+ // Add the set handler to the fan on/off characteristic
58
+ this.service
59
+ .getCharacteristic(this.hapChar.On)
60
+ .onSet(async value => this.internalStateUpdate(value))
61
+
62
+ // Add the set handler to the fan speed characteristic
63
+ this.service
64
+ .getCharacteristic(this.hapChar.RotationSpeed)
65
+ .setProps({ minStep: this.brightStep })
66
+ .onSet(async value => this.internalSpeedUpdate(value))
67
+
68
+ // Add the get handlers only if the user hasn't disabled the disableNoResponse setting
69
+ if (!platform.config.disableNoResponse) {
70
+ this.service.getCharacteristic(this.hapChar.On).onGet(() => {
71
+ if (!this.isOnline) {
72
+ throw new this.hapErr(-70402)
73
+ }
74
+ return this.service.getCharacteristic(this.hapChar.On).value
75
+ })
76
+ this.service.getCharacteristic(this.hapChar.RotationSpeed).onGet(() => {
77
+ if (!this.isOnline) {
78
+ throw new this.hapErr(-70402)
79
+ }
80
+ return this.service.getCharacteristic(this.hapChar.RotationSpeed).value
81
+ })
82
+ }
83
+
84
+ // Output the customised options to the log
85
+ const normalLogging = this.enableLogging ? 'standard' : 'disable'
86
+ const opts = JSON.stringify({
87
+ brightnessStep: this.brightStep,
88
+ logging: this.enableDebugLogging ? 'debug' : normalLogging,
89
+ offlineAsOff: !!this.offlineAsOff,
90
+ showAs: 'fan',
91
+ })
92
+ this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
93
+ }
94
+
95
+ async internalStateUpdate(value) {
96
+ try {
97
+ const newValue = value ? 'on' : 'off'
98
+ if (this.cacheState === newValue) {
99
+ return
100
+ }
101
+ const params = {}
102
+ switch (this.accessory.context.eweUIID) {
103
+ case 36:
104
+ case 44:
105
+ // KING-M4, D1
106
+ params.switch = newValue
107
+ break
108
+ case 57:
109
+ params.state = newValue
110
+ break
111
+ default:
112
+ return
113
+ }
114
+ await this.platform.sendDeviceUpdate(this.accessory, params)
115
+ this.cacheState = newValue
116
+ if (this.enableLogging) {
117
+ this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
118
+ }
119
+ } catch (err) {
120
+ this.platform.deviceUpdateError(this.accessory, err, true)
121
+ setTimeout(() => {
122
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
123
+ }, 2000)
124
+ throw new this.hapErr(-70402)
125
+ }
126
+ }
127
+
128
+ async internalSpeedUpdate(value) {
129
+ try {
130
+ if (this.cacheSpeed === value) {
131
+ return
132
+ }
133
+ const updateKey = generateRandomString(5)
134
+ this.updateKeySpeed = updateKey
135
+ await sleep(500)
136
+ if (updateKey !== this.updateKeySpeed) {
137
+ return
138
+ }
139
+ const params = {}
140
+ switch (this.accessory.context.eweUIID) {
141
+ case 36:
142
+ params.bright = Math.round((value * 9) / 10 + 10)
143
+ // KING-M4 eWeLink scale is 10-100 and HomeKit scale is 0-100
144
+ break
145
+ case 44:
146
+ params.brightness = value
147
+ // D1 eWeLink scale matches HomeKit scale of 0-100
148
+ params.mode = 0
149
+ break
150
+ case 57:
151
+ params.channel0 = Math.round((value * 23) / 10 + 25).toString()
152
+ // Device eWeLink scale is 25-255 and HomeKit scale is 0-100.
153
+ break
154
+ default:
155
+ return
156
+ }
157
+ await this.platform.sendDeviceUpdate(this.accessory, params)
158
+ this.cacheSpeed = value
159
+ if (this.enableLogging) {
160
+ this.log('[%s] %s [%s%].', this.name, this.lang.curSpeed, this.cacheSpeed)
161
+ }
162
+ } catch (err) {
163
+ this.platform.deviceUpdateError(this.accessory, err, true)
164
+ setTimeout(() => {
165
+ this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
166
+ }, 2000)
167
+ throw new this.hapErr(-70402)
168
+ }
169
+ }
170
+
171
+ async externalUpdate(params) {
172
+ try {
173
+ if (this.accessory.context.eweUIID === 57) {
174
+ if (params.state && params.state !== this.cacheState) {
175
+ this.service.updateCharacteristic(this.hapChar.On, params.state === 'on')
176
+ this.cacheState = params.state
177
+ if (params.updateSource && this.enableLogging) {
178
+ this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
179
+ }
180
+ }
181
+ } else if (params.switch && params.switch !== this.cacheState) {
182
+ this.service.updateCharacteristic(this.hapChar.On, params.switch === 'on')
183
+ this.cacheState = params.switch
184
+ if (params.updateSource && this.enableLogging) {
185
+ this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
186
+ }
187
+ }
188
+
189
+ switch (this.accessory.context.eweUIID) {
190
+ case 36:
191
+ // KING-M4 eWeLink scale is 10-100 and HomeKit scale is 0-100.
192
+ if (hasProperty(params, 'bright')) {
193
+ const nb = Math.round(((params.bright - 10) * 10) / 9)
194
+ if (nb !== this.cacheSpeed) {
195
+ this.service.updateCharacteristic(this.hapChar.RotationSpeed, nb)
196
+ this.cacheSpeed = nb
197
+ if (params.updateSource && this.enableLogging) {
198
+ this.log('[%s] %s [%s%].', this.name, this.lang.curSpeed, nb)
199
+ }
200
+ }
201
+ }
202
+ break
203
+ case 44:
204
+ // D1 eWeLink scale matches HomeKit scale of 0-100
205
+ if (hasProperty(params, 'brightness')) {
206
+ const nb = params.brightness
207
+ if (nb !== this.cacheSpeed) {
208
+ this.service.updateCharacteristic(this.hapChar.RotationSpeed, nb)
209
+ this.cacheSpeed = nb
210
+ if (params.updateSource && this.enableLogging) {
211
+ this.log('[%s] %s [%s%].', this.name, this.lang.curSpeed, nb)
212
+ }
213
+ }
214
+ }
215
+ break
216
+ case 57:
217
+ // Device eWeLink scale is 25-255 and HomeKit scale is 0-100.
218
+ if (hasProperty(params, 'channel0')) {
219
+ const ns = Math.round(((Number.parseInt(params.channel0, 10) - 25) * 10) / 23)
220
+ if (ns !== this.cacheSpeed) {
221
+ this.service.updateCharacteristic(this.hapChar.RotationSpeed, ns)
222
+ this.cacheSpeed = ns
223
+ if (params.updateSource && this.enableLogging) {
224
+ this.log('[%s] %s [%s%].', this.name, this.lang.curSpeed, ns)
225
+ }
226
+ }
227
+ }
228
+ break
229
+ default:
230
+ }
231
+ } catch (err) {
232
+ this.platform.deviceUpdateError(this.accessory, err, false)
233
+ }
234
+ }
235
+
236
+ markStatus(isOnline) {
237
+ this.isOnline = isOnline
238
+
239
+ // Show as off if offlineAsOff is enabled
240
+ if (this.offlineAsOff && !isOnline && this.cacheState !== 'off') {
241
+ this.service.updateCharacteristic(this.hapChar.On, false)
242
+ this.cacheState = 'off'
243
+ if (this.enableLogging) {
244
+ this.log('[%s] %s [%s - offline]', this.name, this.lang.curState, this.cacheState)
245
+ }
246
+ }
247
+ }
248
+
249
+ currentState() {
250
+ const toReturn = {}
251
+ toReturn.services = ['light']
252
+ toReturn.light = {
253
+ state: this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off',
254
+ speed: this.service.getCharacteristic(this.hapChar.RotationSpeed).value,
255
+ }
256
+ return toReturn
257
+ }
258
+ }
@@ -0,0 +1,163 @@
1
+ import platformConsts from '../../utils/constants.js'
2
+ import { generateRandomString, sleep } 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
+ this.operationTime = deviceConf.operationTime || platformConsts.defaultValues.operationTime
25
+
26
+ // Set the correct logging variables for this accessory
27
+ switch (deviceConf.overrideLogging) {
28
+ case 'standard':
29
+ this.enableLogging = true
30
+ this.enableDebugLogging = false
31
+ break
32
+ case 'debug':
33
+ this.enableLogging = true
34
+ this.enableDebugLogging = true
35
+ break
36
+ case 'disable':
37
+ this.enableLogging = false
38
+ this.enableDebugLogging = false
39
+ break
40
+ default:
41
+ this.enableLogging = !platform.config.disableDeviceLogging
42
+ this.enableDebugLogging = platform.config.debug
43
+ break
44
+ }
45
+
46
+ // If the accessory has a switch service then remove it
47
+ if (this.accessory.getService(this.hapServ.Switch)) {
48
+ this.accessory.removeService(this.accessory.getService(this.hapServ.Switch))
49
+ }
50
+
51
+ // If the accessory has a garage service then remove it
52
+ if (this.accessory.getService(this.hapServ.GarageDoorOpener)) {
53
+ this.accessory.removeService(this.accessory.getService(this.hapServ.GarageDoorOpener))
54
+ }
55
+
56
+ // Add the lock service if it doesn't already exist
57
+ this.service = this.accessory.getService(this.hapServ.LockMechanism)
58
+ || this.accessory.addService(this.hapServ.LockMechanism)
59
+
60
+ // Add the set handler to the lock target state characteristic
61
+ this.service.getCharacteristic(this.hapChar.LockTargetState).onSet((value) => {
62
+ // We don't use await as we want the callback to be run straight away
63
+ this.internalUpdate(value)
64
+ })
65
+
66
+ // Add the get handlers only if the user hasn't disabled the disableNoResponse setting
67
+ if (!platform.config.disableNoResponse) {
68
+ this.service.getCharacteristic(this.hapChar.LockCurrentState).onGet(() => {
69
+ if (!this.isOnline) {
70
+ throw new this.hapErr(-70402)
71
+ }
72
+ return this.service.getCharacteristic(this.hapChar.LockCurrentState).value
73
+ })
74
+ this.service.getCharacteristic(this.hapChar.LockTargetState).onGet(() => {
75
+ if (!this.isOnline) {
76
+ throw new this.hapErr(-70402)
77
+ }
78
+ return this.service.getCharacteristic(this.hapChar.LockTargetState).value
79
+ })
80
+ }
81
+
82
+ // Output the customised options to the log
83
+ const normalLogging = this.enableLogging ? 'standard' : 'disable'
84
+ const opts = JSON.stringify({
85
+ logging: this.enableDebugLogging ? 'debug' : normalLogging,
86
+ showAs: 'garage_eachen',
87
+ showAsEachen: 'lock',
88
+ })
89
+ this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
90
+ }
91
+
92
+ async internalUpdate(value) {
93
+ const currentState = this.service.getCharacteristic(this.hapChar.LockTargetState).value
94
+ try {
95
+ // Don't continue if the value is the same as before
96
+ if (value === currentState) {
97
+ return
98
+ }
99
+
100
+ // Generate the params
101
+ const params = { switch: value === 0 ? 'on' : 'off' }
102
+ this.inUse = true
103
+ await this.platform.sendDeviceUpdate(this.accessory, params)
104
+ this.service.updateCharacteristic(this.hapChar.LockTargetState, value)
105
+ this.service.updateCharacteristic(this.hapChar.LockCurrentState, value)
106
+ await sleep(3000)
107
+ this.inUse = false
108
+ if (this.enableLogging) {
109
+ this.log(
110
+ '[%s] %s [%s].',
111
+ this.name,
112
+ this.lang.curState,
113
+ value === 0 ? this.lang.lockUnlocked : this.lang.lockLocked,
114
+ )
115
+ }
116
+ } catch (err) {
117
+ this.inUse = false
118
+ this.platform.deviceUpdateError(this.accessory, err, true)
119
+ setTimeout(() => {
120
+ this.service.updateCharacteristic(this.hapChar.LockTargetState, currentState)
121
+ }, 2000)
122
+ this.service.updateCharacteristic(this.hapChar.LockTargetState, new this.hapErr(-70402))
123
+ }
124
+ }
125
+
126
+ async externalUpdate(params) {
127
+ try {
128
+ if (!params.switch || this.inUse) {
129
+ return
130
+ }
131
+
132
+ // In a period of three seconds we want to only use the 'last' update
133
+ const updateKey = generateRandomString(5)
134
+ this.updateKey = updateKey
135
+ await sleep(3000)
136
+ if (this.updateKey !== updateKey) {
137
+ return
138
+ }
139
+
140
+ // Update the characteristics
141
+ const newValue = params.switch === 'on' ? 0 : 1
142
+ if (this.service.getCharacteristic(this.hapChar.LockTargetState).value !== newValue) {
143
+ this.service.updateCharacteristic(this.hapChar.LockTargetState, newValue)
144
+ this.service.updateCharacteristic(this.hapChar.LockCurrentState, newValue)
145
+ }
146
+
147
+ if (params.updateSource && this.enableLogging) {
148
+ this.log(
149
+ '[%s] %s [%s].',
150
+ this.name,
151
+ this.lang.curState,
152
+ params.switch === 'on' ? this.lang.lockUnlocked : this.lang.lockLocked,
153
+ )
154
+ }
155
+ } catch (err) {
156
+ this.platform.deviceUpdateError(this.accessory, err, false)
157
+ }
158
+ }
159
+
160
+ markStatus(isOnline) {
161
+ this.isOnline = isOnline
162
+ }
163
+ }