@homebridge-plugins/homebridge-govee 11.32.2-beta.21 → 11.32.2-beta.23

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 (49) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/device/appliance-basic.js +8 -20
  3. package/lib/device/base.js +80 -0
  4. package/lib/device/cooler-single.js +7 -22
  5. package/lib/device/dehumidifier-H7150.js +7 -25
  6. package/lib/device/diffuser-H7161.js +5 -18
  7. package/lib/device/fan-H1370.js +13 -46
  8. package/lib/device/fan-H7100.js +9 -32
  9. package/lib/device/fan-H7105.js +15 -53
  10. package/lib/device/fan-H7107.js +15 -53
  11. package/lib/device/heater-single.js +7 -22
  12. package/lib/device/heater1a.js +11 -40
  13. package/lib/device/heater1b.js +17 -61
  14. package/lib/device/heater2.js +23 -81
  15. package/lib/device/humidifier-H7140.js +9 -32
  16. package/lib/device/humidifier-H7141.js +7 -25
  17. package/lib/device/humidifier-H7142.js +13 -46
  18. package/lib/device/humidifier-H7143.js +7 -25
  19. package/lib/device/humidifier-H7160.js +13 -46
  20. package/lib/device/ice-maker-H7172.js +8 -25
  21. package/lib/device/index.js +2 -2
  22. package/lib/device/kettle.js +5 -16
  23. package/lib/device/light-switch.js +5 -18
  24. package/lib/device/light.js +14 -41
  25. package/lib/device/outlet-single.js +8 -18
  26. package/lib/device/purifier-H7120.js +14 -45
  27. package/lib/device/purifier-H7122.js +14 -45
  28. package/lib/device/purifier-H7123.js +14 -45
  29. package/lib/device/purifier-H7126.js +12 -38
  30. package/lib/device/purifier-single.js +7 -19
  31. package/lib/device/sensor-basic.js +3 -10
  32. package/lib/device/sensor-co2.js +3 -10
  33. package/lib/device/sensor-leak.js +4 -9
  34. package/lib/device/sensor-monitor.js +3 -10
  35. package/lib/device/sensor-presence.js +3 -10
  36. package/lib/device/sensor-probe.js +52 -0
  37. package/lib/device/sensor-thermo-switch.js +4 -9
  38. package/lib/device/sensor-thermo.js +4 -9
  39. package/lib/device/switch-double.js +6 -18
  40. package/lib/device/switch-single.js +6 -19
  41. package/lib/device/switch-triple.js +5 -18
  42. package/lib/device/tap-single.js +7 -19
  43. package/lib/device/template.js +3 -10
  44. package/lib/device/tv-single.js +6 -18
  45. package/lib/device/valve-single.js +7 -19
  46. package/lib/utils/constants.js +17 -3
  47. package/lib/utils/dispatch.js +1 -1
  48. package/package.json +1 -1
  49. package/lib/device/sensor-thermo4.js +0 -66
package/CHANGELOG.md CHANGED
@@ -40,6 +40,8 @@ All notable changes to `@homebridge-plugins/homebridge-govee` will be documented
40
40
  - test: check what the plugin sends over aws, the local network and the public api, none of which was covered before
41
41
  - feat: say when govee has not listed a capability the plugin is about to use, since the request then succeeds and the device does nothing
42
42
  - docs: note that the local network api accepts the raw command form, which is how scenes work without the cloud
43
+ - refactor: give every device one shared starting point, so the way a failed command is reported and undone is decided in one place rather than a hundred
44
+ - feat: recognise eleven more meat thermometers, which report what they send so their readings can be worked out, and stop the one already known printing its whole update as a warning
43
45
 
44
46
  ## v11.32.1 (2026-08-02)
45
47
 
@@ -1,7 +1,8 @@
1
1
  import { describeSources, resolveControls } from '../utils/capabilities.js'
2
- import { base64ToHex, getTwoItemPosition, hexToTwoItems, parseError } from '../utils/functions.js'
2
+ import { base64ToHex, getTwoItemPosition, hexToTwoItems } from '../utils/functions.js'
3
3
  import platformLang from '../utils/lang-en.js'
4
4
  import { logUnknownData, reportUnsupportedControl } from '../utils/report-unknown.js'
5
+ import GoveeDevice from './base.js'
5
6
 
