基于Python/Capl脚本 对通信矩阵报文(Flexray/CAN)的周期检测(一)

📘前言

  • 🍅 在汽车电子系统测试中,离不开对报文周期的测试,如果系统比较复杂,要处理成千上万个报文,如果纯手动测试,会耗费人力,在CAPL脚本的基础上,通过python 解析 arxml 文件中的Flxeray 和 dbc 文件中的 CAN报文。形成自动化的测试脚本。

  • 🍅演示软硬件环境 Win10 x64 ; CANoe 11 SP2 x64

请添加图片描述

请添加图片描述

📗 分析并提取Flexray 报文

  • 1️⃣ 通过xml marker 工具打开 flexray.arxml 报文矩阵,分析后,得知flexray的报文结构如下图,
    flexray

  • 2️⃣ 明确我们测试周期需要的参数,Flexray 报文我们需要提取报文名字和报文周期时间 ,而报文周期时间由调度表参数(Slot,Base,Repetition)决定,所以我们需要提取总共4个参数,Name ,Slot,Base,Repetition ,具体代码如下:
 from lxml import etree
import re
import os

class cycleTimeTest():
    def __init__(self, *args, **kwargs): # real signature unknown
        self.frames_name = []
        self.slot_ID = []
        self.base_cycle = []
        self.cycle_repetition = []

    def arxml(self):
        html = etree.parse('./files/test.arxml')#just have one arxmal file
        if html:
            root = html.getroot() 
            print(root.tag)  # 开始认为返回的root tag 应该是 ’AUTOSAR‘ ,结果却是 ’{http://autosar.org/schema/r4.0}AUTOSAR ‘ 
            AR_PACKAGES =root.findall("./%sAR-PACKAGES//%sAR-PACKAGE"%(base_tag,base_tag))
            # print(AR_PACKAGES)           
            frames = AR_PACKAGES[1].findall(".//%sFLEXRAY-CLUSTER//%sFLEXRAY-FRAME-TRIGGERING"%(base_tag,base_tag))# 得到所有的 flexray 报文
            # print(Frames)
            for frame in frames:
                name = frame.find(".//%sFRAME-REF"%(base_tag)).text.split(r'/')[-1]  
                if re.match('FlcFLC_FlexrayFr', name):#这里有个过滤的动作,因为我们只需要测试ECU发过来的报文,而ECU的报文名字都有'FlcFLC_FlexrayFr' 
                    self.frames_name.append(name)

                    slot = frame.find(".//%sSLOT-ID"%(base_tag)).text   # 得到flexray 报文 slot 参数
                    self.slot_ID.append(slot)

                    cycle = frame.find(".//%sCYCLE-REPETITION//%sBASE-CYCLE"%(base_tag,base_tag)).text # 得到flexray 报文 base cycle 参数
                    self.base_cycle.append(cycle)

                    repetition = frame.find(".//%sCYCLE-REPETITION//%sCYCLE-REPETITION"%(base_tag,base_tag)).text.split(r'-')[-1] # 得到flexray 报文 cycle repetition 参数
                    self.cycle_repetition.append(repetition)

            print(self.frames_name)
            print(self.slot_ID)
            print(self.base_cycle)
            print(self.cycle_repetition)
        else:
            print("parse file failed!")


if __name__ == '__main__':
    c = cycleTimeTest()
    c.arxml()

  • 3️⃣ 测试结果如下,总共有195个满足测试条件的Flexray报文:

,

📗 分析提取can报文

  • 1️⃣ 通过notepad 打开 .dbc文件。可以分析出dbc文件的结果如下图
  • 以第一行为例解释下报文的格式: BO_ 是开始标识,80 是报文ID,紧接着字符串是报文名字,8是报文长度,FLC是报文发出者
  • 报文下面SG开头的,是这个报文的信号参数,包括信号的长度,起始终止位等。
  • 我们明确Can报文周期测试我们需要提取的参数是什么

在这里插入图片描述

下图,红色 笔着色的是 报文 cycle参数,比如 BA_ “GenMsgCycleTime” BO_ 80 10; 就表明
ID为80的报文cycle 是10ms

.
在这里插入图片描述


  • 2️⃣ 解析代码
from lxml import etree
import re
import os

