Set Up the VeriStand Bench
This guide takes PC1 (charger and NI VeriStand) and PC2 (vehicle) from a fresh Windows installation to a validated bench, using only the files and scripts in ChargeLink-0.5.0-rc2-bench-kit-win64.zip. Nothing is built or generated in VeriStand: the system definition and plant model are delivered ready to deploy, and the owner host deploys them for every session. What each file is, and how a session then runs, is on the NI VeriStand Bench page.
Before you start
Have ready (details in Prerequisites):
- PC1: Windows 11 Pro x64 with at least 13 logical processors, NI VeriStand 2024 Q4 installed and licensed, the .NET 10 runtime x64, the Microsoft Visual C++ 2015-2022 Redistributable x64, and 20 GB free disk space.
- PC2: Windows 10 or 11 x64 with Windows PowerShell 5.1 and the Visual C++ 2015-2022 Redistributable x64.
- One Ethernet adapter on each PC for the direct PC1-PC2 link, IPv6 enabled. Note each adapter's name (
Get-NetAdapter). - The package ZIP and its
ChargeLink-0.5.0-rc2-bench-kit-win64.zip.sha256file. - Either your own ISO 15118-20 Annex B certificates and keys for both PCs, or the decision to generate the engineering bench PKI in step 3.
The package's docs\INSTALL-PC1.md and docs\INSTALL-PC2.md contain the same steps.
Step 1 — check NI VeriStand and .NET on PC1
Get-FileHash 'C:\Program Files\National Instruments\VeriStand 2024\veristand-server.exe','C:\Program Files\National Instruments\VeriStand 2024\NationalInstruments.VeriStand.SystemDefinitionAPI.dll'
dotnet --list-runtimes
Compare the two hashes with the table in docs\INSTALL-PC1.md, section 1. A different NI build is not the environment the bench was verified with; record the difference before relying on a result. dotnet --list-runtimes must list Microsoft.NETCore.App 10.0.x. New-BenchConfiguration.ps1 also checks that veristand-server.exe and NationalInstruments.VeriStand.ClientAPI.dll exist in the VeriStand folder.
Step 2 — unpack and verify the package on PC1
Verify the archive against its .sha256 file, unpack it to a local folder without spaces, and check every file:
Get-FileHash 'C:\Downloads\ChargeLink-0.5.0-rc2-bench-kit-win64.zip' -Algorithm SHA256
Get-Content 'C:\Downloads\ChargeLink-0.5.0-rc2-bench-kit-win64.zip.sha256'
Expand-Archive 'C:\Downloads\ChargeLink-0.5.0-rc2-bench-kit-win64.zip' -DestinationPath 'C:\ChargeLink\0.5.0-rc2'
cd C:\ChargeLink\0.5.0-rc2
Get-Content .\manifest\SHA256SUMS | ForEach-Object {
$hash, $path = $_ -split ' ', 2
if ((Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ne $hash.ToUpperInvariant()) { throw "Changed: $path" }
}
'all files verified'
If the ZIP contains a top-level ChargeLink-0.5.0-rc2-bench-kit-win64 folder, run the check inside it and use that folder in place of C:\ChargeLink\0.5.0-rc2 below. If docs\SIGNING.md says the package is signed, also check Get-AuthenticodeSignature .\pc1\bin\chargelink.exe.
Step 3 — TLS material
ISO 15118-20 requires mutual TLS 1.3 with the certificate profiles of ISO 15118-20 Annex B. Choose one of the two ways.
A. The engineering bench PKI (engineering and test use only)
Run this once on PC1, from a working folder outside the package (the CLI keeps its runtime state in .chargelink under the current folder). The output folder must not exist yet:
New-Item -ItemType Directory -Force C:\ChargeLink\work | Out-Null; cd C:\ChargeLink\work
C:\ChargeLink\0.5.0-rc2\pc1\bin\chargelink.exe evse tls-material-init --bench-pki --output-dir C:\ProgramData\DEVlink\ChargeLink\tls\engineering-pki
It writes new keys and certificates on every run, readable only by their owner and SYSTEM, and prints no key:
| File in the output folder | Used by |
|---|---|
pc1\secc-cert-chain.pem, pc1\secc-key.pem, pc1\v2g-root-ca.pem | PC1, through New-BenchConfiguration.ps1 -EngineeringPki (step 5) |
pc2\vehicle-cert-chain.pem, pc2\vehicle-key.pem, pc2\v2g-root-ca.pem | PC2: copy them unchanged into the pc2\tls folder (step 7) |
engineering-pki-manifest.json, README-ENGINEERING-ONLY.txt | your record (fingerprints, validity, file hashes; no key) |
Every certificate carries the subject O ChargeLink ENGINEERING ONLY - not for production. The SECC accepts it only when the bench configuration allows it, which -EngineeringPki does. The root and sub-CA keys are discarded when the command ends, and there is no revocation service for this PKI. To replace the material, generate into a new folder, run step 5 again with -Force, and copy the new pc2 files to PC2.
B. Your own PKI
| File (your names) | Role | Used by |
|---|---|---|
| SECC certificate chain (PEM, leaf first) | SECC identity, Annex B profile | PC1 -TlsCertChain |
| SECC private key (PEM) | SECC leaf key | PC1 -TlsKey |
| Trust anchor for vehicle certificates (PEM) | root the EVCC chain validates to | PC1 -TlsTrustAnchor |
| V2G root (PEM) | root the SECC chain validates to | PC2 pc2\tls\v2g-root-ca.pem |
| Vehicle certificate chain and key (PEM) | EVCC identity, Annex B vehicle profile | PC2 pc2\tls\vehicle-cert-chain.pem, pc2\tls\vehicle-key.pem |
Keep the PC1 files outside the package folder, for example in C:\ProgramData\DEVlink\ChargeLink\tls\pc1, readable only by the operator account.
Step 4 — firewall on PC1 (administrator, once)
The SECC answers SDP on UDP 15118 and accepts TLS on TCP 50118, on the link adapter only. Replace the adapter name and, if different, the package path:
$alias = 'Ethernet 3'; $exe = 'C:\ChargeLink\0.5.0-rc2\pc1\bin\chargelink.exe'
New-NetFirewallRule -DisplayName 'DEVlink ChargeLink EVSE SDP UDP 15118' -Direction Inbound -Action Allow -Profile Any -InterfaceAlias $alias -Protocol UDP -LocalPort 15118 -RemoteAddress 'fe80::/10' -Program $exe
New-NetFirewallRule -DisplayName 'DEVlink ChargeLink EVSE TCP' -Direction Inbound -Action Allow -Profile Any -InterfaceAlias $alias -Protocol TCP -LocalPort 50118 -RemoteAddress 'fe80::/10' -Program $exe
New-NetFirewallRule -DisplayName 'DEVlink ChargeLink ICMPv6 Diagnostics' -Direction Inbound -Action Allow -Profile Any -InterfaceAlias $alias -Protocol ICMPv6 -IcmpType 128 -RemoteAddress 'fe80::/10'
The rules name the executable by path; create them again if the package folder moves. The gRPC service the owner host starts listens on 127.0.0.1:50051 only and needs no rule.
Step 5 — bench configuration on PC1
Record the link adapter, the TLS files and the NI folder once, from pc1. With the engineering bench PKI:
cd C:\ChargeLink\0.5.0-rc2\pc1
powershell -NoProfile -ExecutionPolicy Bypass -File .\New-BenchConfiguration.ps1 -InterfaceAlias 'Ethernet 3' `
-EngineeringPki C:\ProgramData\DEVlink\ChargeLink\tls\engineering-pki
It prints a warning that the bench runs with engineering material. With your own PKI:
powershell -NoProfile -ExecutionPolicy Bypass -File .\New-BenchConfiguration.ps1 -InterfaceAlias 'Ethernet 3' `
-TlsCertChain C:\ProgramData\DEVlink\ChargeLink\tls\pc1\secc-cert-chain.pem `
-TlsKey C:\ProgramData\DEVlink\ChargeLink\tls\pc1\secc-key.pem `
-TlsTrustAnchor C:\ProgramData\DEVlink\ChargeLink\tls\pc1\v2g-root-ca.pem
The script reads the adapter's interface index and its preferred IPv6 link-local address, checks the NI files and the TLS files, and writes pc1\bench-configuration.json. It prints the address PC2 connects to; note it. Further parameters: -VeriStandDir (default C:\Program Files\National Instruments\VeriStand 2024), -RunsRoot (default runs next to pc1), -Force to replace an existing file. Run it again with -Force whenever the adapter or the TLS files change: a link-local address can change when the adapter is reinstalled.
Step 6 — validate on PC1
powershell -NoProfile -ExecutionPolicy Bypass -File .\Start-SeccSession.ps1 -ValidateOnly
powershell -NoProfile -ExecutionPolicy Bypass -File .\Start-SeccSession.ps1 -Mode Manual -ValidateOnly
Each renders one run's native.json and campaign-configuration.json from pc1\templates and has the owner host check them. It starts no VeriStand runtime and no listener. Both must print Configuration accepted by the owner host.
Step 7 — install the EVCC on PC2
- Copy the package's
pc2folder to PC2, for example toC:\ChargeLinkExternalEvcc, together with a copy ofmanifest\SHA256SUMS, and check the sixpc2/files:cd C:\ChargeLinkExternalEvcc Get-Content .\SHA256SUMS | Where-Object { $_ -match ' pc2/' } | ForEach-Object { $hash, $path = $_ -split ' ', 2 $local = $path.Substring(4) if ((Get-FileHash -LiteralPath $local -Algorithm SHA256).Hash -ne $hash.ToUpperInvariant()) { throw "Changed: $local" } } 'pc2 files verified' - TLS files. Place
vehicle-cert-chain.pem,vehicle-key.pemandv2g-root-ca.peminpc2\tls(seepc2\tls\README.txt). With the engineering bench PKI, these are the three files from itspc2folder, copied unchanged, for example with a removable drive (delete the copy on the drive afterwards). Copy them again whenever PC1's material is regenerated. Restrictpc2\tlsto the operator account. - Firewall (administrator, once), if the Windows firewall filters outbound traffic on PC2:
$alias = 'Ethernet 3'; $exe = 'C:\ChargeLinkExternalEvcc\chargelink.exe' New-NetFirewallRule -DisplayName 'DEVlink ChargeLink EVCC SDP UDP 15118' -Direction Outbound -Action Allow -Profile Any -InterfaceAlias $alias -Protocol UDP -RemotePort 15118 -RemoteAddress 'ff02::1' -Program $exe New-NetFirewallRule -DisplayName 'DEVlink ChargeLink EVCC TCP' -Direction Outbound -Action Allow -Profile Any -InterfaceAlias $alias -Protocol TCP -RemotePort '49152-65535' -RemoteAddress 'fe80::/10' -Program $exe New-NetFirewallRule -DisplayName 'DEVlink ChargeLink ICMPv6 Diagnostics' -Direction Inbound -Action Allow -Profile Any -InterfaceAlias $alias -Protocol ICMPv6 -IcmpType 128 -RemoteAddress 'fe80::/10' - EV cases.
Start-Evcc.ps1setsCHARGELINK_ISO20_LIVE_SEMANTIC_CASEtocases\nominal.json(-Case Nominal, the default) orcases\emergency-transition.json(-Case EmergencyTransition), andCHARGELINK_ISO20_FULL_WIRE_SESSION_MANIFESTtocases\full-wire-session-manifest.json. The EVCC refuses a live session without them. Do not edit them.
Step 8 — check the link
Start a session on PC1 (Start-SeccSession.ps1, see Running a session) so that the SECC listens, then probe it from PC2 without starting an ISO 15118 session:
cd C:\ChargeLinkExternalEvcc
powershell -NoProfile -ExecutionPolicy Bypass -File .\Start-Evcc.ps1 -PeerIpv6 fe80::xxxx:xxxx:xxxx:xxxx -InterfaceAlias 'Ethernet 3' -ProbeOnly -WaitSeconds 60
-PeerIpv6 is the address step 5 printed, without the % zone; the launcher scopes it to PC2's own adapter. The launcher's defaults for -PeerIpv6 and -InterfaceAlias are placeholders: pass both every time, or edit the two defaults in Start-Evcc.ps1 once for this bench (its SHA-256 then differs from the manifest, which is expected; record the change). The probe opens and closes one TCP connection. The SECC waits for the EVCC only for its phase timeout (120 s in automation mode), so let that PC1 run end before the first real session.
The bench is ready. Continue with Running a session.
Troubleshooting the setup
| Message or symptom | Cause | Action |
|---|---|---|
Changed: <path> during verification | A file differs from manifest\SHA256SUMS | Unpack the verified ZIP again; do not run a changed package. |
Expected exactly one connected adapter named '…' | Wrong adapter name, or the link is down | Check Get-NetAdapter; connect the cable; pass the exact name. |
Expected exactly one preferred IPv6 link-local address on '…' | IPv6 disabled on the adapter, or the address is not ready yet | Enable IPv6 on the adapter; check Get-NetIPAddress -InterfaceAlias '…' -AddressFamily IPv6. |
NI VeriStand file missing: … | VeriStand 2024 not installed, or installed elsewhere | Install NI VeriStand 2024 Q4, or pass -VeriStandDir. |
… bench-configuration.json exists; pass -Force to replace it. | The bench is already configured | Add -Force if you mean to replace it. |
No engineering PKI at … (engineering-pki-manifest.json missing) | -EngineeringPki points to the wrong folder | Pass the folder given to --output-dir in step 3. |
… is ChargeLink engineering material, which the SECC refuses unless allowed … | Engineering certificates passed as your own PKI | Use -EngineeringPki <folder> instead of the three TLS parameters. |
… holds no PEM private key, … must not contain a private key, … holds no PEM certificate | TLS files swapped or in the wrong format | Pass the chain, key and trust anchor to the matching parameters, PEM encoded. |
Warning: TLS file is inside the kit folder | Key material stored in the package folder | Move it outside the package folder and run step 5 again with -Force. |
The owner host did not accept the configuration … in step 6 | A path or value in the rendered configuration is wrong, or the .NET 10 runtime is missing | Read <run>\validation.log; check step 1; run step 5 again. |
Probe: SECC did not accept connections within … s | No session listening on PC1, a wrong address or adapter, or missing PC1 firewall rules | Start a PC1 session first; check the address, the adapter names and the rules from step 4. |
Session-time problems are covered in NI VeriStand Bench, Troubleshooting.
Uninstalling
Delete the package folder and runs_root; remove the firewall rules (Remove-NetFirewallRule -DisplayName 'DEVlink ChargeLink*') on both PCs; delete %ProgramData%\DEVlink\ChargeLink\RuntimeOwnership\native-activation.state on PC1; and destroy the TLS keys (for the engineering bench PKI: its output folder on PC1 and the pc2\tls files on PC2).

