ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ECUTEST+TSMasterAPI+Python:CAN信号交互测试组合方案

ECUTEST+TSMasterAPI+Python:CAN信号交互测试组合方案 做过ECU台架测试的兄弟应该都有这种体会测试环境在ECUTEST里搭好了、用例序列也排好了表面上一切都在按计划执行但一到要跟CAN总线上的信号做交互——发一帧自定义报文、动态读一个信号值、根据ECU的实时反馈调整输入——就开始难受。ECUTEST本身擅长的是测试流程编排和结果管理可真要去解析信号、控制总线收发靠它自带的配置项折腾起来又慢又绕还得掂量资源占用。于是我换了一套组合拳ECUTEST继续干它最擅长的测试编排TSMasterAPI加上Python负责所有CAN总线层面的信号交互两边通过稳定的接口配合各管一段。这套方案我实测了小半年用来做ECU功能回归测试和信号级验证稳定性和灵活度都让我挺满意。这篇就把思路、代码、踩过的坑全部摊开讲给正在为CAN交互测试头秃的朋友一个可以直接抄作业的参考。1. 为什么要把TSMasterAPI、Python和ECUTEST拧在一起1.1 ECUTEST解决的是“测什么”的问题ECUTEST这类工具的定位是把你设计好的测试用例变成可重复执行的测试序列。它擅长管理测试步骤、维护测试数据、记录最终结果非常适合做ECU功能级别的回归验证。但它不是总线工具对CAN报文的解析、信号级别的读写、动态总线数据的模拟并不是它的主场。你要在测试中途插入一帧自定义报文或者根据被测对象的实际响应实时改变输入参数用ECUTEST自带的机制实现起来很费劲写出来的测试代码还难维护。1.2 Python加TSMasterAPI补上“怎么测”的短板TSMasterAPI本质上是把TSMaster的总线能力开放出来让你能用Python去做CAN报文收发、信号解析、总线数据记录这些操作。把这一层能力补到ECUTEST旁边就等于给测试序列加了一双能直接摸到总线的“手”。测试逻辑依然由ECUTEST控制但凡是涉及到总线的操作全部交给Python脚本来干。这个分工方式解决了三个实际痛点总线操作灵活度上来了你想发什么报文、读哪个信号、等哪种响应改Python脚本就行不用在ECUTEST的配置界面里反复折腾。脚本可以独立调试Python脚本单独跑通之后再接入ECUTEST整体联调问题定位范围一下子缩小了很多。复用性高总线操作封装成函数之后一套脚本可以在多个测试项目里复用换DBC、换通道、换被测对象只需要改配置不用重写逻辑。2. 环境准备与TSMasterAPI核心概念2.1 环境搭建整体环境其实不复杂梳理下来就是三层底层是CAN硬件和被测ECU中间是TSMaster负责总线接入上层是Python脚本调用TSMasterAPI来做具体操作。我的环境清单如下TMaster软件本体用于创建工程、加载DBC、管理硬件通道Python运行时建议3.8以上的版本太老的版本有些新特性用不了tsmasterapi库直接pip install tsmasterapi就能装CAN接口硬件我用的是同星自家的USBCAN卡驱动装好后在TSMaster里能看到设备ECUTEST软件版本我这里用的是比较新的2022版不同版本在调用外部脚本的方式上略有差异这里有个容易忽略的地方TSMasterAPI不只是装了pip包就算完TSMaster本体通常也需要打开或至少处于可连接状态脚本才能通过API去调用通道配置和总线资源。我早期踩过这个坑脚本一执行就报错找不到设备排查了半天才发现是TSMaster软件没启动实例连接。2.2 理解TSMasterAPI的对象模型TSMasterAPI上手的关键是抓住它几个核心对象的层级关系。我用大白话描述一下根对象是应用对象负责启动TSMaster、管理工程文件。从应用对象往下是通道对象一个通道对应一条实际的总线接口比如CAN1、CAN2。通道对象下面是报文对象对应CAN总线上一帧一帧的数据。再往下才是信号对象对应DBC文件里定义好的物理量比如车速、转速、开关状态。这条链路理解了写代码就有方向感了。需要注意的一点是DBC文件对信号解析至关重要。信号就是一个裸的16进制字节序列只有加载了对应的DBCAPI才知道哪几个bit代表车速、分辨率多少、偏移量怎么算。所以工程里DBC文件没配好后面解析出来的信号值大概率是错的。2.3 先写一个最小脚本试通链路在接入ECUTEST之前强烈建议先用一个最简脚本把链路整体跑通。这就好比搭水管先通水再装修排查起来省事很多。import time from tsmasterapi import TSMasterApp app TSMasterApp() app.start() can1 app.get_can_channel(1) can1.set_bitrate(500000) can1.start() tx_frame can1.create_tx_frame(0x123) tx_frame.set_signal_by_name(VehicleSpeed, 60) can1.send_frame(tx_frame) time.sleep(0.2) rx_frame can1.rx_frames.get(0x456) if rx_frame: status rx_frame.get_signal_by_name(VCUStatus) print(VCU status:, status) can1.stop() app.close()这段代码做的事情就是启动TSMaster链路把CAN1通道配成500k波特率并启动向ID为0x123的报文里写入VehicleSpeed信号值为60发出去然后去读ID为0x456的报文里的VCUStatus信号。如果你的链路通了这个脚本跑起来应该能正常打出一个状态值。这一步跑到位了后面接ECUTEST就只是流程层面的问题。3. 实战案例Python脚本控制ECUTEST完成CAN信号交互测试3.1 测试场景设计我把这个案例设计成一个很典型的场景被测对象是VCU我们要验证VCU在车速信号变化时的状态切换逻辑。ECUTEST负责整个测试序列的编排比如上电、等待系统自检、记录结果、下电。而发送车速信号、读取VCU反馈状态、判断是否符合预期这些车身总线层面的操作全部由Python脚本来做。测试步骤如下ECUTEST上电进入预置状态。调用Python脚本通过CAN总线发送车速60km/h的报文。脚本继续读取VCU反馈的状态报文解析出VCU状态信号。脚本把解析结果和判定结论写入结果文件并将退出码返回给ECUTEST。ECUTEST根据脚本返回的结果决定该用例是通过还是失败并记入测试报告。这个分工的好处是ECUTEST始终是做“导演”Python脚本是“演员”CAN总线是舞台分工清楚出问题了也知道去哪里查。3.2 Python脚本的完整实现脚本的核心逻辑分三块发送信号、读取信号、输出结果。这里我直接贴上关键代码并做一些说明。import json import sys import time from tsmasterapi import TSMasterApp DBC_PATH C:/projects/vcu_control/vcu.dbc TX_FRAME_ID 0x123 RX_FRAME_ID 0x456 def send_vehicle_speed(can, speed): frame can.create_tx_frame(TX_FRAME_ID) frame.set_signal_by_name(VehicleSpeed, speed) can.send_frame(frame) def read_vcu_status(can, timeout1.0): end_time time.time() timeout while time.time() end_time: frame can.rx_frames.get(RX_FRAME_ID) if frame: return frame.get_signal_by_name(VCUStatus) time.sleep(0.02) return None def main(speed, expected_status): app TSMasterApp() app.start() app.load_dbc(DBC_PATH) can app.get_can_channel(1) can.set_bitrate(500000) can.start() result { case: VCU_Speed_Status_Check, speed: speed, expected_status: expected_status, actual_status: None, pass: False, } try: send_vehicle_speed(can, speed) actual read_vcu_status(can) result[actual_status] actual result[pass] (actual expected_status) except Exception as exc: result[error] str(exc) finally: can.stop() app.close() with open(result.json, w, encodingutf-8) as fp: json.dump(result, fp, indent2) sys.exit(0 if result[pass] else 1) if __name__ __main__: main(int(sys.argv[1]), int(sys.argv[2]))这个脚本的接口很简单传入车速值和期望状态值执行后在当前目录生成一个result.json退出码代表测试结论。这样的接口设计就是为了方便后续在ECUTEST里调用。脚本里的关键点有两个一是超时机制读取CU反馈状态时不可能无限等下去设置1秒超时是经验值实测下来VCU响应快的时候几十毫秒就回复了1秒足够覆盖绝大部分正常和异常场景二是结果文件的输出JSON格式清晰易解析ECUTEST拿到这个文件就能知道被测对象的实际表现到底是什么。3.3 ECUTEST端接入ECUTEST这边要做的事不复杂核心就是如何在测试序列中调用外部脚本并把脚本返回的结果纳入测试结论。ECUTEST本身支持在测试用例中执行外部命令。我用的方式是在测试步骤里配一个执行外部程序的节点命令行写法大概是python C:/projects/vcu_control/can_signal_check.py 60 160是车速信号值1是期望的VCU状态码。脚本执行完退出码是0说明通过非0说明失败ECUTEST通过捕获这个退出码就能自动判定用例结果。这里有个细节值得注意ECUTEST调用外部Python脚本时工作目录不一定是你脚本所在目录而脚本里又涉及相对路径的DBC和结果文件所以最稳妥的方式还是在脚本里把路径全部写成绝对路径或者动态获取脚本所在目录。我在实际项目里就是一开始没注意这个问题结果ECUTEST跑起来之后脚本报错找不到DBC文件排查了好久才意识到是工作目录的问题。4. 常见问题排查与经验教训4.1 最容易踩的五个坑我把实际运行中遇到的高频问题整理成了一张表格方便你对照排查问题现象可能原因解决思路脚本报错找不到TSMaster设备TMaster软件未运行或硬件驱动没有正确加载先确认TSMaster能正常操作CAN设备再跑脚本信号值解析出来明显不对DBC文件没有正确加载或者加载的是错误的DBC版本在TSMaster里先加载DBC用批量加载接口配置好再做信号解析ECUTEST调用脚本后一直超时脚本里的超时时间设置得太短或者CAN总线波特率不匹配先把脚本独立跑一遍确认耗时再调整ECUTEST侧的等待时间退出码取不到用例结果判定不准工作目录不对导致结果文件写到了别处或者脚本异常退出使用绝对路径并在脚本里加全局异常捕获保证异常情况下也有明确的退出码几帧报文连续发送时偶尔丢帧发送间隔太短总线负载率高或者CAN卡缓存不足调整发送间隔必要时改用周期发送模式降低总线冲突概率这些坑里最隐蔽的就是工作目录的问题。因为脚本独立运行的时候一切正常一进ECUTEST就出状况这就是环境差异导致的。排查这类问题的思路也很简单在脚本里打日志把当前工作目录、DBC路径、结果文件路径都打印出来一眼就能看出是哪一步偏了。4.2 从项目实测中总结的几条经验踩过几次坑之后我给自己定了几条硬规矩实测对提升稳定性和排查效率很有帮助所有Python脚本先单独跑通再接入ECUTEST。脚本和ECUTEST同时出问题时排查是最费时间的分开排查快得多。脚本里要加详细的日志输出包括发送的报文明细、读到的原始报文数据、解析出的信号值全部记录下来。这不仅是排查问题的手段也是后期做测试证据链的重要素材。信号交互的代码尽量封装成独立函数一个函数只干一件事不要在一个脚本里塞入太多逻辑。这样后续换DBC、换信号名改动点集中在配置区测试逻辑不受影响。涉及时间相关的控制尽量用可配置的超时参数而不要写死。ECU冷启动、热复位的响应时间差异很大把超时做成可配置项遇到不同项目时调整起来很方便。5. 这套组合的边界与扩展玩法5.1 这套方案还能往哪里延伸ECUTEST按钮式的调用Python脚本只是最基础的用法。做了一段时间之后你会发现这套组合的可扩展性其实超出预期这里分享几个我在实际项目中尝试过或正在实施的扩展方向。第一把Python脚本从零散的独立文件整理成一个公共测试库。所有总线操作都封装成库函数不同测试用例只需要传入不同的参数不用重复造轮子。我在项目里就是这样做的后面新增测试场景时基本只需要写一个配置文件加一小段调用代码开发效率明显提升。第二在脚本里加入DBC文件的自动切换能力。不同车型、不同配置的VCUDBC文件可能不一样测试时手动切换又容易出错。把DBC路径做成可配置项由ECUTEST传入脚本启动时动态加载这样同一个用例就能跑多个车型整体灵活性高很多。第三更进一步的思路是让Python脚本不只做“应答式”的操作而是模拟完整的ECU交互时序。比如测试车窗防夹功能脚本可以持续发送车窗位置信号同时监控电流信号的跳变自动判断防夹逻辑是否触发。这种复杂的时序交互靠ECUTEST的静态配置很难做到但用Python脚本就完全可控。代码上无非是再加一个循环按时间序列发送和采集信号。5.2 我的最终使用建议如果你正准备上手这套组合我的建议是不要一上来就想把全部场景自动化先从一两条最核心的测试用例开始跑通链路再逐步扩展。链路跑通之后你很快就能体会到把总线操控能力放到Python这边的好处后面自然会想设计出更多可复用的测试模块。再提一个很多人会忽略的点TSMasterAPI的文档包括DBC加载、报文发送、信号解析建议都通读一遍。这个库的接口设计整体很直观但少了某个步骤可能导致后面排查半天提前花半小时过一遍文档后面省下来的时间远不止半小时。最后说一句这套方案本质上就是把合适的工作交给合适的工具ECUTEST编排流程Python操作总线TSMasterAPI打通连接。按这个思路去设计测试架构未来遇到再复杂的信号交互需求你也会有自己的解决框架。
返回列表