@homebridge-plugins/homebridge-govee 10.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1937 -0
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/config.schema.json +1727 -0
- package/eslint.config.js +49 -0
- package/lib/connection/aws.js +174 -0
- package/lib/connection/ble.js +208 -0
- package/lib/connection/cert/AmazonRootCA1.pem +20 -0
- package/lib/connection/http.js +240 -0
- package/lib/connection/lan.js +284 -0
- package/lib/device/cooler-single.js +300 -0
- package/lib/device/dehumidifier-H7150.js +182 -0
- package/lib/device/dehumidifier-H7151.js +157 -0
- package/lib/device/diffuser-H7161.js +117 -0
- package/lib/device/diffuser-H7162.js +117 -0
- package/lib/device/fan-H7100.js +274 -0
- package/lib/device/fan-H7101.js +330 -0
- package/lib/device/fan-H7102.js +274 -0
- package/lib/device/fan-H7105.js +503 -0
- package/lib/device/fan-H7106.js +274 -0
- package/lib/device/fan-H7111.js +335 -0
- package/lib/device/heater-single.js +300 -0
- package/lib/device/heater1a.js +353 -0
- package/lib/device/heater1b.js +616 -0
- package/lib/device/heater2.js +838 -0
- package/lib/device/humidifier-H7140.js +224 -0
- package/lib/device/humidifier-H7141.js +257 -0
- package/lib/device/humidifier-H7142.js +522 -0
- package/lib/device/humidifier-H7143.js +157 -0
- package/lib/device/humidifier-H7148.js +157 -0
- package/lib/device/humidifier-H7160.js +446 -0
- package/lib/device/ice-maker-H7162.js +46 -0
- package/lib/device/index.js +105 -0
- package/lib/device/kettle.js +269 -0
- package/lib/device/light-switch.js +86 -0
- package/lib/device/light.js +617 -0
- package/lib/device/outlet-double.js +121 -0
- package/lib/device/outlet-single.js +172 -0
- package/lib/device/outlet-triple.js +160 -0
- package/lib/device/purifier-H7120.js +336 -0
- package/lib/device/purifier-H7121.js +336 -0
- package/lib/device/purifier-H7122.js +449 -0
- package/lib/device/purifier-H7123.js +411 -0
- package/lib/device/purifier-H7124.js +411 -0
- package/lib/device/purifier-H7126.js +296 -0
- package/lib/device/purifier-H7127.js +296 -0
- package/lib/device/purifier-H712C.js +296 -0
- package/lib/device/purifier-single.js +119 -0
- package/lib/device/sensor-button.js +22 -0
- package/lib/device/sensor-contact.js +22 -0
- package/lib/device/sensor-leak.js +87 -0
- package/lib/device/sensor-monitor.js +190 -0
- package/lib/device/sensor-presence.js +53 -0
- package/lib/device/sensor-thermo.js +144 -0
- package/lib/device/sensor-thermo4.js +55 -0
- package/lib/device/switch-double.js +121 -0
- package/lib/device/switch-single.js +95 -0
- package/lib/device/switch-triple.js +160 -0
- package/lib/device/tap-single.js +108 -0
- package/lib/device/template.js +43 -0
- package/lib/device/tv-single.js +84 -0
- package/lib/device/valve-single.js +155 -0
- package/lib/fakegato/LICENSE +21 -0
- package/lib/fakegato/fakegato-history.js +814 -0
- package/lib/fakegato/fakegato-storage.js +108 -0
- package/lib/fakegato/fakegato-timer.js +125 -0
- package/lib/fakegato/uuid.js +27 -0
- package/lib/homebridge-ui/public/index.html +433 -0
- package/lib/homebridge-ui/server.js +10 -0
- package/lib/index.js +8 -0
- package/lib/platform.js +1967 -0
- package/lib/utils/colour.js +564 -0
- package/lib/utils/constants.js +579 -0
- package/lib/utils/custom-chars.js +225 -0
- package/lib/utils/eve-chars.js +68 -0
- package/lib/utils/functions.js +117 -0
- package/lib/utils/lang-en.js +131 -0
- package/package.json +75 -0
|
@@ -0,0 +1,838 @@
|
|
|
1
|
+
import { hs2rgb, rgb2hs } from '../utils/colour.js'
|
|
2
|
+
import {
|
|
3
|
+
base64ToHex,
|
|
4
|
+
farToCen,
|
|
5
|
+
generateCodeFromHexValues,
|
|
6
|
+
generateRandomString,
|
|
7
|
+
getTwoItemPosition,
|
|
8
|
+
hasProperty,
|
|
9
|
+
hexToDecimal,
|
|
10
|
+
hexToTwoItems,
|
|
11
|
+
nearestHalf,
|
|
12
|
+
parseError,
|
|
13
|
+
sleep,
|
|
14
|
+
} from '../utils/functions.js'
|
|
15
|
+
import platformLang from '../utils/lang-en.js'
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
H7131 and H7132
|
|
19
|
+
{
|
|
20
|
+
"mode": {
|
|
21
|
+
"options": [
|
|
22
|
+
{
|
|
23
|
+
"name": "Low",
|
|
24
|
+
"value": "1"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "Medium",
|
|
28
|
+
"value": "2"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "High",
|
|
32
|
+
"value": "3"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "Fan",
|
|
36
|
+
"value": "4"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "Auto",
|
|
40
|
+
"value": "5"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
*/
|
|
46
|
+
export default class {
|
|
47
|
+
constructor(platform, accessory) {
|
|
48
|
+
// Set up variables from the platform
|
|
49
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
50
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
51
|
+
this.hapServ = platform.api.hap.Service
|
|
52
|
+
this.platform = platform
|
|
53
|
+
|
|
54
|
+
// Set up variables from the accessory
|
|
55
|
+
this.accessory = accessory
|
|
56
|
+
|
|
57
|
+
// Set up objects
|
|
58
|
+
this.speedCode = {
|
|
59
|
+
25: 'OgUJAAAAAAAAAAAAAAAAAAAAADY=',
|
|
60
|
+
50: 'OgUBAQAAAAAAAAAAAAAAAAAAAD8=',
|
|
61
|
+
75: 'OgUBAgAAAAAAAAAAAAAAAAAAADw=',
|
|
62
|
+
100: 'OgUBAwAAAAAAAAAAAAAAAAAAAD0=',
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.speedCodeLabel = {
|
|
66
|
+
0: 'auto',
|
|
67
|
+
25: 'fan-only',
|
|
68
|
+
50: 'low',
|
|
69
|
+
75: 'medium',
|
|
70
|
+
100: 'high',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.tempCodeAuto = {
|
|
74
|
+
5: 'MwUDAZAEAAAAAAAAAAAAAAAAAKA=',
|
|
75
|
+
6: 'MwUDAZBoAAAAAAAAAAAAAAAAAMw=',
|
|
76
|
+
7: 'MwUDAZEwAAAAAAAAAAAAAAAAAJU=',
|
|
77
|
+
8: 'MwUDAZH4AAAAAAAAAAAAAAAAAF0=',
|
|
78
|
+
9: 'MwUDAZLAAAAAAAAAAAAAAAAAAGY=',
|
|
79
|
+
10: 'MwUDAZOIAAAAAAAAAAAAAAAAAC8=',
|
|
80
|
+
11: 'MwUDAZPsAAAAAAAAAAAAAAAAAEs=',
|
|
81
|
+
12: 'MwUDAZS0AAAAAAAAAAAAAAAAABQ=',
|
|
82
|
+
13: 'MwUDAZV8AAAAAAAAAAAAAAAAAN0=',
|
|
83
|
+
14: 'MwUDAZZEAAAAAAAAAAAAAAAAAOY=',
|
|
84
|
+
15: 'MwUDAZcMAAAAAAAAAAAAAAAAAK8=',
|
|
85
|
+
16: 'MwUDAZdwAAAAAAAAAAAAAAAAANM=',
|
|
86
|
+
17: 'MwUDAZg4AAAAAAAAAAAAAAAAAJQ=',
|
|
87
|
+
18: 'MwUDAZkAAAAAAAAAAAAAAAAAAK0=',
|
|
88
|
+
19: 'MwUDAZnIAAAAAAAAAAAAAAAAAGU=',
|
|
89
|
+
20: 'MwUDAZqQAAAAAAAAAAAAAAAAAD4=',
|
|
90
|
+
21: 'MwUDAZr0AAAAAAAAAAAAAAAAAFo=',
|
|
91
|
+
22: 'MwUDAZu8AAAAAAAAAAAAAAAAABM=',
|
|
92
|
+
23: 'MwUDAZyEAAAAAAAAAAAAAAAAACw=',
|
|
93
|
+
24: 'MwUDAZ1MAAAAAAAAAAAAAAAAAOU=',
|
|
94
|
+
25: 'MwUDAZ4UAAAAAAAAAAAAAAAAAL4=',
|
|
95
|
+
26: 'MwUDAZ54AAAAAAAAAAAAAAAAANI=',
|
|
96
|
+
27: 'MwUDAZ9AAAAAAAAAAAAAAAAAAOs=',
|
|
97
|
+
28: 'MwUDAaAIAAAAAAAAAAAAAAAAAJw=',
|
|
98
|
+
29: 'MwUDAaDQAAAAAAAAAAAAAAAAAEQ=',
|
|
99
|
+
30: 'MwUDAaGYAAAAAAAAAAAAAAAAAA0=',
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.tempCodeAutoTurn = {
|
|
103
|
+
5: 'OgUDAZAEAAAAAAAAAAAAAAAAAKk=',
|
|
104
|
+
6: 'OgUDAZBoAAAAAAAAAAAAAAAAAMU=',
|
|
105
|
+
7: 'OgUDAZEwAAAAAAAAAAAAAAAAAJw=',
|
|
106
|
+
8: 'OgUDAZH4AAAAAAAAAAAAAAAAAFQ=',
|
|
107
|
+
9: 'OgUDAZLAAAAAAAAAAAAAAAAAAG8=',
|
|
108
|
+
10: 'OgUDAZOIAAAAAAAAAAAAAAAAACY=',
|
|
109
|
+
11: 'OgUDAZPsAAAAAAAAAAAAAAAAAEI=',
|
|
110
|
+
12: 'OgUDAZS0AAAAAAAAAAAAAAAAAB0=',
|
|
111
|
+
13: 'OgUDAZV8AAAAAAAAAAAAAAAAANQ=',
|
|
112
|
+
14: 'OgUDAZZEAAAAAAAAAAAAAAAAAO8=',
|
|
113
|
+
15: 'OgUDAZcMAAAAAAAAAAAAAAAAAKY=',
|
|
114
|
+
16: 'OgUDAZdwAAAAAAAAAAAAAAAAANo=',
|
|
115
|
+
17: 'OgUDAZg4AAAAAAAAAAAAAAAAAJ0=',
|
|
116
|
+
18: 'OgUDAZkAAAAAAAAAAAAAAAAAAKQ=',
|
|
117
|
+
19: 'OgUDAZnIAAAAAAAAAAAAAAAAAGw=',
|
|
118
|
+
20: 'OgUDAZqQAAAAAAAAAAAAAAAAADc=',
|
|
119
|
+
21: 'OgUDAZr0AAAAAAAAAAAAAAAAAFM=',
|
|
120
|
+
22: 'OgUDAZu8AAAAAAAAAAAAAAAAABo=',
|
|
121
|
+
23: 'OgUDAZyEAAAAAAAAAAAAAAAAACU=',
|
|
122
|
+
24: 'OgUDAZ1MAAAAAAAAAAAAAAAAAOw=',
|
|
123
|
+
25: 'OgUDAZ4UAAAAAAAAAAAAAAAAALc=',
|
|
124
|
+
26: 'OgUDAZ54AAAAAAAAAAAAAAAAANs=',
|
|
125
|
+
27: 'OgUDAZ9AAAAAAAAAAAAAAAAAAOI=',
|
|
126
|
+
28: 'OgUDAaAIAAAAAAAAAAAAAAAAAJU=',
|
|
127
|
+
29: 'OgUDAaDQAAAAAAAAAAAAAAAAAE0=',
|
|
128
|
+
30: 'OgUDAaGYAAAAAAAAAAAAAAAAAAQ=',
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Fix v9.4.0 -> v9.4.1 bug
|
|
132
|
+
// Remove any light service if it exists
|
|
133
|
+
if (this.accessory.getService(this.hapServ.Lightbulb)) {
|
|
134
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Lightbulb))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Add the heater service if it doesn't already exist
|
|
138
|
+
this.service = this.accessory.getService(this.hapServ.HeaterCooler)
|
|
139
|
+
if (!this.service) {
|
|
140
|
+
this.service = this.accessory.addService(this.hapServ.HeaterCooler)
|
|
141
|
+
this.service.updateCharacteristic(this.hapChar.CurrentTemperature, 20)
|
|
142
|
+
this.service.updateCharacteristic(this.hapChar.HeatingThresholdTemperature, 20)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Add the fan service if it doesn't already exist
|
|
146
|
+
this.fanService = this.accessory.getService(this.hapServ.Fan)
|
|
147
|
+
|| this.accessory.addService(this.hapServ.Fan)
|
|
148
|
+
|
|
149
|
+
// Add the night light service if it doesn't already exist
|
|
150
|
+
this.lightService = this.accessory.getService(this.hapServ.Lightbulb)
|
|
151
|
+
|| this.accessory.addService(this.hapServ.Lightbulb)
|
|
152
|
+
|
|
153
|
+
// Add the set handler to the heater active characteristic
|
|
154
|
+
this.service
|
|
155
|
+
.getCharacteristic(this.hapChar.Active)
|
|
156
|
+
.onSet(async value => this.internalStateUpdate(value))
|
|
157
|
+
this.cacheState = this.service.getCharacteristic(this.hapChar.Active).value === 1 ? 'on' : 'off'
|
|
158
|
+
|
|
159
|
+
// Add options to the heater target state characteristic
|
|
160
|
+
this.service
|
|
161
|
+
.getCharacteristic(this.hapChar.TargetHeaterCoolerState)
|
|
162
|
+
.setProps({
|
|
163
|
+
minValue: 0,
|
|
164
|
+
maxValue: 1,
|
|
165
|
+
validValues: [0, 1],
|
|
166
|
+
})
|
|
167
|
+
.onSet(async value => this.internalModeUpdate(value))
|
|
168
|
+
|
|
169
|
+
this.cacheTemp = this.service.getCharacteristic(this.hapChar.CurrentTemperature).value
|
|
170
|
+
|
|
171
|
+
// Add the set handler and a range to the heater target temperature characteristic
|
|
172
|
+
this.service
|
|
173
|
+
.getCharacteristic(this.hapChar.HeatingThresholdTemperature)
|
|
174
|
+
.setProps({
|
|
175
|
+
minValue: 5,
|
|
176
|
+
maxValue: 30,
|
|
177
|
+
minStep: 1,
|
|
178
|
+
})
|
|
179
|
+
.onSet(async value => this.internalTempUpdate(value))
|
|
180
|
+
this.cacheTarg = this.service.getCharacteristic(this.hapChar.HeatingThresholdTemperature).value
|
|
181
|
+
|
|
182
|
+
// Add the set handler to the heater swing mode characteristic (for oscillation)
|
|
183
|
+
this.service
|
|
184
|
+
.getCharacteristic(this.hapChar.SwingMode)
|
|
185
|
+
.onSet(async value => this.internalSwingUpdate(value))
|
|
186
|
+
this.cacheSwing = this.service.getCharacteristic(this.hapChar.SwingMode).value === 1 ? 'on' : 'off'
|
|
187
|
+
|
|
188
|
+
// Add the set handler to the heater lock characteristic (for oscillation)
|
|
189
|
+
this.service
|
|
190
|
+
.getCharacteristic(this.hapChar.LockPhysicalControls)
|
|
191
|
+
.onSet(async value => this.internalLockUpdate(value))
|
|
192
|
+
this.cacheLock = this.service.getCharacteristic(this.hapChar.LockPhysicalControls).value === 1 ? 'on' : 'off'
|
|
193
|
+
|
|
194
|
+
// Add the set handler to the fan on/off characteristic
|
|
195
|
+
this.fanService
|
|
196
|
+
.getCharacteristic(this.hapChar.On)
|
|
197
|
+
.onSet(async value => this.internalFanStateUpdate(value))
|
|
198
|
+
this.cacheFanState = this.fanService.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
|
|
199
|
+
|
|
200
|
+
// Add the set handler to the fan rotation speed characteristic
|
|
201
|
+
this.fanService
|
|
202
|
+
.getCharacteristic(this.hapChar.RotationSpeed)
|
|
203
|
+
.setProps({
|
|
204
|
+
minStep: 25,
|
|
205
|
+
validValues: [0, 25, 50, 75, 100],
|
|
206
|
+
})
|
|
207
|
+
.onSet(async value => this.internalSpeedUpdate(value))
|
|
208
|
+
this.cacheSpeed = this.fanService.getCharacteristic(this.hapChar.RotationSpeed).value
|
|
209
|
+
|
|
210
|
+
// Obtain the current mode
|
|
211
|
+
this.cacheMode = this.speedCodeLabel[this.cacheSpeed]
|
|
212
|
+
|
|
213
|
+
// Add the set handler to the lightbulb on/off characteristic
|
|
214
|
+
this.lightService.getCharacteristic(this.hapChar.On).onSet(async (value) => {
|
|
215
|
+
await this.internalLightStateUpdate(value)
|
|
216
|
+
})
|
|
217
|
+
this.cacheLightState = this.lightService.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
|
|
218
|
+
|
|
219
|
+
// Add the set handler to the lightbulb brightness characteristic
|
|
220
|
+
this.lightService
|
|
221
|
+
.getCharacteristic(this.hapChar.Brightness)
|
|
222
|
+
.onSet(async (value) => {
|
|
223
|
+
await this.internalBrightnessUpdate(value)
|
|
224
|
+
})
|
|
225
|
+
this.cacheBright = this.lightService.getCharacteristic(this.hapChar.Brightness).value
|
|
226
|
+
|
|
227
|
+
// Add the set handler to the lightbulb hue characteristic
|
|
228
|
+
this.lightService.getCharacteristic(this.hapChar.Hue).onSet(async (value) => {
|
|
229
|
+
await this.internalColourUpdate(value)
|
|
230
|
+
})
|
|
231
|
+
this.cacheHue = this.lightService.getCharacteristic(this.hapChar.Hue).value
|
|
232
|
+
this.cacheSat = this.lightService.getCharacteristic(this.hapChar.Saturation).value
|
|
233
|
+
|
|
234
|
+
// Output the customised options to the log
|
|
235
|
+
const opts = JSON.stringify({})
|
|
236
|
+
platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async internalStateUpdate(value) {
|
|
240
|
+
try {
|
|
241
|
+
const newValue = value === 1 ? 'on' : 'off'
|
|
242
|
+
|
|
243
|
+
// Don't continue if the new value is the same as before
|
|
244
|
+
if (this.cacheState === newValue) {
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Send the request to the platform sender function
|
|
249
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
250
|
+
cmd: 'stateHeat',
|
|
251
|
+
value: value === 1,
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
// If turning off then we also want to show the fan as off
|
|
255
|
+
if (newValue === 'off') {
|
|
256
|
+
this.fanService.updateCharacteristic(this.hapChar.On, false)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Cache the new state and log if appropriate
|
|
260
|
+
if (this.cacheState !== newValue) {
|
|
261
|
+
this.cacheState = newValue
|
|
262
|
+
this.accessory.log(`${platformLang.curState} [${newValue}]`)
|
|
263
|
+
}
|
|
264
|
+
} catch (err) {
|
|
265
|
+
// Catch any errors during the process
|
|
266
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
267
|
+
|
|
268
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
269
|
+
setTimeout(() => {
|
|
270
|
+
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
|
|
271
|
+
}, 2000)
|
|
272
|
+
throw new this.hapErr(-70402)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async internalModeUpdate(value) {
|
|
277
|
+
try {
|
|
278
|
+
// value can be 0 (auto) or 1 (heat)
|
|
279
|
+
let codeToSend
|
|
280
|
+
let newMode
|
|
281
|
+
if (value === 0) {
|
|
282
|
+
// Need to set to auto - hopefully we have a cacheTarg
|
|
283
|
+
// Need to use the turn version of the code since we are changing to this mode
|
|
284
|
+
codeToSend = this.tempCodeAutoTurn[this.cacheTarg]
|
|
285
|
+
newMode = 'auto'
|
|
286
|
+
} else {
|
|
287
|
+
// Need to set to heat - hopefully we have a cacheSpeed, if we don't set to 25 (fan-only)
|
|
288
|
+
codeToSend = this.speedCode[this.cacheSpeed] || this.speedCode[25]
|
|
289
|
+
newMode = this.speedCodeLabel[this.cacheSpeed] || this.speedCodeLabel[25]
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Send the request to the platform sender function
|
|
293
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
294
|
+
cmd: 'multiSync',
|
|
295
|
+
value: codeToSend,
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
// If the new mode is auto then we should turn off the fan
|
|
299
|
+
if (newMode === 'auto') {
|
|
300
|
+
this.fanService.updateCharacteristic(this.hapChar.On, false)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Cache the new state and log if appropriate
|
|
304
|
+
if (this.cacheMode !== newMode) {
|
|
305
|
+
this.cacheTarg = newMode
|
|
306
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
307
|
+
}
|
|
308
|
+
} catch (err) {
|
|
309
|
+
// Catch any errors during the process
|
|
310
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
311
|
+
|
|
312
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
313
|
+
setTimeout(() => {
|
|
314
|
+
this.service.updateCharacteristic(
|
|
315
|
+
this.hapChar.TargetHeaterCoolerState,
|
|
316
|
+
this.cacheMode === 'auto' ? 0 : 1,
|
|
317
|
+
)
|
|
318
|
+
}, 2000)
|
|
319
|
+
throw new this.hapErr(-70402)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async internalTempUpdate(value) {
|
|
324
|
+
try {
|
|
325
|
+
// Don't continue if the new value is the same as before
|
|
326
|
+
if (this.cacheTarg === value) {
|
|
327
|
+
return
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// If the current mode is not auto then we need to change it to auto and use the turn version of the code
|
|
331
|
+
const codeToSend = this.cacheMode === 'auto' ? this.tempCodeAuto[value] : this.tempCodeAutoTurn[value]
|
|
332
|
+
|
|
333
|
+
// Send the request to the platform sender function
|
|
334
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
335
|
+
cmd: 'multiSync',
|
|
336
|
+
value: codeToSend,
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
// Cache the new state and log if appropriate
|
|
340
|
+
this.cacheMode = 'auto'
|
|
341
|
+
if (this.cacheTarg !== value) {
|
|
342
|
+
this.cacheTarg = value
|
|
343
|
+
this.accessory.log(`${platformLang.curTarg} [${this.cacheTarg}°C]`)
|
|
344
|
+
}
|
|
345
|
+
} catch (err) {
|
|
346
|
+
// Catch any errors during the process
|
|
347
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
348
|
+
|
|
349
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
350
|
+
setTimeout(() => {
|
|
351
|
+
this.service.updateCharacteristic(this.hapChar.HeatingThresholdTemperature, this.cacheTarg)
|
|
352
|
+
}, 2000)
|
|
353
|
+
throw new this.hapErr(-70402)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
async internalSwingUpdate(value) {
|
|
358
|
+
try {
|
|
359
|
+
// value === 0 -> swing mode OFF
|
|
360
|
+
// value === 1 -> swing mode ON
|
|
361
|
+
const newValue = value === 1 ? 'on' : 'off'
|
|
362
|
+
|
|
363
|
+
// Don't continue if the new value is the same as before
|
|
364
|
+
if (this.cacheSwing === newValue) {
|
|
365
|
+
return
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Send the request to the platform sender function
|
|
369
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
370
|
+
cmd: 'multiSync',
|
|
371
|
+
value: value === 1 ? 'Mx8BAQAAAAAAAAAAAAAAAAAAACw=' : 'Mx8BAAAAAAAAAAAAAAAAAAAAAC0=',
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
// Cache the new state and log if appropriate
|
|
375
|
+
if (this.cacheSwing !== newValue) {
|
|
376
|
+
this.cacheSwing = newValue
|
|
377
|
+
this.accessory.log(`${platformLang.curSwing} [${newValue}]`)
|
|
378
|
+
}
|
|
379
|
+
} catch (err) {
|
|
380
|
+
// Catch any errors during the process
|
|
381
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
382
|
+
|
|
383
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
384
|
+
setTimeout(() => {
|
|
385
|
+
this.service.updateCharacteristic(
|
|
386
|
+
this.hapChar.SwingMode,
|
|
387
|
+
this.cacheSwing === 'on' ? 1 : 0,
|
|
388
|
+
)
|
|
389
|
+
}, 2000)
|
|
390
|
+
throw new this.hapErr(-70402)
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async internalLockUpdate(value) {
|
|
395
|
+
try {
|
|
396
|
+
// value === 0 -> child lock OFF
|
|
397
|
+
// value === 1 -> child lock ON
|
|
398
|
+
const newValue = value === 1 ? 'on' : 'off'
|
|
399
|
+
|
|
400
|
+
// Don't continue if the new value is the same as before
|
|
401
|
+
if (this.cacheLock === newValue) {
|
|
402
|
+
return
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Send the request to the platform sender function
|
|
406
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
407
|
+
cmd: 'multiSync',
|
|
408
|
+
value: value === 1 ? 'Mx8CAQAAAAAAAAAAAAAAAAAAAC8=' : 'Mx8CAAAAAAAAAAAAAAAAAAAAAC4=',
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
// Cache the new state and log if appropriate
|
|
412
|
+
if (this.cacheLock !== newValue) {
|
|
413
|
+
this.cacheLock = newValue
|
|
414
|
+
this.accessory.log(`${platformLang.curLock} [${newValue}]`)
|
|
415
|
+
}
|
|
416
|
+
} catch (err) {
|
|
417
|
+
// Catch any errors during the process
|
|
418
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
419
|
+
|
|
420
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
421
|
+
setTimeout(() => {
|
|
422
|
+
this.service.updateCharacteristic(
|
|
423
|
+
this.hapChar.LockPhysicalControls,
|
|
424
|
+
this.cacheLock === 'on' ? 1 : 0,
|
|
425
|
+
)
|
|
426
|
+
}, 2000)
|
|
427
|
+
throw new this.hapErr(-70402)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
async internalFanStateUpdate(value) {
|
|
432
|
+
try {
|
|
433
|
+
const newValue = value ? 'on' : 'off'
|
|
434
|
+
|
|
435
|
+
// The fan is used for the following modes:
|
|
436
|
+
// - 0%__: Auto
|
|
437
|
+
// - 25%_: Fan Only Mode
|
|
438
|
+
// - 50%_: Low Mode
|
|
439
|
+
// - 75%_: Medium Mode
|
|
440
|
+
// - 100%: High Mode
|
|
441
|
+
// If the main heater is turned off then this fan should be turned off too
|
|
442
|
+
// If the main heater is turned on then this fan speed should revert to the current mode
|
|
443
|
+
|
|
444
|
+
// Don't continue if the new value is the same as before
|
|
445
|
+
if (this.cacheFanState === newValue) {
|
|
446
|
+
return
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Turning fan on:
|
|
450
|
+
// We should not need to worry about a command for turning the fan ON, since
|
|
451
|
+
// the correct mode command will be sent when selecting the fan speed
|
|
452
|
+
// However we should mark the heater "active" characteristic as ON
|
|
453
|
+
if (newValue === 'on') {
|
|
454
|
+
if (this.cacheState !== 'on') {
|
|
455
|
+
this.cacheState = 'on'
|
|
456
|
+
this.service.updateCharacteristic(this.hapChar.Active, 1)
|
|
457
|
+
this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
|
|
458
|
+
}
|
|
459
|
+
this.cacheFanState = 'on'
|
|
460
|
+
return
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// Turning fan off:
|
|
464
|
+
// We should send a command to set the heater mode to AUTO
|
|
465
|
+
this.cacheFanState = 'off'
|
|
466
|
+
this.cacheMode = 'auto'
|
|
467
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, 0)
|
|
468
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
469
|
+
} catch (err) {
|
|
470
|
+
// Catch any errors during the process
|
|
471
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
472
|
+
|
|
473
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
474
|
+
setTimeout(() => {
|
|
475
|
+
this.fanService.updateCharacteristic(this.hapChar.On, this.cacheFanState === 'on')
|
|
476
|
+
}, 2000)
|
|
477
|
+
throw new this.hapErr(-70402)
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
async internalSpeedUpdate(value) {
|
|
482
|
+
try {
|
|
483
|
+
// Don't continue if the new value is the same as before
|
|
484
|
+
if (this.cacheSpeed === value || value === 0) {
|
|
485
|
+
return
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Value should be one of 25, 50, 75, 100
|
|
489
|
+
const codeToSend = this.speedCode[value]
|
|
490
|
+
|
|
491
|
+
// Send the request to the platform sender function
|
|
492
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
493
|
+
cmd: 'multiSync',
|
|
494
|
+
value: codeToSend,
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
// Cache the new state and log if appropriate
|
|
498
|
+
this.cacheFanState = 'on'
|
|
499
|
+
this.service.updateCharacteristic(this.hapChar.Active, 1)
|
|
500
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, 1)
|
|
501
|
+
if (this.cacheSpeed !== value) {
|
|
502
|
+
this.cacheSpeed = value
|
|
503
|
+
this.cacheMode = this.speedCodeLabel[value]
|
|
504
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
505
|
+
}
|
|
506
|
+
} catch (err) {
|
|
507
|
+
// Catch any errors during the process
|
|
508
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
509
|
+
|
|
510
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
511
|
+
setTimeout(() => {
|
|
512
|
+
this.fanService.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
|
|
513
|
+
}, 2000)
|
|
514
|
+
throw new this.hapErr(-70402)
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
async internalLightStateUpdate(value) {
|
|
519
|
+
try {
|
|
520
|
+
const newValue = value ? 'on' : 'off'
|
|
521
|
+
|
|
522
|
+
// Don't continue if the new value is the same as before
|
|
523
|
+
if (this.cacheLightState === newValue) {
|
|
524
|
+
return
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Generate the hex values for the code
|
|
528
|
+
const hexValues = [0x3A, 0x1B, 0x01, 0x01, `0x0${value ? '1' : '0'}`]
|
|
529
|
+
|
|
530
|
+
// Send the request to the platform sender function
|
|
531
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
532
|
+
cmd: 'multiSync',
|
|
533
|
+
value: generateCodeFromHexValues(hexValues),
|
|
534
|
+
})
|
|
535
|
+
|
|
536
|
+
// Cache the new state and log if appropriate
|
|
537
|
+
if (this.cacheLightState !== newValue) {
|
|
538
|
+
this.cacheLightState = newValue
|
|
539
|
+
this.accessory.log(`${platformLang.curLight} [${newValue}]`)
|
|
540
|
+
}
|
|
541
|
+
} catch (err) {
|
|
542
|
+
// Catch any errors during the process
|
|
543
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
544
|
+
|
|
545
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
546
|
+
setTimeout(() => {
|
|
547
|
+
this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on')
|
|
548
|
+
}, 2000)
|
|
549
|
+
throw new this.hapErr(-70402)
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
async internalBrightnessUpdate(value) {
|
|
554
|
+
try {
|
|
555
|
+
// This acts like a debounce function when endlessly sliding the brightness scale
|
|
556
|
+
const updateKeyBright = generateRandomString(5)
|
|
557
|
+
this.updateKeyBright = updateKeyBright
|
|
558
|
+
await sleep(350)
|
|
559
|
+
if (updateKeyBright !== this.updateKeyBright) {
|
|
560
|
+
return
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Don't continue if the new value is the same as before
|
|
564
|
+
if (value === this.cacheBright) {
|
|
565
|
+
return
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Generate the hex values for the code
|
|
569
|
+
const hexValues = [0x3A, 0x1B, 0x01, 0x02, value]
|
|
570
|
+
|
|
571
|
+
// Send the request to the platform sender function
|
|
572
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
573
|
+
cmd: 'multiSync',
|
|
574
|
+
value: generateCodeFromHexValues(hexValues),
|
|
575
|
+
})
|
|
576
|
+
|
|
577
|
+
// Govee considers 0% brightness to be off
|
|
578
|
+
if (value === 0) {
|
|
579
|
+
setTimeout(() => {
|
|
580
|
+
this.cacheLightState = 'off'
|
|
581
|
+
if (this.lightService.getCharacteristic(this.hapChar.On).value) {
|
|
582
|
+
this.lightService.updateCharacteristic(this.hapChar.On, false)
|
|
583
|
+
this.accessory.log(`${platformLang.curLight} [${this.cacheLightState}]`)
|
|
584
|
+
}
|
|
585
|
+
this.lightService.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
|
|
586
|
+
}, 1500)
|
|
587
|
+
return
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Cache the new state and log if appropriate
|
|
591
|
+
if (this.cacheBright !== value) {
|
|
592
|
+
this.cacheBright = value
|
|
593
|
+
this.accessory.log(`${platformLang.curBright} [${value}%]`)
|
|
594
|
+
}
|
|
595
|
+
} catch (err) {
|
|
596
|
+
// Catch any errors during the process
|
|
597
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
598
|
+
|
|
599
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
600
|
+
setTimeout(() => {
|
|
601
|
+
this.lightService.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
|
|
602
|
+
}, 2000)
|
|
603
|
+
throw new this.hapErr(-70402)
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
async internalColourUpdate(value) {
|
|
608
|
+
try {
|
|
609
|
+
// This acts like a debounce function when endlessly sliding the colour wheel
|
|
610
|
+
const updateKeyColour = generateRandomString(5)
|
|
611
|
+
this.updateKeyColour = updateKeyColour
|
|
612
|
+
await sleep(300)
|
|
613
|
+
if (updateKeyColour !== this.updateKeyColour) {
|
|
614
|
+
return
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Don't continue if the new value is the same as before
|
|
618
|
+
if (value === this.cacheHue) {
|
|
619
|
+
return
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// Calculate RGB values
|
|
623
|
+
const newRGB = hs2rgb(value, this.lightService.getCharacteristic(this.hapChar.Saturation).value)
|
|
624
|
+
|
|
625
|
+
// Generate the hex values for the code
|
|
626
|
+
const hexValues = [0x3A, 0x1B, 0x05, 0x0D, ...newRGB]
|
|
627
|
+
|
|
628
|
+
// Send the request to the platform sender function
|
|
629
|
+
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
630
|
+
cmd: 'multiSync',
|
|
631
|
+
value: generateCodeFromHexValues(hexValues),
|
|
632
|
+
})
|
|
633
|
+
|
|
634
|
+
// Cache the new state and log if appropriate
|
|
635
|
+
if (this.cacheHue !== value) {
|
|
636
|
+
this.cacheHue = value
|
|
637
|
+
this.accessory.log(`${platformLang.curColour} [rgb ${newRGB.join(' ')}]`)
|
|
638
|
+
}
|
|
639
|
+
} catch (err) {
|
|
640
|
+
// Catch any errors during the process
|
|
641
|
+
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
642
|
+
|
|
643
|
+
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
644
|
+
setTimeout(() => {
|
|
645
|
+
this.lightService.updateCharacteristic(this.hapChar.Hue, this.cacheHue)
|
|
646
|
+
}, 2000)
|
|
647
|
+
throw new this.hapErr(-70402)
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
externalUpdate(params) {
|
|
652
|
+
// Update the active characteristic
|
|
653
|
+
if (params.state && params.state !== this.cacheState) {
|
|
654
|
+
this.cacheState = params.state
|
|
655
|
+
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
|
|
656
|
+
this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// Update the current temperature characteristic
|
|
660
|
+
if (hasProperty(params, 'temperature')) {
|
|
661
|
+
const newTemp = nearestHalf(farToCen(params.temperature / 100))
|
|
662
|
+
if (newTemp !== this.cacheTemp) {
|
|
663
|
+
this.cacheTemp = newTemp
|
|
664
|
+
this.service.updateCharacteristic(this.hapChar.CurrentTemperature, this.cacheTemp)
|
|
665
|
+
this.accessory.log(`${platformLang.curTemp} [${this.cacheTemp}°C]`)
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Update the target temperature characteristic
|
|
670
|
+
if (hasProperty(params, 'setTemperature')) {
|
|
671
|
+
const newTemp = Math.round(farToCen(params.setTemperature / 100))
|
|
672
|
+
if (newTemp !== this.cacheTarg) {
|
|
673
|
+
// A change in target temperature would suggest the device is in auto mode
|
|
674
|
+
// If incorrect, the code change will pick this up later
|
|
675
|
+
this.cacheTarg = newTemp
|
|
676
|
+
this.cacheFanState = 'off'
|
|
677
|
+
this.cacheSpeed = 0
|
|
678
|
+
this.cacheMode = 'auto'
|
|
679
|
+
this.service.updateCharacteristic(this.hapChar.HeatingThresholdTemperature, this.cacheTarg)
|
|
680
|
+
this.accessory.log(`${platformLang.curTarg} [${this.cacheTarg}°C]`)
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Check for some other scene/mode change
|
|
685
|
+
(params.commands || []).forEach((command) => {
|
|
686
|
+
const hexString = base64ToHex(command)
|
|
687
|
+
const hexParts = hexToTwoItems(hexString)
|
|
688
|
+
|
|
689
|
+
// Return now if not a device query update code
|
|
690
|
+
if (getTwoItemPosition(hexParts, 1) !== 'aa') {
|
|
691
|
+
return
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`
|
|
695
|
+
|
|
696
|
+
switch (deviceFunction) {
|
|
697
|
+
case '1b01': {
|
|
698
|
+
const newLightState = getTwoItemPosition(hexParts, 4) === '01' ? 'on' : 'off'
|
|
699
|
+
if (this.cacheLightState !== newLightState) {
|
|
700
|
+
this.cacheLightState = newLightState
|
|
701
|
+
this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on')
|
|
702
|
+
this.accessory.log(`${platformLang.curLight} [${this.cacheLightState}]`)
|
|
703
|
+
}
|
|
704
|
+
const newBrightness = hexToDecimal(getTwoItemPosition(hexParts, 5))
|
|
705
|
+
if (this.cacheBright !== newBrightness) {
|
|
706
|
+
this.cacheBright = newBrightness
|
|
707
|
+
this.lightService.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
|
|
708
|
+
this.accessory.log(`${platformLang.curBright} [${this.cacheBright}%]`)
|
|
709
|
+
}
|
|
710
|
+
break
|
|
711
|
+
}
|
|
712
|
+
case '1b05': {
|
|
713
|
+
// Night light colour
|
|
714
|
+
const newR = hexToDecimal(getTwoItemPosition(hexParts, 5))
|
|
715
|
+
const newG = hexToDecimal(getTwoItemPosition(hexParts, 6))
|
|
716
|
+
const newB = hexToDecimal(getTwoItemPosition(hexParts, 7))
|
|
717
|
+
|
|
718
|
+
const hs = rgb2hs(newR, newG, newB)
|
|
719
|
+
|
|
720
|
+
// Check for a colour change
|
|
721
|
+
if (hs[0] !== this.cacheHue) {
|
|
722
|
+
// Colour is different so update Homebridge with new values
|
|
723
|
+
this.lightService.updateCharacteristic(this.hapChar.Hue, hs[0])
|
|
724
|
+
this.lightService.updateCharacteristic(this.hapChar.Saturation, hs[1]);
|
|
725
|
+
[this.cacheHue] = hs
|
|
726
|
+
|
|
727
|
+
// Log the change
|
|
728
|
+
this.accessory.log(`${platformLang.curColour} [rgb ${newR} ${newG} ${newB}]`)
|
|
729
|
+
}
|
|
730
|
+
break
|
|
731
|
+
}
|
|
732
|
+
case '1f00':
|
|
733
|
+
case '1f01': {
|
|
734
|
+
// Swing Mode
|
|
735
|
+
const newSwing = getTwoItemPosition(hexParts, 3) === '01' ? 'on' : 'off'
|
|
736
|
+
if (this.cacheSwing !== newSwing) {
|
|
737
|
+
this.cacheSwing = newSwing
|
|
738
|
+
this.service.updateCharacteristic(this.hapChar.SwingMode, this.cacheSwing === 'on' ? 1 : 0)
|
|
739
|
+
this.accessory.log(`${platformLang.curSwing} [${this.cacheSwing}]`)
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Child Lock
|
|
743
|
+
const newLock = getTwoItemPosition(hexParts, 4) === '01' ? 'on' : 'off'
|
|
744
|
+
if (this.cacheLock !== newLock) {
|
|
745
|
+
this.cacheLock = newLock
|
|
746
|
+
this.service.updateCharacteristic(this.hapChar.LockPhysicalControls, this.cacheLock === 'on' ? 1 : 0)
|
|
747
|
+
this.accessory.log(`${platformLang.curLock} [${this.cacheLock}]`)
|
|
748
|
+
}
|
|
749
|
+
break
|
|
750
|
+
}
|
|
751
|
+
case '0509': {
|
|
752
|
+
// Fan-only mode
|
|
753
|
+
const newModeLabel = 'fan-only'
|
|
754
|
+
if (this.cacheMode !== newModeLabel) {
|
|
755
|
+
this.cacheMode = newModeLabel
|
|
756
|
+
this.cacheFanState = 'on'
|
|
757
|
+
this.cacheSpeed = 25
|
|
758
|
+
this.fanService.updateCharacteristic(this.hapChar.On, true)
|
|
759
|
+
this.fanService.updateCharacteristic(this.hapChar.RotationSpeed, 25)
|
|
760
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, 1)
|
|
761
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
762
|
+
}
|
|
763
|
+
break
|
|
764
|
+
}
|
|
765
|
+
case '0501': { // Speed
|
|
766
|
+
const newMode = getTwoItemPosition(hexParts, 4)
|
|
767
|
+
switch (newMode) {
|
|
768
|
+
case '01': {
|
|
769
|
+
const newModeLabel = 'low'
|
|
770
|
+
if (this.cacheMode !== newModeLabel) {
|
|
771
|
+
this.cacheMode = newModeLabel
|
|
772
|
+
this.cacheFanState = 'on'
|
|
773
|
+
this.cacheSpeed = 50
|
|
774
|
+
this.fanService.updateCharacteristic(this.hapChar.On, true)
|
|
775
|
+
this.fanService.updateCharacteristic(this.hapChar.RotationSpeed, 50)
|
|
776
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, 1)
|
|
777
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
778
|
+
}
|
|
779
|
+
break
|
|
780
|
+
}
|
|
781
|
+
case '02': {
|
|
782
|
+
const newModeLabel = 'medium'
|
|
783
|
+
if (this.cacheMode !== newModeLabel) {
|
|
784
|
+
this.cacheMode = newModeLabel
|
|
785
|
+
this.cacheFanState = 'on'
|
|
786
|
+
this.cacheSpeed = 75
|
|
787
|
+
this.fanService.updateCharacteristic(this.hapChar.On, true)
|
|
788
|
+
this.fanService.updateCharacteristic(this.hapChar.RotationSpeed, 75)
|
|
789
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, 1)
|
|
790
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
791
|
+
}
|
|
792
|
+
break
|
|
793
|
+
}
|
|
794
|
+
case '03': {
|
|
795
|
+
const newModeLabel = 'high'
|
|
796
|
+
if (this.cacheMode !== newModeLabel) {
|
|
797
|
+
this.cacheMode = newModeLabel
|
|
798
|
+
this.cacheFanState = 'on'
|
|
799
|
+
this.cacheSpeed = 100
|
|
800
|
+
this.fanService.updateCharacteristic(this.hapChar.On, true)
|
|
801
|
+
this.fanService.updateCharacteristic(this.hapChar.RotationSpeed, 100)
|
|
802
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, 1)
|
|
803
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
804
|
+
}
|
|
805
|
+
break
|
|
806
|
+
}
|
|
807
|
+
default:
|
|
808
|
+
break
|
|
809
|
+
}
|
|
810
|
+
break
|
|
811
|
+
}
|
|
812
|
+
case '0503': { // Target temperature (thermostat mode on)
|
|
813
|
+
const newModeLabel = 'auto'
|
|
814
|
+
if (this.cacheMode !== newModeLabel) {
|
|
815
|
+
this.cacheMode = newModeLabel
|
|
816
|
+
this.cacheFanState = 'off'
|
|
817
|
+
this.cacheSpeed = 0
|
|
818
|
+
this.fanService.updateCharacteristic(this.hapChar.On, false)
|
|
819
|
+
this.fanService.updateCharacteristic(this.hapChar.RotationSpeed, 0)
|
|
820
|
+
this.service.updateCharacteristic(this.hapChar.TargetHeaterCoolerState, 0)
|
|
821
|
+
this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
|
|
822
|
+
}
|
|
823
|
+
break
|
|
824
|
+
}
|
|
825
|
+
case '1a00': // Target temperature (thermostat mode off)
|
|
826
|
+
case '1100': // Timer off
|
|
827
|
+
case '1101': // Timer on
|
|
828
|
+
case '1600': // Display mode off
|
|
829
|
+
case '1601': // Display mode on
|
|
830
|
+
// We do not need to do anything for these
|
|
831
|
+
break
|
|
832
|
+
default:
|
|
833
|
+
this.accessory.logDebugWarn(`${platformLang.newScene}: [${command}] [${hexString}]`)
|
|
834
|
+
break
|
|
835
|
+
}
|
|
836
|
+
})
|
|
837
|
+
}
|
|
838
|
+
}
|