经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
python脚本制作、生成、创建一个CANdbc文件
来源:cnblogs  作者:冻雨冷雾  时间:2024/1/5 9:12:24  对本文有异议

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

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

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

  1. import cantools
  2. db = cantools.database.load_file('xxxx.dbc')
  3. cantools.database.dump_file(db, 'bar.dbc')

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

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Wed Dec 27 18:09:18 2023
  4. @author: xm
  5. 如何创建生成canfd还待挖掘
  6. """
  7.  
  8. import cantools
  9. # 定义一个消息
  10. message1 = cantools.db.Message( #cantools.database.can.message.Message
  11. frame_id=0x19FB5101, #435900673
  12. name='PFC_VacReport',
  13. length=8,
  14. bus_name='PFC',
  15. header_byte_order='big_endian',
  16. is_extended_frame=True,
  17. # is_multiplexed=True,
  18. # refresh=True,
  19. is_fd=False,
  20. send_type='cyclic',
  21. senders=['PFC'],
  22. cycle_time=20,
  23. comment='input voltage',
  24. unused_bit_pattern=255,
  25. # unpack_container=True,
  26. signals=[
  27. cantools.db.Signal(
  28. name='P_VacRpt_VacRms_A',
  29. start=0,
  30. length=12,
  31. is_signed=False,
  32. scale=0.1,
  33. offset=0,
  34. minimum=0,
  35. maximum=409.5,
  36. unit='V',
  37. invalid=None,
  38. initial=0,
  39. # is_multiplexer=False,
  40. # is_float=False,
  41. receivers=['IFB','LC'],
  42. # multiplexer_signal=None,
  43. # multiplexer_ids=None,
  44. byte_order='little_endian', #little_endian big_endian
  45. comment='valid voltage phase A',
  46. ),
  47. cantools.db.Signal(
  48. name='P_VacRpt_VacRms_B',
  49. start=12,
  50. length=12,
  51. is_signed=False,
  52. scale=0.1,
  53. offset=0,
  54. minimum=0,
  55. maximum=409.5,
  56. unit='V',
  57. invalid=None,
  58. initial=0,
  59. # is_multiplexer=False,
  60. # is_float=False,
  61. receivers=['IFB','LC'],
  62. # multiplexer_signal=None,
  63. # multiplexer_ids=None,
  64. byte_order='little_endian',
  65. comment='valid voltage phase b',
  66. ),
  67. cantools.db.Signal(
  68. name='P_VacRpt_VacRms_C',
  69. start=24,
  70. length=12,
  71. is_signed=False,
  72. scale=0.1,
  73. offset=0,
  74. minimum=0,
  75. maximum=409.5,
  76. unit='V',
  77. invalid=None,
  78. initial=0,
  79. # is_multiplexer=False,
  80. # is_float=False,
  81. receivers=['IFB','LC'],
  82. # multiplexer_signal=None,
  83. # multiplexer_ids=None,
  84. byte_order='little_endian',
  85. comment='valid voltage phase c',
  86. ),
  87. ]
  88. )
  89. node1 = cantools.db.Node(
  90. name='PFC'
  91. )
  92. # 定义一个数据库
  93. database = cantools.db.Database(
  94. messages=[message1],
  95. nodes=[node1,],
  96. version='1.0'
  97. )
  98. # 保存为DBC文件
  99. cantools.database.dump_file(database, 'example.dbc')
View Code

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

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Wed Dec 27 20:35:47 2023
  4. @author: xm Azhe
  5. """
  6.  
  7. import pandas as pd
  8. import cantools
  9. import openpyxl
  10. file_path = r'D:\代码\dbc文件处理\xx.xlsx'
  11.  
  12. # In[0] 文件改造,合并单元格填充
  13. # 打开Excel文件
  14. workbook = openpyxl.load_workbook(file_path)
  15. # 遍历所有工作表
  16. for worksheet in workbook.worksheets:
  17. # 获取所有合并单元格
  18. merged_cells = worksheet.merged_cells
  19. # if worksheet.title=='IFB协议E2E ':
  20. # print(merged_cells)
  21. # 遍历合并单元格
  22. for merged_cell in list(merged_cells):
  23. # 获取合并单元格的起始行、列和结束行、列
  24. start_row, start_col, end_row, end_col = merged_cell.min_row,merged_cell.min_col,merged_cell.max_row,merged_cell.max_col,
  25. # 拆分
  26. worksheet.unmerge_cells(start_row=start_row,start_column=start_col,end_row=end_row,end_column=end_col)
  27. # 获取合并单元格的值
  28. cell_value = worksheet.cell(start_row, start_col).value
  29. # if worksheet.title=='IFB协议E2E ':
  30. # print(merged_cell)
  31. # print('\n')
  32. # 将合并单元格内的所有单元格都替换为该值
  33. for row in range(start_row, end_row + 1):
  34. for col in range(start_col, end_col + 1):
  35. worksheet.cell(row, col).value = cell_value
  36. file_path1=file_path.replace('.xlsx','_dealed.xlsx')
  37. # 保存Excel文件
  38. workbook.save(file_path1)
  39. # In[0] excel内包含公式,需要刷新公式,否则会读取为nan
  40. import win32com.client
  41. # Start an instance of Excel
  42. xlapp = win32com.client.DispatchEx("Excel.Application")
  43. # Open the workbook in said instance of Excel
  44. wb = xlapp.workbooks.open(file_path1)
  45. # Optional, e.g. if you want to debug
  46. # xlapp.Visible = True
  47. # Refresh all data connections.
  48. wb.RefreshAll()
  49. wb.Save()
  50. # Quit
  51. xlapp.Quit()
  52. # In[1] df读取,删除信号名称为空,忽略第一行
  53. def str_to_num(s):
  54. try:
  55. return int(s)
  56. except ValueError:
  57. try:
  58. return float(s)
  59. except ValueError:
  60. return s
  61. df={}
  62. for s in pd.ExcelFile(file_path1).sheet_names:
  63. # print(s)
  64. if ('协议' in s) & (s!='协议说明'):
  65. df[s] = pd.read_excel(file_path1, sheet_name=s,skiprows=1, engine='openpyxl')
  66. df[s] = df[s].dropna(subset=['数据名称'])
  67. node_list=[]
  68. msg_list=[]
  69. # cnt=1
  70. for s in list(df.keys()):
  71. node_list.append(cantools.db.Node(name=s.replace(' ','').replace('协议E2E','')))
  72. msg_list_tmp=list(df[s]['ID'].drop_duplicates())
  73. for i in msg_list_tmp:
  74. # if s=='LVDC协议E2E':
  75. # cnt1=1
  76. # print('y')
  77. signals_list_tmp=[]
  78. df_sig_list_tmp=list(df[s]['数据名称'][df[s]['ID']==i])
  79. for j in df_sig_list_tmp:
  80. signals_list_tmp.append(
  81. cantools.db.Signal(
  82. name=j,
  83. start=str_to_num(df[s]['起始位'][df[s]['数据名称']==j]),
  84. length=str_to_num(df[s]['长度'][df[s]['数据名称']==j]),
  85. is_signed=False,
  86. scale=df[s]['精度'][df[s]['数据名称']==j].values[0],
  87. offset=str_to_num(df[s]['OFFSET'][df[s]['数据名称']==j]),
  88. minimum=df[s]['Min'][df[s]['数据名称']==j].values[0],
  89. maximum=df[s]['Max'][df[s]['数据名称']==j].values[0],
  90. unit=str(df[s]['单位'][df[s]['数据名称']==j].values[0]),
  91. invalid=None, #未采用dbc
  92. initial=str_to_num(df[s]['Initial'][df[s]['数据名称']==j]),
  93. # is_multiplexer=False,
  94. # is_float=False,
  95. receivers=df[s]['接收'][df[s]['数据名称']==j].values[0].split('&'),
  96. # multiplexer_signal=None,
  97. # multiplexer_ids=None,
  98. byte_order='little_endian', #little_endian big_endian
  99. comment=str(df[s]['说明'][df[s]['数据名称']==j].values[0]),
  100. # comments=None
  101. ))
  102. msg_list.append(cantools.db.Message( #cantools.database.can.message.Message
  103. frame_id=int(i[:i.index("\n")], 16),
  104. name=i[i.index("(")+1:i.index(")")],
  105. length=8,
  106. bus_name=df[s]['发送'][df[s]['ID']==i].values[0],
  107. header_byte_order='big_endian',
  108. is_extended_frame=True,
  109. is_fd=False,
  110. send_type='cyclic',
  111. senders=[df[s]['发送'][df[s]['ID']==i].values[0]],
  112. cycle_time=str_to_num(df[s]['周期'][df[s]['ID']==i].values[0][:df[s]['周期'][df[s]['ID']==i].values[0].index("ms")]),
  113. comment=str(df[s]['备注'][df[s]['ID']==i].values[0]),
  114. unused_bit_pattern=255,
  115. # unpack_container=True,
  116. signals=signals_list_tmp
  117. ))
  118. # if s=='LVDC协议E2E':
  119. # cnt1=cnt1+1
  120. # if cnt1==3:
  121. # break
  122. # cnt=cnt+1
  123. # if cnt==5:
  124. # break
  125. database = cantools.db.Database(
  126. # messages=[message1],
  127. messages=msg_list,
  128. nodes=node_list,
  129. version='1.0'
  130. )
  131. cantools.database.dump_file(database, file_path.split('\\')[-1].replace('.xlsx','.dbc').replace('.xls','.dbc').replace('.csv','.dbc'))
View Code

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

 

原文链接:https://www.cnblogs.com/techs-wenzhe/p/17943020

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号