Skip to content

fix(bthome): emit measurement object ids in ascending order - #17

Open
jnimmo wants to merge 1 commit into
dz0ny:mainfrom
jnimmo:fix/object-id-ordering
Open

fix(bthome): emit measurement object ids in ascending order#17
jnimmo wants to merge 1 commit into
dz0ny:mainfrom
jnimmo:fix/object-id-ordering

Conversation

@jnimmo

@jnimmo jnimmo commented Jul 11, 2026

Copy link
Copy Markdown

Problem

BTHome v2 requires object ids within a single advertisement payload to be in non-decreasing numerical order. build_advertisement_data_() wrote measurements in rotation-traversal order, which violated this. Home Assistant's bthome_ble parser warns on every update:

BTHome sensor XXXX: BTHome device is not sending object ids in numerical order
(from low to high object id). This can cause issues with your BTHome receiver,
payload: 00084a0000010045a70145c4002e67

Values still decode correctly (each object is self-describing), but the warning is valid and some stricter receivers can mishandle it.

Root cause

Two effects combined:

  1. Sensors aren't necessarily declared in object_id order. In the reported config the ids are 0x01, 0x45, 0x45, 0x2E, 0x4A, so even a single unsplit packet came out unsorted.
  2. The rotation cursor starts mid-list and wraps ((start + i) % count), placing a high id before a low one whenever measurements are split across packets or a sensor is skipped (NaN / no state). The reported payload …4a…01…45…45…2e… is exactly a wrap that started at voltage.

There was also a latent issue: sensors and binary sensors were selected with independent budgets, so when a payload overflows one advertisement, binary sensors could be starved indefinitely.

Fix

Separate selection from write order:

  • Rotation still decides which measurements go in each packet (for fair coverage when split).
  • The selected set is sorted by object_id before encoding.
  • Sensors and binary sensors share a single combined cursor and are ordered together, because their id ranges overlap (e.g. temperature 0x45 vs door 0x1A) and a single cursor also prevents either category from starving the other.

Net effect for the reported config: the payload is now always 01 2e 45 45 4a (ascending), regardless of rotation state.

Verification

No ESPHome toolchain was available locally, so the selection/sort/rotation logic was extracted into a standalone harness and checked to be non-decreasing across: every rotation start, forced packet-splitting, overlapping sensor+binary ids, NaN/absent sensors, and a mixed overflow case confirming binary sensors are no longer starved. A negative control reproduced the exact reported out-of-order payload from the pre-fix logic.

Fixes #15

BTHome v2 requires object ids within a payload to be non-decreasing.
build_advertisement_data_() wrote measurements in rotation-traversal
order, so two things broke the ordering:

- Sensors are not necessarily declared in object_id order, so even a
  full (unsplit) packet could be out of order.
- The rotation cursor starts mid-list and wraps, placing a high object
  id before a low one whenever measurements are split across packets or
  a sensor is skipped (NaN / no state).

Home Assistant's bthome_ble parser warns on this:
  "BTHome device is not sending object ids in numerical order"

Separate the two concerns: rotation still decides *which* measurements
go in each packet, but the selected set is now sorted by object_id
before being encoded. Sensors and binary sensors are rotated and
ordered through a single combined cursor, because their object_id
ranges overlap (e.g. temperature 0x45 vs door 0x1A) and because a
single cursor also prevents one category from starving the other when
the payload is split across packets.

Fixes dz0ny#15

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jnimmo
jnimmo marked this pull request as draft July 11, 2026 04:41
@jnimmo
jnimmo marked this pull request as ready for review July 11, 2026 09:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error in HA: BTHome device is not sending object ids in numerical order

1 participant