ChargeLink

ISO 15118-2

ChargeLink plays both roles of ISO 15118-2 (2014) for AC and DC EIM sessions, over IPv6 SDP, TCP or TLS 1.2 with server authentication, V2GTP and EXI. As vehicle, ChargeLink runs one session against your charger: iso2-evcc for DC, iso2-ac-evcc for AC. As charger, ChargeLink runs plant-coupled on the NI VeriStand bench for AC and DC; for DC there is also a generic listener that answers the message sequence without a plant.

Before you start

RequirementWhat you need
HardwareA Windows PC for ChargeLink with an Ethernet adapter on the link to the other side. For the plant-coupled charger: the NI VeriStand bench of the package. A powerline (PLC) link needs the hardware described in Connecting to Real PLC Hardware.
NetworkIPv6 enabled on that adapter; link-local addresses (fe80::/10), no router. UDP 15118 (SDP) and the TCP port of the session (default 50118) open in Windows Firewall for fe80::/10 (Install and Activate). Run the preflight.
LicenceAn active ChargeLink licence on the ChargeLink PC (chargelink --json license status). A command that needs it stops with exit code 20 (CL-LICENSE-001).
TLS materialOptional. EIM runs on TLS 1.2 with server authentication (the charger presents a private-environment identity that the vehicle trusts) or on plain TCP in a trusted environment. As charger: a SECC chain and key (iso2-pki generates an engineering set), or for the generic listener with Windows SChannel a PKCS#12 (PFX) identity. As vehicle: the private operator root the charger's chain validates to. See TLS and PKI.
$CL   = 'C:\Program Files\DEVlink\ChargeLink\<VERSION>\charger\bin\chargelink.exe'
$Data = "$env:ProgramData\DEVlink\ChargeLink\data"
$IfIndex   = <INTERFACE_INDEX>
$Advertise = 'fe80::<ADDRESS>%' + $IfIndex
$Pki       = "$Data\pki"

The kit has a charger\ and a vehicle\ folder; chargelink.exe is the same binary in both.

# engineering TLS identity for the private environment (SECC chain and key, private root); the folder must not exist
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json iso2-pki --output-dir "$Data\pki\iso2"

ChargeLink as charger

ChargerProfile IDWhat it does
DC, plant-couplediso15118_2_dc_eimFull DC EIM session on the NI VeriStand bench; the plant values come from the bench. Needs --plant-grpc-endpoint, --requested-power-kw and --target-voltage-v.
AC, plant-couplediso15118_2_ac_eimFull AC EIM session on the NI VeriStand bench. Needs --plant-grpc-endpoint.
DC, generic listeneriso15118_2_dc_evse_reference (aliases iso2-dc-eim-nominal, dc_fast); with SChannel TLS iso2-dc-eim-tls-schannelAnswers the message sequence with scripted replies and no plant (no contactor, no energy). Protocol exchange only.

The plant-coupled AC and DC chargers are verified with the ChargeLink vehicle on the VeriStand bench.

Plant-coupled charger (AC and DC)

The charger runs on the NI VeriStand bench, coupled to the bench's plant endpoint. The session has this shape (DC shown; for AC use --profile-id iso15118_2_ac_eim with the same power and voltage targets):

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse start --run-id $Run `
  --protocol iso15118-2 --profile-id iso15118_2_dc_eim `
  --plant-grpc-endpoint <BENCH_PLANT_ENDPOINT> --requested-power-kw <kW> --target-voltage-v <V> `
  --host '::' --interface-index $IfIndex --advertise-ipv6 $Advertise `
  --tls --tls-cert "$Data\pki\iso2\secc-chain.pem" --tls-key "$Data\pki\iso2\secc-key.pem" --allow-engineering-tls-identity

Leave out the --tls options for plain TCP. --allow-engineering-tls-identity is needed with the engineering identity from iso2-pki.

Generic listener (DC)

The generic listener answers your vehicle's DC EIM requests with scripted replies. It checks discovery, transport, optional TLS, V2GTP framing and message sequencing; it has no plant and delivers no energy, and it is not for full sessions.

