@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.
Files changed (78) hide show
  1. package/CHANGELOG.md +1937 -0
  2. package/LICENSE +21 -0
  3. package/README.md +72 -0
  4. package/config.schema.json +1727 -0
  5. package/eslint.config.js +49 -0
  6. package/lib/connection/aws.js +174 -0
  7. package/lib/connection/ble.js +208 -0
  8. package/lib/connection/cert/AmazonRootCA1.pem +20 -0
  9. package/lib/connection/http.js +240 -0
  10. package/lib/connection/lan.js +284 -0
  11. package/lib/device/cooler-single.js +300 -0
  12. package/lib/device/dehumidifier-H7150.js +182 -0
  13. package/lib/device/dehumidifier-H7151.js +157 -0
  14. package/lib/device/diffuser-H7161.js +117 -0
  15. package/lib/device/diffuser-H7162.js +117 -0
  16. package/lib/device/fan-H7100.js +274 -0
  17. package/lib/device/fan-H7101.js +330 -0
  18. package/lib/device/fan-H7102.js +274 -0
  19. package/lib/device/fan-H7105.js +503 -0
  20. package/lib/device/fan-H7106.js +274 -0
  21. package/lib/device/fan-H7111.js +335 -0
  22. package/lib/device/heater-single.js +300 -0
  23. package/lib/device/heater1a.js +353 -0
  24. package/lib/device/heater1b.js +616 -0
  25. package/lib/device/heater2.js +838 -0
  26. package/lib/device/humidifier-H7140.js +224 -0
  27. package/lib/device/humidifier-H7141.js +257 -0
  28. package/lib/device/humidifier-H7142.js +522 -0
  29. package/lib/device/humidifier-H7143.js +157 -0
  30. package/lib/device/humidifier-H7148.js +157 -0
  31. package/lib/device/humidifier-H7160.js +446 -0
  32. package/lib/device/ice-maker-H7162.js +46 -0
  33. package/lib/device/index.js +105 -0
  34. package/lib/device/kettle.js +269 -0
  35. package/lib/device/light-switch.js +86 -0
  36. package/lib/device/light.js +617 -0
  37. package/lib/device/outlet-double.js +121 -0
  38. package/lib/device/outlet-single.js +172 -0
  39. package/lib/device/outlet-triple.js +160 -0
  40. package/lib/device/purifier-H7120.js +336 -0
  41. package/lib/device/purifier-H7121.js +336 -0
  42. package/lib/device/purifier-H7122.js +449 -0
  43. package/lib/device/purifier-H7123.js +411 -0
  44. package/lib/device/purifier-H7124.js +411 -0
  45. package/lib/device/purifier-H7126.js +296 -0
  46. package/lib/device/purifier-H7127.js +296 -0
  47. package/lib/device/purifier-H712C.js +296 -0
  48. package/lib/device/purifier-single.js +119 -0
  49. package/lib/device/sensor-button.js +22 -0
  50. package/lib/device/sensor-contact.js +22 -0
  51. package/lib/device/sensor-leak.js +87 -0
  52. package/lib/device/sensor-monitor.js +190 -0
  53. package/lib/device/sensor-presence.js +53 -0
  54. package/lib/device/sensor-thermo.js +144 -0
  55. package/lib/device/sensor-thermo4.js +55 -0
  56. package/lib/device/switch-double.js +121 -0
  57. package/lib/device/switch-single.js +95 -0
  58. package/lib/device/switch-triple.js +160 -0
  59. package/lib/device/tap-single.js +108 -0
  60. package/lib/device/template.js +43 -0
  61. package/lib/device/tv-single.js +84 -0
  62. package/lib/device/valve-single.js +155 -0
  63. package/lib/fakegato/LICENSE +21 -0
  64. package/lib/fakegato/fakegato-history.js +814 -0
  65. package/lib/fakegato/fakegato-storage.js +108 -0
  66. package/lib/fakegato/fakegato-timer.js +125 -0
  67. package/lib/fakegato/uuid.js +27 -0
  68. package/lib/homebridge-ui/public/index.html +433 -0
  69. package/lib/homebridge-ui/server.js +10 -0
  70. package/lib/index.js +8 -0
  71. package/lib/platform.js +1967 -0
  72. package/lib/utils/colour.js +564 -0
  73. package/lib/utils/constants.js +579 -0
  74. package/lib/utils/custom-chars.js +225 -0
  75. package/lib/utils/eve-chars.js +68 -0
  76. package/lib/utils/functions.js +117 -0
  77. package/lib/utils/lang-en.js +131 -0
  78. package/package.json +75 -0
