ChargeLink Native

EVSE Role Guide

In the EVSE role ChargeLink is the charger-side communication controller (SECC). It advertises itself through SDP on UDP 15118, accepts the vehicle's TCP connection (plain or TLS), frames V2GTP, decodes EXI and answers the protocol sequence. This page explains the listener modes, the lifecycle files, the TLS adapters and the day-to-day commands that apply to every protocol. Protocol-specific steps are in the runbooks.

Listener modes

ModeCommand shapeSocketsUse
Dry-runevse start --dry-run --protocol P --profile-id IDnoneValidate profile and configuration; prints the activation catalog with the exact listener and EVCC commands for every protocol.
Timed listenerevse start --protocol P --profile-id ID --host :: ...UDP 15118, TCPListener that stops after --max-runtime-ms (default 500 ms). Useful for port and firewall checks.
External-EVCC sessionevse start --external-evcc-session ...UDP 15118, TCPKeeps listening until the runtime limit or an operator stop; serves the reference responses (or the plant-coupled runtime for ISO 15118-20 DC EIM).
Plant-coupled runtimeas above plus --plant-grpc-endpoint, --requested-power-kw, --target-voltage-v and CHARGELINK_ISO20_RUNTIME_PROFILEUDP 15118, TCP, gRPC clientISO 15118-20 DC EIM with dynamic responses; started by the VeriStand owner host.

--foreground is accepted for compatibility with earlier scripts and only recorded; the listener always runs in the foreground of the shell that started it. Use a dedicated PowerShell window per listener and stop it with evse stop from another window or Ctrl+C.

Network options

OptionMeaning
--host ::Bind address. Use :: (all IPv6 interfaces) for an external peer, ::1 for same-PC tests.
--udp-port 15118SDP port. 15118 is the ISO 15118 value; change it only for isolated experiments.
--tcp-port 50118V2GTP port advertised in the SDP response. 0 auto-allocates from 49152–65535.
--advertise-ipv6 fe80::...%NThe link-local address placed in the SDP response. Must be an address of the bench adapter with its zone index.
--interface-index NWindows interface index of the bench adapter; selects the multicast scope for SDP.
--max-runtime-ms, --heartbeat-interval-msRuntime limit and heartbeat period. With --external-evcc-session use a long limit (for example 1800000 ms) and 1000 ms heartbeats.
--run-idYour run identifier. Without it ChargeLink generates cl-evse-<unix_ms>.
--exi-mode chargelink-exiThe native codec. Leave at the default.
--can-backend, --can-channel, --can-bitrateRecorded in the session metadata for DC-CAN profiles; no CAN driver is started.

TLS adapters

SelectionAdapterVersionsClient authenticationUse with
--tls --tls-cert --tls-key --tls-cafile --require-carustls (default)ISO 15118-20: TLS 1.3 only with the named groups secp521r1 and x448 and the ISO 15118-20 cipher suites (--iso20-curve-profile, --allow-legacy-tls-named-groups); other protocols: 1.2 and 1.3Mutual when --require-ca; mandatory for ISO 15118-20ISO 15118-20; ISO 15118-2 peers that support TLS 1.3 or plain rustls 1.2
--tls --external-evcc-windows-tls --tls-pfx F --tls-pfx-password-env VARWindows SChannelTLS 1.2 onlynoneISO 15118-2 external EVCCs that require TLS 1.2 with ECDSA through the Windows stack
--tls --external-evcc-dev-tlsrustls, tolerant SNITLS 1.2 onlynoneEngineering interoperability with development EVCC simulators; never production
any of the above plus --allow-engineering-tls-identityas selectedas selectedas selectedRequired when the server identity comes from evse tls-material-init (subject marked "ENGINEERING ONLY"); without it the listener refuses to start. Development and test only.

PEM aliases: --cert, --key, --ca; --tls-pkcs12 for --tls-pfx. Passwords belong in --tls-pfx-password-env, never on the command line. The complete certificate requirements are in TLS, PKI and Plug & Charge.

Lifecycle and role locks

Every listener owns a session directory under the runtime root and an active role lock:

<runtime-root>\sessions\<run-id>\state.json      protocol, profile, host, ports, status
<runtime-root>\sessions\<run-id>\pid.json        process id and executable
<runtime-root>\sessions\<run-id>\lock.json       session lock, stale_after_ms 300000
<runtime-root>\sessions\<run-id>\heartbeat.json  sequence and last heartbeat time
<runtime-root>\sessions\<run-id>\lifecycle.log   starting / running / stopped lines
<runtime-root>\sessions\<run-id>\stop.flag       written by evse stop
<runtime-root>\active\evse.lock.json             one EVSE at a time per runtime root

Only one EVSE session can be live per runtime root. A second evse start fails with CL-RUNTIME-001 while the lock is held. A session becomes stale when its PID is gone or the heartbeat is older than 300 s; stale sessions are inspectable but do not block a new start after recovery.

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse status                      # the active session (or --run-id X)
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse list-state
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime list --role evse
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime inspect --run-id <RUN_ID>
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime locks
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse stop --run-id <RUN_ID>        # writes stop.flag; the listener exits at its next heartbeat
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime recover --stale-only --dry-run
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json runtime recover --stale-only       # release locks of dead sessions

Never delete runtime files by hand while a listener is running. evse live-preflight --recover-stale performs the same recovery as part of the preflight.

Evidence produced by a listener

File (under the run directory)Content
command_result.jsonThe JSON result of the command, as printed.
evse_listener_status.json, evse_runtime_status.json, live_runtime_status.jsonBound ports, advertised address, stop reason, runtime state.
sdp_diagnostics.jsonSDP requests received and responses sent.
tls_handshake_diagnostics.jsonNegotiated version, cipher, peer certificate metadata (fingerprints, no bodies).
session_handshake_artifact_gate.jsonRequired versus observed states and messages; status passed, attention_required, failed or not_evaluated.
traces\evse-listener.jsonl, traces\live-v2gtp-frames.jsonlChronological listener events and every V2GTP frame with direction, payload type, length and decode verdict.
protocol\*-live-stack-evidence.jsonLane-specific evidence (for example ISO 15118-2 AC/DC and PnC).
manifest.jsonInventory with SHA-256 per file and redaction class.

Evaluate a run with evse live-closure-gate --run-id X --source external-evcc --require-sdp --require-tcp-peer --require-tls --require-v2gtp --require-exi. Each --require-* flag turns a missing observation into a gate failure.

Diagnostic lanes without a peer

These commands write evidence from built-in fixtures and are useful for regression and support cases:

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse listener-policy
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse external-evcc-session-policy       # the activation catalog for every protocol
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse iso20-setup-path --write-artifacts
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse iso20-dc-charge-loop-path --write-artifacts
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse iso20-completion-pass --write-artifacts
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse iso2-setup-path --write-artifacts
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse din70121-dc-setup-path --write-artifacts
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse legacy-hlc-completion-pass --protocol all --energy-mode all --write-artifacts
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse tls-pki-doctor --tls --tls-cert C --tls-key K --tls-cafile CA --require-ca
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse live-closure-plan --advertise-ipv6 $Advertise --interface-index $IfIndex

Safety rule for physical benches

The reference-responder lanes never command a power stage. The plant-coupled lane commands a simulated plant through the VeriStand owner host, whose safe start-up profile keeps the contactor open and current at zero until the protocol and the safety inputs (Safety.InterlockClosed, Safety.IsolationValid, Safety.EmergencyStop) permit closure, and which fails safe on watchdog expiry. Any coupling to real power electronics is outside the software and requires its own safety design.