ChargeLink

gRPC Integration API

The Integration API (chargelink.integration.v1, version 1.8.0) is the stable automation interface of ChargeLink for your own automation clients; the NI VeriStand bench uses it too. It is served by chargelink integration serve as plaintext HTTP/2 gRPC on 127.0.0.1:50051.

Start the server

The kit has a charger\ and a vehicle\ folder; the CLI is charger\bin\chargelink.exe.

$CL   = 'C:\Program Files\DEVlink\ChargeLink\<VERSION>\charger\bin\chargelink.exe'
$Data = "$env:ProgramData\DEVlink\ChargeLink\data"
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. StartSession then starts a charger listener for it and answers RUNNING only once the listener is ready; Session.listener, GetProtocolState and both event streams report the listener's state (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. Every CLI command with --endpoint or --grpc-endpoint reads the file named by CHARGELINK_API_TOKEN_FILE, or <runtime-root>\integration\api-token when the variable is unset. On the NI VeriStand bench, the owner host handles the token itself. 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

CommandExercisesOutput
integration session-smokeCreate, start, stop, delete a session recordsession ID and states
integration full-smoke --evidence-source DIRThe baseline services with a supplied evidence directory or manifestreport
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-smokeVendor-neutral HIL adapter SDK with the deterministic hardware simulator: lifecycle, mapping, calibration, sync, faults, interlocks, emergency stop, evidencehil-smoke directory
integration xil-smokeASAM XIL bridge reference (Framework, MAPort, EESPort) with the deterministic reference providerxil-smoke directory
integration factory-smokeFactory/EOL station, recipe, measurement, disposition, label and evidencefactory-smoke directory
integration enterprise-smokeEditions, RBAC, service identities, sealed secrets, audit chain, fleet, signed updates, rollback (reference implementation)enterprise-smoke directory
integration compatibilityAPI compatibility of the installed releasereport

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 exercise the service workflows with reference implementations, not physical equipment.

Services

14 services: HealthService, ConfigurationService, SessionService, ProtocolService, SignalService, TimeService, SilService, HilService, XilService, TestCampaignService, EvidenceService, ReportService, FactoryService and EnterpriseService. 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

  1. Obtain integration.proto (package chargelink.integration.v1) for the installed release from your ChargeLink delivery or from the schemas/docs directory of the package.
  2. Generate a client with your language's gRPC tooling (protoc, grpcio-tools, grpc-dotnet, and so on).
  3. Call HealthService.GetHealth and GetCapabilities first and compare api_version with the version you generated against. Minor versions are additive. This manual documents API version 1.8.0. On the NI VeriStand bench, use the owner host and chargelink.exe from the same release; components of different releases refuse each other.
  4. Use the CLI smokes as reference behaviour: if session-smoke passes and your client fails, the difference is in the client.

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

SymptomCheckAction
integration health failsGet-Process chargelink; Test-NetConnection 127.0.0.1 -Port 50051; netstat -ano | findstr :50051Start the server; fix the endpoint or the port owner
Health passes, your client failssession-smoke, signals smokeCompare request shapes and API version; capture the client's error
GetProtocolState is unobservedthe session carries no "listener" objectExpected 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 stalePoint 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-rootUse the same state root on every start