CANoe自动生成CAPL脚本:利用Python读取DBC文件批量生成测试脚本和VXT文件

第一步读取.dbc文件,获取带E2E校验的报文,生成excel表格,目标生成结果如下

因为E2E报文都是含有CRC和counter的信号,我们可以以此作为依据筛选,然后再获取目标报文的关键信息填到表格中

import cantools
from openpyxl import Workbook
import re

def GetSigDataId(filePath):
    fileList = []
    with open(filePath, 'r', encoding='utf-8') as f:
        fileList = f.readlines()
        

        
    sigDataIdMap = {}
    for line in fileList:
        result = re.match(r'BA_\s+"E2EDataId"\s+SG_\s+\d+\s+(\w+)\s+(\d+);', line)
        
        if (result):
            sigName = result.group(1)
            dataId = result.group(2)
            sigDataIdMap[sigName] = dataId
        
    return sigDataIdMap
         
def find_messages_with_crc_and_counter(dbc_file_path, excel_file_path, sigDataIdMap):    
    try:
        # 载入 DBC 文件
        db = cantools.database.load_file(dbc_file_path)
    except FileNotFoundError:
        print(f"错误:找不到位于 {dbc_file_path} 的 DBC 文件")
        return

    for message in db.messages:
        has_crc_signal = any("CRC" in signal.name for signal in message.signals)
        crc_signal_names = [signal.name for signal in message.signals if "CRC" in signal.name]
        has_counter_signal = any("Counter" in signal.name for signal in message.signals)
        counter_signal_names = [signal.name for signal in message.signals if "Counter" in signal.name]
        

        if has_crc_signal and has_counter_signal:
            sending_node = message.senders[0] if message.senders else 'N/A'
            message_period = message.cycle_time if message.cycle_time is not None else 'N/A'
            dataId = sigDataIdMap[counter_signal_names[0]]
            dataId=int(dataId)
            ws.append([dbc_file_path, message.name, ', '.join(crc_signal_names), ', '.join(counter_signal_names), hex(dataId), sending_node, hex(message.frame_id), message_period, message.length])
            processed_messages.add(message)


if __name__ == "__main__":
    dbc_file_paths = ["CAN4.dbc","CAN5.dbc"]
    excel_file_path = "messagewithE2E.xlsx"

    wb = Workbook()
    ws = wb.active
    # 写入表头
    ws.append(["DBC 文件", "报文名称", "CRC 信号", "Counter 信号", "E2E_DATAID", "发送节点","报文标识", "报文周期 (毫秒)","报文长度","检测变量","是否TX"])
        # 将 DBC 数据写入 Excel,包含同时具有 CRC 和 Counter 信号的报文
    processed_messages = set()  # 记录处理过的报文


    for dbc_file_path in dbc_file_paths:
        sigDataIdMap = GetSigDataId(dbc_file_path)
        find_messages_with_crc_and_counter(dbc_file_path, excel_file_path, sigDataIdMap)

    # 保存 Excel 文件
    wb.save(excel_file_path)
    print(f"已保存同时具有 CRC 和 Counter 信号的报文至 {excel_file_path}")

第二步,我们用for循环,读取excel的关键内容,批量生成case,vxt 

import openpyxl

def generate_test_cases_vxt(excel_file, can_file, vxt_file):
    wb = openpyxl.load_workbook(excel_file)
    ws = wb.active

    # Assuming the first row contains column headers
    headers = [cell.value for cell in ws[1]]

    # Get the column indices for required data
    dbc_index = headers.index('DBC 文件')
    msg_name_index = headers.index('报文名称')
    a2lvaliable_index =  headers.index('检测变量')

    # Initialize variables to store test case content and names
    test_cases_content = ""
    test_cases_names = ""
    test_vxt=""

    # Iterate through rows starting from the second row
    for row in ws.iter_rows(min_row=2, values_only=True):
        dbc_file = row[dbc_index]
        msg_name = row[msg_name_index]
        a2lvaliable =row[a2lvaliable_index]

        # Generate test case content
        test_case_content = f"testcase TC1_RX_{msg_name}_msg()\n"
        test_case_content += "{\n"
        test_case_content += f"  Start_Logging('TC1_RX_{msg_name}_msg');\n"
        test_case_content += f"  //赋中间值\n"
        test_case_content += f"  testStep(\"Info\",\"Set Signalvalue = middlevalue\");\n"
        test_case_content += f"  for(i = 2; i < 54; i++ )\n"
        test_case_content += "   {\n"
        test_case_content += f"    {msg_name}_msg.byte(i) = 0x88;\n"
        test_case_content += "   }\n"
        test_case_content += f"  setTimerCyclic(Timer_{msg_name}_msg,20);\n"
        test_case_content += f"  TestWaitFortimeout(500);\n"
        test_case_content += f"  //CRC判断\n"
        test_case_content += f"  if(@XCP::A2L::{a2lvaliable} == 0)\n"
        test_case_content += "   {\n"
        test_case_content += f"    testStepPass(\"CheckResult\", \"E2E check pass {a2lvaliable} == {{@XCP::A2L::{a2lvaliable}}}\");\n"
        test_case_content += "   }\n"
        test_case_content += f"  else\n"
        test_case_content += f"   {{\n"
        test_case_content += f"    testStepFail(\"CheckResult\", \"{a2lvaliable} != 0\");\n"
        test_case_content += "   }\n"
        test_case_content += f"  cancelTimer(Timer_{msg_name}_msg);\n"
        test_case_content += f"  testWaitForTimeout(500);\n"
        test_case_content += f"  stopLogging('Logging');\n"
        test_case_content += "}\n\n"

        # Generate test case name
        test_case_name = f"TC1_RX_{msg_name}_msg"

        # Append test case content and name to respective variables
        test_cases_content += test_case_content
        # test_cases_names += "<capltestcase name="test_case_name"/>" + "\n"
        test_cases_names += f"   <capltestcase name=\"{test_case_name}\"/>\n"
        test_vxt = f"""<?xml version="1.0" encoding="iso-8859-1"?>
<!--Vector Test Automation Editor 2.1.34.0-->
<testmodule title="Someip_test" version="1.0" xmlns="http://www.vector-informatik.de/CANoe/TestModule/1.27">
<testgroup title="E2E_Test"> \
{test_cases_names}
</testgroup>
</testmodule>
        """


    # Write test case content to .can file
    with open(can_file, 'w', encoding='utf-8') as f:
        f.write(test_cases_content)

    # Write test case names to .vxt file
    with open(vxt_file, 'w', encoding='utf-8') as f:
        f.write(test_vxt)

    wb.close()
    


if __name__ == "__main__":
    excel_file = "messagewithE2E.xlsx"
    can_file = "testcases.can"
    vxt_file = "testcases.vxt"
    generate_test_cases_vxt(excel_file, can_file, vxt_file)

第三步,我们可以把生成的.can和.vxt文件导入到canoe

作者:DYS_个人练习生

物联沃分享整理
物联沃-IOTWORD物联网 » CANoe自动生成CAPL脚本:利用Python读取DBC文件批量生成测试脚本和VXT文件

发表回复