gRPC Integration API
The Integration API (chargelink.integration.v1, version 1.8.0) is the stable automation boundary of ChargeLink Native. The CLI, the NI VeriStand owner host and your own automation clients all use it. It is served by chargelink integration serve as plaintext HTTP/2 gRPC on 127.0.0.1:50051.
Start the server
$CL = 'C:\ChargeLink\0.5.0-rc2\pc1\bin\chargelink.exe'
$Data = 'C:\ChargeLinkData'
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" `
integration serve --listen 127.0.0.1:50051 --state-root "$Data\runtime\integration"
Keep the window open; the process runs in the foreground and stops with Ctrl+C. --state-root defaults to <runtime-root>\integration. There is no Windows service wrapper; run the server from a dedicated shell, a scheduled task or your own supervisor. Bind only to loopback unless the network design in Production Security is in place.
Verify from the CLI
$EP = 'http://127.0.0.1:50051'
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json integration health --endpoint $EP
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json integration capabilities --endpoint $EP
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json integration session-smoke --endpoint $EP --protocol iso15118-2 --role evse
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json signals list --endpoint $EP
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json signals smoke --endpoint $EP
Expected: health_status: serving, api_version: 1.8.0, product ChargeLink Native; capabilities with 19 capability entries (each with enabled and a claim_boundary), the protocol list, max_page_size 1000, max_signal_batch_size 512 and 94 canonical signals. integration capabilities without --endpoint answers in embedded mode without a server.
The capability bound-live-protocol-observer: a session whose configuration_json carries a "listener" object is bound. SessionService.Start then launches chargelink evse start --external-evcc-session for it and answers RUNNING only once the listener is ready; Session.listener, GetProtocolState and both event streams report the state derived from the listener's own evidence (requested, listener ready, peer connected, protocol running, protocol ended, protocol failed). Unknown keys in the listener object are refused, a bound listener reports only the first protocol session of its run, and a stand-alone listener started from the CLI stays unbound (GetProtocolState = unobserved). None of this establishes electrical state.
Access token
At every start the server writes a new 256-bit random token to <state-root>\api-token (readable by the owner and SYSTEM only) before it opens the port, and every call must carry it as authorization: Bearer <token>; a missing or wrong token is answered UNAUTHENTICATED. ChargeLink's own clients (every CLI command with --endpoint or --grpc-endpoint, the operator bridge, the listener's plant client) read the file named by CHARGELINK_API_TOKEN_FILE, or <runtime-root>\integration\api-token when the variable is unset. The NI VeriStand owner host sets the variable for the processes it starts. A third-party client reads the file itself and adds the header. The server accepts only a loopback --listen address; a non-loopback address is refused with exit 40 before any token is written.
$env:CHARGELINK_API_TOKEN_FILE = "$Data\runtime\integration\api-token" # only when the state root differs from the runtime root default
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json integration health --endpoint $EP
Read and write canonical signals
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json signals list --endpoint $EP --namespace Vehicle
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json signals read --endpoint $EP --signal Vehicle.SocPct --signal Charger.PresentVoltageV --signal Protocol.SessionState
chargelink --runtime-root "$Data\runtime" --artifact-root "$Data\artifacts" --json signals write --endpoint $EP --signal Vehicle.SocPct=35 --signal Vehicle.TargetVoltageV=800
Signals are written as ID=VALUE; only bidirectional signals accept writes. The full dictionary with units and directions is on the VeriStand Signal Mapping page.
Built-in smokes
| Command | Exercises | Output |
|---|---|---|
integration session-smoke | Create, start, stop, delete a session record | session ID and states |
integration full-smoke --evidence-source DIR | The accepted baseline services with a supplied evidence directory or manifest | report |
integration sil-smoke [--ipv6-host ::1 --interface-index 0] | Deterministic time, both managed SIL roles over real IPv6 loopback networking, TLS/EXI, campaign bridge | .chargelink\integration\sil-smoke (or --output) |
integration hil-smoke | Vendor-neutral HIL adapter SDK with the deterministic hardware simulator: lifecycle, mapping, calibration, sync, faults, interlocks, emergency stop, evidence | hil-smoke directory |
integration xil-smoke | ASAM XIL bridge reference (Framework, MAPort, EESPort) with the deterministic reference provider | xil-smoke directory |
integration factory-smoke | Factory/EOL station, recipe, measurement, disposition, label and evidence | factory-smoke directory |
integration enterprise-smoke | Editions, RBAC, service identities, sealed secrets, audit chain, fleet, signed updates, rollback (deterministic reference cryptography) | enterprise-smoke directory |
integration compatibility | Protobuf compatibility and customer-selector policy | report |
Each smoke writes a report whose claim_boundary states what it proves. The SIL smoke is the closest thing to a full two-role protocol session without hardware; the HIL, XIL, factory and enterprise smokes prove orchestration contracts with deterministic reference implementations, not physical equipment.
Services
15 services: HealthService, ConfigurationService, SessionService, ProtocolService, SignalService, TimeService, SilService, HilService, XilService, TestCampaignService, EvidenceService, ReportService, FactoryService, EnterpriseService, ReleaseCandidateService. Every request carries a RequestContext (request_id, correlation_id, session_id, campaign_id, requested_api, idempotency_key) and every response a ResponseContext. The RPC list is in the Integration API Reference.
Write your own client
- Obtain
integration.proto(packagechargelink.integration.v1) for the installed release from your ChargeLink delivery or from theschemas/docsdirectory of the package. - Generate a client with your language's gRPC tooling (protoc, grpcio-tools, grpc-dotnet, tonic, and so on).
- Call
HealthService.GetHealthandGetCapabilitiesfirst and compareapi_versionwith the version you generated against. Minor versions are additive (1.0 baseline, 1.1, 1.2 HIL, 1.3 XIL, 1.4 factory, 1.5 enterprise, 1.6, 1.7 listener binding, 1.8 host-monotonic stamps). This manual documents API version 1.8.0; a client, an owner host and a SECC from different releases refuse each other. - Use the CLI smokes as reference behaviour: if
session-smokepasses and your client fails, the difference is in the client.
The VeriStand owner host uses a JSON-lines stdio bridge instead of a generated client: chargelink veristand operator-bridge --endpoint $EP reads commands (health, create_session, start_session, stop_session, get_session, read_signals, write_signals) on stdin and answers on stdout. It is started and supervised by the owner host and is useful for diagnostics only.
Security boundary
The management API is local only: loopback addresses, a per-start bearer token, no TLS transport. The token protects the API from other local accounts and from processes that cannot read the state root; it does not protect against the account that runs ChargeLink or an administrator. Remote access is not offered; do not expose the port through a proxy or tunnel. EnterpriseService.EvaluateAuthorization exists as an RPC but is not enforced on other calls.
Troubleshooting
| Symptom | Check | Action |
|---|---|---|
integration health fails | Get-Process chargelink; Test-NetConnection 127.0.0.1 -Port 50051; netstat -ano | findstr :50051 | Start the server; fix the endpoint or the port owner |
| Health passes, your client fails | session-smoke, signals smoke | Compare request shapes and API version; capture the client's error |
GetProtocolState is unobserved | the session carries no "listener" object | Expected for a CLI-started or unbound listener; bind the session or read the listener's artifacts |
CL-RUNTIME-001, "does not have valid authentication credentials" | token file missing, unreadable or stale | Point CHARGELINK_API_TOKEN_FILE at the running server's <state-root>\api-token; the file changes at every server start |
| State lost after restart | --state-root | Use the same state root on every start |

