详解如何使用python脚本制作生成CANdbc
最近在工作中,有同事拿了一个excel的dbc表格,在用官方的dbc工具一个一个创建信号,大概看了一下共累计20多个节点,300多个信号,居然在手动处理,顿感无语。。
于是在网络上搜相关的dbc 通过脚本生成方式,竟然没搜到!那只能全网首发一个给广大汽车软件同行谋个福利。
(经过国内一番搜索,一无所获。于是乎转谷歌搜索,在cantools 这个库官网文件下找到这么一个指令:)
import cantools db = cantools.database.load_file('MS11_E4U2_CCU_PTCANFD_230701.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=[ js 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, python 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')
接下来就是解析对应的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]), l编程ength=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]android), 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'))
有制作dbc的小伙伴们有福了
以上就是详解如何使用python脚本制作生成CANdbc的详细内容,更多关于python生成CANdbc的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论