class cycleTimeTest():
    def __init__(self, *args, **kwargs): # real signature unknown
        #flexray
        self.frames_name = []
        self.slot_ID = []
        self.base_cycle = []
        self.cycle_repetition = []
        #can
        self.can_mesages_name = []
        self.can_mesages_id = []
        self.can_mesages_peried = []

    def get_abspath(self,file_suffix):
        '''
        @这个函数根据文件后缀,选出所有符合条件的文件
        '''
        self.root_path = os.path.dirname(os.path.abspath(__file__))  # log文件的目录
        self.root_path = os.path.join(self.root_path, "files")
        self.fileList = os.listdir(self.root_path)
        self.get_files = []
        for file in self.fileList:
            if file.split(".")[-1] == file_suffix:
                self.get_files.append(os.path.join(self.root_path, file))
        return self.get_files

    def arxml(self):
        html = etree.parse('./files/test.arxml')#just have one arxmal file
        if html:
            root = html.getroot() 
            print(root.tag)  # 开始认为返回的root tag 应该是 ’AUTOSAR‘ ,结果却是 ’{http://autosar.org/schema/r4.0}AUTOSAR ‘ 
            base_tag  = "{http://autosar.org/schema/r4.0}" 
            AR_PACKAGES =root.findall("./%sAR-PACKAGES//%sAR-PACKAGE"%(base_tag,base_tag))
            # print(AR_PACKAGES)           
            frames = AR_PACKAGES[1].findall(".//%sFLEXRAY-CLUSTER//%sFLEXRAY-FRAME-TRIGGERING"%(base_tag,base_tag))# 得到所有的 flexray 报文
            # print(Frames)
            for frame in frames:
                name = frame.find(".//%sFRAME-REF"%(base_tag)).text.split(r'/')[-1]  
                if re.match('FlcFLC_FlexrayFr', name):#这里有个过滤的动作,因为我们只需要测试ECU发过来的报文,而ECU的报文名字都有'FlcFLC_FlexrayFr' 
                    self.frames_name.append(name)

                    slot = frame.find(".//%sSLOT-ID"%(base_tag)).text   # 得到flexray 报文 slot 参数
                    self.slot_ID.append(int(slot))

                    cycle = frame.find(".//%sCYCLE-REPETITION//%sBASE-CYCLE"%(base_tag,base_tag)).text # 得到flexray 报文 base cycle 参数
                    self.base_cycle.append(int(cycle))

                    repetition = frame.find(".//%sCYCLE-REPETITION//%sCYCLE-REPETITION"%(base_tag,base_tag)).text.split(r'-')[-1] # 得到flexray 报文 cycle repetition 参数
                    self.cycle_repetition.append(int(repetition))
            print(self.frames_name)
            print(self.slot_ID)
            print(self.base_cycle)
            print(self.cycle_repetition)
            return 1
        else:
            print("parse file failed!")
    def dbc(self):
    
        self.dbcfiles = self.get_abspath('dbc')
        if self.dbcfiles:
            for i in range(len(self.dbcfiles)):
                print(self.get_files[i])
                self.get_can_message_name_and_id(self.dbcfiles[i])
            print(self.can_mesages_name)
            print(self.can_mesages_id)
            print(self.can_mesages_peried)


    def get_can_message_name_and_id(self,filename):
        f = open(filename)
        if f:
            line = f.readline()  # read next line
            while line:  # read by line
                message_search_obj = re.search(message_pattern, line.strip())  # 匹配到message
                # print(message_search_obj)
               if message_search_obj:
                    id = message_search_obj.group(1) # message id
                    name = message_search_obj.group(2)# message name
                    cycle = self.get_can_message_cycle(filename,id)  # message cycle
                    if cycle: #如果读取的cycle 为None, 这样的 报文不需要测
                        self.can_mesages_id.append(int(id))
                        self.can_mesages_name.append(name)
                        self.can_mesages_peried.append(cycle)
                line = f.readline()
            f.close()
        else:
            print("open file :%s failed"%filename)

    def get_can_message_cycle(self,filename,id):
        f = open(filename)
        if f:
            line = f.readline()
            while line:
                # eg:BA_ "GenMsgCycleTime" BO_ 72 10 cycle is 10ms ;
                cycle_pattern = re.compile(r'''BA_ "GenMsgCycleTime" BO_ %s (.*?);''' % id,re.S) # 报文的周期 需要根据报文ID获取
                message_search_obj = re.search(cycle_pattern, line.strip())
                if message_search_obj:
                    cycle = int(float(message_search_obj.group(1)))
                    f.close()
                    return cycle
                line = f.readline()
            f.close()
        else:
            print("open file :%s failed"%filename)
if __name__ == '__main__':
    c = cycleTimeTest()
    c.arxml()
    c.dbc()


  • 3️⃣ 测试结果如下图,虽然穿进去3个dbc文件,但是目标ECU 发出的有效的报文就只有8个报文:

在这里插入图片描述


🌎总结

请添加图片描述

7

  • 🚩要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!

  • 🚩 有微信的小伙伴可以关注下浪哥车载诊断,一个行业内小小圈子,群里有网盘资料源码还有各路大神 闲时交流交流技术,聊聊工作机会啥的。

  • 🚩如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
    18
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚂蚁小兵

慢慢长夜磨一章好文章,费烟!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值