1. 工具库简介
1.1 python-can
定位:通用的 can 总线通信库,支持多种硬件接口(socketcan、pcan、kvaser 等)。
核心功能:
连接物理 can 设备或虚拟接口。
发送/接收 can 报文(标准帧、扩展帧)。
支持 can fd(灵活数据速率)。
适用场景:快速搭建 can 通信原型,兼容性强。
1.2 canard(can 协议栈)
定位:专注于 uds(iso 14229) 和 j1939 等高层协议解析的库。
核心功能:
解析 dbc 文件,自动化生成信号值。
支持 uds 诊断服务(如 0x22 读数据、0x2e 写数据)。
处理多帧传输(如 iso-tp 协议)。
适用场景:需要与 ecu 进行诊断交互的自动化测试。
2. 环境准备
2.1 安装库
# 安装通用 can 库 pip install python-can # 安装 canard(uds 协议支持) pip install canard
2.2 硬件准备
物理设备:pcan-usb、kvaser、vector 设备(需安装对应驱动)。
虚拟测试:使用 socketcan(linux 虚拟 can 接口)或 canoe 模拟总线。
3. 核心功能实现示例
3.1 使用 python-can 收发 can 报文
import can
# 连接 can 接口(以 socketcan 为例)
bus = can.interface.bus(channel='vcan0', bustype='socketcan')
# 发送单帧数据
msg = can.message(
arbitration_id=0x123, # can id
data=[0x01, 0x02, 0x03, 0x04],
is_extended_id=false # 标准帧
)
bus.send(msg)
# 接收数据
for msg in bus:
print(f"received: id={hex(msg.arbitration_id)}, data={msg.data}")
# 关闭连接
bus.shutdown()3.2 使用 canard 解析 dbc 文件
from canard import canard
from canard.hw import socketcan
# 加载 dbc 文件
dbc = canard()
dbc.load_dbc('vehicle.dbc')
# 创建虚拟 can 接口
dev = socketcan.socketcandev('vcan0')
dev.start()
# 解析接收到的报文
def on_message(msg):
decoded = dbc.decode_message(msg.arbitration_id, msg.data)
print(f"信号值: {decoded}")
dev.add_listener(on_message)3.3 实现 uds 诊断服务(基于 canard)
from canard.proto.uds import udsclient
# 创建 uds 客户端
uds = udsclient(transport=can.bus(bustype='socketcan', channel='vcan0'))
# 发送诊断请求:读取 ecu 序列号(服务 0x22,参数 0xf189)
response = uds.request([0x22, 0xf1, 0x89])
if response:
print(f"ecu 序列号: {bytes(response.data[2:]).decode()}")
else:
print("请求超时")4. 自动化测试脚本设计
4.1 测试场景示例:车门状态验证
def test_door_status():
bus = can.interface.bus(channel='vcan0', bustype='socketcan')
# 发送车门控制命令(id=0x200,数据=[0x01] 表示开门)
bus.send(can.message(arbitration_id=0x200, data=[0x01]))
# 等待并验证车门状态反馈(预期 id=0x201,数据[0]=0x01)
for msg in bus:
if msg.arbitration_id == 0x201:
assert msg.data[0] == 0x01, "车门未正确打开"
break
bus.shutdown()
4.2 集成测试框架(如 pytest)
import pytest
@pytest.fixture
def can_bus():
bus = can.interface.bus(channel='vcan0', bustype='socketcan')
yield bus
bus.shutdown()
def test_engine_rpm(can_bus):
# 发送转速请求命令
can_bus.send(can.message(arbitration_id=0x700, data=[0x03]))
# 验证响应是否在合理范围(如 800-5000 rpm)
for msg in can_bus:
if msg.arbitration_id == 0x701:
rpm = int.from_bytes(msg.data[2:4], byteorder='big')
assert 800 <= rpm <= 5000, "转速异常"
break
5. 高级应用技巧
5.1 can fd 支持
# 使用 python-can 发送 can fd 报文
msg = can.message(
arbitration_id=0x123,
data=[i % 256 for i in range(64)], # 64 字节数据
is_fd=true,
bitrate_switch=true # 启用比特率切换
)
bus.send(msg)
5.2 与 hil 系统集成
# 连接 vector 硬件(需安装 xl driver)
bus = can.interface.bus(
bustype='vector',
channel=1,
app_name='python_hil_test'
)
# 发送同步周期性报文
task = bus.send_periodic(msgs=[msg1, msg2], period=0.1)
task.stop() # 停止发送
5.3 自动化测试报告生成
# 使用 pytest-html 生成测试报告 pytest.main(["--html=report.html"])
6. 常见问题与调试
6.1 硬件连接失败
现象:canerror: error sending message
解决:
检查设备驱动是否安装(如 pcan 需安装 pcan-basic api)。
确认通道权限(linux 需 sudo ip link set vcan0 up)。
6.2 dbc 解析错误
现象:keyerror: 'unknown frame id'
解决:确保 dbc 文件中包含目标 can id 的定义。
6.3 多帧传输处理
# 使用 canard 处理 iso-tp 多帧传输 from canard.proto.iso_tp import isotptransport tp = isotptransport(can_bus, tx_id=0x7e0, rx_id=0x7e8) data = tp.recv() # 接收长数据(自动重组)
以上就是如何使用python编写测试脚本的详细内容,更多关于python测试脚本的资料请关注代码网其它相关文章!
发表评论