如何用python脚本制作生成CANdbc

最近在工作中,有同事拿了一个excel的dbc表格,在用官方的dbc工具一个一个创建信号,大概看了一下共累计20多个节点,300多个信号,居然在手动处理,顿感无语。。

于是在网络上搜相关的dbc 通过脚本生成方式,竟然没搜到!那只能全网首发一个给广大汽车软件同行谋个福利。

(经过国内一番搜索,一无所获。于是乎转谷歌搜索,在cantools 这个库官网文件下找到这么一个指令:)

复制代码
import cantools
db = cantools.database.load_file('xxxx.dbc')
cantools.database.dump_file(db, 'bar.dbc')

 上文代码实现了一个读取加转存,读取了一个dbc并转而生成了一个dbc,于是自行分析读取的candbc数据结构,再结合chatgpt给出的示例,进行重构数据。最终简单的示例代码如下:

复制代码
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 27 18:09:18 2023

@author: xm

如何创建生成canfd还待挖掘

"""

import cantools

# db = cantools.database.load_file('MS11_E4U2_CCU_PTCANFD_230701.dbc')
# cantools.database.dump_file(db, 'bar.dbc')

# 定义一个消息
message1 = cantools.db.Message( #cantools.database.can.message.Message
    frame_id=0x19FB5101, #435900673
    name='PFC_VacReport',
    length=8,
    bus_name='PFC',
    header_byte_order='big_endian',
    is_extended_frame=True,
    # is_multiplexed=True,
    # refresh=True,
    is_fd=False,
    send_type='cyclic',
    senders=['PFC'],
    cycle_time=20,
    comment='input voltage',
    unused_bit_pattern=255,
    # unpack_container=True,
    signals=[
        cantools.db.Signal(
            name='P_VacRpt_VacRms_A',
            start=0,
            length=12,
            is_signed=False,
            scale=0.1,
            offset=0,
            minimum=0,
            maximum=409.5,
            unit='V',
            invalid=None,
            initial=0,
            # is_multiplexer=False,
            # is_float=False,
            receivers=['IFB','LC'],
            # multiplexer_signal=None,
            # multiplexer_ids=None,
            byte_order='little_endian', #little_endian big_endian
            comment='valid voltage phase A',
        ),
        cantools.db.Signal(
            name='P_VacRpt_VacRms_B',
            start=12,
            length=12,
            is_signed=False,
            scale=0.1,
            offset=0,
            minimum=0,
            maximum=409.5,
            unit='V',
            invalid=None,
            initial=0,
            # is_multiplexer=False,
            # is_float=False,
            receivers=['IFB','LC'],
            # multiplexer_signal=None,
            # multiplexer_ids=None,
            byte_order='little_endian',
            comment='valid voltage phase b',
        ),
        cantools.db.Signal(
            name='P_VacRpt_VacRms_C',
            start=24,
            length=12,
            is_signed=False,
            scale=0.1,
            offset=0,
            minimum=0,
            maximum=409.5,
            unit='V',
            invalid=None,
            initial=0,
            # is_multiplexer=False,
            # is_float=False,
            receivers=['IFB','LC'],
            # multiplexer_signal=None,
            # multiplexer_ids=None,
            byte_order='little_endian',
            comment='valid voltage phase c',
        ),
    ]
)



node1 = cantools.db.Node(
    name='PFC'
)



# 定义一个数据库
database = cantools.db.Database(
    messages=[message1],
    nodes=[node1,],
    version='1.0'
)

# 保存为DBC文件
cantools.database.dump_file(database, 'example.dbc')

View Code

接下来就是解析对应的excel,创建不同的msg和signal再进行组合了。这里要注意,如果excel内涉及合并单元格,以及公式计算,需要用下文代码中的两个 In【0】部分来处理掉

复制代码
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 27 20:35:47 2023

@author: xm Azhe

"""

import pandas as pd
import cantools
import openpyxl

file_path = r'D:\代码\dbc文件处理\xx.xlsx'

# In[0] 文件改造,合并单元格填充
# 打开Excel文件
workbook = openpyxl.load_workbook(file_path)

# 遍历所有工作表
for worksheet in workbook.worksheets:
    # 获取所有合并单元格
    merged_cells = worksheet.merged_cells
    # if worksheet.title=='IFB协议E2E ':
    #     print(merged_cells)
    # 遍历合并单元格
    for merged_cell in list(merged_cells):

        # 获取合并单元格的起始行、列和结束行、列
        start_row, start_col, end_row, end_col = merged_cell.min_row,merged_cell.min_col,merged_cell.max_row,merged_cell.max_col,
        # 拆分
        worksheet.unmerge_cells(start_row=start_row,start_column=start_col,end_row=end_row,end_column=end_col)
         # 获取合并单元格的值
        cell_value = worksheet.cell(start_row, start_col).value
        # if worksheet.title=='IFB协议E2E ':
            # print(merged_cell)
            # print('\n')
        # 将合并单元格内的所有单元格都替换为该值
        for row in range(start_row, end_row + 1):
            for col in range(start_col, end_col + 1):
                worksheet.cell(row, col).value = cell_value
file_path1=file_path.replace('.xlsx','_dealed.xlsx')
# 保存Excel文件
workbook.save(file_path1)

