@homebridge-plugins/homebridge-govee 11.29.3 → 11.30.0-beta.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 +8 -0
- package/lib/connection/ble.js +5 -9
- package/lib/platform.js +31 -4
- package/lib/utils/command-builder.js +9 -1
- package/lib/utils/lang-en.js +1 -0
- package/lib/utils/response-parser.js +11 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@homebridge-plugins/homebridge-govee` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## v11.30.0 (Pending Release)
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- chore(ble): let noble apply its own adapter timeout instead of racing a second one
|
|
10
|
+
- fix: restore aws brightness scaling, so lights reach the brightness asked for (#1262) (@gradyg21)
|
|
11
|
+
- fix: skip a periodic sync when the previous one is still running, so slow responses stop stacking up (#1256) (@schwaggy)
|
|
12
|
+
|
|
5
13
|
## v11.29.3 (2026-07-21)
|
|
6
14
|
|
|
7
15
|
### Changed
|
package/lib/connection/ble.js
CHANGED
|
@@ -174,20 +174,16 @@ export default class BLEConnection {
|
|
|
174
174
|
return true
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
let timeoutId
|
|
178
177
|
try {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
])
|
|
178
|
+
// noble applies the timeout itself and removes its own state listener when
|
|
179
|
+
// it expires. Racing it against a second, shorter timer here just meant
|
|
180
|
+
// noble kept waiting - and holding its listener - for another five seconds
|
|
181
|
+
// after we had already given up.
|
|
182
|
+
await btClient.waitForPoweredOnAsync(timeout)
|
|
185
183
|
return true
|
|
186
184
|
} catch (err) {
|
|
187
185
|
this.log.warn('[BLE] failed to power on adapter: %s.', err.message)
|
|
188
186
|
return false
|
|
189
|
-
} finally {
|
|
190
|
-
clearTimeout(timeoutId)
|
|
191
187
|
}
|
|
192
188
|
}
|
|
193
189
|
|
package/lib/platform.js
CHANGED
|
@@ -57,6 +57,9 @@ export default class {
|
|
|
57
57
|
this.deviceConf = {}
|
|
58
58
|
this.ignoredDevices = []
|
|
59
59
|
|
|
60
|
+
// Periodic syncs currently running, so a slow one is not started twice
|
|
61
|
+
this.syncsInFlight = new Set()
|
|
62
|
+
|
|
60
63
|
// Make sure user is running Homebridge v1.5 or above
|
|
61
64
|
if (!api.versionGreaterOrEqual?.('1.5.0')) {
|
|
62
65
|
throw new Error(platformLang.hbVersionFail)
|
|
@@ -217,6 +220,7 @@ export default class {
|
|
|
217
220
|
}
|
|
218
221
|
break
|
|
219
222
|
}
|
|
223
|
+
case 'awsBrightnessNoScale':
|
|
220
224
|
case 'hideLight':
|
|
221
225
|
case 'hideModeGreenTea':
|
|
222
226
|
case 'hideModeOolongTea':
|
|
@@ -776,7 +780,7 @@ export default class {
|
|
|
776
780
|
|
|
777
781
|
this.refreshBLEInterval = setInterval(async () => {
|
|
778
782
|
try {
|
|
779
|
-
await this.goveeBLESync()
|
|
783
|
+
await this.runPeriodicSync('BLE', () => this.goveeBLESync())
|
|
780
784
|
} catch (err) {
|
|
781
785
|
this.log.warn('[BLE] sync failed: %s', parseError(err))
|
|
782
786
|
}
|
|
@@ -790,7 +794,7 @@ export default class {
|
|
|
790
794
|
if (this.httpClient && httpSyncNeeded) {
|
|
791
795
|
this.goveeHTTPSync()
|
|
792
796
|
this.refreshHTTPInterval = setInterval(
|
|
793
|
-
() => this.goveeHTTPSync(),
|
|
797
|
+
() => this.runPeriodicSync('HTTP', () => this.goveeHTTPSync()),
|
|
794
798
|
this.config.httpRefreshTime * 1000,
|
|
795
799
|
)
|
|
796
800
|
}
|
|
@@ -799,7 +803,7 @@ export default class {
|
|
|
799
803
|
const openApiRefresh = (this.config.openApiRefreshTime || this.config.httpRefreshTime) * 1000
|
|
800
804
|
this.goveeOpenApiSync()
|
|
801
805
|
this.refreshOpenApiInterval = setInterval(
|
|
802
|
-
() => this.goveeOpenApiSync(),
|
|
806
|
+
() => this.runPeriodicSync('OPENAPI', () => this.goveeOpenApiSync()),
|
|
803
807
|
openApiRefresh,
|
|
804
808
|
)
|
|
805
809
|
|
|
@@ -819,7 +823,7 @@ export default class {
|
|
|
819
823
|
// No need for await as catches its own errors, we poll specific models that need it
|
|
820
824
|
this.goveeAWSSync(true)
|
|
821
825
|
this.refreshAWSInterval = setInterval(
|
|
822
|
-
() => this.goveeAWSSync(),
|
|
826
|
+
() => this.runPeriodicSync('AWS', () => this.goveeAWSSync()),
|
|
823
827
|
60000,
|
|
824
828
|
)
|
|
825
829
|
}
|
|
@@ -1363,6 +1367,7 @@ export default class {
|
|
|
1363
1367
|
|
|
1364
1368
|
if (this.awsClient) {
|
|
1365
1369
|
accessory.context.useAwsControl = true
|
|
1370
|
+
accessory.context.awsBrightnessNoScale = deviceConf.awsBrightnessNoScale
|
|
1366
1371
|
accessory.context.awsColourMode = deviceConf.awsColourMode || platformConsts.defaultValues.awsColourMode
|
|
1367
1372
|
awsDevices.push(device.device)
|
|
1368
1373
|
|
|
@@ -1441,6 +1446,28 @@ export default class {
|
|
|
1441
1446
|
}
|
|
1442
1447
|
}
|
|
1443
1448
|
|
|
1449
|
+
/**
|
|
1450
|
+
* Run a periodic sync, skipping this run if the previous one is still going.
|
|
1451
|
+
*
|
|
1452
|
+
* The intervals fire on a timer regardless of how long a sync takes, and the
|
|
1453
|
+
* http request timeout and the default refresh interval are both thirty
|
|
1454
|
+
* seconds. A single slow response therefore guaranteed the next sync started
|
|
1455
|
+
* before the last had finished, and those stacked up - piling more requests
|
|
1456
|
+
* onto an endpoint that was already struggling (#1256).
|
|
1457
|
+
*/
|
|
1458
|
+
async runPeriodicSync(name, sync) {
|
|
1459
|
+
if (this.syncsInFlight.has(name)) {
|
|
1460
|
+
this.log.debugWarn('[%s] %s', name, platformLang.syncStillRunning)
|
|
1461
|
+
return
|
|
1462
|
+
}
|
|
1463
|
+
this.syncsInFlight.add(name)
|
|
1464
|
+
try {
|
|
1465
|
+
await sync()
|
|
1466
|
+
} finally {
|
|
1467
|
+
this.syncsInFlight.delete(name)
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1444
1471
|
async goveeAWSSync(allDevices = false) {
|
|
1445
1472
|
const pollList = allDevices ? awsDevices : awsDevicesToPoll
|
|
1446
1473
|
if (pollList.length === 0) {
|
|
@@ -111,7 +111,15 @@ function buildBrightnessCommand(params, context) {
|
|
|
111
111
|
return {
|
|
112
112
|
awsParams: {
|
|
113
113
|
cmd: 'brightness',
|
|
114
|
-
|
|
114
|
+
// Most devices take 0-254 over AWS, so HomeKit's 0-100 has to be scaled
|
|
115
|
+
// up. A handful expect 0-100 already and are opted out per device with
|
|
116
|
+
// `awsBrightnessNoScale`. Dropping this scaling made every AWS device
|
|
117
|
+
// land at roughly a third of the requested brightness (#1262).
|
|
118
|
+
data: {
|
|
119
|
+
val: context.awsBrightnessNoScale
|
|
120
|
+
? params.value
|
|
121
|
+
: Math.round(params.value * 2.54),
|
|
122
|
+
},
|
|
115
123
|
},
|
|
116
124
|
bleParams: {
|
|
117
125
|
cmd: CMD.BRIGHTNESS,
|
package/lib/utils/lang-en.js
CHANGED
|
@@ -130,6 +130,7 @@ export default {
|
|
|
130
130
|
storageSetupErr: 'Could not setup storage client as',
|
|
131
131
|
storageWriteErr: 'could not save accessory to file as',
|
|
132
132
|
syncFail: 'sync failed as',
|
|
133
|
+
syncStillRunning: 'skipping this sync as the previous one has not finished yet',
|
|
133
134
|
viaAL: 'via adaptive lighting',
|
|
134
135
|
unknownCommand: 'unknown command in payload received',
|
|
135
136
|
}
|
|
@@ -49,8 +49,18 @@ export function parseDeviceUpdate(params, context) {
|
|
|
49
49
|
|
|
50
50
|
// BRIGHTNESS
|
|
51
51
|
if (params.state && hasProperty(params.state, 'brightness')) {
|
|
52
|
-
|
|
52
|
+
// AWS reports 0-254 on most devices, so it has to come back down to
|
|
53
|
+
// HomeKit's 0-100. Without this every AWS reading of 100 or more clamped
|
|
54
|
+
// to full brightness (#1262). The other sources already report 0-100.
|
|
55
|
+
if (params.source === 'AWS') {
|
|
56
|
+
data.brightness = context.awsBrightnessNoScale
|
|
57
|
+
? params.state.brightness
|
|
58
|
+
: Math.round(params.state.brightness / 2.54)
|
|
59
|
+
} else {
|
|
60
|
+
data.brightness = params.state.brightness
|
|
61
|
+
}
|
|
53
62
|
}
|
|
63
|
+
// Govee occasionally sends a value outside [0, 100] anyway
|
|
54
64
|
if (hasProperty(data, 'brightness')) {
|
|
55
65
|
data.brightness = Math.max(Math.min(data.brightness, 100), 0)
|
|
56
66
|
}
|
package/package.json
CHANGED