跳转到内容

CLI JSON-RPC(PC 版 MCAL-CAN)

ecb_cli rpc 会启动一个 JSON-RPC 2.0 服务,让 PC 上用 C 实现的 AUTOSAR MCAL CAN 驱动可以打开 EcuBus-Pro 的 CAN 适配器、收发报文,并按 Can_MainFunction_* 的方式轮询事件。

服务端负责真正的硬件。你的 Can.c 仍保持 AUTOSAR 形态(Can_InitCan_WriteCan_MainFunction_Read 等),每个 API 对应一次 JSON-RPC 调用。

[AUTOSAR CanIf / COM]
        |
[PC Can.c  MCAL]  -- TCP JSON-RPC -->  [ecb_cli rpc]  -- 厂商库 -->  PEAK / Kvaser / Vector / simulate / ...

POSIX C 示例见 resources/examples/mcal_can_rpc

启动服务

bash
ecb_cli rpc -h
bash
# TCP(默认):127.0.0.1:17320
ecb_cli rpc

# 指定地址和端口
ecb_cli rpc -H 127.0.0.1 -p 17320 --log-level=debug

# Can.Init 未提供 controllers[] 时,使用工程里的 CAN 设备
ecb_cli rpc ./resources/examples/can/Can.ecb

# 启动时立刻打开工程设备(C 侧可省略 Can.Init)
ecb_cli rpc ./project.ecb --auto-init

# Unix domain socket(Linux / macOS)
ecb_cli rpc --socket /tmp/ecb-rpc.sock

# 标准输入/输出,每行一个 JSON(日志打到 stderr)
ecb_cli rpc --stdio

报文格式

  • 传输:TCP、Unix socket 或 stdio。
  • 分帧:NDJSON(一个 JSON + \n)。也接受首尾相连的 JSON,以及 LSP 风格的 Content-Length
  • 规范:JSON-RPC 2.0,包含 batch 和通知(无 id)。
  • 只使用命名参数(params 为对象),方便 C 拼 JSON。

请求:

json
{"jsonrpc":"2.0","method":"Can.Write","params":{"hth":0,"id":256,"sdu":[1,2,3,4],"swPduHandle":1},"id":1}

成功 / 失败:

json
{"jsonrpc":"2.0","result":{"result":"E_OK","resultCode":0,"ts":1234},"id":1}
{"jsonrpc":"2.0","error":{"code":-32601,"message":"Method not found: foo"},"id":1}

CAN 数据可以是字节数组 [1,2,3] hex 字符串 "01 02 03" / "0x010203"。CAN id 可以是 256"256""0x100"

错误码

代码含义
-32700解析错误
-32600非法请求
-32601方法不存在
-32602参数非法
-32603内部错误
-32000CAN / 驱动错误
-32001控制器或设备不存在
-32002控制器未 STARTED
-32003HTH / HRH 不存在
-32004超时
-32005已经初始化

AUTOSAR 的 Can_WriteE_NOT_OK / CAN_BUSY 不会走 JSON-RPC error,而是放在 result 里。

两层 API

层次方法C MCAL 中的用途
AUTOSAR 风格Can.InitCan.WriteCan.MainFunction_*直接对应 SWS_Can
底层can.opencan.writecan.readcan.subscribe调试、非 AUTOSAR 客户端

rpc.discover 返回完整方法目录(名称、参数、AUTOSAR 对应关系)。

方法名在可能冲突时区分大小写:can.write(底层,使用 controllerId)与 Can.Write(AUTOSAR,使用 hth)不是同一个方法。

sys.pingsys.versionsys.listMethodssys.shutdown 始终可用。

hw.listVendorshw.listDeviceshw.getVersion 用于枚举适配器。

MCAL 映射

