Govee H5054 decoder accepts degenerate `fffffffffffe` frame as ID 0 / Unknown event
I observed the Govee H5054 decoder accept what appears to be a false-positive / degenerate RF frame as a valid Govee-Water message.
rtl_433 -V
rtl_433 version 25.02-47-g7433023b branch master at 202510122058 inputs file rtl_tcp RTL-SDRThe same packet was decoded twice about 5 seconds apart:
{
"time": "2026-09-12 12:10:27",
"model": "Govee-Water",
"id": 0,
"event": "Unknown",
"code": "fffffffffffe",
"mic": "PARITY",
"mod": "ASK",
"freq": 433.92358,
"rssi": -25.4681,
"snr": 3.37385,
"noise": -28.842
}and:
{
"time": "2026-09-12 12:10:32",
"model": "Govee-Water",
"id": 0,
"event": "Unknown",
"code": "fffffffffffe",
"mic": "PARITY",
"mod": "ASK",
"freq": 433.92374,
"rssi": -22.441,
"snr": 5.52257,
"noise": -27.9636
}I have not been able to reproduce the signal since and unfortunately do not have an IQ/sample capture.
Why this appears to be a decoder false positive
The current govee_decode() saves the raw code and then inverts the bitbuffer.
Therefore:
received/raw: ff ff ff ff ff fe
after invert: 00 00 00 00 00 01This results in:
id = 0x0000
event = 0x000
b[5] = 0x01
parity = 0
checksum = 0The current false-positive checks appear to be:
if (id == 0xffff) {
return DECODE_ABORT_EARLY;
}
if (b[5] == 0) {
return DECODE_ABORT_EARLY;
}
...
if (event == 0xffff) {
return DECODE_ABORT_EARLY;
}So this packet is not rejected:
id == 0x0000, not0xffffb[5] == 0x01, not zero- event is zero, not
0xffff
The parity check also passes accidentally because the first five inverted bytes are all zero:
xor_bytes(b, 5) = 0
folded checksum = 0
(b[5] >> 1) & 0x0f = 0
checksum == parityThe decoder consequently emits:
model = Govee-Water
id = 0
event = Unknown
mic = PARITYPossible fix
The comments/code indicate the last byte after inversion is expected to have the form:
101PPPP1The false-positive packet has:
00000001So it may be preferable to validate the fixed bits of this byte instead of only checking whether the byte is zero.
For example, if 101PPPP1 is valid for all devices handled by this legacy decoder:
if ((b[5] & 0xe1) != 0xa1) {
return DECODE_ABORT_EARLY;
}This would reject the observed 0x01 while retaining the four parity bits.
A simpler additional sanity check would be:
if (id == 0x0000 || id == 0xffff) {
return DECODE_ABORT_EARLY;
}but validating the documented fixed bits seems preferable if those bits are known to be invariant.
Expected behavior
A frame such as:
fffffffffffewhich becomes:
000000000001after inversion should not be emitted as a valid Govee-Water device with ID 0 merely because the zero-valued data also produces a zero-valued parity nibble.
Related issues
- #1809 — Govee H5054 uses incorrect parity check
- #1964 — RFC: Data sanity checking and filtering in rtl_433
#1964 specifically discusses the general problem of degenerate/all-zero buffers passing weak integrity checks. This appears to be a concrete instance of that problem in the legacy Govee decoder.
Additional information
I only captured the decoded rtl_433 output through MQTT/Home Assistant, not the original RF sample, and the signal has not recurred so far. I am reporting it because the exact raw code value is available and the current decoder behavior appears explainable directly from the decoder logic.
**ChatGPT assisted with preparing this issue report.
Source: merbanan/rtl_433