From 732b6282bb75aa03cb9f3753d00a3dee4cd9b25d Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Sun, 12 Jul 2026 19:52:40 +0200 Subject: [PATCH] Check full cc ff constant pair in Govee-H5310 status frames The status-frame disambiguator against the Govee-H5112 dual-probe thermometer (which shares this frame's outer length and 0x71 marker) only checked dec[9] == 0xff. Genuine H5310 status frames carry the constant pair 0xcc 0xff at dec[8-9], so also require dec[8] == 0xcc, strengthening the rejection of foreign frames from ~1/256 residual ambiguity on arbitrary data to ~1/65536. For genuine H5112 frames the separation was already sound either way (dec[9] == 0xff would require an impossible humidity above 102% RH), and H5112 now symmetrically rejects frames whose humidity decodes above 100% RH -- the two accept-sets are disjoint without relying on decoder priority ordering. Doc comment updated to describe the two-sided separation. Verified: both genuine H5310 status codes (rtl_433_tests#503) still decode; H5112's own status frames still fall through to the H5112 decoder. Full local regression suite: no new false positives. --- src/devices/govee_h5310.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/devices/govee_h5310.c b/src/devices/govee_h5310.c index 7f25186b..7b4e4bfd 100644 --- a/src/devices/govee_h5310.c +++ b/src/devices/govee_h5310.c @@ -170,13 +170,16 @@ resolves that cross-model mislabeling. Status-reply frames from the H5112 dual-probe thermometer share this same outer length (LL=0x1f) and marker (0x71). H5310 status frames always carry -the constant pair 0xcc 0xff at dec[8-9]; H5112's own dec[9] is instead part -of its packed sensor word and only rarely happens to equal 0xff. This decoder -rejects the frame (falling through to H5112) whenever dec[9] != 0xff -- a -reliable but not perfect disambiguator (roughly 1/256 of genuine H5112 status -frames could still be misclaimed here). There is no equivalent fix for a -similar ambiguity on ping frames (see below); the fixed length/marker alone -isn't enough there. +the constant pair 0xcc 0xff at dec[8-9]; H5112's own dec[8-9] are instead +part of its packed sensor word (probe temperature and humidity bits), which +never decode to cc ff for physically possible readings -- dec[9] == 0xff +alone would already require an impossible humidity above 102% RH. This +decoder rejects the frame (falling through to H5112) unless both constants +match, and the H5112 decoder symmetrically rejects frames whose humidity +decodes above 100% RH, so the two accept-sets are disjoint for genuine +frames without relying on decoder priority ordering. There is no equivalent +fix for a similar ambiguity on ping frames (see below); the fixed +length/marker alone isn't enough there. Ping/connectivity frame, LL == 0x1c (28), 25-byte decrypted payload, marker 0x70. Observed correlating with app-side actions (Network Test, unit-display @@ -338,10 +341,12 @@ static int govee_h5310_decode(r_device *decoder, bitbuffer_t *bitbuffer) event = "Periodic Update"; } else { - // dec[9] is 0xff in genuine H5310 status frames (the "cc ff" constant - // pair); H5112 status responses share this outer_len/marker but carry - // sensor data at dec[9] instead, only rarely equal to 0xff. - if (dec[9] != 0xff) { + // dec[8-9] is the constant pair 0xcc 0xff in genuine H5310 status + // frames; H5112 status responses share this outer_len/marker but + // carry sensor data in these bytes instead (probe temperature and + // humidity bits, which never decode to cc ff for physically possible + // readings). + if (dec[8] != 0xcc || dec[9] != 0xff) { return DECODE_ABORT_EARLY; } battery_pct = dec[GOVEE_H5310_STATUS_BATTERY_OFFSET];