Skip to content

feat(obd): log every command sent and every response that yields no v… - #63

Merged
eigger merged 2 commits into
mainfrom
feat/obd-log-unparsed-responses
Jul 30, 2026
Merged

feat(obd): log every command sent and every response that yields no v…#63
eigger merged 2 commits into
mainfrom
feat/obd-log-unparsed-responses

Conversation

@eigger

@eigger eigger commented Jul 30, 2026

Copy link
Copy Markdown
Owner

…alue

An Accent RB diesel showed empty odometer sensors with nothing in the log to explain why. Only successfully parsed responses were logged, so a poll that returned NO DATA, timed out, or was refused by the ECU left no trace at all — the sensor simply stayed blank and there was no way to tell whether the request had even gone out.

Log each transmitted command as TX, tagged with the sensor key when the command is a poll, so "never requested" is distinguishable from "requested, no answer".

Log as RX the two cases that previously vanished:

  • the response could not be normalized (NO DATA, timeout, adapter failure), reported with the raw ELM327 text
  • the response is a UDS negative response, reported with the service and the NRC name

The negative-response case needs its own branch because 0x7F falls inside the response-mode range that normalizeElm327Response accepts, so a refusal parsed "successfully" and was then dropped downstream when no sensor matched its decoded mode and pid. explainNegativeResponse only inspects the head of a normalized payload, so a 0x7F byte sitting in the middle of real data is not mistaken for a refusal.

eigger and others added 2 commits July 30, 2026 12:17
…alue

An Accent RB diesel showed empty odometer sensors with nothing in the log to
explain why. Only successfully parsed responses were logged, so a poll that
returned NO DATA, timed out, or was refused by the ECU left no trace at all —
the sensor simply stayed blank and there was no way to tell whether the request
had even gone out.

Log each transmitted command as TX, tagged with the sensor key when the command
is a poll, so "never requested" is distinguishable from "requested, no answer".

Log as RX the two cases that previously vanished:

- the response could not be normalized (NO DATA, timeout, adapter failure),
  reported with the raw ELM327 text
- the response is a UDS negative response, reported with the service and the
  NRC name

The negative-response case needs its own branch because 0x7F falls inside the
response-mode range that normalizeElm327Response accepts, so a refusal parsed
"successfully" and was then dropped downstream when no sensor matched its
decoded mode and pid. explainNegativeResponse only inspects the head of a
normalized payload, so a 0x7F byte sitting in the middle of real data is not
mistaken for a refusal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An Accent RB diesel answered 21 01 but appeared to ignore 21 03, which is
where the odometer lives. It was not ignoring it — the app was throwing the
response away.

ELM327 prints a multi-frame response as a total length on its own line
followed by numbered frame lines:

    03F
    0:6103AABBCCDDEEFF
    1:...

extractPayloadBytes skipped that length line with the regex \d{3}, which only
matches three decimal digits. A length containing A-F does not match, so the
header was treated as payload, the accumulated hex became odd-length, and the
whole response was rejected as unparseable — silently, since a null parse was
never logged.

That is why 21 01 worked and 21 03 did not: 41 bytes is 0x029, all digits, so
it was skipped by luck. A 21 03 frame carrying the odometer at bytes 57-60
needs 63 bytes, which is 0x03F, and every length from 0x02A up that contains
a hex letter had the same fate.

Follow the approach already proven in the ESPHome ble_elm327 component: keep
numbered frame lines and unnumbered lines apart, drop unnumbered fragments of
three hex characters or fewer since data always comes in even-length pairs,
and prefer the framed lines when any exist so stray fragments cannot be
concatenated into the payload.

Single-frame responses and the doubled replies that come back from a 7DF
broadcast are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@eigger
eigger merged commit 6118e8d into main Jul 30, 2026
3 checks passed
@eigger
eigger deleted the feat/obd-log-unparsed-responses branch July 30, 2026 03:27
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.

1 participant