ChargeLink Native

IEC 61851-23/-24 System A Runbook

ChargeLink Native implements the DC charging control communication of IEC 61851-23 / IEC 61851-24 System A, the CAN-based DC scheme of those standards. Both roles exist: a station (charger, EVSE side) that runs against a simulated System A plant, and an EV (vehicle side). They run a session from start-up through the insulation check and energy transfer to shutdown, and ChargeLink judges each session against its own ledger of timing and state rules, whose values follow IEC 61851-24 (System A). The stack is built as chargelink dc-can chademo; chademo in command names is a legacy identifier for IEC 61851-23/-24 System A.

$CL   = 'C:\ChargeLink\0.5.0-rc2\pc1\bin\chargelink.exe'
$Data = 'C:\ChargeLinkData'

1. What the stack implements

IEC 61851-23/-24 System A runtime: station, plant and owner on PC1, EV on PC2, CAN through the hub or Kvaser, and the station phases PC1 · chargelink dc-can chademo evse System A station role sends the periodic station messages judges the case, writes the reports profile iec61851_23_24_system_a_station Simulated System A plant voltage, current, contactors, latch, CP / CP2 / CP3 / CS pilot lines, isolation in-process owner grants and revokes Virtual CAN hub · TCP 47100 newline-delimited JSON frames chargelink.t5.virtual_can_hub.v1 or a Kvaser CANlib channel Plant link · TCP 47101 EV-side contactor, switches and measurements for the EV on PC2 chargelink.t5.plant_link.v2 PC2 · chargelink dc-can chademo ev System A EV role sends the periodic EV messages requests current, enables charging, closes its contactor, asks to stop profile iec61851_23_24_system_a_ev --hub PC1:47100 --plant-link PC1:47101 lane-f runs both roles on one PC in the same process (no PC2 needed) stop: chargelink evcc stop --run-id CAN plant STATION PHASE NAMES (as printed in roles/station-report.json) Handshake WaitPermission Latching PreCheck InsulationCheck PostCheck WaitEvContactor EnergyTransfer RampDown WaitWelding VoltageRemoval EndCommunication Finished A fault or stop request in any phase goes to RampDown and runs the same shutdown chain.
The System A runtime: station, plant, owner, CAN hub and plant link on PC1; the EV on PC2 (or in the same process for the one-PC case matrix); the station phase names used in the reports.

Messages on the bus

The station and the EV exchange the periodic EV and station messages of IEC 61851-23/-24 System A, over a virtual CAN hub or a Kvaser CANlib channel. The trace of each cycle records every frame with its bus timestamp, so ChargeLink's message-timing rule (ledger row L-004) is checked from the evidence, not assumed. A frame with a wrong length or an unknown identifier is counted as a bus error; case k6 checks that values the standard requires a station to tolerate do not end the session.

Station phases

The station reports its progress with the phase names shown in the figure; they are the names printed in roles\station-report.json: Handshake, WaitPermission, Latching, PreCheck, InsulationCheck, PostCheck, WaitEvContactor, EnergyTransfer, RampDown, WaitWelding, VoltageRemoval, EndCommunication and Finished. A fault or stop request in any phase goes to RampDown and runs the same shutdown chain; the report states the shutdown kind (normal or an error shutdown), its cause and the times at which current reached zero, the switches opened and the connector unlatched.

Rules the station enforces

The limit and timing values of these rules follow IEC 61851-24 (System A); ChargeLink checks them from the evidence of every cycle.

ChargeLink ruleStation action
Communication-loss timeouterror shutdown (cases k5a, k5b, k5c, k12)
Normal-stop ramp startchecked in L-037
Zero-current deadlinechecked in L-038
Welding-detection deadlineswitches open after the EV's report or at the deadline (L-039, case k15)
Unlatch voltage limitconnector unlatched only below it (L-040)
Overvoltage toleranceerror shutdown when exceeded (case k10)
Overcurrent toleranceerror shutdown when exceeded (case k11)
Latch-fault detectionemergency shutdown (case k8c)

