---
title: "Diagnostics over UDS, DoIP and VCIs"
---

# Diagnostics over UDS, DoIP and VCIs

Define ECUs on CAN, over DoIP or through a VCI's D-PDU API, connect and unlock them, read fault memory, identifiers and routines, use the Diagnostic Console with ODX, PDX or CDD descriptions, and report a description as HTML and CSV.

**State:** ISO-TP, UDS and the Diagnostic Console are modelled: built and run against a simulated ECU (can-isotp and udsoncan over python-can) and, for DoIP, against the Eclipse OpenSOVD ECU simulator and a DoIP test entity, with doipclient as an independent client. VCIs through the D-PDU API are kit shipped, modelled against a test library. OEM seed-key libraries are kit shipped: proved on Linux and under Wine with libraries written for the tests, not yet run against an OEM library on Windows. ODX and PDX reading is verified on vendor examples against odxtools; CDD reading is modelled. **No real ECU, gateway, VCI or vehicle has been used.**

Only on a bench ECU, with a way to recover it.

## Define an ECU

In the **Diagnostics** panel's **ECUs** view, run **Add ECU...**.

**On CAN:** give the channel, the request and response identifiers (ISO-TP normal, normal fixed, extended or mixed addressing; physical and functional), the ISO-TP timing, and the ECU's description file. **Open CAN Channel for ECU...** opens the channel the definition names.

**Over DoIP:**

1. Choose the DoIP transport, then discover. Pick the network: every IPv4 network by interface, VLAN interfaces such as `eth0.30` included, and each interface with a link-local IPv6 address as `<interface> over IPv6`.
2. See each entity that answers vehicle identification, with its address, logical address, VIN, EID, GID, further action, sync status and protocol version, and keep it by address, VIN or EID.
3. Set the tester's and ECU's logical addresses, the functional address, the routing activation type and OEM data, the protocol version (2010, 2012, 2019), TLS on port 3496 (always, or only when routing activation is refused with 0x07) with your CA and client certificate files, and the DoIP timing parameters.
4. **Set DoIP TLS Client Key...** stores the client key and its passphrase in secret storage, never in settings or the file.

Over IPv4 the request goes to the chosen interface's broadcast address, so it leaves tagged on that VLAN only; over IPv6 it goes to ff02::1 on the interface, and the connection goes to the discovered `fe80::...%interface` address. **Check DoIP Entity** reads entity status and diagnostic power mode.