6
7
  /**
7
8
  * A starting point for any appliance whose power command is known but whose
@@ -20,16 +21,10 @@ import { logUnknownData, reportUnsupportedControl } from '../utils/report-unknow
20
21
  *
21
22
  * Once that data arrives the model gets a proper handler and stops using this.
22
23
  */
23
- class ApplianceBasic {
24
+ class ApplianceBasic extends GoveeDevice {
24
25
  constructor(platform, accessory, config) {
25
- // Set up variables from the platform
26
- this.hapChar = platform.api.hap.Characteristic
27
- this.hapErr = platform.api.hap.HapStatusError
28
- this.hapServ = platform.api.hap.Service
29
- this.platform = platform
30
-
26
+ super(platform, accessory)
31
27
  // Set up variables from the accessory
32
- this.accessory = accessory
33
28
  this.config = config
34
29
 
35
30
  // Work out what this particular device can do, rather than what its model
@@ -174,11 +169,9 @@ class ApplianceBasic {
174
169
  this.cacheToggles[control] = value
175
170
  this.accessory.log(`current ${control} [${value ? 'on' : 'off'}]`)
176
171
  } catch (err) {
177
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
178
- setTimeout(() => {
172
+ this.failUpdate(err, () => {
179
173
  this.service.updateCharacteristic(characteristic, previous)
180
- }, 2000)
181
- throw new this.hapErr(-70402)
174
+ })
182
175
  }
183
176
  }
184
177
 
@@ -211,14 +204,9 @@ class ApplianceBasic {
211
204
  }
212
205
  this.accessory.log(`${platformLang.curState} [${newValue}]`)
213
206
  } catch (err) {
214
- // Catch any errors during the process
215
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
216
-
217
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
218
- setTimeout(() => {
207
+ this.failUpdate(err, () => {
219
208
  this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
220
- }, 2000)
221
- throw new this.hapErr(-70402)
209
+ })
222
210
  }
223
211
  }
224
212
 
@@ -0,0 +1,80 @@
1
+ import { parseError } from '../utils/functions.js'
2
+ import platformLang from '../utils/lang-en.js'
3
+
4
+ /**
5
+ * What every device handler needs, in one place.
6
+ *
7
+ * Each handler used to open with the same five assignments, build its tiles the
8
+ * same way, and end every control with the same six-line failure block. That
9
+ * last one was written out a hundred times over, which meant the delay before a
10
+ * control snaps back, and the error HomeKit is given, were a hundred separate
11
+ * decisions that happened to agree.
12
+ */
13
+ export default class GoveeDevice {
14
+ constructor(platform, accessory) {
15
+ this.hapChar = platform.api.hap.Characteristic
16
+ this.hapErr = platform.api.hap.HapStatusError
17
+ this.hapServ = platform.api.hap.Service
18
+ this.platform = platform
19
+ this.accessory = accessory
20
+ }
21
+
22
+ /**
23
+ * The line at startup saying which of this device's settings are not the
24
+ * defaults.
25
+ */
26
+ logInitOptions(options = {}) {
27
+ this.platform.log(
28
+ '[%s] %s %s.',
29
+ this.accessory.displayName,
30
+ platformLang.devInitOpts,
31
+ JSON.stringify(options),
32
+ )
33
+ }
34
+
35
+ /**
36
+ * Get a tile, making it if it is not there yet.
37
+ */
38
+ getOrAddService(serviceType, name, subtype) {
39
+ return this.accessory.getService(name ?? serviceType)
40
+ || this.accessory.addService(serviceType, name, subtype)
41
+ }
42
+
43
+ /**
44
+ * Drop a tile if the device has one, for when a setting has changed what this
45
+ * device should look like. Leaving the old one behind gives the owner a tile
46
+ * that no longer does anything.
47
+ */
48
+ removeServiceIfPresent(serviceType) {
49
+ const existing = this.accessory.getService(serviceType)
50
+ if (existing) {
51
+ this.accessory.removeService(existing)
52
+ }
53
+ return !!existing
54
+ }
55
+
56
+ /**
57
+ * Give up on a control, put it back the way it was, and tell HomeKit.
58
+ *
59
+ * The three parts matter together: the log line says what went wrong, the
60
+ * revert stops the tile showing a state the device is not in, and the error
61
+ * is what makes HomeKit show it as not responding rather than quietly
62
+ * accepting a change that never happened.
63
+ *
64
+ * `revert` is a function rather than a value so it is read when it runs, two
65
+ * seconds later, which is the behaviour this replaced.
66
+ *
67
+ * @param {Error} err whatever went wrong
68
+ * @param {Function} [revert] puts the control back
69
+ * @throws {object} always - the caller is expected to let this bubble up
70
+ */
71
+ failUpdate(err, revert) {
72
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
73
+
74
+ if (revert) {
75
+ setTimeout(revert, 2000)
76
+ }
77
+
78
+ throw new this.hapErr(-70402)
79
+ }
80
+ }
@@ -1,16 +1,11 @@
1
1
  import { generateRandomString, hasProperty, parseError } from '../utils/functions.js'