# In[0] excel内包含公式,需要刷新公式,否则会读取为nan
import win32com.client
# Start an instance of Excel
xlapp = win32com.client.DispatchEx("Excel.Application")
# Open the workbook in said instance of Excel
wb = xlapp.workbooks.open(file_path1)
# Optional, e.g. if you want to debug
# xlapp.Visible = True
# Refresh all data connections.
wb.RefreshAll()
wb.Save()
# Quit
xlapp.Quit()


# In[1] df读取,删除信号名称为空,忽略第一行
def str_to_num(s):
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            return s
        
df={}
for s in pd.ExcelFile(file_path1).sheet_names:
    # print(s)
    if ('协议' in s) & (s!='协议说明'):
        df[s] = pd.read_excel(file_path1, sheet_name=s,skiprows=1, engine='openpyxl')
        df[s] = df[s].dropna(subset=['数据名称'])
        


node_list=[]
msg_list=[]
# cnt=1
for s in list(df.keys()):
    node_list.append(cantools.db.Node(name=s.replace(' ','').replace('协议E2E','')))
    msg_list_tmp=list(df[s]['ID'].drop_duplicates())
    for i in msg_list_tmp:
        # if s=='LVDC协议E2E':
        #     cnt1=1
        #     print('y')
        signals_list_tmp=[]
        df_sig_list_tmp=list(df[s]['数据名称'][df[s]['ID']==i])
        for j in df_sig_list_tmp:
            signals_list_tmp.append(
                cantools.db.Signal(
                    name=j,
                    start=str_to_num(df[s]['起始位'][df[s]['数据名称']==j]),
                    length=str_to_num(df[s]['长度'][df[s]['数据名称']==j]),
                    is_signed=False,
                    scale=df[s]['精度'][df[s]['数据名称']==j].values[0],
                    offset=str_to_num(df[s]['OFFSET'][df[s]['数据名称']==j]),
                    minimum=df[s]['Min'][df[s]['数据名称']==j].values[0],
                    maximum=df[s]['Max'][df[s]['数据名称']==j].values[0],
                    unit=str(df[s]['单位'][df[s]['数据名称']==j].values[0]),
                    invalid=None, #未采用dbc
                    initial=str_to_num(df[s]['Initial'][df[s]['数据名称']==j]),
                    # is_multiplexer=False,
                    # is_float=False,
                    receivers=df[s]['接收'][df[s]['数据名称']==j].values[0].split('&'),
                    # multiplexer_signal=None,
                    # multiplexer_ids=None,
                    byte_order='little_endian', #little_endian big_endian
                    comment=str(df[s]['说明'][df[s]['数据名称']==j].values[0]),
                    # comments=None
                ))

        msg_list.append(cantools.db.Message( #cantools.database.can.message.Message
            frame_id=int(i[:i.index("\n")], 16),
            name=i[i.index("(")+1:i.index(")")],
            length=8,
            bus_name=df[s]['发送'][df[s]['ID']==i].values[0],
            header_byte_order='big_endian',
            is_extended_frame=True,
            is_fd=False,
            send_type='cyclic',
            senders=[df[s]['发送'][df[s]['ID']==i].values[0]],
            cycle_time=str_to_num(df[s]['周期'][df[s]['ID']==i].values[0][:df[s]['周期'][df[s]['ID']==i].values[0].index("ms")]),
            comment=str(df[s]['备注'][df[s]['ID']==i].values[0]),
            unused_bit_pattern=255,
            # unpack_container=True,
            signals=signals_list_tmp
            ))
        # if s=='LVDC协议E2E':
        #     cnt1=cnt1+1
        #     if cnt1==3:
        #         break
    # cnt=cnt+1
    # if cnt==5:
    #     break

database = cantools.db.Database(
    # messages=[message1],
    messages=msg_list,
    nodes=node_list,
    version='1.0'
)
    
cantools.database.dump_file(database, file_path.split('\\')[-1].replace('.xlsx','.dbc').replace('.xls','.dbc').replace('.csv','.dbc'))    

View Code

应该是全网首发了哈,有制作dbc的小伙伴们有福了,记得点赞,使用中有问题可以评论联系,会看的。

相关推荐
固定资产管理系统软件5 小时前
商务局RFID固定资产管理系统的应用价值与落地要点解析
大数据·python
lancyu6 小时前
关于多轮对话机器人的上下文Token优化和解决方案
人工智能·python·深度学习·机器学习·chatgpt·机器人·prompt
草莓橙子碗7 小时前
Claude 使用指南
开发语言·python
工具分享7 小时前
陪跑跟品爆单AI选品助手,高效跟品会赔本吗?
人工智能·python
COOLMO研究AI7 小时前
Python 如何实现 AI API 的提示词(Prompt)版本管理与热更新
人工智能·python·prompt
老郑聊AI业财智造7 小时前
Transformer 技术架构与源码分析
人工智能·python·深度学习·语言模型·架构·transformer·软件工程
程序员三藏7 小时前
自动化测试用例编写详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
230万光年的思念8 小时前
分子动力学模拟参考文献
python
HongXu_CaiYi9 小时前
0103-python相关-函数、文件
python
vortex510 小时前
从Conda到UV:Python项目依赖管理的现代演进
python·conda·uv