![DoIP entity discovery listing each entity that answered vehicle identification with its address, logical address, VIN, EID and GID.](https://neuralinverse.com/docs-images/modules/automotive/doip-discovery.webp)

**Through a VCI (D-PDU API)...:**

1. The Editor finds the MVCI root description file where vendors register it (on Windows the registry value `Root File` of `HKEY_LOCAL_MACHINE\SOFTWARE\D-PDU API`, else `C:\Program Files\D-PDU API\pdu_api_root_x64.xml`; on Linux `/etc/pdu_api_root.xml`; or `neuralInverse.automotive.dpduRootFile`).
2. Pick one of the D-PDU APIs it lists, then a VCI the API reports (with its state), or **The First Available VCI**.
3. Enter the ECU's CAN identifiers in the ECU editor.

The API's library is loaded in a helper process of its own. Each UDS request is one D-PDU API ComPrimitive on ISO 15765 over CAN; the API does ISO-TP and timing. A lost VCI or a crash of the vendor's library closes the link and says why in the Automotive output, which also records the protocol and every ComParam the API took.

![Add ECU through a VCI: the VCIs the D-PDU API reports, one available, one in use or lost, and The First Available VCI.](https://neuralinverse.com/docs-images/modules/automotive/vci-picker.webp)

ECU definitions are kept in workspace storage, or with **Save ECU Definitions to Workspace** in `.vscode/automotive-ecus.json`, which has a JSON schema (`"transport": "doip"` or `"vci"` for the other transports). **Open ECU Definitions File**, **Select ECU...**, **Edit ECU Connection...** and **Remove ECU...** manage them.

## Connect, unlock and read

1. **Connect to ECU for Diagnostics (UDS)**. **Toggle Tester Present** keeps the session alive.
2. **Read ECU Identification** reads the standard identification identifiers in one action, named from the description.
3. **Change Diagnostic Session...** and **Unlock ECU (Security Access)...**. Seed-key runs the OEM's algorithm from the OEM's seed-key library (a GenerateKeyEx or GenerateKeyExOpt DLL, loaded in a helper process of the library's own bitness) or from an external command set in **Configure Seed-Key Commands...**, never in the Editor's own process, and only in a trusted workspace.
4. **Fault Memory** view: DTCs as P, C, B or U codes with their status flags named, severity, snapshot and extended data records decoded, filter by status; clearing asks first.
5. **Data Identifiers** view: read and write any identifier as hex, ASCII, decimal or, with a description, as physical values by name; **Read All**.
6. **Routines** view: start, stop and request results by name with their parameters.
7. **ECU Reset...**, and **Disconnect ECU Diagnostics (UDS)** when done.

The UDS client also runs communication control, control DTC setting, and request download and upload with transfer data. Negative responses are named by code, response pending extends to P2*, and the ECU's timing is adopted. The **Operation Log** view records every request and response with service, duration and outcome; DoIP control messages appear beside the UDS requests. **Clear Operation Log** clears it; **Show Diagnostics Output** opens the Automotive output.

## Use the ECU's description

**Set Diagnostic Description...** names the ECU's PDX archive, ODX document or CANdela file (`.cdd`) and, optionally, its variant. Every Diagnostics view, the Operation Log and the agent tools then speak the description: DTC names, texts and severity; identifiers with physical values, units and value names; routines, sessions and security levels by name.

- **ODX and PDX:** base and ECU variants with inheritance, protocols, functional groups and classes, every coded type, computation method and structure; PDX archives stored or deflated. **Identify ECU Variant** identifies the variant from the description's identification patterns.
- **CDD:** CANdelaStudio files are read into the same model: data types, protocol services, diagnostic classes, base and ECU variants, DIDs, DTCs with records, negative response codes and CAN identifiers. A CDD holds no variant identification the reader can establish, so for a CDD **Identify ECU Variant** sends nothing and you choose the variant, which is saved in the ECU definition. What a CDD holds that the reader does not interpret is a warning in Problems at its place, never a guess.

**Generate Diagnostic Description Report** (context menu of a PDX, ODX or CDD file or its editor tab, or the Command Palette) writes one variant's report into a folder you choose and opens it in the Integrated Browser: an HTML page without scripts and one CSV file per table (variants and how each is identified, services, every parameter with position, type and conversion, data identifiers, DTCs, snapshot and extended data record layouts, routines, sessions, security levels, single-ECU jobs as declared, and what was not interpreted). A provenance file names each source with its size and SHA-256, the tool version and the time; the CSV files of the same file, variant and tool version are byte for byte the same each time. An earlier report is replaced only after you confirm. Verified for PDX against odxtools on 12 public descriptions; modelled for CDD.

## The Diagnostic Console

The **Diagnostic Console** lists every service of the ECU's description by name, grouped by the description's functional classes (CDD: its diagnostic classes), with a filter.

1. Choose a service. Its form shows coded constants fixed and takes physical values or value names with units and limits.
2. The request bytes update as you type, with what the request changes in the ECU.
3. **Send** (or Enter) sends it physically or functionally addressed, on CAN, DoIP or the VCI. The response is decoded by name; a negative response is named by its code.

Raw requests in hexadecimal work for any ECU, with or without a description; session changes, resets and security access sent this way keep the ECU's state in the panel. Every exchange goes to the Operation Log and the console's own history.

![The Diagnostic Console with services grouped by functional class and a ReadDTCInformation response decoded by name.](https://neuralinverse.com/docs-images/modules/automotive/diagnostic-console-dtcs.webp)

![A refused security access named serviceNotSupportedInActiveSession, with the console's history and the Operation Log.](https://neuralinverse.com/docs-images/modules/automotive/console-negative-response.webp)

Every request that changes the ECU (any service but reading data, DTCs, memory and scaling, and tester present) asks first, naming the ECU, its interface, the change and the request bytes.

Reprogramming, flash jobs and end-of-line sequences are on [Reprogramming and end of line](https://neuralinverse.com/docs/modules/automotive/reprogramming/); tests generated from the description on [Diagnostic tests](https://neuralinverse.com/docs/modules/automotive/diagnostic-tests/); J1939 diagnostics on [J1939 networks](https://neuralinverse.com/docs/modules/automotive/j1939/); UDS over LIN on [LIN bus](https://neuralinverse.com/docs/modules/automotive/lin/).

**Not verified:** a real ECU, flash bootloader, DoIP gateway or vehicle; routing to ECUs behind a gateway; TLS against an entity other than Python's ssl module; VLAN and IPv6 discovery outside Linux veth links in a VM; a vendor's D-PDU API or VCI (UNUM32 on 64-bit Linux D-PDU APIs is assumed to be 32 bits); an OEM seed-key library on Windows; a packaged, code-signed build with the helper processes; Windows and macOS.