2
2
  import platformLang from '../utils/lang-en.js'
3
+ import GoveeDevice from './base.js'
3
4
 
4
- export default class {
5
+ export default class extends GoveeDevice {
5
6
  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.platform = platform
11
-
7
+ super(platform, accessory)
12
8
  // Set up variables from the accessory
13
- this.accessory = accessory
14
9
  this.temperatureSource = accessory.context.temperatureSource;
15
10
 
16
11
  // Remove any old services from simulations
@@ -149,14 +144,9 @@ export default class {
149
144
  value === 1 ? newOnState : 0,
150
145
  )
151
146
  } 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(() => {
147
+ this.failUpdate(err, () => {
157
148
  this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
158
- }, 2000)
159
- throw new this.hapErr(-70402)
149
+ })
160
150
  }
161
151
  }
162
152
 
@@ -211,17 +201,12 @@ export default class {
211
201
  this.cacheCool === 'on' ? 3 : 1,
212
202
  )
213
203
  } catch (err) {
214
- // Catch any errors during the process
215
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
216
-
217
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
218
- setTimeout(() => {
204
+ this.failUpdate(err, () => {
219
205
  this.service.updateCharacteristic(
220
206
  this.hapChar.CoolingThresholdTemperature,
221
207
  this.accessory.context.cacheTarget,
222
208
  )
223
- }, 2000)
224
- throw new this.hapErr(-70402)
209
+ })
225
210
  }
226
211
  }
227
212
 
@@ -2,10 +2,10 @@ import {
2
2
  base64ToHex,
3
3
  getTwoItemPosition,
4
4
  hexToTwoItems,
5
- parseError,
6
5
  } from '../utils/functions.js'
7
6
  import platformLang from '../utils/lang-en.js'
8
7
  import { logUnknownData } from '../utils/report-unknown.js'
8
+ import GoveeDevice from './base.js'
9
9
 
10
10
  /*
11
11
  H7150, H7151 and H7152
@@ -32,17 +32,9 @@ import { logUnknownData } from '../utils/report-unknown.js'
32
32
  }
33
33
  }
34
34
  */
