利用python给文件加CRC校验信息

小编:饿狼 更新时间:2022-09-01
利用python给文件加CRC校验信息

HELLO,大家好,好久不见,最近太忙了, 几个月没有更新文章了。

最近在项目开发过程中,做每个项目的bootloader升级时,就得修订对应的头部打包脚本,或者是有界面的打包工具,都需要把对应的厂商、项目相关的信息手动输入,每打包一次,需要手动输入一次这些项目相关的数据,太麻烦了!!!

本文,将使用python+配置文件的方式,自动读取源bin文件并自动生成可定制化的带头部的目的文件。

废话不多说,见我72变。

利用python给文件加CRC校验信息
  • 需要编写配置文件,我提供一个配置文件案例: 将其保存为xxxx.headconfig

注意文件名字不重要,后缀名一定需要是.headconfig

具体怎么增加填充修订xxxx.headconfig,如下文件,请自行填充。

hello, 这是自动打包头部的工具,请按照项目属性进行配置. 我们需要配置编译生成的输出的文件名【可带编译路径】: ====================================================== 0、>>testota.bin>> 我们需要设置升级文件头部信息,请按照项目属性进行配置. ================升级文件头部配置起始==================== ================请按规定修订定制值====================== 1、厂商ID:8字节 ##XXXX1234## 2、产品规格:8字节 ##XXXX5678## 3、硬件版本号:3字节 ##V001## 4、固件版本号:3字节 ##V001## 5、... ================升级文件头部配置结束==================== 最后,我们需要设置输出文件名信息,请按照项目属性进行配置. ================输出文件名配置起始====================== ================请按规定修订定制值====================== 1、项目名称: @@XXX123@@ 2、硬件版本号 @@V100@@ 3、固件版本号 @@V100@@ 4、... ================输出文件名配置结束====================== 再见

  • 编写python解析该文件,具体代码我直接给出:
  • 测试环境为windows

import crcmod import re import os import sys # 方法1, 与方法2效果一致 cr16_xmodem = crcmod.predefined.mkCrcFun('modbus') # 方法2, 与方法1效果一致 # cr16_xmodem = crcmod.mkCrcFun(0x18005, initCrc=0xFFFF, rev=True, xorOut=0x0000) # print(hex(cr16_xmodem(bytearray(data)))) header_mes = [] out_bin = [] in_bin = [] # 厂商ID:8字节 # 产品规格:8字节 # 硬件版本号:4字节 # 固件版本号:4字节 head_conf_len = [8, 8, 4, 4] HEADER_LENGTH = 64 TOOLS_VERSION = 'V1.0.0' print('') print('**************************科学防疫,健康生活**************************') print('* *') print('**************************自动打包头部工具***************************') print('* *') print('**************************工具版本号:%s%s' % (TOOLS_VERSION,'**************************')) str_update_pat = re.compile(r'\##(.*)\##') str_outpath_pat = re.compile(r'\@@(.*)\@@') str_in_bin_path_pat = re.compile(r'\>>(.*)\>>') # 提取文件夹下的地址+文件名 def file_name(file_dir, file_pat): L = [] for root, dirs, files in os.walk(file_dir): for file in files: if os.path.splitext(file)[1] == file_pat: L.append(os.path.join(root, file)) return L # 获取头部配置文件 config_path_list = file_name('.', '.headconfig') config_path = '' for conf in config_path_list: config_path += conf.strip(); print('头部配置文件:%s' % conf) if (len(config_path_list) != 1): print('头部配置文件不存在或者存在多份!') os.system('cmd') sys.exit(1) with open(config_path, 'rt', encoding='utf8') as conf: configs = conf.readlines() for line in configs: header_mes += str_update_pat.findall(line) out_bin += str_outpath_pat.findall(line) in_bin += str_in_bin_path_pat.findall(line) # 拼接头部填充值 header_mes_str = '' header_mes_one_len = [] for line in header_mes: header_mes_one_len.append(len(line.strip())) header_mes_str += line # 拼接输出文件名 out_bin_path = '' for line in out_bin: out_bin_path += line.strip() + '-' # 拼接输入文件名 in_bin_path = '' for line in in_bin: in_bin_path += line.strip() out_bin_path = out_bin_path.rstrip('-') out_bin_path += '-UP.bin' print('头部数据:%s' % header_mes_str) print('输出文件名:%s' % out_bin_path) print('输入文件路径:%s' % (in_bin_path)) if header_mes_one_len != head_conf_len: print('头部配置不符合规范,请检查头部配置!') os.system('cmd') sys.exit(2) if(os.path.exists(in_bin_path) != True): print('输入文件不存在!') os.system('cmd') sys.exit(3) try: srcbin_len = os.path.getsize(in_bin_path) with open(in_bin_path, 'rb') as sf: srcbin = sf.read() except UnicodeError: print('文件编码出错!') else: print('源文件的长度:%d' % srcbin_len) srcbin_crc = cr16_xmodem(srcbin) print('源文件CRC值:', hex(srcbin_crc)) header_mes = list(header_mes_str.encode('utf-8')) srcbin_len_bytes = int(srcbin_len).to_bytes(4, byteorder='big', signed=False) for i in range(len(srcbin_len_bytes)): header_mes.append(srcbin_len_bytes[i]) srcbin_crc_bytes = int(srcbin_crc).to_bytes(2, byteorder='big', signed=False) for i in range(len(srcbin_crc_bytes)): header_mes.append(srcbin_crc_bytes[i]) header_mes_crc = cr16_xmodem(bytearray(header_mes)) print('头部CRC【填充0xFF前】:', hex(header_mes_crc)) head_mes_crc_bytes = int(header_mes_crc).to_bytes(2, byteorder='big', signed=False) for i in range(len(head_mes_crc_bytes)): header_mes.append(head_mes_crc_bytes[i]) print('填充前头部的长度:%d' % (len(header_mes))) for i in range(len(header_mes), HEADER_LENGTH): header_mes.append(0xFF) print('填充后头部的长度:%d' % (len(header_mes))) with open(out_bin_path, 'wb') as out: out.write(bytearray(header_mes)) out.write(bytearray(srcbin)) with open(out_bin_path, 'rb') as rout: outbin_file = rout.read() outbin_len = os.path.getsize(out_bin_path) print('填充头部后的输出文件长度:%d' % outbin_len) print('填充头部后的输出文件CRC:', hex(cr16_xmodem(outbin_file))) if ((srcbin_len + HEADER_LENGTH) != outbin_len): print('**************************头部填充失败了**************************') else: print('**************************头部填充成功了**************************') print('') os.system('cmd')

  • 为了能在没有安装python环境的电脑上运行,此处将python脚本进行打包成exe文件:

//将保留打印输出调试信息 pyinstaller -F --clean auto_add_header.py //如果不保留打印调试信息 pyinstaller -F -w --clean auto_add_header.py //可以修改exe文件图标,一定需要是.ico文件 pyinstaller -F -i test.ico auto_add_header.py

  • 可以在dist文件夹下生成auto_add_header.exe文件
  • 准备好test.bin, head_mes.headconfig, auto_add_header.exe,双击auto_add_header.exe文件, 会有如下输出:
利用python给文件加CRC校验信息

如果头部配置文件输入不符合规范,如:



利用python给文件加CRC校验信息

执行窗口会有如下输出:



利用python给文件加CRC校验信息

好了,差不多了,工具拿走不谢!



利用python给文件加CRC校验信息

最后,希望大家科学防疫,健康生活!!!