Skip to content

feat(xcp): add XCP master implementation with worker script API - #432

Draft
frankie-zeng wants to merge 2 commits into
masterfrom
cursor/add-xcp-implementation-aa65
Draft

feat(xcp): add XCP master implementation with worker script API#432
frankie-zeng wants to merge 2 commits into
masterfrom
cursor/add-xcp-implementation-aa65

Conversation

@frankie-zeng

@frankie-zeng frankie-zeng commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds an XCP (ASAM MCD-1 XCP) master to EcuBus-Pro, following the existing CAN-TP architecture, and exposes it to user scripts. This is the first iteration: it adds the main-process implementation plus the worker/script API surface (no renderer/UI yet).

The protocol codec is implemented test-first, constrained by the byte-level test vectors of the mature open-source XCP master pyXCP (pyxcp/tests/test_master.py). The byte encodings are dictated by the ASAM XCP standard; the ported vectors act as a correctness oracle.

What's included

Mirrors the CAN-TP layering (worker/cantp.tsnodeItem.canApidocan/cantp.ts):

  • src/main/xcp/xcpProtocol.ts — pure, transport-agnostic command builders and response parsers. Covers STD, calibration/paging (CAL_PAG), DAQ and programming (PGM) commands, with Intel/Motorola byte-order handling negotiated at CONNECT.
  • src/main/xcp/xcpMaster.tsXcpMaster, a high-level master over a pluggable XcpTransport, tracking slave properties (byte order, MAX_CTO/MAX_DTO, resources).
  • src/main/xcp/xcpCan.tsXcpCanTransport, XCP-on-CAN binding on the existing CAN_SOCKET/CanBase layer.
  • src/main/worker/xcp.ts — worker script API (XcpCreateConnection, XcpConnect, XcpGetStatus, XcpShortUpload, XcpSetMta, DAQ/PGM helpers, ...) bridged via a new xcpApi RPC, mirroring the CAN-TP worker API. Re-exported from worker/index.ts.
  • src/main/nodeItem.tsxcpApi handler that opens/closes connections and dispatches whitelisted XcpMaster methods.
  • src/main/worker/node.d.ts — ambient *?asset / *?asset&asarUnpack module declarations. This is a pre-existing gap that prevented npm run worker:js from emitting the worker bundle (ts-loader TS2307 on those asset imports, unrelated to XCP); adding the shims — identical in spirit to the existing *.node / *.html?raw shims in the same file — unblocks the mandated worker rebuild.

Example script usage

import { XcpCreateConnection, XcpConnect, XcpShortUpload, XcpCloseConnection } from 'ecubus-worker'

Util.Init(async () => {
  const handle = await XcpCreateConnection({ name: 'ecu', canIdCmd: 0x7e0, canIdResp: 0x7e1, padding: true })
  const info = await XcpConnect(handle)
  console.log('MAX_CTO', info.maxCto, 'MAX_DTO', info.maxDto)
  const mem = await XcpShortUpload(handle, 4, 0x1000)
  console.log('mem', mem)
  await XcpCloseConnection(handle)
})

Testing

  • test/xcp/xcp.test.ts79 tests: command builders and response parsers for every STD/CAL_PAG/DAQ/PGM command, plus XcpMaster end-to-end flow over a mock transport. Expectations are the pyXCP vectors minus the 4-byte XCP-on-Ethernet transport header.
  • test/xcp/xcpCan.test.ts5 end-to-end tests driving XcpMaster through the real XcpCanTransport over the simulate CAN backend, against a tiny simulated XCP slave (CONNECT / GET_STATUS / SHORT_UPLOAD / SET_MTA / DISCONNECT).
  • test/xcp/xcpCanSocketcan.test.ts — the same 5 XCP-on-CAN session tests over SocketCAN: two independent sockets sharing one bus, exchanging packed Linux struct can_frame buffers. Prefers a real vcan/can interface when AF_CAN works; falls back to an in-process bus on kernels without CONFIG_CAN.
  • test/docan/socketcan.test.ts — SocketCAN ABI codec tests (checked against Python struct.pack of can_frame / canfd_frame), two-socket I/O, fan-out, timeout, and kernel vcan smoke tests (skipped when AF_CAN is unavailable).
  • Shared slave/session harness: test/xcp/xcpCanHarness.ts. Linux AF_CAN worker: test/helpers/socketcan_worker.py.
  • npm run test -- --run test/xcp test/docan/socketcan.test.ts100 passed, 2 skipped (kernel vcan; this Cloud kernel has no CONFIG_CAN).
  • npm run typecheck → clean (node + web). npm run worker:js → builds and the bundle + generated worker typings include the XCP API.

To run the real kernel path on a normal Linux host:

sudo ip link add dev vcan0 type vcan && sudo ip link set up vcan0
npm run test -- --run test/docan/socketcan.test.ts test/xcp/xcpCanSocketcan.test.ts

Scope / follow-ups

  • First iteration is main + script API only, XCP-on-CAN. Future iterations could add XCP-on-Ethernet, DAQ measurement streaming/decoding, seed & key DLL integration, and renderer UI.
  • This does not register a production SocketCAN vendor in the Hardware tab (see Linux SocketCan Support #87 / Socketcan nodejs 接口 #300). The new tests cover the SocketCAN wire format and two-socket isolation model so XCP-on-CAN is proven beyond the in-process simulate bus.
Open in Web Open in Cursor 

Add an XCP (ASAM MCD-1 XCP) master, mirroring the CAN-TP architecture:

- src/main/xcp/xcpProtocol.ts: transport-agnostic command/response codec
  covering STD, CAL/PAG, DAQ and PGM commands, with Intel/Motorola byte-order
  handling. Byte layout validated against the pyXCP master test vectors.
- src/main/xcp/xcpMaster.ts: high-level XcpMaster over a pluggable transport,
  negotiating slave byte order at CONNECT.
- src/main/xcp/xcpCan.ts: XCP-on-CAN transport binding on the existing CAN layer.
- src/main/worker/xcp.ts: worker script API (XcpCreateConnection, XcpConnect,
  XcpShortUpload, DAQ/PGM helpers, ...) bridged via the 'xcpApi' RPC.
- nodeItem.ts: xcpApi handler dispatching whitelisted master methods.

Tests (test/xcp): 79 codec/master vectors ported from pyXCP plus 5 end-to-end
XCP-on-CAN tests over the simulate backend.

Also add ambient *?asset / *?asset&asarUnpack module declarations so the worker
webpack bundle builds (pre-existing gap that blocked npm run worker:js).
Drive XCP-on-CAN through two independent SocketCAN sockets that exchange
packed Linux can_frame/canfd_frame buffers, in addition to the existing
simulate backend. Prefer a real vcan/can interface when AF_CAN works;
fall back to an in-process bus on kernels without CONFIG_CAN (this Cloud
VM). Frame layout is checked against Python struct.pack of the uapi ABI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants