@homebridge-plugins/homebridge-govee 11.32.0-beta.30 → 11.32.0-beta.32

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 CHANGED
@@ -38,6 +38,9 @@ All notable changes to `@homebridge-plugins/homebridge-govee` will be documented
38
38
  - chore: count a repeated commit subject once when syncing the changelog
39
39
  - chore(github): check the changelog against the commits in ci
40
40
  - fix(openapi): report govee's own reason when it refuses a command, instead of the command appearing to succeed (#1324)
41
+ - fix: report why a command failed instead of claiming no connection method was available (#1324)
42
+ - fix(ble): use the segment-based colour command for the H617A, whose LEDs ignore the simple RGB colour commands (#1332)
43
+ - feat: add support for the H1250 ceiling light pro as an rgb light (#1333)
41
44
 
42
45
  ## v11.31.0 (2026-07-24)
43
46
 
package/lib/platform.js CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  parseDeviceId,
26
26
  parseError,
27
27
  pfxToCertAndKey,
28
+ updateFailureError,
28
29
  } from './utils/functions.js'
29
30
  import platformLang from './utils/lang-en.js'
30
31
  import { parseDeviceUpdate } from './utils/response-parser.js'
@@ -1864,7 +1865,7 @@ export default class {
1864
1865
  // No BLE fallback for this command — surface any earlier failure so HAP reverts
1865
1866
  if (!data.bleParams) {
1866
1867
  if (attempted) {
1867
- throw lastError || new Error(platformLang.noConnMethod)
1868
+ throw updateFailureError(lastError, platformLang.noConnMethod)
1868
1869
  }
1869
1870
  return true
1870
1871
  }
@@ -1883,10 +1884,17 @@ export default class {
1883
1884
  return true
1884
1885
  } catch (err) {
1885
1886
  // Bluetooth didn't work or not enabled
1887
+ lastError = err
1886
1888
  accessory.logDebugWarn(`${platformLang.notBLESent} ${parseError(err)}`)
1887
1889
  }
1888
1890
  }
1889
- throw new Error(platformLang.noConnMethod)
1891
+
1892
+ // Every method available for this command has now been tried and failed.
1893
+ // Report the last real reason rather than "no connection method
1894
+ // available" - there WAS one, it was tried, and something specific went
1895
+ // wrong. Saying otherwise sends the user to the connection-method docs
1896
+ // when the answer was "the device is offline" (#1324).
1897
+ throw updateFailureError(lastError, platformLang.noConnMethod)
1890
1898
  })
1891
1899
  }
1892
1900
 
