微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

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

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

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

废话不多说,见我72变。

首先,需要编写配置文件,我提供一个配置文件案例: 将其保存为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,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,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文件,会有如下输出

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


执行窗口会有如下输出


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


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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