35
- export default class GoveeDehumidifierH7150 {
35
+ export default class GoveeDehumidifierH7150 extends GoveeDevice {
36
36
  constructor(platform, accessory) {
37
- // Set up variables from the platform
38
- this.hapChar = platform.api.hap.Characteristic
39
- this.hapErr = platform.api.hap.HapStatusError
40
- this.hapServ = platform.api.hap.Service
41
- this.platform = platform
42
-
43
- // Set up variables from the accessory
44
- this.accessory = accessory
45
-
37
+ super(platform, accessory)
46
38
  // Speed codes
47
39
  this.value2Code = {
48
40
  1: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=',
@@ -108,14 +100,9 @@ export default class GoveeDehumidifierH7150 {
108
100
  this.cacheState = newValue
109
101
  this.accessory.log(`${platformLang.curState} [${newValue}]`)
110
102
  } catch (err) {
111
- // Catch any errors during the process
112
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
113
-
114
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
115
- setTimeout(() => {
103
+ this.failUpdate(err, () => {
116
104
  this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
117
- }, 2000)
118
- throw new this.hapErr(-70402)
105
+ })
119
106
  }
120
107
  }
121
108
 
@@ -147,14 +134,9 @@ export default class GoveeDehumidifierH7150 {
147
134
  this.cacheSpeed = value
148
135
  this.accessory.log(`${platformLang.curSpeed} [${value}]`)
149
136
  } catch (err) {
150
- // Catch any errors during the process
151
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
152
-
153
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
154
- setTimeout(() => {
137
+ this.failUpdate(err, () => {
155
138
  this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed)
156
- }, 2000)
157
- throw new this.hapErr(-70402)
139
+ })
158
140
  }
159
141
  }
160
142
 
@@ -2,22 +2,14 @@ import {
2
2
  base64ToHex,
3
3
  getTwoItemPosition,
4
4
  hexToTwoItems,
5
- parseError,
6
5
  } from '../utils/functions.js'
7
6
  import platformLang from '../utils/lang-en.js'
8
7
  import { logUnknownData } from '../utils/report-unknown.js'
8
+ import GoveeDevice from './base.js'
9
9
 
10
- export default class {
10
+ export default class extends GoveeDevice {
11
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
-
12
+ super(platform, accessory)
21
13
  // Remove fan service if exists
22
14
  if (this.accessory.getService(this.hapServ.Fan)) {
23
15
  this.accessory.removeService(this.accessory.getService(this.hapServ.Fan))
@@ -71,14 +63,9 @@ export default class {
71
63
 
72
64
  this.service.updateCharacteristic(this.hapChar.CurrentAirPurifierState, value === 1 ? 2 : 0)
73
65
  } catch (err) {
74
- // Catch any errors during the process
75
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
76
-
77
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
78
- setTimeout(() => {
66
+ this.failUpdate(err, () => {
79
67
  this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
80
- }, 2000)
81
- throw new this.hapErr(-70402)
68
+ })
82
69
  }
83
70
  }
84
71
 
@@ -6,11 +6,11 @@ import {
6
6
  getTwoItemPosition,
7
7
  hexToTwoItems,
8
8
  hkPercentToFanSpeed,
9
- parseError,
10
9
  sleep,
11
10
  } from '../utils/functions.js'
12
11
  import platformLang from '../utils/lang-en.js'
13
12
  import { logUnknownData } from '../utils/report-unknown.js'
13
+ import GoveeDevice from './base.js'
14
14
 
15
15
  /*
16
16
  Codes below were decoded from a real device's AWS status reports in
@@ -20,17 +20,9 @@ import { logUnknownData } from '../utils/report-unknown.js'
20
20
  The light reports through the standard state/brightness/kelvin fields
21
21
  (colour temperature only, 2700-6500K)
22
22
  */
23
- export default class {
23
+ export default class extends GoveeDevice {
24
24
  constructor(platform, accessory) {
25
- // Set up variables from the platform
26
- this.hapChar = platform.api.hap.Characteristic
27
- this.hapErr = platform.api.hap.HapStatusError
28
- this.hapServ = platform.api.hap.Service
29
- this.platform = platform
30
-
31
- // Set up variables from the accessory
32
- this.accessory = accessory
33
-
25
+ super(platform, accessory)
34
26
  // Set up custom variables for this device type
35
27
  const deviceConf = platform.deviceConf[accessory.context.gvDeviceId]
36
28
  this.hideLight = deviceConf && deviceConf.hideLight
@@ -138,14 +130,9 @@ export default class {
138
130
  this.accessory.log(`${platformLang.curState} [${newValue}]`)
139
131
  }
140
132
  } catch (err) {
141
- // Catch any errors during the process
142
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
143
-
144
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
145
- setTimeout(() => {
133
+ this.failUpdate(err, () => {
146
134
  this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
147
- }, 2000)
148
- throw new this.hapErr(-70402)
135
+ })
149
136
  }
150
137
  }
151
138
 
@@ -176,14 +163,9 @@ export default class {
176
163
  this.accessory.log(`${platformLang.curSpeed} [${value}]`)
177
164
  }
178
165
  } catch (err) {
179
- // Catch any errors during the process
180
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
181
-
182
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
183
- setTimeout(() => {
166
+ this.failUpdate(err, () => {
184
167
  this.service.updateCharacteristic(this.hapChar.RotationSpeed, fanSpeedToHkPercent(this.cacheSpeed, this.speedSteps))
185
- }, 2000)
186
- throw new this.hapErr(-70402)
168
+ })
187
169
  }
188
170
  }
189
171
 
@@ -208,14 +190,9 @@ export default class {
208
190
  this.accessory.log(`${platformLang.curLight} [${newValue}]`)
209
191
  }
210
192
  } catch (err) {
211
- // Catch any errors during the process
212
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
213
-
214
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
215
- setTimeout(() => {
193
+ this.failUpdate(err, () => {
216
194
  this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on')
217
- }, 2000)
218
- throw new this.hapErr(-70402)
195
+ })
219
196
  }
220
197
  }
221
198
 