@@ -129,6 +129,7 @@ export default {
129
129
 
130
130
  models: {
131
131
  rgb: [
132
+ 'H1250', // 18-Inch Ceiling Light Pro, https://github.com/homebridge-plugins/homebridge-govee/issues/1333
132
133
  'H1270', // Ceiling Light Ultra
133
134
  'H1401',
134
135
  'H14C0', // https://github.com/homebridge-plugins/homebridge-govee/issues/1301
@@ -19,6 +19,11 @@ const modelOverrides = {
19
19
  H6053: { bleColorCmd: COLOR_SUB.RGB_EXTENDED, bleColorCmdSuffix: [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F] },
20
20
  H6072: { bleColorCmd: COLOR_SUB.RGB_EXTENDED, bleColorCmdSuffix: [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F] },
21
21
  H6199: { bleColorCmd: COLOR_SUB.RGB_EXTENDED, bleColorCmdSuffix: [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F] },
22
+ // H617A is the same RGBIC family as the H617E below - the simple RGB command
23
+ // is accepted but the LEDs never change, so it needs the extended format too.
24
+ // Brightness works on the default 0xFF scale, so only the colour command is
25
+ // overridden (#1332)
26
+ H617A: { bleColorCmd: COLOR_SUB.RGB_EXTENDED, bleColorCmdSuffix: [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F] },
22
27
  // H617E is an RGBIC strip which ignores the 0x0D command - it needs the
23
28
  // segment-based extended format, as seen in its own TTR rule data (#1290)
24
29
  H617E: { bleColorCmd: COLOR_SUB.RGB_EXTENDED, bleColorCmdSuffix: [0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F], bleBrightnessScale: 0x64 },
@@ -162,6 +162,23 @@ function describeControlFailure(responseData) {
162
162
  return state.errorMsg || responseData?.msg || responseData?.message || 'the device rejected the command'
163
163
  }
164
164
 
165
+ /**
166
+ * Choose the error to report once every connection method has been exhausted.
167
+ *
168
+ * "No connection method available" is only true when nothing could be tried. If
169
+ * a method WAS tried and failed, that failure is the answer worth having — an
170
+ * offline device, a refused command, a Bluetooth timeout. Reporting the generic
171
+ * message instead discards it and points the user at the connection-method
172
+ * documentation, which is the wrong place to look when the connection was fine
173
+ * and the device simply said no (#1324).
174
+ *
175
+ * The original error object is passed through untouched, so flags set on it
176
+ * upstream (`deviceRefusal`) still reach the caller.
177
+ */
178
+ function updateFailureError(lastError, fallbackMessage) {
179
+ return lastError ?? new Error(fallbackMessage)
180
+ }
181
+
165
182
  export {
166
183
  base64ToHex,
167
184
  cenToFar,
@@ -182,4 +199,5 @@ export {
182
199
  pfxToCertAndKey,
183
200
  sleep,
184
201
  statusToActionCode,
202
+ updateFailureError,
185
203
  }
@@ -18,6 +18,7 @@ import {
18
18
  nearestHalf,
19
19
  parseDeviceId,
20
20
  parseError,
21
+ updateFailureError,
21
22
  } from './functions.js'
22
23
 
23
24
  /**
@@ -247,3 +248,45 @@ describe('describeControlFailure', () => {
247
248
  expect(describeControlFailure(undefined)).toBeNull()
248
249
  })
249
250
  })
251
+
252
+ /**
253
+ * The bug (#1324): when a command had a Bluetooth fallback, every earlier
254
+ * failure was thrown away and replaced with "no connection method available".
255
+ * That is worse than vague — it is untrue, and its link sends the user off to
256
+ * configure connection methods when the real answer was that Govee had said
257
+ * the device was offline.
258
+ */
259
+ describe('updateFailureError', () => {
260
+ it('reports govee\'s own refusal rather than the generic message', () => {
261
+ const refusal = new Error('Device is offline. Please check the Wi-Fi connection.')
262
+ const chosen = updateFailureError(refusal, 'no connection method available')
263
+
264
+ expect(chosen.message).toBe('Device is offline. Please check the Wi-Fi connection.')
265
+ })
266
+
267
+ it('passes the original error through, so upstream flags survive', () => {
268
+ const refusal = new Error('Device is offline. Please check the Wi-Fi connection.')
269
+ refusal.deviceRefusal = true
270
+
271
+ const chosen = updateFailureError(refusal, 'no connection method available')
272
+
273
+ // Same object, not a copy - platform.js reads `deviceRefusal` off it to
274
+ // decide whether to print a stack line.
275
+ expect(chosen).toBe(refusal)
276
+ expect(chosen.deviceRefusal).toBe(true)
277
+ })
278
+
279
+ it('falls back to the generic message only when nothing was tried', () => {
280
+ expect(updateFailureError(undefined, 'no connection method available').message)
281
+ .toBe('no connection method available')
282
+ expect(updateFailureError(null, 'no connection method available').message)
283
+ .toBe('no connection method available')
284
+ })
285
+
286
+ it('keeps a bluetooth timeout rather than masking it', () => {
287
+ const bleFailure = new Error('BLE update failed: Connection timeout')
288
+
289
+ expect(updateFailureError(bleFailure, 'no connection method available').message)
290
+ .toBe('BLE update failed: Connection timeout')
291
+ })
292
+ })
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@homebridge-plugins/homebridge-govee",
3
3
  "alias": "Govee",
4
4
  "type": "module",
5
- "version": "11.32.0-beta.30",
5
+ "version": "11.32.0-beta.32",
6
6
  "description": "Homebridge plugin to integrate Govee devices into HomeKit.",
7
7
  "author": {
8
8
  "name": "bwp91",