The station also watches the plant: the plant link carries a watchdog (case k4 trips it), the in-process owner can revoke its grant at any time (case k7), and an insulation fault or earth leakage measured by the plant ends the session (cases k2a, k2b). The plant starts and must end in the safe state (contactors open, unlatched, zero voltage); each cycle records that as a pre- and post-cycle check.

2. The one-PC case matrix (lane-f)

The lane-f command runs the station, the EV, the simulated plant, the owner and the virtual CAN bus in one process on one PC. It is the regression run and the first thing to run on a new installation. It needs no network, no second PC and no CAN hardware.

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo lane-f --cases all --run-id matrix-<DATE> --out "$Data\artifacts\t5-chademo"
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo lane-f --cases n1,k1,k5b --run-id matrix-quick

Expected with --cases all: exit code 0, "status": "passed", cycles_requested 29, cycles_run 29, cycles_passed 29, cycles_failed 0, cycles_blocked 0; one console line per cycle (<run-id> cycle 2 of 29: n1 passed); the process raises its own priority class to High and reports it. The result records the workload it found at the start (build, .NET, PowerShell, VeriStand and ChargeLink processes) and whether the bench lock was held. About four minutes. A case counts only when it runs against the implemented roles: a cycle whose pre-checks fail (bus not empty, plant not safe, owner not active) is reported as blocked, not as a pass.

