@homebridge-plugins/homebridge-govee 11.32.2-beta.14 → 11.32.2-beta.15
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 +2 -0
- package/lib/device/dehumidifier-H7150.js +1 -1
- package/lib/device/fan-H7100.js +11 -1
- package/lib/device/index.js +3 -5
- package/package.json +1 -1
- package/lib/device/dehumidifier-H7152.js +0 -186
- package/lib/device/fan-H7101.js +0 -347
package/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,8 @@ All notable changes to `@homebridge-plugins/homebridge-govee` will be documented
|
|
|
30
30
|
- refactor: point the H7151 and H7111 at the handlers they were byte-for-byte copies of
|
|
31
31
|
- refactor: build the ice maker size codes from the model rather than writing both orderings out by hand
|
|
32
32
|
- refactor: build the switch and outlet tiles of a multi-socket device from one handler instead of two copies of it
|
|
33
|
+
- fix: move the H7152 dehumidifier's speed slider when it reports a new speed, which until now only the H7150 and H7151 did
|
|
34
|
+
- refactor: point the H7101 and H7111 fans at the H7100 handler they matched command for command
|
|
33
35
|
|
|
34
36
|
## v11.32.1 (2026-08-02)
|
|
35
37
|
|
package/lib/device/fan-H7100.js
CHANGED
|
@@ -10,6 +10,16 @@ import {
|
|
|
10
10
|
import platformLang from '../utils/lang-en.js'
|
|
11
11
|
import { logUnknownData } from '../utils/report-unknown.js'
|
|
12
12
|
|
|
13
|
+
/*
|
|
14
|
+
The models on this handler and the modes each offers:
|
|
15
|
+
|
|
16
|
+
H7100, H7102, H7106 -> Sleep, Nature, Custom, Auto
|
|
17
|
+
H7101 -> Sleep, Nature, Turbo, Custom, Auto
|
|
18
|
+
H7111 -> Sleep, Nature, Custom, Auto
|
|
19
|
+
H1310, R1310 -> as the H7100, but its oscillation status message has
|
|
20
|
+
never been confirmed, so it is not read back
|
|
21
|
+
*/
|
|
22
|
+
|
|
13
23
|
export default class GoveeFanH7100 {
|
|
14
24
|
constructor(platform, accessory) {
|
|
15
25
|
// Set up variables from the platform
|
|
@@ -267,7 +277,7 @@ export default class GoveeFanH7100 {
|
|
|
267
277
|
this.cacheSpeed = this.autoSpeed
|
|
268
278
|
// Cache auto so we can tell it apart from "user asked for max speed"
|
|
269
279
|
this.service.updateCharacteristic(this.hapChar.RotationSpeed, 100)
|
|
270
|
-
this.accessory.log(`${platformLang.curSpeed} [auto]`)
|
|
280
|
+
this.accessory.log(`${platformLang.curSpeed} [auto -> 100%]`)
|
|
271
281
|
}
|
|
272
282
|
break
|
|
273
283
|
}
|
package/lib/device/index.js
CHANGED
|
@@ -7,11 +7,9 @@ import {
|
|
|
7
7
|
} from './appliance-basic.js'
|
|
8
8
|
import deviceCoolerSingle from './cooler-single.js'
|
|
9
9
|
import deviceDehumidifierH7150 from './dehumidifier-H7150.js'
|
|
10
|
-
import deviceDehumidifierH7152 from './dehumidifier-H7152.js'
|
|
11
10
|
import deviceDiffuserH7161 from './diffuser-H7161.js'
|
|
12
11
|
import deviceFanH1370 from './fan-H1370.js'
|
|
13
12
|
import deviceFanH7100 from './fan-H7100.js'
|
|
14
|
-
import deviceFanH7101 from './fan-H7101.js'
|
|
15
13
|
import deviceFanH7105 from './fan-H7105.js'
|
|
16
14
|
import deviceFanH7107 from './fan-H7107.js'
|
|
17
15
|
import deviceHeater1A from './heater1a.js'
|
|
@@ -53,7 +51,7 @@ export default {
|
|
|
53
51
|
deviceCoolerSingle,
|
|
54
52
|
deviceDehumidifierH7150,
|
|
55
53
|
deviceDehumidifierH7151: deviceDehumidifierH7150, // identical to the H7150
|
|
56
|
-
deviceDehumidifierH7152,
|
|
54
|
+
deviceDehumidifierH7152: deviceDehumidifierH7150, // same device, and this gives it proper speed feedback
|
|
57
55
|
deviceDiffuserH7161,
|
|
58
56
|
deviceDiffuserH7162: deviceDiffuserH7161, // identical to the H7161
|
|
59
57
|
deviceDehumidifierBasic,
|
|
@@ -64,10 +62,10 @@ export default {
|
|
|
64
62
|
deviceFanH7100,
|
|
65
63
|
deviceFanH7102: deviceFanH7100, // identical to the H7100
|
|
66
64
|
deviceFanH7106: deviceFanH7100, // identical to the H7100
|
|
67
|
-
deviceFanH7101,
|
|
65
|
+
deviceFanH7101: deviceFanH7100, // identical to the H7100, with a turbo mode it is never sent
|
|
68
66
|
deviceFanH7105,
|
|
69
67
|
deviceFanH7107,
|
|
70
|
-
deviceFanH7111:
|
|
68
|
+
deviceFanH7111: deviceFanH7100, // same fan without the turbo mode, which is not sent
|
|
71
69
|
deviceHeaterSingle,
|
|
72
70
|
deviceHeater1A,
|
|
73
71
|
deviceHeater1B,
|
package/package.json
CHANGED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
base64ToHex,
|
|
3
|
-
getTwoItemPosition,
|
|
4
|
-
hexToTwoItems,
|
|
5
|
-
parseError,
|
|
6
|
-
} from '../utils/functions.js'
|
|
7
|
-
import platformLang from '../utils/lang-en.js'
|
|
8
|
-
import { logUnknownData } from '../utils/report-unknown.js'
|
|
9
|
-
|
|
10
|
-
export default class {
|
|
11
|
-
constructor(platform, accessory) {
|
|
12
|
-
// Set up variables from the platform
|
|
13
|
-
this.hapChar = platform.api.hap.Characteristic
|
|
14
|
-
this.hapErr = platform.api.hap.HapStatusError
|
|
15
|
-
this.hapServ = platform.api.hap.Service
|
|
16
|
-
this.platform = platform
|
|
17
|
-
|
|
18
|
-
// Set up variables from the accessory
|
|
19
|
-
this.accessory = accessory
|
|
20
|
-
|
|
21
|
-
// Speed codes
|
|
22
|
-
this.value2Code = {
|
|
23
|
-
1: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=',
|
|
24
|
-
2: 'MwUBAgAAAAAAAAAAAAAAAAAAADU=',
|
|
25
|
-
3: 'MwUBAwAAAAAAAAAAAAAAAAAAADQ=',
|
|
26
|
-
4: 'MwUBBAAAAAAAAAAAAAAAAAAAADM=',
|
|
27
|
-
5: 'MwUBBQAAAAAAAAAAAAAAAAAAADI=',
|
|
28
|
-
6: 'MwUBBgAAAAAAAAAAAAAAAAAAADE=',
|
|
29
|
-
7: 'MwUBBwAAAAAAAAAAAAAAAAAAADA=',
|
|
30
|
-
8: 'MwUBCAAAAAAAAAAAAAAAAAAAAD8=',
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Migrate old %-rotation speed to unitless
|
|
34
|
-
const existingFanService = this.accessory.getService(this.hapServ.Fan)
|
|
35
|
-
if (existingFanService) {
|
|
36
|
-
if (existingFanService.getCharacteristic(this.hapChar.RotationSpeed).props.unit === 'percentage') {
|
|
37
|
-
this.accessory.removeService(existingFanService)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Add the fan service if it doesn't already exist
|
|
42
|
-
this.service = this.accessory.getService(this.hapServ.Fan) || this.accessory.addService(this.hapServ.Fan)
|
|
43
|
-
|
|
44
|
-
// Add the set handler to the fan on/off characteristic
|
|
45
|
-
this.service
|
|
46
|
-
.getCharacteristic(this.hapChar.On)
|
|
47
|
-
.onSet(async value => this.internalStateUpdate(value))
|
|
48
|
-
this.cacheState = this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
|
|
49
|
-
|
|
50
|
-
// Add the set handler to the fan rotation speed characteristic
|
|
51
|
-
this.service
|
|
52
|
-
.getCharacteristic(this.hapChar.RotationSpeed)
|
|
53
|
-
.setProps({
|
|
54
|
-
maxValue: 8,
|
|
55
|
-
minStep: 1,
|
|
56
|
-
minValue: 0,
|
|
57
|
-
unit: 'unitless',
|
|
58
|
-
})
|
|
59
|
-
.onSet(async value => this.internalSpeedUpdate(value))
|
|
60
|
-
this.cacheSpeed = this.service.getCharacteristic(this.hapChar.RotationSpeed).value
|
|
61
|
-
|
|
62
|
-
// Output the customised options to the log
|
|
63
|
-
const opts = JSON.stringify({})
|
|
64
|
-
platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async internalStateUpdate(value) {
|
|
68
|
-
try {
|
|
69
|
-
const newValue = value ? 'on' : 'off'
|
|
70
|
-
|
|
71
|
-
// Don't continue if the new value is the same as before
|
|
72
|
-
if (this.cacheState === newValue) {
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Send the request to the platform sender function
|
|
77
|
-
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
78
|
-
cmd: 'stateHumi',
|
|
79
|
-
value: value ? 1 : 0,
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
// Cache the new state and log if appropriate
|
|
83
|
-
this.cacheState = newValue
|
|
84
|
-
this.accessory.log(`${platformLang.curState} [${newValue}]`)
|
|
85
|
-
} catch (err) {
|
|
86
|
-
// Catch any errors during the process
|
|
87
|
-
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
88
|
-
|
|
89
|
-
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
90
|
-
setTimeout(() => {
|
|
91
|
-
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
92
|
-
}, 2000)
|
|
93
|
-
throw new this.hapErr(-70402)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async internalSpeedUpdate(value) {
|
|
98
|
-
try {
|
|
99
|
-
// Don't continue if the speed is 0
|
|
100
|
-
if (value === 0) {
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Don't continue if the speed value won't have effect
|
|
105
|
-
if (value === this.cacheSpeed) {
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Get the scene code for this value
|
|
110
|
-
const newCode = this.value2Code[value]
|
|
111
|
-
|
|
112
|
-
// Send the request to the platform sender function
|
|
113
|
-
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
114
|
-
cmd: 'ptReal',
|
|
115
|
-
value: newCode,
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
// Cache the new state and log if appropriate
|
|
119
|
-
this.cacheSpeed = value
|
|
120
|
-
this.accessory.log(`${platformLang.curSpeed} [${value}]`)
|
|
121
|
-
} catch (err) {
|
|
122
|
-
// Catch any errors during the process
|
|
123
|
-
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
124
|
-
|
|
125
|
-
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
|
|
128
|
-
}, 2000)
|
|
129
|
-
throw new this.hapErr(-70402)
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
externalUpdate(params) {
|
|
134
|
-
// Check for an ON/OFF change
|
|
135
|
-
if (params.state && params.state !== this.cacheState) {
|
|
136
|
-
this.cacheState = params.state
|
|
137
|
-
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
138
|
-
|
|
139
|
-
// Log the change
|
|
140
|
-
this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Handle OpenAPI workMode
|
|
144
|
-
if (params.workMode) {
|
|
145
|
-
const mode = params.workMode.modeValue
|
|
146
|
-
this.accessory.log(`${platformLang.curMode} [${mode}]`)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Check for some other scene/mode change
|
|
150
|
-
(params.commands || []).forEach((command) => {
|
|
151
|
-
const hexString = base64ToHex(command)
|
|
152
|
-
const hexParts = hexToTwoItems(hexString)
|
|
153
|
-
|
|
154
|
-
// Return now if not a device query update code
|
|
155
|
-
if (getTwoItemPosition(hexParts, 1) !== 'aa') {
|
|
156
|
-
return
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`
|
|
160
|
-
|
|
161
|
-
switch (deviceFunction) {
|
|
162
|
-
case '0501':
|
|
163
|
-
case '0502': {
|
|
164
|
-
// Speed update
|
|
165
|
-
const newSpeedValue = Number.parseInt(getTwoItemPosition(hexParts, 4), 16)
|
|
166
|
-
if (newSpeedValue >= 1 && newSpeedValue <= 8) {
|
|
167
|
-
if (newSpeedValue !== this.cacheSpeed) {
|
|
168
|
-
this.cacheSpeed = newSpeedValue
|
|
169
|
-
this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
|
|
170
|
-
this.accessory.log(`${platformLang.curSpeed} [${this.cacheSpeed}]`)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
break
|
|
174
|
-
}
|
|
175
|
-
default:
|
|
176
|
-
logUnknownData(this.accessory, {
|
|
177
|
-
kind: 'scene',
|
|
178
|
-
source: params.source,
|
|
179
|
-
raw: command,
|
|
180
|
-
hex: hexString,
|
|
181
|
-
})
|
|
182
|
-
break
|
|
183
|
-
}
|
|
184
|
-
})
|
|
185
|
-
}
|
|
186
|
-
}
|
package/lib/device/fan-H7101.js
DELETED
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
base64ToHex,
|
|
3
|
-
fanSpeedToHkPercent,
|
|
4
|
-
getTwoItemPosition,
|
|
5
|
-
hexToTwoItems,
|
|
6
|
-
hkPercentToFanSpeed,
|
|
7
|
-
parseError,
|
|
8
|
-
} from '../utils/functions.js'
|
|
9
|
-
import platformLang from '../utils/lang-en.js'
|
|
10
|
-
import { logUnknownData } from '../utils/report-unknown.js'
|
|
11
|
-
|
|
12
|
-
/*
|
|
13
|
-
H7101 and H7111
|
|
14
|
-
{
|
|
15
|
-
"mode": {
|
|
16
|
-
"options": [
|
|
17
|
-
{
|
|
18
|
-
"name": "Custom",
|
|
19
|
-
"value": 2
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"name": "Auto",
|
|
23
|
-
"value": 3
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"name": "Sleep",
|
|
27
|
-
"value": 5
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"name": "Nature",
|
|
31
|
-
"value": 6
|
|
32
|
-
}
|
|
33
|
-
]
|
|
34
|
-
},
|
|
35
|
-
"gear": {
|
|
36
|
-
"options": [
|
|
37
|
-
{
|
|
38
|
-
"name": "gear",
|
|
39
|
-
"value": [
|
|
40
|
-
1,
|
|
41
|
-
2,
|
|
42
|
-
3,
|
|
43
|
-
4,
|
|
44
|
-
5,
|
|
45
|
-
6,
|
|
46
|
-
7,
|
|
47
|
-
8
|
|
48
|
-
]
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// NOTES
|
|
55
|
-
H7101 -> Sleep, Nature, Turbo, Custom, Auto
|
|
56
|
-
H7111 -> Sleep, Nature, Custom, Auto (no turbo)
|
|
57
|
-
|
|
58
|
-
sleep
|
|
59
|
-
[31/10/2022, 20:52:08] [Govee] [Device1] [AWS] receiving update {"source":"AWS","result":1,"commands":["qgUFAAAAAAAAAAAAAAAAAAAAAKo=","qgUABQAAAAAAAAAAAAAAAAAAAKo="]}.
|
|
60
|
-
[31/10/2022, 20:52:08] [Govee] [Device1] new scene code: [qgUFAAAAAAAAAAAAAAAAAAAAAKo=] [aa050500000000000000000000000000000000aa].
|
|
61
|
-
[31/10/2022, 20:52:08] [Govee] [Device1] new scene code: [qgUABQAAAAAAAAAAAAAAAAAAAKo=] [aa050005000000000000000000000000000000aa].
|
|
62
|
-
|
|
63
|
-
nature
|
|
64
|
-
[31/10/2022, 20:52:43] [Govee] [Device1] [AWS] receiving update {"source":"AWS","result":1,"commands":["qgUGAAAAAAAAAAAAAAAAAAAAAKk=","qgUABgAAAAAAAAAAAAAAAAAAAKk="]}.
|
|
65
|
-
[31/10/2022, 20:52:43] [Govee] [Device1] new scene code: [qgUGAAAAAAAAAAAAAAAAAAAAAKk=] [aa050600000000000000000000000000000000a9].
|
|
66
|
-
[31/10/2022, 20:52:43] [Govee] [Device1] new scene code: [qgUABgAAAAAAAAAAAAAAAAAAAKk=] [aa050006000000000000000000000000000000a9].
|
|
67
|
-
*/
|
|
68
|
-
|
|
69
|
-
export default class GoveeFanH7101 {
|
|
70
|
-
constructor(platform, accessory) {
|
|
71
|
-
// Set up variables from the platform
|
|
72
|
-
this.hapChar = platform.api.hap.Characteristic
|
|
73
|
-
this.hapErr = platform.api.hap.HapStatusError
|
|
74
|
-
this.hapServ = platform.api.hap.Service
|
|
75
|
-
this.platform = platform
|
|
76
|
-
|
|
77
|
-
// Set up variables from the accessory
|
|
78
|
-
this.accessory = accessory
|
|
79
|
-
|
|
80
|
-
// Codes etc
|
|
81
|
-
this.speedCodes = {
|
|
82
|
-
1: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=',
|
|
83
|
-
2: 'MwUBAgAAAAAAAAAAAAAAAAAAADU=',
|
|
84
|
-
3: 'MwUBAwAAAAAAAAAAAAAAAAAAADQ=',
|
|
85
|
-
4: 'MwUBBAAAAAAAAAAAAAAAAAAAADM=',
|
|
86
|
-
5: 'MwUBBQAAAAAAAAAAAAAAAAAAADI=',
|
|
87
|
-
6: 'MwUBBgAAAAAAAAAAAAAAAAAAADE=',
|
|
88
|
-
7: 'MwUBBwAAAAAAAAAAAAAAAAAAADA=',
|
|
89
|
-
8: 'MwUBCAAAAAAAAAAAAAAAAAAAAD8=',
|
|
90
|
-
9: 'MwUAAwAAAAAAAAAAAAAAAAAAADU=', // auto mode
|
|
91
|
-
}
|
|
92
|
-
this.autoSpeed = 9
|
|
93
|
-
// Real speed steps, excluding auto - HomeKit percentages map onto these
|
|
94
|
-
this.speedSteps = 8
|
|
95
|
-
|
|
96
|
-
// Remove any old original Fan services
|
|
97
|
-
if (this.accessory.getService(this.hapServ.Fan)) {
|
|
98
|
-
this.accessory.removeService(this.accessory.getService(this.hapServ.Fan))
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Rebuild the fan service if it was cached under an older speed scale, as
|
|
102
|
-
// HomeKit keeps the old props until the service itself is replaced
|
|
103
|
-
const existingService = this.accessory.getService(this.hapServ.Fanv2)
|
|
104
|
-
if (existingService) {
|
|
105
|
-
const { props } = existingService.getCharacteristic(this.hapChar.RotationSpeed)
|
|
106
|
-
if (props.unit === 'percentage' || props.maxValue !== 100) {
|
|
107
|
-
this.accessory.removeService(existingService)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Add the fan service for the fan if it doesn't already exist
|
|
112
|
-
this.service = this.accessory.getService(this.hapServ.Fanv2) || this.accessory.addService(this.hapServ.Fanv2)
|
|
113
|
-
|
|
114
|
-
// Add the set handler to the fan on/off characteristic
|
|
115
|
-
this.service
|
|
116
|
-
.getCharacteristic(this.hapChar.Active)
|
|
117
|
-
.onSet(async value => this.internalStateUpdate(value))
|
|
118
|
-
this.cacheState = this.service.getCharacteristic(this.hapChar.Active).value ? 'on' : 'off'
|
|
119
|
-
|
|
120
|
-
// Add the set handler to the fan rotation speed characteristic
|
|
121
|
-
this.service
|
|
122
|
-
.getCharacteristic(this.hapChar.RotationSpeed)
|
|
123
|
-
.setProps({
|
|
124
|
-
maxValue: 100,
|
|
125
|
-
minStep: 1,
|
|
126
|
-
minValue: 0,
|
|
127
|
-
unit: 'unitless',
|
|
128
|
-
})
|
|
129
|
-
.onSet(async value => this.internalSpeedUpdate(value))
|
|
130
|
-
this.cacheSpeed = this.service.getCharacteristic(this.hapChar.RotationSpeed).value
|
|
131
|
-
|
|
132
|
-
// Add the set handler to the fan swing mode
|
|
133
|
-
this.service
|
|
134
|
-
.getCharacteristic(this.hapChar.SwingMode)
|
|
135
|
-
.onSet(async value => this.internalSwingUpdate(value))
|
|
136
|
-
this.cacheSwing = this.service.getCharacteristic(this.hapChar.SwingMode).value === 1 ? 'on' : 'off'
|
|
137
|
-
|
|
138
|
-
// Output the customised options to the log
|
|
139
|
-
const opts = JSON.stringify({})
|
|
140
|
-
platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async internalStateUpdate(value) {
|
|
144
|
-
try {
|
|
145
|
-
const newValue = value ? 'on' : 'off'
|
|
146
|
-
|
|
147
|
-
// Don't continue if the new value is the same as before
|
|
148
|
-
if (this.cacheState === newValue) {
|
|
149
|
-
return
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Send the request to the platform sender function
|
|
153
|
-
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
154
|
-
cmd: 'ptReal',
|
|
155
|
-
value: value ? 'MwEBAAAAAAAAAAAAAAAAAAAAADM=' : 'MwEAAAAAAAAAAAAAAAAAAAAAADI=',
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
// Cache the new state and log if appropriate
|
|
159
|
-
if (this.cacheState !== newValue) {
|
|
160
|
-
this.cacheState = newValue
|
|
161
|
-
this.accessory.log(`${platformLang.curState} [${newValue}]`)
|
|
162
|
-
}
|
|
163
|
-
} catch (err) {
|
|
164
|
-
// Catch any errors during the process
|
|
165
|
-
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
166
|
-
|
|
167
|
-
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
168
|
-
setTimeout(() => {
|
|
169
|
-
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
|
|
170
|
-
}, 2000)
|
|
171
|
-
throw new this.hapErr(-70402)
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async internalSpeedUpdate(value) {
|
|
176
|
-
try {
|
|
177
|
-
// Don't continue if the value is 0
|
|
178
|
-
if (value === 0) {
|
|
179
|
-
return
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// HomeKit sends a percentage - map it onto this model's real speed steps
|
|
183
|
-
value = hkPercentToFanSpeed(value, this.speedSteps)
|
|
184
|
-
|
|
185
|
-
// Don't continue if the new value is the same as before
|
|
186
|
-
if (this.cacheSpeed === value) {
|
|
187
|
-
return
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const codeToSend = this.speedCodes[value]
|
|
191
|
-
|
|
192
|
-
const isAuto = value === this.autoSpeed
|
|
193
|
-
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
194
|
-
cmd: 'ptReal',
|
|
195
|
-
value: codeToSend,
|
|
196
|
-
openApi: this.accessory.context.openApiCapabilities?.workMode
|
|
197
|
-
? { instance: 'workMode', capabilityType: 'devices.capabilities.work_mode', value: isAuto ? { workMode: 3 } : { workMode: 1, modeValue: value } }
|
|
198
|
-
: undefined,
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
// Cache the new state and log if appropriate
|
|
202
|
-
if (this.cacheSpeed !== value) {
|
|
203
|
-
this.cacheSpeed = value
|
|
204
|
-
this.accessory.log(`${platformLang.curSpeed} [${value}]`)
|
|
205
|
-
}
|
|
206
|
-
} catch (err) {
|
|
207
|
-
// Catch any errors during the process
|
|
208
|
-
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
209
|
-
|
|
210
|
-
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
211
|
-
setTimeout(() => {
|
|
212
|
-
this.service.updateCharacteristic(this.hapChar.RotationSpeed, fanSpeedToHkPercent(this.cacheSpeed, this.speedSteps, this.autoSpeed))
|
|
213
|
-
}, 2000)
|
|
214
|
-
throw new this.hapErr(-70402)
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
async internalSwingUpdate(value) {
|
|
219
|
-
try {
|
|
220
|
-
const newValue = value ? 'on' : 'off'
|
|
221
|
-
// Don't continue if the new value is the same as before
|
|
222
|
-
if (this.cacheSwing === value) {
|
|
223
|
-
return
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
await this.platform.sendDeviceUpdate(this.accessory, {
|
|
227
|
-
cmd: 'ptReal',
|
|
228
|
-
value: value ? 'Mx8BAQAAAAAAAAAAAAAAAAAAACw=' : 'Mx8BAAAAAAAAAAAAAAAAAAAAAC0=',
|
|
229
|
-
openApi: this.accessory.context.openApiCapabilities?.oscillationToggle
|
|
230
|
-
? { instance: 'oscillationToggle', capabilityType: 'devices.capabilities.toggle', value: value ? 1 : 0 }
|
|
231
|
-
: undefined,
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
// Cache the new state and log if appropriate
|
|
235
|
-
if (this.cacheSwing !== newValue) {
|
|
236
|
-
this.cacheSwing = newValue
|
|
237
|
-
this.accessory.log(`${platformLang.curSwing} [${newValue}]`)
|
|
238
|
-
}
|
|
239
|
-
} catch (err) {
|
|
240
|
-
// Catch any errors during the process
|
|
241
|
-
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
|
|
242
|
-
|
|
243
|
-
// Throw a 'no response' error and set a timeout to revert this after 2 seconds
|
|
244
|
-
setTimeout(() => {
|
|
245
|
-
this.service.updateCharacteristic(this.hapChar.SwingMode, this.cacheSwing === 'on' ? 1 : 0)
|
|
246
|
-
}, 2000)
|
|
247
|
-
throw new this.hapErr(-70402)
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
externalUpdate(params) {
|
|
252
|
-
// Update the active characteristic
|
|
253
|
-
if (params.state && params.state !== this.cacheState) {
|
|
254
|
-
this.cacheState = params.state
|
|
255
|
-
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
|
|
256
|
-
this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Handle OpenAPI workMode (speed or auto)
|
|
260
|
-
if (params.workMode) {
|
|
261
|
-
let newSpeed
|
|
262
|
-
if (params.workMode.workMode === 3) {
|
|
263
|
-
newSpeed = this.autoSpeed
|
|
264
|
-
} else {
|
|
265
|
-
newSpeed = params.workMode.modeValue
|
|
266
|
-
}
|
|
267
|
-
if (Number.isFinite(newSpeed) && newSpeed >= 1 && newSpeed <= this.autoSpeed && this.cacheSpeed !== newSpeed) {
|
|
268
|
-
this.cacheSpeed = newSpeed
|
|
269
|
-
const hkSpeed = fanSpeedToHkPercent(newSpeed, this.speedSteps, this.autoSpeed)
|
|
270
|
-
this.service.updateCharacteristic(this.hapChar.RotationSpeed, hkSpeed)
|
|
271
|
-
this.accessory.log(`${platformLang.curSpeed} [${newSpeed} -> ${hkSpeed}%]`)
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// Handle OpenAPI toggles
|
|
276
|
-
if (params.toggles?.oscillationToggle !== undefined) {
|
|
277
|
-
const newSwing = params.toggles.oscillationToggle ? 'on' : 'off'
|
|
278
|
-
if (this.cacheSwing !== newSwing) {
|
|
279
|
-
this.cacheSwing = newSwing
|
|
280
|
-
this.service.updateCharacteristic(this.hapChar.SwingMode, this.cacheSwing === 'on' ? 1 : 0)
|
|
281
|
-
this.accessory.log(`${platformLang.curSwing} [${this.cacheSwing}]`)
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Check for some other scene/mode change
|
|
286
|
-
(params.commands || []).forEach((command) => {
|
|
287
|
-
const hexString = base64ToHex(command)
|
|
288
|
-
const hexParts = hexToTwoItems(hexString)
|
|
289
|
-
|
|
290
|
-
// Return now if not a device query update code
|
|
291
|
-
if (getTwoItemPosition(hexParts, 1) !== 'aa') {
|
|
292
|
-
return
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (getTwoItemPosition(hexParts, 2) === '08') {
|
|
296
|
-
// Sensor Attached?
|
|
297
|
-
const dev = hexString.substring(4, hexString.length - 24)
|
|
298
|
-
this.accessory.context.sensorAttached = dev !== '000000000000'
|
|
299
|
-
return
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`
|
|
303
|
-
|
|
304
|
-
switch (deviceFunction) {
|
|
305
|
-
case '0501': {
|
|
306
|
-
// Fan speed
|
|
307
|
-
const newSpeed = Number.parseInt(getTwoItemPosition(hexParts, 4), 16)
|
|
308
|
-
if (newSpeed >= 1 && newSpeed <= this.speedSteps && this.cacheSpeed !== newSpeed) {
|
|
309
|
-
this.cacheSpeed = newSpeed
|
|
310
|
-
const hkSpeed = fanSpeedToHkPercent(newSpeed, this.speedSteps, this.autoSpeed)
|
|
311
|
-
this.service.updateCharacteristic(this.hapChar.RotationSpeed, hkSpeed)
|
|
312
|
-
this.accessory.log(`${platformLang.curSpeed} [${newSpeed} -> ${hkSpeed}%]`)
|
|
313
|
-
}
|
|
314
|
-
break
|
|
315
|
-
}
|
|
316
|
-
case '0500': {
|
|
317
|
-
// Mode change (auto = 0x03)
|
|
318
|
-
if (getTwoItemPosition(hexParts, 4) === '03' && this.cacheSpeed !== this.autoSpeed) {
|
|
319
|
-
this.cacheSpeed = this.autoSpeed
|
|
320
|
-
// Cache auto so we can tell it apart from "user asked for max speed"
|
|
321
|
-
this.service.updateCharacteristic(this.hapChar.RotationSpeed, 100)
|
|
322
|
-
this.accessory.log(`${platformLang.curSpeed} [auto -> 100%]`)
|
|
323
|
-
}
|
|
324
|
-
break
|
|
325
|
-
}
|
|
326
|
-
case '1f01': {
|
|
327
|
-
// Swing Mode
|
|
328
|
-
const newSwing = getTwoItemPosition(hexParts, 4) === '01' ? 'on' : 'off'
|
|
329
|
-
if (this.cacheSwing !== newSwing) {
|
|
330
|
-
this.cacheSwing = newSwing
|
|
331
|
-
this.service.updateCharacteristic(this.hapChar.SwingMode, this.cacheSwing === 'on' ? 1 : 0)
|
|
332
|
-
this.accessory.log(`${platformLang.curSwing} [${this.cacheSwing}]`)
|
|
333
|
-
}
|
|
334
|
-
break
|
|
335
|
-
}
|
|
336
|
-
default:
|
|
337
|
-
logUnknownData(this.accessory, {
|
|
338
|
-
kind: 'scene',
|
|
339
|
-
source: params.source,
|
|
340
|
-
raw: command,
|
|
341
|
-
hex: hexString,
|
|
342
|
-
})
|
|
343
|
-
break
|
|
344
|
-
}
|
|
345
|
-
})
|
|
346
|
-
}
|
|
347
|
-
}
|