@homebridge-plugins/homebridge-govee 11.30.0-beta.2 → 11.30.0-beta.3
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 +1 -0
- package/config.schema.json +30 -0
- package/lib/platform.js +14 -0
- package/lib/utils/constants.js +2 -1
- package/lib/utils/lang-en.js +1 -0
- package/lib/utils/response-parser.js +59 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,7 @@ All notable changes to `@homebridge-plugins/homebridge-govee` will be documented
|
|
|
9
9
|
- chore(ble): let noble apply its own adapter timeout instead of racing a second one
|
|
10
10
|
- fix: restore aws brightness scaling, so lights reach the brightness asked for (#1262) (@gradyg21)
|
|
11
11
|
- fix: skip a periodic sync when the previous one is still running, so slow responses stop stacking up (#1256) (@schwaggy)
|
|
12
|
+
- fix: work out whether the openapi sensor temperature is celsius or fahrenheit, so thermometers no longer read too high (#1269) (@tdporter)
|
|
12
13
|
|
|
13
14
|
## v11.29.3 (2026-07-21)
|
|
14
15
|
|
package/config.schema.json
CHANGED
|
@@ -1143,6 +1143,35 @@
|
|
|
1143
1143
|
"functionBody": "return (model.thermoDevices && model.thermoDevices[arrayIndices] && model.thermoDevices[arrayIndices].deviceId && [23,26].includes(model.thermoDevices[arrayIndices].deviceId.length) && !model.thermoDevices[arrayIndices].ignoreDevice);"
|
|
1144
1144
|
}
|
|
1145
1145
|
},
|
|
1146
|
+
"openApiTempUnit": {
|
|
1147
|
+
"type": "string",
|
|
1148
|
+
"title": "OpenAPI Temperature Unit",
|
|
1149
|
+
"description": "Govee's OpenAPI reports the temperature in whatever unit your Govee app is set to, without saying which. Leave this on Auto and the plugin will work it out. Only set it manually if the reported temperature is wrong.",
|
|
1150
|
+
"default": "auto",
|
|
1151
|
+
"oneOf": [
|
|
1152
|
+
{
|
|
1153
|
+
"title": "Auto (Recommended)",
|
|
1154
|
+
"enum": [
|
|
1155
|
+
"auto"
|
|
1156
|
+
]
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
"title": "Celsius",
|
|
1160
|
+
"enum": [
|
|
1161
|
+
"c"
|
|
1162
|
+
]
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
"title": "Fahrenheit",
|
|
1166
|
+
"enum": [
|
|
1167
|
+
"f"
|
|
1168
|
+
]
|
|
1169
|
+
}
|
|
1170
|
+
],
|
|
1171
|
+
"condition": {
|
|
1172
|
+
"functionBody": "return (model.thermoDevices && model.thermoDevices[arrayIndices] && model.thermoDevices[arrayIndices].deviceId && [23,26].includes(model.thermoDevices[arrayIndices].deviceId.length) && !model.thermoDevices[arrayIndices].ignoreDevice);"
|
|
1173
|
+
}
|
|
1174
|
+
},
|
|
1146
1175
|
"showExtraSwitch": {
|
|
1147
1176
|
"type": "boolean",
|
|
1148
1177
|
"title": "Show Extra Switch",
|
|
@@ -1625,6 +1654,7 @@
|
|
|
1625
1654
|
"thermoDevices[].deviceId",
|
|
1626
1655
|
"thermoDevices[].ignoreDevice",
|
|
1627
1656
|
"thermoDevices[].lowBattThreshold",
|
|
1657
|
+
"thermoDevices[].openApiTempUnit",
|
|
1628
1658
|
"thermoDevices[].showExtraSwitch"
|
|
1629
1659
|
]
|
|
1630
1660
|
}
|
package/lib/platform.js
CHANGED
|
@@ -236,6 +236,7 @@ export default class {
|
|
|
236
236
|
this.deviceConf[id][k] = v === 'false' ? false : !!v
|
|
237
237
|
break
|
|
238
238
|
case 'awsColourMode':
|
|
239
|
+
case 'openApiTempUnit':
|
|
239
240
|
case 'showAs': {
|
|
240
241
|
if (typeof v !== 'string' || !platformConsts.allowed[k].includes(v)) {
|
|
241
242
|
logIgnore(`${key}.${id}.${k}`)
|
|
@@ -1291,6 +1292,13 @@ export default class {
|
|
|
1291
1292
|
accessory.context.temperatureSource = deviceConf.temperatureSource
|
|
1292
1293
|
}
|
|
1293
1294
|
|
|
1295
|
+
// Add the openApiTempUnit config to the context if set to something other than auto
|
|
1296
|
+
if (deviceConf.openApiTempUnit && deviceConf.openApiTempUnit !== 'auto') {
|
|
1297
|
+
accessory.context.openApiTempUnit = deviceConf.openApiTempUnit
|
|
1298
|
+
} else {
|
|
1299
|
+
delete accessory.context.openApiTempUnit
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1294
1302
|
// Get a supported command list if provided, with their options
|
|
1295
1303
|
if (device.supportCmds && Array.isArray(device.supportCmds)) {
|
|
1296
1304
|
accessory.context.supportedCmds = device.supportCmds
|
|
@@ -1969,6 +1977,12 @@ export default class {
|
|
|
1969
1977
|
delete data.kelvinOutOfRange
|
|
1970
1978
|
}
|
|
1971
1979
|
|
|
1980
|
+
// Skip the reading if we can't tell whether govee sent celsius or fahrenheit
|
|
1981
|
+
if (data.temperatureUnitUnknown) {
|
|
1982
|
+
accessory.logDebugWarn(platformLang.openApiTempUnitUnknown)
|
|
1983
|
+
delete data.temperatureUnitUnknown
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1972
1986
|
// Check if we actually parsed anything useful (more than just the source property)
|
|
1973
1987
|
if (Object.keys(data).length > 1) {
|
|
1974
1988
|
try {
|
package/lib/utils/constants.js
CHANGED
|
@@ -92,7 +92,7 @@ export default {
|
|
|
92
92
|
'temperatureSource',
|
|
93
93
|
],
|
|
94
94
|
leakDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold'],
|
|
95
|
-
thermoDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold', 'showExtraSwitch'],
|
|
95
|
+
thermoDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold', 'openApiTempUnit', 'showExtraSwitch'],
|
|
96
96
|
fanDevices: ['label', 'deviceId', 'ignoreDevice', 'hideLight'],
|
|
97
97
|
heaterDevices: ['label', 'deviceId', 'ignoreDevice', 'tempReporting'],
|
|
98
98
|
humidifierDevices: ['label', 'deviceId', 'ignoreDevice'],
|
|
@@ -112,6 +112,7 @@ export default {
|
|
|
112
112
|
],
|
|
113
113
|
iceMakerDevices: ['label', 'deviceId', 'ignoreDevice'],
|
|
114
114
|
awsColourMode: ['default', 'rgb', 'redgreenblue'],
|
|
115
|
+
openApiTempUnit: ['auto', 'c', 'f'],
|
|
115
116
|
showAs: [
|
|
116
117
|
'default',
|
|
117
118
|
'audio',
|
package/lib/utils/lang-en.js
CHANGED
|
@@ -17,6 +17,7 @@ export default {
|
|
|
17
17
|
available: 'client enabled',
|
|
18
18
|
availableWithDevices: n => `client enabled and found ${n} device(s)`,
|
|
19
19
|
openApiNoKey: 'api key not provided',
|
|
20
|
+
openApiTempUnitUnknown: 'ignoring the openapi temperature as it is unclear whether govee sent celsius or fahrenheit - you can set this in the plugin settings for this device',
|
|
20
21
|
brand: 'Govee',
|
|
21
22
|
bleNonControl: 'will be visible but uncontrollable as BLE not available',
|
|
22
23
|
bleNoPackage: 'required hardware/packages not available',
|
|
@@ -2,6 +2,50 @@ import platformConsts from './constants.js'
|
|
|
2
2
|
|
|
3
3
|
const hasProperty = (obj, prop) => Object.hasOwn(obj, prop)
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Works out which unit an OpenAPI `sensorTemperature` value is in.
|
|
7
|
+
*
|
|
8
|
+
* Govee's OpenAPI reports this value in whatever unit the Govee app is set to, and
|
|
9
|
+
* sends no unit alongside it. The HTTP API always reports hundredths of a degree
|
|
10
|
+
* Celsius, so where a device has both we can compare the two and see which fits.
|
|
11
|
+
*
|
|
12
|
+
* @param {number} value - The raw OpenAPI sensorTemperature value
|
|
13
|
+
* @param {object} context - Accessory context
|
|
14
|
+
* @returns {'c'|'f'|null} The unit, or null if it cannot be determined
|
|
15
|
+
*/
|
|
16
|
+
function resolveOpenApiTempUnit(value, context) {
|
|
17
|
+
// An explicit setting always wins
|
|
18
|
+
if (context.openApiTempUnit === 'c' || context.openApiTempUnit === 'f') {
|
|
19
|
+
return context.openApiTempUnit
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Govee may declare the unit on the capability itself
|
|
23
|
+
const declared = context.openApiCapabilities?.sensorTemperature?.parameters?.unit
|
|
24
|
+
if (typeof declared === 'string') {
|
|
25
|
+
if (declared.toLowerCase().startsWith('f')) {
|
|
26
|
+
return 'f'
|
|
27
|
+
}
|
|
28
|
+
if (declared.toLowerCase().startsWith('c')) {
|
|
29
|
+
return 'c'
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Otherwise compare against the last HTTP reading, which is always Celsius
|
|
34
|
+
const reference = context.lastHttpTempCelsius
|
|
35
|
+
if (typeof reference === 'number') {
|
|
36
|
+
const asCelsius = Math.abs(value - reference)
|
|
37
|
+
const asFahrenheit = Math.abs(((value - 32) * 5) / 9 - reference)
|
|
38
|
+
if (asFahrenheit + 0.5 < asCelsius) {
|
|
39
|
+
return 'f'
|
|
40
|
+
}
|
|
41
|
+
if (asCelsius + 0.5 < asFahrenheit) {
|
|
42
|
+
return 'c'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
|
|
5
49
|
/**
|
|
6
50
|
* Parses a raw device update payload into a standardised data object.
|
|
7
51
|
* Handles different payload structures from AWS, LAN, OpenAPI, and legacy devices.
|
|
@@ -97,6 +141,11 @@ export function parseDeviceUpdate(params, context) {
|
|
|
97
141
|
// CURRENT TEMPERATURE
|
|
98
142
|
if (hasProperty(params, 'temperature')) {
|
|
99
143
|
data.temperature = params.temperature
|
|
144
|
+
|
|
145
|
+
// The HTTP value is always Celsius, so keep it as a reference for the OpenAPI value
|
|
146
|
+
if (params.source === 'HTTP' && Number.isFinite(params.temperature)) {
|
|
147
|
+
context.lastHttpTempCelsius = params.temperature / 100
|
|
148
|
+
}
|
|
100
149
|
} else if (params?.state?.sta && hasProperty(params.state.sta, 'curTem')) {
|
|
101
150
|
data.temperature = params.state.sta.curTem
|
|
102
151
|
}
|
|
@@ -136,7 +185,16 @@ export function parseDeviceUpdate(params, context) {
|
|
|
136
185
|
|
|
137
186
|
// SENSOR TEMPERATURE (OpenAPI property)
|
|
138
187
|
if (params.state && hasProperty(params.state, 'sensorTemperature')) {
|
|
139
|
-
|
|
188
|
+
const sensorTemp = Number(params.state.sensorTemperature)
|
|
189
|
+
const unit = resolveOpenApiTempUnit(sensorTemp, context)
|
|
190
|
+
if (unit === 'f') {
|
|
191
|
+
data.temperature = Math.round((((sensorTemp - 32) * 5) / 9) * 100)
|
|
192
|
+
} else if (unit === 'c') {
|
|
193
|
+
data.temperature = Math.round(sensorTemp * 100)
|
|
194
|
+
} else {
|
|
195
|
+
// Unit unknown, so report nothing rather than a wrong reading
|
|
196
|
+
data.temperatureUnitUnknown = true
|
|
197
|
+
}
|
|
140
198
|
}
|
|
141
199
|
|
|
142
200
|
// SENSOR HUMIDITY (OpenAPI property)
|
package/package.json
CHANGED