CaseTitleWhat is judged
bus_self_testVirtual bus, plant and owner self-testThe lane's own fixtures work before any protocol case runs (one-PC matrix only).
n1Nominal session, EV-initiated normal stopComplete session; energy transfer reaches the EV target; normal shutdown timing; latch, insulation check, pilot lines and station state order.
n2Station-initiated normal stop (user stop)Same as n1 with the stop coming from the station side.
k1Station emergency stop, judged as a station-triggered error shutdownEmergency stop input on the plant; error shutdown chain and flags.
k2aInsulation fault during the insulation checkCheck fails; no permission to close; safe end.
k2bEarth leakage during energy transferError shutdown from the transfer phase.
k3aEV contactor welded before the insulation checkStation detects the closed EV contactor and refuses to proceed.
k4Plant communication loss (plant watchdog)Plant link watchdog trips; station goes safe.
k5aPeer abort: EV process killed during transferCommunication-loss timeout; error shutdown.
k5bSilent peer during energy transferCommunication-loss monitor during transfer.
k5cSilent peer during parameter exchangeCommunication-loss monitor before permission.
k5dEV-flagged error shutdownEV sets a fault flag; station performs the error shutdown.
k6Frame integrity and tolerated valuesWrong-length and unknown frames are rejected; tolerated values do not end the session.
k7Owner lossOwner revokes its grant; station ends the session safely.
k8aEV opens switch k while charging is enabledPermission withdrawn mid-session.
k8bLoss of CP3 continuity (emergency shutdown)Pilot-line loss handled as an emergency shutdown.
k8cConnector latch malfunctionLatch feedback lost; emergency shutdown.
k9Incompatible EV, and insulation check without permissionParameter incompatibility ends the session; the check never starts without permission.
k10Side B overvoltageOvervoltage beyond its tolerance; error shutdown.
k11Side B overcurrentOvercurrent beyond its tolerance; error shutdown.
k12CAN bus-off of the EV node during energy transferCommunication loss after the EV node leaves the bus; error shutdown.
k13CAN bus-off of the station node during energy transferThe station's own node leaves the bus; safe end.
k14Error frames and an error-passive EV node during energy transfer, without data lossBus errors that do not lose data must not end the session.
k15The EV never reports welding detection finished (deadline L-039)Station opens its switches at the deadline.
k16The EV never gives permission (the station's stage timeout)Session ends at the stage timeout without an insulation check.
k17The EV never closes its contactor after CP2 (the station's stage timeout)Session ends at the stage timeout; voltage removed.
k18Loss of protective-conductor continuity during transfer (emergency shutdown)PE continuity lost; emergency shutdown.
k19Vehicle coupler disconnected during transfer: pilot lines, PE and DC contacts (emergency shutdown)All coupler circuits open at once; emergency shutdown.
k20CP broken during transfer: the SV1 interlock drops the EV contactor and the EV stopsThe EV side opens; the station ends the session.

3. Two-PC SIL lane: station on PC1, EV on PC2

The two-PC lane puts the EV on a second machine so that the CAN messages and the plant coupling cross a real network. PC1 runs the station, the plant, the owner, the CAN hub and the plant link; PC2 runs the EV. The station decides which case runs in each session and tells the EV what to do through the plant link, so PC2 needs no case list. Validate both sides first:

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo evse --dry-run --cases all
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo ev --dry-run --hub 127.0.0.1:47100 --plant-link 127.0.0.1:47101

The EV dry-run answers "mode": "dry_run", "status": "validated", session_status dry_run_validated, profile_id iec61851_23_24_system_a_ev, protocol chademo-classic, role evcc, backend_id virtual-can-hub, run id ev-t5-<timestamp>, and under t5.settings the backend, hub, plant link, connect_wait_s and the run directory <artifact-root>\t5-chademo\…; it opens no socket and no CAN channel. The station dry-run prints the same shape with profile_id iec61851_23_24_system_a_station, the bind addresses, ev_wait_s and the case list, but it first binds the hub and plant-link ports to prove they are free. The default ports 47100 and 47101 can be refused on a PC that runs Docker Desktop or WSL: Windows reserves a block of ports for them (on the reference PC 43500 to 47350) that netstat does not show, so the check fails with CL-CONFIG-001 "cannot be bound" although nothing listens. Pass ports outside that block on both sides, for example --hub-bind 127.0.0.1:52100 --plant-link-bind 127.0.0.1:52101 on PC1 and --hub <PC1>:52100 --plant-link <PC1>:52101 on PC2; the station dry-run then answers "status": "validated" with session_status dry_run_validated, profile_id iec61851_23_24_system_a_station, role evse, the case list and the claim boundary of the two-PC lane. The error message names this cause.

PC1 (station; replace the address with PC1's bench IPv4 address):

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo evse --hub-bind 192.0.2.10:47100 --plant-link-bind 192.0.2.10:47101 --allow-network `
  --cases n1,n2,k1,k5b --sessions 1 --ev-wait-s 600 --run-id chademo-pc1-<DATE>

PC2 (EV):

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo ev --hub 192.0.2.10:47100 --plant-link 192.0.2.10:47101 `
  --sessions 4 --connect-wait-s 600 --run-id chademo-pc2-<DATE>
  • --allow-network is required whenever the hub or the plant link listens on anything but loopback. Without it the station refuses to bind. Open TCP 47100 and 47101 on PC1's firewall for PC2's address only.
  • --cases on PC1 accepts the same case identifiers as the one-PC matrix, or all for every case except the one-PC bus self-test (19 cases). --sessions N repeats the case list N times; 0 repeats until chargelink evse stop --run-id <id>. On PC2 --sessions counts sessions, one per case offered; 0 runs until chargelink evcc stop --run-id <id>, and a stop lets the current session finish.
  • --ev-wait-s (PC1) and --connect-wait-s (PC2) bound how long each side waits for the other per session; 0 waits until stopped. Start PC1 first; PC2 retries until PC1 serves the next session.
  • Progress: chargelink --json runtime list shows both runs with their role and run id while they are active; chargelink --json evse status and chargelink --json evcc status work as for the IPv6 roles.
  • The station judges each session with the same checks as the one-PC matrix and writes the same evidence layout (section 5). PC2 writes its own session-NNN\ev-report.json per session; collect it together with PC1's run directory.

The activation catalogue of the build (chargelink --json evse external-evcc-session-policy) lists the same two commands under protocol chademo-classic with status t5_iec61851_system_a_two_pc_runtime_engineering_evidence and tls_recommended: false: CAN carries no TLS, and the hub and plant link are plaintext bench links. Keep them on an isolated bench network.

4. CAN on a Kvaser channel

Instead of the network hub, both roles can put their frames on a Kvaser CAN channel through Kvaser CANlib (canlib32.dll from the Kvaser driver package), at the System A bus parameters, which the roles set themselves. The plant link still runs over TCP, so PC1 and PC2 are connected by Ethernet and by CAN.

# PC1
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo evse --can-backend kvaser --kvaser-channel 0 --plant-link-bind 192.0.2.10:47101 --allow-network --cases n1 --run-id chademo-kvaser-pc1
# PC2
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo ev --can-backend kvaser --kvaser-channel 0 --plant-link 192.0.2.10:47101 --run-id chademo-kvaser-pc2

--kvaser-channel is the CANlib channel number (0 is the first channel; Kvaser virtual channels count). With two virtual channels on one PC the lane runs in the same way as on the hub and is a useful driver check before hardware is attached. The chosen hardware is one Kvaser Leaf v3 per PC (classic CAN, hardware timestamps of 50 µs, two 120 Ω terminators on a 1:1 D-sub 9 cable); no vehicle or charger has been connected. Check the driver and channels with Kvaser's own tools before starting a run; a missing DLL or channel is reported as a startup error, not as a protocol result.

Check the adapters and the cable

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo kvaser-check
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo kvaser-check --channel 0 --send 100              # PC1: send 100 test frames (identifier 0x7F0), 10 ms apart
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo kvaser-check --channel 0 --listen-s 10 --expect 100   # PC2: listen and require them

Without --channel the command only lists the CANlib channels: number, name (for example Kvaser Leaf v3 #0 (Channel 0) or Virtual #0 (Channel 0)), EAN, serial number, whether silent mode is supported and whether the channel is virtual; "status": "ok" with an empty problems list. With --channel it opens the channel at the System A bus parameters, reads them back, sends or listens for test frames and reports sent, received, received_by_id, send_errors and bus_health. Run it on both PCs before the first physical session: it is the cable test of the hardware runbook.

Repeatability in fresh processes

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo repeatability --clean 10 --faults k1,k2b,k4,k5a,k5b,k7,k8b,k12,k13 --run-id repeat-<DATE>

The repeatability lane runs N consecutive clean sessions (default 10), then each listed fault case followed by a clean recovery session, every cycle in fresh station and EV processes with a fresh run id and a fresh bus; --faults none runs only the clean sessions, --cycle-timeout-s (default 300) bounds a cycle. It answers the question "does the stack recover after each fault without a restart of anything but the session". The evidence folder defaults to <artifact-root>\t5-chademo.

Combined matrix and repeatability run

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo qualify --cases all --clean 10 --run-id qual-<DATE>

qualify runs the case matrix and then the repeatability run under one manifest and judges the rows Q1 to Q5 (frame audit, bus errors, timing, deadlines, repeatability) from the evidence. A row whose cases did not all run is reported incomplete and never counts. --source-root names the folder that holds the System A profile (config/lane-f/profiles); the other options are those of repeatability.

5. Evidence

The one-PC matrix writes to --out (default <artifact-root>\t5-chademo) under a folder named after the run id; the two-PC station writes <artifact-root>\t5-chademo\t5-<timestamp> unless --out is given.

FileContent
RESULT.jsonSchema chargelink.lane_f.v1: run id, status (passed, failed, incomplete or stopped), cycle counts, whether the operator stopped it, the verdict per cycle, the workload found at the start, whether the bench lock was held, and the claim boundary text.
MANIFEST.jsonEvery file of the run with size and SHA-256, written last.
cycle-NNN\CYCLE.jsonCase, title, kind, the ledger rows the case covers, verdict, the pre-cycle and post-cycle checks (fresh folder, empty bus, plant safe, owner active; all nodes detached, plant safe again) and the named checks with their result and detail, for example energy_transfer_reaches_the_ev_target.
cycle-NNN\traces\can-bus.jsonl, protocol\can-bus-summary.jsonEvery CAN frame with timestamp, identifier, length and payload (schema chargelink.t5.can_bus_trace.v1) and the per-identifier summary.
cycle-NNN\traces\plant.jsonlPlant snapshots: voltage, current, contactors, latch, pilot lines, isolation, emergency stop, watchdog.
cycle-NNN\owner\owner-journal.jsonlOwner grants and revocations.
cycle-NNN\roles\case1-…, case2-…, case3-…, over_target-…, over_maximum-… station and EV reportsCases that run several sessions or sub-cases (k6, k9) write one report pair per sub-case instead of a single pair.
cycle-NNN\roles\station-report.json, roles\ev-report.jsonPer role: finished, killed or timed out, frames sent and received, bus errors, the shutdown record (kind, cause, times), the owner outcome, the phase and event timeline and the message-timing statistics.

A complete 29-cycle run writes 238 files. The evidence is plain JSON and JSON Lines; nothing in it is a credential, so the whole folder can be archived or attached to a support case. Verify MANIFEST.json hashes before you rely on a copied run.

6. Reading a result

  • status: passed with all cycles passed is the only outcome that supports a statement such as "the ChargeLink System A station and EV pass the 29-case matrix on build X".
  • A failed cycle names the failing check in CYCLE.json; read the station and EV reports and the CAN trace around the timestamp in the check detail.
  • blocked means the cycle never ran (pre-checks failed). Typical causes on the two-PC lane: PC2 did not connect within --ev-wait-s, the hub port is in use, or a previous run left the plant unsafe. Restart with a fresh run id.
  • stopped records an operator stop; incomplete a run that ended without a verdict for every requested cycle.
  • The run record and QUALIFICATION.json carry two flags: lane_f_test_support and lane_f_relaxed_checks_used. A run counts only when both are false; a run made with test support or relaxed checks is engineering diagnosis, not evidence.
  • A timing check margin close to the limit on a loaded PC is a scheduling artefact, not a protocol defect: the roles are Windows processes, not real-time controllers. Re-run on an idle machine before reporting it.

7. Bench safety when real hardware is present

When the Kvaser backend is attached to a physical bus, the bench is a live electrical environment even though ChargeLink only drives CAN. Use an isolated, current-limited supply or an approved HIL interface; verify CAN-H, CAN-L, reference ground and termination with the bench powered down; keep the emergency stop accessible; start with contactors inhibited. The plant in this release is simulated: the station's voltage and current values are the model's, not measurements, and must not be used to control a real power stage.

8. Earlier DC-CAN lanes (still available)

These are the scripted DC-CAN lanes of the kit.

The following commands predate the System A stack and remain in the binary. They use a minimal fixture frame catalogue and a closure simulator, and are useful only as software smoke tests; they are not the System A implementation and their adapter kinds (peak-pcan, vector-xl, kvaser-canlib, socketcan, slcan, lawicel, usbtin) are descriptors that never open hardware.

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can catalog
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can virtual-run --protocol chademo --profile dc_can_virtual_evse --frame-count 8 --sample-period-ms 50
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo-live-run --run-id chademo-live-01
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo-can-adapter-loop --run-id chademo-loop-01 --adapter-kind peak-pcan --adapter-mode loopback --channel PCAN_USBBUS1 --bitrate-kbps 500
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo-fault-campaign --run-id chademo-fault-01
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json dc-can chademo-longrun-campaign --run-id chademo-longrun-01 --cycles 25 --mode loopback

dc-can release-gate still reports status: blocked_until_future_evidence and compliance_claim: none_dc_can_foundation_only; the gate has not been re-scored for the System A stack. The chademo-session conformance package (21 cases, 20 executable, 1 blocked pending a physical CAN backend) in the Test Package Catalog is likewise the earlier package and is not the System A case matrix.