@@ -246,14 +223,9 @@ export default class {
246
223
  this.accessory.log(`${platformLang.curBright} [${value}%]`)
247
224
  }
248
225
  } catch (err) {
249
- // Catch any errors during the process
250
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
251
-
252
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
253
- setTimeout(() => {
226
+ this.failUpdate(err, () => {
254
227
  this.lightService.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
255
- }, 2000)
256
- throw new this.hapErr(-70402)
228
+ })
257
229
  }
258
230
  }
259
231
 
@@ -287,14 +259,9 @@ export default class {
287
259
  this.cacheKelvin = k
288
260
  this.accessory.log(`${platformLang.curColour} [${k}K]`)
289
261
  } catch (err) {
290
- // Catch any errors during the process
291
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
292
-
293
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
294
- setTimeout(() => {
262
+ this.failUpdate(err, () => {
295
263
  this.lightService.updateCharacteristic(this.hapChar.ColorTemperature, this.cacheMired)
296
- }, 2000)
297
- throw new this.hapErr(-70402)
264
+ })
298
265
  }
299
266
  }
300
267
 
@@ -5,10 +5,10 @@ import {
5
5
  getTwoItemPosition,
6
6
  hexToTwoItems,
7
7
  hkPercentToFanSpeed,
8
- parseError,
9
8
  } from '../utils/functions.js'
10
9
  import platformLang from '../utils/lang-en.js'
11
10
  import { logUnknownData } from '../utils/report-unknown.js'
11
+ import GoveeDevice from './base.js'
12
12
 
13
13
  /*
14
14
  The models on this handler and the modes each offers:
@@ -20,17 +20,9 @@ import { logUnknownData } from '../utils/report-unknown.js'
20
20
  never been confirmed, so it is not read back
21
21
  */
22
22
 
23
- export default class GoveeFanH7100 {
23
+ export default class GoveeFanH7100 extends GoveeDevice {
24
24
  constructor(platform, accessory) {
25
- // Set up variables from the platform
26
- this.hapChar = platform.api.hap.Characteristic
27
- this.hapErr = platform.api.hap.HapStatusError
28
- this.hapServ = platform.api.hap.Service
29
- this.platform = platform
30
-
31
- // Set up variables from the accessory
32
- this.accessory = accessory
33
-
25
+ super(platform, accessory)
34
26
  // Which of the models on this handler have a confirmed meaning for the
35
27
  // oscillation status message
36
28
  this.readsSwingStatus = getDeviceCapabilities(accessory.context.gvModel).readsSwingStatus
@@ -119,14 +111,9 @@ export default class GoveeFanH7100 {
119
111
  this.accessory.log(`${platformLang.curState} [${newValue}]`)
120
112
  }
121
113
  } 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(() => {
114
+ this.failUpdate(err, () => {
127
115
  this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
128
- }, 2000)
129
- throw new this.hapErr(-70402)
116
+ })
130
117
  }
131
118
  }
132
119
 
@@ -162,14 +149,9 @@ export default class GoveeFanH7100 {
162
149
  this.accessory.log(`${platformLang.curSpeed} [${value}]`)
163
150
  }
164
151
  } catch (err) {
165
- // Catch any errors during the process
166
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
167
-
168
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
169
- setTimeout(() => {
152
+ this.failUpdate(err, () => {
170
153
  this.service.updateCharacteristic(this.hapChar.RotationSpeed, fanSpeedToHkPercent(this.cacheSpeed, this.speedSteps, this.autoSpeed))
171
- }, 2000)
172
- throw new this.hapErr(-70402)
154
+ })
173
155
  }
174
156
  }
175
157
 
@@ -195,14 +177,9 @@ export default class GoveeFanH7100 {
195
177
  this.accessory.log(`${platformLang.curSwing} [${newValue}]`)
196
178
  }
197
179
  } catch (err) {
198
- // Catch any errors during the process
199
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
200
-
201
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
202
- setTimeout(() => {
180
+ this.failUpdate(err, () => {
203
181
  this.service.updateCharacteristic(this.hapChar.SwingMode, this.cacheSwing === 'on' ? 1 : 0)
204
- }, 2000)
205
- throw new this.hapErr(-70402)
182
+ })
206
183
  }
207
184
  }
208
185
 
@@ -8,23 +8,15 @@ import {
8
8
  hexToDecimal,
9
9
  hexToTwoItems,
10
10
  hkPercentToFanSpeed,
11
- parseError,
12
11
  sleep,
13
12
  } from '../utils/functions.js'