AUTOSAR APIJSON-RPC 方法
Can_InitCan.Init
Can_DeInitCan.DeInit
Can_GetVersionInfoCan.GetVersionInfo
Can_SetControllerModeCan.SetControllerModeCAN_T_START / CAN_T_STOP / CAN_T_SLEEP / CAN_T_WAKEUP
Can_GetControllerModeCan.GetControllerMode
Can_DisableControllerInterruptsCan.DisableControllerInterrupts(可嵌套)
Can_EnableControllerInterruptsCan.EnableControllerInterrupts
Can_WriteCan.Write
Can_GetControllerErrorStateCan.GetControllerErrorState
Can_GetControllerTxErrorCounterCan.GetControllerTxErrorCounter
Can_GetControllerRxErrorCounterCan.GetControllerRxErrorCounter
Can_SetBaudrateCan.SetBaudrate(控制器须为 STOPPED)
Can_CheckWakeupCan.CheckWakeup
Can_MainFunction_WriteCan.MainFunction_Writeconfirmations[]CanIf_TxConfirmation
Can_MainFunction_ReadCan.MainFunction_Readindications[]CanIf_RxIndication
Can_MainFunction_BusOffCan.MainFunction_BusOff
Can_MainFunction_WakeupCan.MainFunction_Wakeup
Can_MainFunction_ModeCan.MainFunction_Mode

控制器模式:CAN_CS_UNINITCAN_CS_STOPPEDCAN_CS_STARTEDCAN_CS_SLEEP

Can.Init 打开硬件后控制器处于 STOPPED(与 AUTOSAR 一致)。发送前需要 Can.SetControllerMode + CAN_T_START

未提供 hardwareObjects 时的默认 Hoh:

  • HTH controllerId * 2 — BASIC 发送(动态 CAN id)
  • HRH controllerId * 2 + 1 — BASIC 接收,标准帧,接收全部
  • HRH controllerId * 2 + 1000 — BASIC 接收,扩展帧,接收全部

Can.Write

json
{
  "hth": 0,
  "swPduHandle": 1,
  "id": "0x100",
  "sdu": [1, 2, 3, 4, 5, 6, 7, 8],
  "idType": "STANDARD"
}

返回 { "result": "E_OK"|"E_NOT_OK"|"CAN_BUSY", "resultCode": 0|1|2, "ts": ... }

FULL HTH 同时只允许 1 帧在途(否则 CAN_BUSY)。BASIC HTH 最多 8 帧。

轮询与推送

轮询(MCAL 常用): C 调度里 Can_MainFunction_Read 调用 Can.MainFunction_Read,再对每条调用 CanIf_RxIndication

推送: can.subscribe 后,服务端发送通知(无 id):can.rxIndicationcan.txConfirmationcan.controllerBusOff 等。

Can_DisableControllerInterrupts 会抑制通知(可嵌套),MainFunction 队列仍会填充。

底层 CAN 方法

尚未封装 AUTOSAR Hoh 时可以使用:can.open / can.write / can.read / can.subscribe / can.startPeriodSend 等。can.open 打开后会直接进入 STARTED。

Simulate 回环(无硬件)

打开两个 simulate handle,在其中一个上发送的帧会出现在另一个的 RX 中(约 1 ms):

json
{"jsonrpc":"2.0","method":"can.open","params":{"vendor":"simulate","handle":0,"controllerId":0},"id":1}
{"jsonrpc":"2.0","method":"can.open","params":{"vendor":"simulate","handle":1,"controllerId":1},"id":2}
{"jsonrpc":"2.0","method":"can.write","params":{"controllerId":0,"id":"0x123","data":[1,2,3,4]},"id":3}
{"jsonrpc":"2.0","method":"can.read","params":{"controllerId":1,"timeoutMs":200},"id":4}

GUI 网关(EcuBus 客户端已在运行)

EcuBus-Pro 图形界面 已启动时,同一套 JSON-RPC 由应用程序提供(默认 127.0.0.1:17320)。此时不要再运行 ecb_cli rpc,CAN 适配器已经由 GUI 占用。

开关、地址和端口在 主页 → 设置 → 常规。修改绑定后点 应用 RPCsys.version 会返回 "role": "gateway"

方向:

来源EcuBus 显示RPC 客户端看到
外部 Can.Write / can.writeTxdir: OUTTX 确认(不会把本帧当 RX 回显)
硬件接收RxRX 指示

RPC 写入走与 GUI 相同的 writeBase,会作为 Tx 发到总线。请先在 GUI 里启动工程以打开设备,然后 Can.Init 会返回已附着的控制器。不要与 ecb_cli rpc 占用同一 TCP 端口。