Skip to content

Zoe fixes 2 - #2

Merged
kronflux merged 5 commits into
mainfrom
zoe-fixes-2
Nov 7, 2026
Merged

kronflux merged 5 commits into
mainfrom
zoe-fixes-2

Conversation

@manio

@manio manio commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

No description provided.

The Zoe profile reported no range. The EVC answers PID 223451 on
7E4/7EC with the range the car shows, in km, as a 16-bit value in the
last two bytes of the reply. This is the PID CanZE reads for the range
of Zoe Phase 2 cars (field 654.42), and it sits on the same ECU as the
state of charge, so it is one more request on the existing addressing.

The new range_km field uses the same byte_index -2 form as
battery_level_wh. It reaches aa-proxy-rs through raw_topic; aa-proxy-rs
ignores it on /battery. A car that does not answer the PID logs a failed
request and the daemon goes on with the next source.

Evidence: read from a 2016 Zoe R240, 223451 returned range_km 30 at
24.28 % state of charge and 4990 Wh, which is about 16.6 kWh/100 km.
The replay test serves that reply (62 34 51 00 1E) in the Zoe read cycle.

Broadcast frame 654, where Phase 1 CanZE reads the range, returned no
frames on that car, so it is not used.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@kronflux

kronflux commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

Thanks! The tests pass locally. Two things before merging:

  1. Stray prompt followed by silence. When the adapter prints a stray > after ATMA and then no frame arrives before the idle timeout, prompt_seen stays true and the cleanup skips the stop CR. If the adapter is in fact still monitoring (a quiet bus), the cleanup ATCRA is eaten as the stop character: the adapter prints a prompt for it and then answers TCRA with ? and a second prompt, so every later reply is off by one until the next reconnect. I reproduced it with a scripted adapter: after the scan, send_cmd("ATI") returned OK (the previous reply) instead of the banner. main behaves the same, so this is not new, but the stray-prompt change is the right place to fix it. Could you send the stop CR and read to the prompt when the scan ends without any frame after a stray prompt, and add a test for "stray prompt, then silence"?

  2. avg_batt_temp position. 2104 with byte_index 1 reads payload byte 4 (the multiframe payload starts 61 04, and byte_index skips three bytes). CanZE lists bits 32-39 as module 1's temperature and bits 600-607 (byte_index 72) as the pack average. Could you check against CanZE or your car and either move it to the average or rename the field (for example battery_module_1_temp_celsius, which matches the other profiles)?

The repository now runs CI on pull requests, so please rebase onto main; the next push will run the tests and the aarch64 build here.

manio and others added 4 commits November 7, 2026 08:52
Some adapters print a bare '>' right after ATMA and still start
monitoring. The scan took it for the end of monitoring and returned
after about 40 ms with no frames, so the external temperature was never
read. A prompt that arrives before any frame is now ignored; a frame
after it shows the ELM is monitoring, so the stop CR is still sent. A
prompt after frames still ends the scan, and silence ends it through
the idle timeout. In that case the ELM may still be monitoring, so the
stop CR is sent; the prompt is not taken for an idle adapter.

The scan logs why it ended, how long it took, how many stray prompts
and which CAN-IDs it saw, and warns when a stop_when frame never
arrived. Each field read from a broadcast frame is logged at debug
level like the UDS ones; the raw lines are logged at trace level.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Some values are four bytes long, such as the Zoe trip distance. A field
with length 4 is now decoded, unsigned or signed, and scaled in f64,
since an f32 cannot hold such a raw value exactly. Validation accepts
length 1 to 4 for uds_pid sources; broadcast frames stay at 1 to 2.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
poll_uds_pid sent a source's pre_request before the PID, but
poll_uds_pid_multiframe ignored it, so a multiframe source could not
open a diagnostic session first. It now sends it after ATH0, with errors
ignored as in the single-frame path.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Add three values the original canze-rs read, with the PIDs and scaling
checked against a real car log:

- trip_km (2233DE, four bytes, x0.0001), sent to /odometer with
  odometer_km
- trip_energy_kwh (2233DD, three bytes, x0.001)
- battery_module_1_temp_celsius (2104 on the battery ECU 79B/7BB, byte
  4 minus 40, after 10C0; this is the temperature of module 1)

The last two go out through raw_topic. The Zoe replay test covers all
three with the values from the log.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@manio

manio commented Nov 7, 2026

Copy link
Copy Markdown
Contributor Author

both addressed

@kronflux
kronflux merged commit 64d7f83 into main Nov 7, 2026
1 check passed
@kronflux
kronflux deleted the zoe-fixes-2 branch November 7, 2026 09:28
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.

2 participants