feat(obd): log every command sent and every response that yields no v… - #63
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…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 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.