@@ -0,0 +1,224 @@
1
+ import { hs2rgb } from '../utils/colour.js'
2
+ import {
3
+ base64ToHex,
4
+ generateCodeFromHexValues,
5
+ getTwoItemPosition,
6
+ hexToTwoItems,
7
+ parseError,
8
+ } from '../utils/functions.js'
9
+ import platformLang from '../utils/lang-en.js'
10
+
11
+ export default class {
12
+ constructor(platform, accessory) {
13
+ // Set up variables from the platform
14
+ this.hapChar = platform.api.hap.Characteristic
15
+ this.hapErr = platform.api.hap.HapStatusError
16
+ this.hapServ = platform.api.hap.Service
17
+ this.platform = platform
18
+
19
+ // Set up variables from the accessory
20
+ this.accessory = accessory
21
+
22
+ // Rotation speed to value in {1, 2, ..., 8}
23
+ this.speed2Value = speed => Math.min(Math.max(Number.parseInt(Math.round(speed / 10), 10), 1), 8)
24
+
25
+ // Speed codes
26
+ this.value2Code = {
27
+ 1: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=',
28
+ 2: 'MwUBAgAAAAAAAAAAAAAAAAAAADU=',
29
+ 3: 'MwUBAwAAAAAAAAAAAAAAAAAAADQ=',
30
+ 4: 'MwUBBAAAAAAAAAAAAAAAAAAAADM=',
31
+ 5: 'MwUBBQAAAAAAAAAAAAAAAAAAADI=',
32
+ 6: 'MwUBBgAAAAAAAAAAAAAAAAAAADE=',
33
+ 7: 'MwUBBwAAAAAAAAAAAAAAAAAAADA=',
34
+ 8: 'MwUBCAAAAAAAAAAAAAAAAAAAAD8=',
35
+ }
36
+
37
+ // Add the fan service if it doesn't already exist
38
+ this.service = this.accessory.getService(this.hapServ.Fan) || this.accessory.addService(this.hapServ.Fan)
39
+
40
+ // Add the night light service if it doesn't already exist
41
+ this.lightService = this.accessory.getService(this.hapServ.Lightbulb)
42
+ || this.accessory.addService(this.hapServ.Lightbulb)
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
+ minStep: 10,
55
+ validValues: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
56
+ })
57
+ .onSet(async value => this.internalSpeedUpdate(value))
58
+ this.cacheSpeed = this.service.getCharacteristic(this.hapChar.RotationSpeed).value
59
+
60
+ // Add the set handler to the lightbulb on/off characteristic
61
+ this.lightService.getCharacteristic(this.hapChar.On).onSet(async (value) => {
62
+ await this.internalLightStateUpdate(value)
63
+ })
64
+ this.cacheLightState = this.lightService.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
65
+
66
+ // Output the customised options to the log
67
+ const opts = JSON.stringify({})
68
+ platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
69
+ }
70
+
71
+ async internalStateUpdate(value) {
72
+ try {
73
+ const newValue = value ? 'on' : 'off'
74
+
75
+ // Don't continue if the new value is the same as before
76
+ if (this.cacheState === newValue) {
77
+ return
78
+ }
79
+
80
+ // Send the request to the platform sender function
81
+ await this.platform.sendDeviceUpdate(this.accessory, {
82
+ cmd: 'stateHumi',
83
+ value: value ? 1 : 0,
84
+ })
85
+
86
+ // Cache the new state and log if appropriate
87
+ this.cacheState = newValue
88
+ this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
89
+ } catch (err) {
90
+ // Catch any errors during the process
91
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
92
+
93
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
94
+ setTimeout(() => {
95
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
96
+ }, 2000)
97
+ throw new this.hapErr(-70402)
98
+ }
99
+ }
100
+
101
+ async internalSpeedUpdate(value) {
102
+ try {
103
+ // Don't continue if the speed is 0
104
+ if (value === 0) {
105
+ return
106
+ }
107
+
108
+ // Get the single Govee value {1, 2, ..., 8}
109
+ const newValue = this.speed2Value(value)
110
+
111
+ // Don't continue if the speed value won't have effect
112
+ if (newValue * 10 === this.cacheSpeed) {
113
+ return
114
+ }
115
+
116
+ // Get the scene code for this value
117
+ const newCode = this.value2Code[newValue]
118
+
119
+ // Send the request to the platform sender function
120
+ await this.platform.sendDeviceUpdate(this.accessory, {
121
+ cmd: 'ptReal',
122
+ value: newCode,
123
+ })
124
+
125
+ // Cache the new state and log if appropriate
126
+ this.cacheSpeed = newValue * 10
127
+ this.accessory.log(`${platformLang.curSpeed} [${newValue}]`)
128
+ } catch (err) {
129
+ // Catch any errors during the process
130
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
131
+
132
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
133
+ setTimeout(() => {
134
+ this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
135
+ }, 2000)
136
+ throw new this.hapErr(-70402)
137
+ }
138
+ }
139
+
140
+ async internalLightStateUpdate(value) {
141
+ try {
142
+ const newValue = value ? 'on' : 'off'
143
+
144
+ // Don't continue if the new value is the same as before
145
+ if (this.cacheLightState === newValue) {
146
+ return
147
+ }
148
+
149
+ // Generate the hex values for the code
150
+ let hexValues
151
+ if (value) {
152
+ // Calculate current RGB values
153
+ const newRGB = hs2rgb(
154
+ this.lightService.getCharacteristic(this.hapChar.Hue).value,
155
+ this.lightService.getCharacteristic(this.hapChar.Saturation).value,
156
+ )
157
+ hexValues = [0x33, 0x1B, 0x01, this.cacheBright, ...newRGB]
158
+ } else {
159
+ hexValues = [0x33, 0x1B, 0x00]
160
+ }
161
+
162
+ // Send the request to the platform sender function
163
+ await this.platform.sendDeviceUpdate(this.accessory, {
164
+ cmd: 'ptReal',
165
+ value: generateCodeFromHexValues(hexValues),
166
+ })
167
+
168
+ // Cache the new state and log if appropriate
169
+ if (this.cacheLightState !== newValue) {
170
+ this.cacheLightState = newValue
171
+ this.accessory.log(`${platformLang.curLight} [${newValue}]`)
172
+ }
173
+ } catch (err) {
174
+ // Catch any errors during the process
175
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
176
+
177
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
178
+ setTimeout(() => {
179
+ this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on')
180
+ }, 2000)
181
+ throw new this.hapErr(-70402)
182
+ }
183
+ }
184
+
185
+ externalUpdate(params) {
186
+ // Check for an ON/OFF change
187
+ if (params.state && params.state !== this.cacheState) {
188
+ this.cacheState = params.state
189
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
190
+
191
+ // Log the change
192
+ this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
193
+ }
194
+
195
+ // Check for some other scene/mode change
196
+ (params.commands || []).forEach((command) => {
197
+ const hexString = base64ToHex(command)
198
+ const hexParts = hexToTwoItems(hexString)
199
+
200
+ // Return now if not a device query update code
201
+ if (getTwoItemPosition(hexParts, 1) !== 'aa') {
202
+ return
203
+ }
204
+
205
+ const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`
206
+
207
+ switch (deviceFunction) {
208
+ case '1b00': // night light off
209
+ case '1b01': { // night light on
210
+ const newNight = deviceFunction === '1b01' ? 'on' : 'off'
211
+ if (newNight !== this.cacheLightState) {
212
+ this.cacheLightState = newNight
213
+ this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on')
214
+ this.accessory.log(`current night light state [${this.cacheLightState}]`)
215
+ }
216
+ break
217
+ }
218
+ default:
219
+ this.accessory.logDebugWarn(`${platformLang.newScene}: [${command}] [${hexString}]`)
220
+ break
221
+ }
222
+ })
223
+ }
224
+ }
@@ -0,0 +1,257 @@
1
+ import {
2
+ base64ToHex,
3
+ getTwoItemPosition,
4
+ hexToTwoItems,
5
+ parseError,
6
+ } from '../utils/functions.js'
7
+ import platformLang from '../utils/lang-en.js'
8
+
9
+ /*
10
+ H7141
11
+ {
12
+ "mode": {
13
+ "options": [
14
+ {
15
+ "name": "Custom",
16
+ "value": 2
17
+ },
18
+ {
19
+ "name": "Auto",
20
+ "value": 3
21
+ }
22
+ ]
23
+ },
24
+ "gear": {
25
+ "options": [
26
+ {
27
+ "name": "gear",
28
+ "value": [
29
+ 1,
30
+ 2,
31
+ 3,
32
+ 4,
33
+ 5,
34
+ 6,
35
+ 7,
36
+ 8
37
+ ]
38
+ }
39
+ ]
40
+ }
41
+ }
42
+ */
43
+ export default class {
44
+ constructor(platform, accessory) {
45
+ // Set up variables from the platform
46
+ this.hapChar = platform.api.hap.Characteristic
47
+ this.hapErr = platform.api.hap.HapStatusError
48
+ this.hapServ = platform.api.hap.Service
49
+ this.platform = platform
50
+
51
+ // Set up variables from the accessory
52
+ this.accessory = accessory
53
+
54
+ // Rotation speed to value in {1, 2, ..., 8}
55
+ this.speed2Value = speed => Math.min(Math.max(Number.parseInt(Math.round(speed / 10), 10), 1), 8)
56
+
57
+ // Speed codes
58
+ this.value2Code = {
59
+ 1: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=',
60
+ 2: 'MwUBAgAAAAAAAAAAAAAAAAAAADU=',
61
+ 3: 'MwUBAwAAAAAAAAAAAAAAAAAAADQ=',
62
+ 4: 'MwUBBAAAAAAAAAAAAAAAAAAAADM=',
63
+ 5: 'MwUBBQAAAAAAAAAAAAAAAAAAADI=',
64
+ 6: 'MwUBBgAAAAAAAAAAAAAAAAAAADE=',
65
+ 7: 'MwUBBwAAAAAAAAAAAAAAAAAAADA=',
66
+ 8: 'MwUBCAAAAAAAAAAAAAAAAAAAAD8=',
67
+ }
68
+
69
+ // Add the fan service if it doesn't already exist
70
+ this.service = this.accessory.getService(this.hapServ.Fan) || this.accessory.addService(this.hapServ.Fan)
71
+
72
+ // Add the set handler to the fan on/off characteristic
73
+ this.service
74
+ .getCharacteristic(this.hapChar.On)
75
+ .onSet(async value => this.internalStateUpdate(value))
76
+ this.cacheState = this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
77
+
78
+ // Add the set handler to the fan rotation speed characteristic
79
+ this.service
80
+ .getCharacteristic(this.hapChar.RotationSpeed)
81
+ .setProps({
82
+ minStep: 10,
83
+ validValues: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
84
+ })
85
+ .onSet(async value => this.internalSpeedUpdate(value))
86
+ this.cacheSpeed = this.service.getCharacteristic(this.hapChar.RotationSpeed).value
87
+ this.cacheSpeedRaw = `0${this.cacheSpeed / 10}` // example '02' for 20%
88
+
89
+ // Output the customised options to the log
90
+ const opts = JSON.stringify({})
91
+ platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
92
+ }
93
+
94
+ async internalStateUpdate(value) {
95
+ try {
96
+ const newValue = value ? 'on' : 'off'
97
+
98
+ // Don't continue if the new value is the same as before
99
+ if (this.cacheState === newValue) {
100
+ return
101
+ }
102
+
103
+ // Send the request to the platform sender function
104
+ await this.platform.sendDeviceUpdate(this.accessory, {
105
+ cmd: 'stateHumi',
106
+ value: value ? 1 : 0,
107
+ })
108
+
109
+ // Cache the new state and log if appropriate
110
+ this.cacheState = newValue
111
+ this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
112
+ } catch (err) {
113
+ // Catch any errors during the process
114
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
115
+
116
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
117
+ setTimeout(() => {
118
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
119
+ }, 2000)
120
+ throw new this.hapErr(-70402)
121
+ }
122
+ }
123
+
124
+ async internalSpeedUpdate(value) {
125
+ try {
126
+ // Don't continue if the speed is 0
127
+ if (value === 0) {
128
+ return
129
+ }
130
+
131
+ // Get the single Govee value {1, 2, ..., 8}
132
+ const newValue = this.speed2Value(value)
133
+
134
+ // Don't continue if the speed value won't have effect
135
+ if (newValue * 10 === this.cacheSpeed) {
136
+ return
137
+ }
138
+
139
+ // Get the scene code for this value
140
+ const newCode = this.value2Code[newValue]
141
+
142
+ // Send the request to the platform sender function
143
+ await this.platform.sendDeviceUpdate(this.accessory, {
144
+ cmd: 'ptReal',
145
+ value: newCode,
146
+ })
147
+
148
+ // Cache the new state and log if appropriate
149
+ this.cacheSpeed = newValue * 10
150
+ this.accessory.log(`${platformLang.curSpeed} [${newValue}]`)
151
+ } catch (err) {
152
+ // Catch any errors during the process
153
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
154
+
155
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
156
+ setTimeout(() => {
157
+ this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
158
+ }, 2000)
159
+ throw new this.hapErr(-70402)
160
+ }
161
+ }
162
+
163
+ externalUpdate(params) {
164
+ // Check for an ON/OFF change
165
+ if (params.state && params.state !== this.cacheState) {
166
+ this.cacheState = params.state
167
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
168
+
169
+ // Log the change
170
+ this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
171
+ }
172
+
173
+ // Check for some other scene/mode change
174
+ (params.commands || []).forEach((command) => {
175
+ const hexString = base64ToHex(command)
176
+ const hexParts = hexToTwoItems(hexString)
177
+
178
+ // Return now if not a device query update code
179
+ if (getTwoItemPosition(hexParts, 1) !== 'aa') {
180
+ return
181
+ }
182
+
183
+ const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`
184
+
185
+ switch (deviceFunction) {
186
+ case '0500': { // mode
187
+ // Mode
188
+ const newModeRaw = getTwoItemPosition(hexParts, 4)
189
+ let newMode
190
+ switch (newModeRaw) {
191
+ case '01': {
192
+ // Manual
193
+ newMode = 'manual'
194
+ break
195
+ }
196
+ case '02': {
197
+ // Custom
198
+ newMode = 'custom'
199
+ break
200
+ }
201
+ case '03': {
202
+ // Auto
203
+ newMode = 'auto'
204
+ break
205
+ }
206
+ default:
207
+ return
208
+ }
209
+ if (this.cacheMode !== newMode) {
210
+ this.cacheMode = newMode
211
+ this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`)
212
+ }
213
+ this.accessory.logDebug(`mode: ${command}`)
214
+ break
215
+ }
216
+ case '0501': {
217
+ // Manual speed
218
+ const newSpeedRaw = getTwoItemPosition(hexParts, 4)
219
+ if (newSpeedRaw !== this.cacheSpeedRaw) {
220
+ this.cacheSpeedRaw = newSpeedRaw
221
+ this.cacheSpeed = Number.parseInt(newSpeedRaw, 10) * 10
222
+ this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
223
+ this.accessory.log(`${platformLang.curSpeed} [${this.cacheSpeed}]`)
224
+ }
225
+ this.accessory.logDebug(`speed: ${command}`)
226
+ break
227
+ }
228
+ case '1100': // timer
229
+ case '1101': // timer
230
+ case '1300': // scheduling
231
+ case '1500': // scheduling
232
+ case '1800': { // indicator light
233
+ break
234
+ }
235
+ default:
236
+ this.accessory.logDebugWarn(`${platformLang.newScene}: [${command}] [${hexString}]`)
237
+ break
238
+ }
239
+ })
240
+ }
241
+ }
242
+
243
+ // H7141
244
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qhIAAAAAAAAAAAAAAAAAAAAAALg=] [aa12 0000 000000000000000000000000000000b8].
245
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qhEAAAAAAAAAAAAAAAAAAAAAALs=] [aa11 0000 000000000000000000000000000000bb].
246
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qgUAAQAAAAAAAAAAAAAAAAAAAK4=] [aa05 0001 000000000000000000000000000000ae].
247
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qgUBCAAAAAAAAAAAAAAAAAAAAKY=] [aa05 0108 000000000000000000000000000000a6].
248
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qgUCAAgAPAA8BQA8ADwB/////6E=] [aa05 0200 08003c003c05003c003c01ffffffffa1].
249
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qgUDuAAAAAAAAAAAAAAAAAAAABQ=] [aa05 03b8 00000000000000000000000000000014].
250
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qhYACAAWDwAAAAAAAAAAAAAAAK0=] [aa16 0008 00160f000000000000000000000000ad].
251
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qghrCzU3MsUAAAAAAAAAAAAAADc=] [aa08 6b0b 353732c5000000000000000000000037].
252
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qhABAvveAAAAAAAAAAAAAAAAAJw=] [aa10 0102 fbde000000000000000000000000009c].
253
+ // [25/12/2022, 06:22:13] [Govee] [Small Humidifier] new scene code: [qhgACAAWDwAAAAAAAAAAAAAAAKM=] [aa18 0008 00160f000000000000000000000000a3].
254
+ // [25/12/2022, 06:35:49] [Govee] [Small Humidifier] new scene code: [qhABAvAbAAAAAAAAAAAAAAAAAFI=] [aa10 0102 f01b0000000000000000000000000052].
255
+ // [25/12/2022, 06:39:44] [Govee] [Small Humidifier] new scene code: [qhABAvfUAAAAAAAAAAAAAAAAAJo=] [aa10 0102 f7d4000000000000000000000000009a].
256
+ // [25/12/2022, 06:41:32] [Govee] [Small Humidifier] new scene code: [qh4CAAAAAAAAAAAAAAAAAAAAALY=] [aa1e 0200 000000000000000000000000000000b6].
257
+ // [25/12/2022, 06:41:32] [Govee] [Small Humidifier] new scene code: [qh4CAAAAAAAAAAAAAAAAAAAAALY=] [aa1e 0200 000000000000000000000000000000b6].