14
13
  import platformLang from '../utils/lang-en.js'
15
14
  import { logUnknownData } from '../utils/report-unknown.js'
15
+ import GoveeDevice from './base.js'
16
16
 
17
- export default class {
17
+ export default class extends GoveeDevice {
18
18
  constructor(platform, accessory) {
19
- // Set up variables from the platform
20
- this.hapChar = platform.api.hap.Characteristic
21
- this.hapErr = platform.api.hap.HapStatusError
22
- this.hapServ = platform.api.hap.Service
23
- this.platform = platform
24
-
25
- // Set up variables from the accessory
26
- this.accessory = accessory
27
-
19
+ super(platform, accessory)
28
20
  // Set up custom variables for this device type
29
21
  const deviceConf = platform.deviceConf[accessory.context.gvDeviceId]
30
22
  this.hideLight = deviceConf && deviceConf.hideLight
@@ -151,14 +143,9 @@ export default class {
151
143
  this.accessory.log(`${platformLang.curState} [${newValue}]`)
152
144
  }
153
145
  } catch (err) {
154
- // Catch any errors during the process
155
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
156
-
157
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
158
- setTimeout(() => {
146
+ this.failUpdate(err, () => {
159
147
  this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0)
160
- }, 2000)
161
- throw new this.hapErr(-70402)
148
+ })
162
149
  }
163
150
  }
164
151
 
@@ -192,14 +179,9 @@ export default class {
192
179
  this.accessory.log(`${platformLang.curSpeed} [${value}]`)
193
180
  }
194
181
  } catch (err) {
195
- // Catch any errors during the process
196
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
197
-
198
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
199
- setTimeout(() => {
182
+ this.failUpdate(err, () => {
200
183
  this.service.updateCharacteristic(this.hapChar.RotationSpeed, fanSpeedToHkPercent(this.cacheSpeed, this.speedSteps, this.autoSpeed))
201
- }, 2000)
202
- throw new this.hapErr(-70402)
184
+ })
203
185
  }
204
186
  }
205
187
 
@@ -233,14 +215,9 @@ export default class {
233
215
  // this.accessory.log(`${platformLang.curSwing} [${newValue}]`)
234
216
  // }
235
217
  } catch (err) {
236
- // Catch any errors during the process
237
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
238
-
239
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
240
- setTimeout(() => {
218
+ this.failUpdate(err, () => {
241
219
  this.service.updateCharacteristic(this.hapChar.SwingMode, this.cacheSwing === 'on' ? 1 : 0)
242
- }, 2000)
243
- throw new this.hapErr(-70402)
220
+ })
244
221
  }
245
222
  }
246
223
 
@@ -268,14 +245,9 @@ export default class {
268
245
  this.accessory.log(`${platformLang.curLight} [${newValue}]`)
269
246
  }
270
247
  } catch (err) {
271
- // Catch any errors during the process
272
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
273
-
274
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
275
- setTimeout(() => {
248
+ this.failUpdate(err, () => {
276
249
  this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on')
277
- }, 2000)
278
- throw new this.hapErr(-70402)
250
+ })
279
251
  }
280
252
  }
281
253
 
@@ -322,14 +294,9 @@ export default class {
322
294
  this.accessory.log(`${platformLang.curBright} [${value}%]`)
323
295
  }
324
296
  } catch (err) {
325
- // Catch any errors during the process
326
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
327
-
328
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
329
- setTimeout(() => {
297
+ this.failUpdate(err, () => {
330
298
  this.lightService.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
331
- }, 2000)
332
- throw new this.hapErr(-70402)
299
+ })
333
300
  }
334
301
  }
335
302
 
@@ -366,14 +333,9 @@ export default class {
366
333
  this.accessory.log(`${platformLang.curColour} [rgb ${newRGB.join(' ')}]`)
367
334
  }
368
335
  } catch (err) {
369
- // Catch any errors during the process
370
- this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
371
-
372
- // Throw a 'no response' error and set a timeout to revert this after 2 seconds
373
- setTimeout(() => {
336
+ this.failUpdate(err, () => {
374
337
  this.lightService.updateCharacteristic(this.hapChar.Hue, this.cacheHue)
375
- }, 2000)
376
- throw new this.hapErr(-70402)
338
+ })
377
339
  }
378
340
  }
379
341