$Run = "iso2-dc-$(Get-Date -Format yyyyMMdd-HHmmss)"

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse live-preflight --source external-evcc `
  --protocol iso15118-2 --profile-id iso15118_2_dc_evse_reference `
  --host '::' --tcp-port 50118 --udp-port 15118 `
  --advertise-ipv6 $Advertise --interface-index $IfIndex --recover-stale

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse start --external-evcc-session --run-id $Run `
  --protocol iso15118-2 --profile-id iso15118_2_dc_evse_reference `
  --host '::' --tcp-port 50118 --udp-port 15118 `
  --advertise-ipv6 $Advertise --interface-index $IfIndex `
  --max-runtime-ms 1800000 --heartbeat-interval-ms 1000

TLS 1.2 with Windows SChannel and a PKCS#12 identity: keep the PFX password out of shell history with an environment variable.

$env:CHARGELINK_PFX_PASSWORD = Read-Host 'PFX password'

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse start --external-evcc-session --run-id $Run `
  --protocol iso15118-2 --profile-id iso2-dc-eim-tls-schannel `
  --host '::' --tcp-port 50118 --udp-port 15118 `
  --advertise-ipv6 $Advertise --interface-index $IfIndex `
  --tls --external-evcc-windows-tls `
  --tls-pfx "$Pki\secc-identity.pfx" --tls-pfx-password-env CHARGELINK_PFX_PASSWORD `
  --max-runtime-ms 1800000

--external-evcc-windows-tls is an alias for --tls-adapter windows-schannel-external-evcc --tls-sni-policy external-evcc-windows-schannel. Without SChannel, --tls --tls-cert --tls-key --tls-cafile uses the built-in TLS adapter.

What a good session looks like

Watch from a second window with evse status --run-id $Run. In the run folder <artifact-root>\<run-id>\, after the session:

  • evse_listener_status.json reads "status": "stopped"; stop_reason says how it stopped.
  • The last row of traces\live-v2gtp-frames.jsonl is the outbound SessionStopRes.
  • command_result.json reads "session_status": "stopped".
  • An AC session also writes protocol\iso2_ac_frames.jsonl.

Do not judge an ISO 15118-2 run by summary.json. For ISO 15118-2, the "status" in summary.json can read "attention_required" after a good session. Read the result in evse_listener_status.json and command_result.json instead.

ChargeLink as vehicle

Your DUT is a charger or SECC. Connect it to the ChargeLink PC's adapter. The vehicle discovers your charger by SDP, connects over TLS 1.2 (server authentication) or TCP, and runs one session: iso2-evcc for DC EIM, iso2-ac-evcc for AC EIM.

DC EIM: iso2-evcc

# discover the charger by SDP, TLS 1.2, 20 CurrentDemandReqs
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json iso2-evcc --sdp-server "[fe80::<CHARGER_ADDRESS>%$IfIndex]:15118" `
  --tls --tls-root "<PRIVATE_ROOT_OF_THE_CHARGER>.pem" `
  --current-demands 20 --target-voltage-v 400 --target-current-a 100 --run-id iso2-ev-<DATE> --artifact-root "$Data\artifacts"

# without SDP, plain TCP, straight to the charger port
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json iso2-evcc --peer "[fe80::<CHARGER_ADDRESS>%$IfIndex]:<SECC_TCP_PORT>" --current-demands 0 --run-id iso2-ev-<DATE>
OptionMeaning
--sdp-server / --peerDiscover the charger through SDP (its UDP socket, [<charger link-local>%<interface>]:15118), or connect to its TCP or TLS port directly.
--tls, --tls-root FILETLS 1.2 with the cipher suites of ISO 15118-2; without --tls EIM runs on TCP. --tls-root names the private operator root(s) the charger chain must validate to (repeatable).
--current-demands N, --period-msCurrentDemandReqs before the vehicle stops (0: until the charger stops) and their period (default 50 ms).
--renegotiate-after NAfter N CurrentDemands the vehicle renegotiates once.
--pause, --resume-session-id HEXEnd with SessionStop Pause instead of Terminate; resume a paused session by its SessionID.
--target-voltage-v, --target-current-a, --max-voltage-v, --max-current-aThe vehicle's targets and limits (defaults 400 V, 100 A, 920 V, 200 A).
--connect-timeout-msConnection timeout (default 2000 ms).
--run-id, --artifact-rootRun ID and the folder the run folder is written to.

AC EIM: iso2-ac-evcc

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json iso2-ac-evcc --sdp-server "[fe80::<CHARGER_ADDRESS>%$IfIndex]:15118" `
  --tls --tls-root "<PRIVATE_ROOT_OF_THE_CHARGER>.pem" `
  --energy-transfer-mode ac-three-phase --ev-max-current-a 16 --charging-statuses 20 --run-id iso2-ac-ev-<DATE> --artifact-root "$Data\artifacts"
OptionMeaning
--sdp-serverThe charger's SDP socket, [<charger link-local>%<interface>]:15118. The vehicle discovers the charger by SDP, then runs one session.
--tls, --tls-root FILETLS 1.2 with server authentication against the private root; without --tls EIM runs on TCP.
--energy-transfer-mode ac-three-phase|ac-single-phaseThe AC energy transfer mode the vehicle requests.
--ev-max-current-a AThe vehicle's maximum current per phase (default 16).
--charging-statuses NChargingStatus exchanges before the vehicle stops.
--run-id, --artifact-rootRun ID and the folder the run folder is written to.

What a good session looks like

  • The command exits with code 0.
  • <artifact-root>\<run-id>\iso2_evcc_report.json reads "passed": true, with run.session.outcome = {"outcome": "ended", "end": "stopped", "charging_session": "Terminate"}.
  • The frames are in traces\live-v2gtp-frames.jsonl.

The reference vehicle profiles (iso15118_2_dc_evcc_reference, iso15118_2_ac_evcc_reference, iso15118_2_dc_evcc_aged_demo) send a ChargeLink-specific encoding that a real charger does not decode. Use them only for evcc start --dry-run and the deterministic simulation. Deterministic simulation for ISO 15118-2 and DIN 70121 is available on request through DEVlink support.

Results and evidence

Each run writes one folder under the artifact root, $Data\artifacts\<run-id>. Stop the charger, then check the evidence:

chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json evse stop --run-id $Run
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json artifacts integrity --run-id $Run

Judge the charger run by evse_listener_status.json and command_result.json, and the vehicle run by iso2_evcc_report.json (see the good-session lists above). artifacts integrity confirms that no file changed after the run. See Trace, Evidence and Reports. The ISO 15118-4 test-case identifiers are available for campaign work in the Test Workflow.

In DEVlink's own interoperability tests, ChargeLink's ISO 15118-2 charger and vehicle (AC and DC, TLS 1.2 and TCP) completed sessions with an independent open-source ISO 15118 implementation. This is not certification.

Limits

  • External Payment (EIM) only. ChargeLink does not provide Plug & Charge (Contract payment, PaymentDetails, CertificateInstallation/Update): evse start refuses an ISO 15118-2 profile whose ID names it (pnc, contract or plug) with exit code 70 (CL-UNSUPPORTED-001) before any socket opens.
  • The charging session of the charger role runs plant-coupled on the NI VeriStand bench, for AC and DC. It is verified with the ChargeLink vehicle.
  • The DC generic listener answers with scripted replies and has no plant: no contactor, no energy, protocol exchange only. Its reply order has a known limitation, so it is not for full sessions and must not be used to control a power stage. There is no AC generic listener.
  • As vehicle, if your charger sends no MeterInfo, that check is not judged.
  • For ISO 15118-2, summary.json can read "attention_required" after a good session; read evse_listener_status.json and command_result.json.
  • No physical charging interface (PLC, control pilot, power stage) is included.

See Capability Boundaries. To check the installation without a DUT, see Self-test without a device under test.

Troubleshooting

SymptomUsually meansAction
summary.json reads attention_required after a session that looked goodExpected for ISO 15118-2Read evse_listener_status.json and command_result.json, or iso2_evcc_report.json on the vehicle side.
TLS fails with a TLS 1.2 ECDSA vehicle on the generic listenerThe built-in TLS adapter or the wrong identity is in useUse --external-evcc-windows-tls with a PFX identity; check tls_handshake_diagnostics.json.
Exit 10, CL-CONFIG-001, at evse start with SChannelThe PFX password variable is emptySet CHARGELINK_PFX_PASSWORD in the same shell before the command.
Exit 70, CL-UNSUPPORTED-001The profile ID names Plug & ChargeUse an EIM profile from the table above.
evse start refuses iso15118_2_dc_eim or iso15118_2_ac_eimThe plant-coupled profile needs --plant-grpc-endpointRun it on the NI VeriStand bench with the bench's plant endpoint.
Your vehicle rejects a reply from the generic listenerThe known reply-order limitation of the generic listenerUse the plant-coupled charger for full sessions; keep the trace for DEVlink support.
iso2-evcc or iso2-ac-evcc exits non-zeroThe session did not end as askedRead run in iso2_evcc_report.json and the last frames in traces\live-v2gtp-frames.jsonl.
Your charger does not decode ChargeLink's vehicle messagesAn evcc start reference profile was usedUse iso2-evcc or iso2-ac-evcc.
iso2-pki failsThe output folder existsName a new folder; the files must not exist.

General failures (licence, ports, firewall, role locks) are in Troubleshooting.