import time import hashlib from math import ceil from tqdm import tqdm from pathlib import Path from . import tools from .tools import ByteConv, IntelHex from .function import protocols, file_upgrade from .DeviceSerial import DeviceSerial ParamMap_LaminaAdapter = { # 1 - Hex # 2 - Int16 # 3 - lnt32 # 4 - str # 5 - addr # 6 - float # 8 - func_callback 0x00: ["硬件版本识别电压", 2, 1000], 0x01: ["输出电容电电压", 2, 10], 0x02: ["参考电压", 2, 10], 0x0E: ["故障字1", 1], 0x0F: ["故障字2", 1], 0x10: ["MPPT工作状态", 1], 0x11: ["系统工作状态", 1], 0x12: ["系统工作模式", 1], 0x13: ["输入电压", 2, 10], 0x14: ["电感电流", 2, 100], 0x15: ["12V电压", 2, 10], 0x16: ["输出电压", 2, 10], 0x17: ["输入电流", 2, 100], 0x18: ["温度1", 2, 10], 0x19: ["温度2", 2, 10], 0x1A: ["输入功率", 3, 1000], 0x1C: ["设备温度", 2, 10], 0x1D: ["开关机状态", 1], 0x1E: ["电池电压", 2, 10], 0x1F: ["并机功率限值", 3, 1000], 0x21: ["输出限功率电压阈值", 2, 10], 0x50: ["启停控制命令" , 2], 0x51: ["故障清除命令" , 2], 0x52: ["参数还原命令" , 2], 0x53: ["设备复位命令" , 2], 0x54: ["主动故障命令" , 2], 0x55: ["短时停机命令" , 2], 0x5E: ["抖动频率上限", 2, 100], 0x5F: ["抖动频率下限", 2, 100], 0x60: ["光伏通道使能", 1], 0x61: ["最小启动输入电压", 2, 10], 0x62: ["最大启动输入电压", 2, 10], 0x63: ["最小停止输入电压", 2, 10], 0x64: ["最大停止输入电压", 2, 10], 0x65: ["最小MPPT电压", 2, 10], 0x66: ["最大MPPT电压", 2, 10], 0x67: ["最小启动输出电压", 2, 10], 0x68: ["最大启动输出电压", 2, 10], 0x69: ["最小停止输出电压", 2, 10], 0x6A: ["最大停止输出电压", 2, 10], 0x6B: ["输入过压保护值", 2, 10], 0x6C: ["输出过压保护值", 2, 10], 0x6D: ["输出欠压保护值", 2, 10], 0x6E: ["电感过流保护值", 2, 100], 0x6F: ["输入过流保护值", 2, 100], 0x70: ["最小电感电流限值", 2, 100], 0x71: ["最大电感电流限值", 2, 100], 0x72: ["浮充电压阈值", 2, 10], 0x73: ["三点法中间阈值", 2, 10], 0x74: ["恒压充电电压", 2, 10], 0x75: ["过温故障值", 2, 10], 0x76: ["过温告警值", 2, 10], 0x77: ["温度恢复值", 2, 10], 0x78: ["最低满载电压", 2, 10], 0x79: ["最高满载电压", 2, 10], 0x7A: ["输入过载保护值", 3, 1000], 0x7C: ["最小功率限值", 3, 1000], 0x7E: ["最大功率限值", 3, 1000], 0x80: ["最大功率限值存储值", 3, 1000], 0x82: ["载波通信地址", 5, 3], 0x85: ["电压环out_max", 2, 100], 0x86: ["电压环out_min", 2, 100], 0x87: ["电流环out_max", 2, 100], 0x88: ["电流环out_min", 2, 100], 0x89: ["MPPT扰动系数k_d_vin", 2, 100], 0x8A: ["dmin", 2, 1000], 0x8B: ["dmax", 2, 1000], 0x8C: ["扫描电压偏移scanvolt_offset", 2, 10], 0x8D: ["电压环Kp", 3, 100000], 0x8F: ["电压环Ki", 3, 100000], 0x91: ["电流环Kp", 3, 100000], 0x93: ["电流环Ki", 3, 100000], 0x95: ["日志级别", 1], 0x96: ["日志输出方式", 1], 0x97: ["采样校准volt_in_a", 2, 1000], 0x98: ["采样校准volt_in_b", 2, 100], 0x99: ["采样校准volt_out_a", 2, 1000], 0x9A: ["采样校准volt_out_b", 2, 100], 0x9B: ["采样校准curr_in_a", 2, 1000], 0x9C: ["采样校准curr_in_b", 2, 100], 0x9D: ["采样校准curr_induc_a", 2, 1000], 0x9E: ["采样校准curr_induc_b", 2, 100], 0x9F: ["采样校准volt_12V_a", 2, 1000], 0xA0: ["采样校准volt_12V_b", 2, 100], 0xA1: ["温度补偿temp1_b", 2, 10], 0xA2: ["温度补偿temp2_b", 2, 10], 0xA3: ["系统工作模式", 2], 0xA4: ["电感电流给定值curr_set", 2, 100], 0xA5: ["抖动频率上限", 2, 100], 0xA6: ["抖动频率下限", 2, 100], 0xA7: ["电池电压判断限值", 2, 10], 0xA8: ["MPPT追踪模式", 1], 0xA9: ["ADC参考电压", 2, 1000], 0xAA: ["保留", 1], 0xAB: ["保留", 1], 0xAC: ["保留", 1], 0xAD: ["保留", 1], 0xAE: ["保留", 1], 0xAF: ["保留", 1], 0xB0: ["版本", 4, 16], 0x100: ["版本(ODM)", 4, 16], 0x110: ["型号", 4, 16], 0x120: ["载波芯片地址", 4, 16], 0x130: ["厂商", 4, 8], 0x138: ["保留", 4, 8], 0x140: ["保留", 4, 16], 0x150: ["保留", 4, 16], 0x160: ["硬件", 4, 16], 0x170: ["SN", 4, 16], 0x180: ["MES", 4, 16], 0x190: ["Datetime", 4, 16], 0x1A0: ["事件记录1", 8, 16], 0x1B0: ["事件记录2", 8, 16], 0x1C0: ["事件记录3", 8, 16], 0x1D0: ["事件记录4", 8, 16], 0x1E0: ["事件记录5", 8, 16], 0x1F0: ["事件记录6", 8, 16], 0x200: ["事件记录-Log", 8, 16], } MemoryMap_SLCP001 = { 'image_size': 0x100000, # 镜像文件大小 'app_size': 0x040000, # 应用程序大小 'boot_size': 0x010000, # Boot程序大小 'boot_addr': 0x000000, # Boot程序地址 'main_addr': 0x010000, # main程序地址 'back_addr': 0x0BC000, # back程序地址 'main_header': 0x0FC000, # main信息地址 'back_header': 0x0FE000, # back信息地址 } MemoryMap_460 = { 'image_size': 0x058000, # 镜像文件大小 'app_size': 0x024000, # 应用程序大小 'boot_size': 0x010000, # Boot程序大小 'boot_addr': 0x000000, # Boot程序地址 'main_addr': 0x00C000, # main程序地址 'back_addr': 0x030000, # back程序地址 'main_header': 0x054000, # main信息地址 'back_header': 0x056000, # back信息地址 } class LaminaAdapter(DeviceSerial): """ 叠光适配器\优化器 使用继承方式实现功能 """ def __init__(self, com_name, addr_645=[0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA], addr_modbus=0x01, type_dev='SLCP101', **kwargs): """ 调用超类实现函数初始化 """ super().__init__(com_name, callbacks=(lambda : protocols.make_frame_dlt645(self.block), lambda frame: protocols.check_frame_dlt645(frame, self.block)), **kwargs) self.device = type_dev match type_dev: case 'SLCP001': self.make_package = lambda *args, **kwargs: GeneratePackage('SLCP001', *args, **kwargs) self.make_image = lambda *args, **kwargs: GenerateImage('SLCP001', *args, **kwargs) case 'SLCP101': self.make_package = lambda *args, **kwargs: GeneratePackage('SLCP101', *args, **kwargs) self.make_image = lambda *args, **kwargs: GenerateImage('SLCP101', *args, **kwargs) case 'SLCP102': self.make_package = lambda *args, **kwargs: GeneratePackage('SLCP102', *args, **kwargs) self.make_image = lambda *args, **kwargs: GenerateImage('SLCP102', *args, **kwargs) case 'DLSY001': self.make_package = lambda *args, **kwargs: GeneratePackage('DLSY001', *args, **kwargs) self.make_image = lambda *args, **kwargs: GenerateImage('DLSY001', *args, **kwargs) case _: self.make_package = None self.make_image = None self.block = { 'addr' : addr_645, 'type' : 'modbus', 'data' : { 'addr_dev' : addr_modbus, 'data_define': ParamMap_LaminaAdapter, }, } def frame_read(self, daddr=0x60, dlen=0x50) -> bool: self.block['data']['type'] = 'read' self.block['data']['data_addr'] = daddr self.block['data']['data_len'] = dlen return self._transfer_data() def frame_write_one(self, daddr=0x85, dval=-900) -> bool: self.block['data']['type'] = 'write_one' self.block['data']['data_addr'] = daddr self.block['data']['data_val'] = dval item_coff = self.block['data']['data_define'][daddr][2] if len(self.block['data']['data_define'][daddr]) > 2 else 1 self.block['data_val'] = int(dval * item_coff) return self._transfer_data() def frame_write_dual(self, daddr=0x91, dval=600) -> bool: self.block['data']['type'] = 'write_dual' self.block['data']['data_addr'] = daddr self.block['data']['data_val'] = dval item_coff = self.block['data']['data_define'][daddr][2] if len(self.block['data']['data_define'][daddr]) > 2 else 1 self.block['data_val'] = int(dval * item_coff) return self._transfer_data() def frame_write_str(self, daddr=0x82, dval=[0x06, 0x05, 0x04, 0x03, 0x02, 0x01]) -> bool: self.block['data']['type'] = 'write_str' self.block['data']['data_addr'] = daddr self.block['data']['data_val'] = dval return self._transfer_data() def frame_read_log(self, step='next') -> bool: self.block['data']['type'] = 'log' self.block['data']['step'] = step return self._transfer_data() def frame_update(self, path_file: Path, makefile: bool = False) -> bool: """ 程序升级 注意: 在使用单板升级测试时, 需要关闭低电压检测功能, 否则无法启动升级流程; """ param_saved = self.flag_print, self.retry, self.time_out self.flag_print = False try: status = 'init' # 初始化 if not path_file.exists(): raise Exception("工程编译目标文件不存在.") if makefile and self.make_package is not None: self.block['data']['file'] = self.make_package(path_file) else: self.block['data']['file'] = path_file.read_bytes() self.block['data']['type'] = 'update' self.block['data']['header_offset'] = 184 status = 'start' # 启动帧 self.block['data']['step'] = 'start' self.block['data']['index'] = 0 assert self._transfer_data() self.block["data"]['file_block_size'] = self.output['upgrade']['length'] # 避免接收到延迟返回报文 time.sleep(self.time_out) status = 'trans' # 文件传输 self.retry = 3 self.time_out = 1.5 self.block["data"]['step'] = 'trans' self.block['data']['index'] = 0 frame_total = ceil((len(self.block["data"]['file']) - self.block['data']['header_offset']) / self.block["data"]['file_block_size']) for idx in tqdm(range(frame_total), desc="File Transmitting"): self.block["data"]['index'] = idx assert self._transfer_data() status = 'end' # 结束升级 self.time_out = 1 self.block["data"]['step'] = 'end' self.block["data"]['index'] += 1 assert self._transfer_data() except Exception as ex: """ 通用异常处理 """ self.flag_print, self.retry, self.time_out = param_saved report = f'Upgrade Fail: {status}' report += f', Frame in {self.block["data"]["index"]}' if status == 'trans' else '' report += f'\n Error by {ex}' if not isinstance(ex, AssertionError) else '' print(report) return False self.flag_print, self.retry, self.time_out = param_saved return True def GeneratePackage(type_dev: str, path_hex: Path, **kwargs) -> bytearray: """ 生成升级包 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(type_dev.encode('ascii')), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } match type_dev: case 'SLCP001': MemoryMap = MemoryMap_SLCP001 case 'SLCP101': MemoryMap = MemoryMap_460 case 'SLCP102': MemoryMap = MemoryMap_460 case 'DLSY001': MemoryMap = MemoryMap_460 case _: raise Exception("Unknow device.") bin_main = IntelHex.file_IntelHex_to_Bin(path_hex.read_text(), len_max=MemoryMap['app_size']) encrypt_main = file_upgrade.file_encryption(bin_main) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_hex.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Package generated successfully.") print(f"File name: {path_hex.name}") print(f"File Info:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") # 组装镜像 Image = [0xFF] * (len(main_header) + len(encrypt_main)) offset_image = 0 Image[offset_image: offset_image + len(main_header)] = main_header offset_image += len(main_header) Image[offset_image: offset_image + len(encrypt_main)] = encrypt_main # 额外处理 if 'output_bin' in kwargs.keys() and kwargs['output_bin']: (path_hex / (path_hex.stem + '.bin')).write_bytes(bin_main) return bytearray(Image) def GenerateImage(type_dev: str, path_boot: Path, path_main: Path, path_back: Path, **kwargs) ->bytearray: """ 镜像生成 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(type_dev.encode('ascii')), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } match type_dev: case 'SLCP001': MemoryMap = MemoryMap_SLCP001 case 'SLCP101': MemoryMap = MemoryMap_460 case 'SLCP102': MemoryMap = MemoryMap_460 case 'DLSY001': MemoryMap = MemoryMap_460 case _: raise Exception("Unknow device.") bin_boot = IntelHex.file_IntelHex_to_Bin(path_boot.read_text(), len_max=MemoryMap['boot_size']) bin_main = IntelHex.file_IntelHex_to_Bin(path_main.read_text(), len_max=MemoryMap['app_size']) bin_back = IntelHex.file_IntelHex_to_Bin(path_back.read_text(), len_max=MemoryMap['app_size']) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_main.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") md5_ctx = hashlib.md5() md5_ctx.update(bin_back) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_back)) config['hex_name'] = list(path_back.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (back_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") # 组装镜像 Image = [0xFF] * MemoryMap['image_size'] Image[MemoryMap['boot_addr']: MemoryMap['boot_addr'] + len(bin_boot)] = bin_boot Image[MemoryMap['main_addr']: MemoryMap['main_addr'] + len(bin_main)] = bin_main Image[MemoryMap['back_addr']: MemoryMap['back_addr'] + len(bin_back)] = bin_back Image[MemoryMap['main_header']: MemoryMap['main_header'] + len(main_header)] = main_header Image[MemoryMap['back_header']: MemoryMap['back_header'] + len(back_header)] = back_header # Log打印 print("Merge Image generated successfully.") print(f"Main File:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") print(f"Back File:") print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 额外文件 if 'output_header' in kwargs.keys() and kwargs['output_header']: (path_main.parent / (path_main.stem + '.header')).write_bytes(main_header) (path_back.parent / (path_back.stem + '.header')).write_bytes(back_header) if 'output_bin' in kwargs.keys() and kwargs['output_bin']: (path_main.parent / (path_main.stem + '.bin')).write_bytes(bin_main) (path_back.parent / (path_back.stem + '.bin')).write_bytes(bin_back) if 'output_encrypt' in kwargs.keys() and kwargs['output_encrypt']: encrypt_main = file_upgrade.file_encryption(bin_main) encrypt_back = file_upgrade.file_encryption(bin_back) (path_main.parent / (path_main.stem + '.encrypt')).write_bytes(encrypt_main) (path_back.parent / (path_back.stem + '.encrypt')).write_bytes(encrypt_back) return bytearray(Image) def GeneratePackage_SLCP001_p4a0(path_hex: Path): """ 叠光适配器-460平台版本 生成升级包 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"SLCP001"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_main = IntelHex.file_IntelHex_to_Bin(path_hex.read_text(), len_max=0x040000) encrypt_main = file_upgrade.file_encryption(bin_main) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_hex.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Package generated successfully.") print(f"File name: {path_hex.name}") print(f"File Info:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") # 组装镜像 Image = [0xFF] * (len(main_header) + len(encrypt_main)) offset_image = 0 Image[offset_image: offset_image + len(main_header)] = main_header offset_image += len(main_header) Image[offset_image: offset_image + len(encrypt_main)] = encrypt_main return bytearray(Image), bin_main def GeneratePackage_SLCP101_p460(path_hex: Path): """ 叠光适配器-460平台版本 生成升级包 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"SLCP101"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_main = IntelHex.file_IntelHex_to_Bin(path_hex.read_text(), len_max=0x024000) encrypt_main = file_upgrade.file_encryption(bin_main) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_hex.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Package generated successfully.") print(f"File name: {path_hex.name}") print(f"File Info:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") # 组装镜像 Image = [0xFF] * (len(main_header) + len(encrypt_main)) offset_image = 0 Image[offset_image: offset_image + len(main_header)] = main_header offset_image += len(main_header) Image[offset_image: offset_image + len(encrypt_main)] = encrypt_main return bytearray(Image), bin_main def GeneratePackage_SLCP102_p460(path_hex: Path): """ 叠光适配器-460平台版本 生成升级包 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"SLCP102"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_main = IntelHex.file_IntelHex_to_Bin(path_hex.read_text(), len_max=0x024000) encrypt_main = file_upgrade.file_encryption(bin_main) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_hex.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Package generated successfully.") print(f"File name: {path_hex.name}") print(f"File Info:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") # 组装镜像 Image = [0xFF] * (len(main_header) + len(encrypt_main)) offset_image = 0 Image[offset_image: offset_image + len(main_header)] = main_header offset_image += len(main_header) Image[offset_image: offset_image + len(encrypt_main)] = encrypt_main return bytearray(Image), bin_main def GenerateImage_SLCP001_p4a0(path_boot: Path, path_main: Path, path_back: Path): """ 叠光适配器-4A0平台版本 镜像生成 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"SLCP001"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_boot = IntelHex.file_IntelHex_to_Bin(path_boot.read_text(), len_max=0x010000) bin_main = IntelHex.file_IntelHex_to_Bin(path_main.read_text(), len_max=0x0CC000) bin_back = IntelHex.file_IntelHex_to_Bin(path_back.read_text(), len_max=0x040000) encrypt_main = file_upgrade.file_encryption(bin_main) encrypt_back = file_upgrade.file_encryption(bin_back) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_main.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") md5_ctx = hashlib.md5() md5_ctx.update(bin_back) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_back)) config['hex_name'] = list(path_back.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (back_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Merge Image generated successfully.") print(f"Main File:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") print(f"Back File:") print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 组装镜像 Image = [0xFF] * 0x100000 offset_image = 0 Image[offset_image: offset_image + len(bin_boot)] = bin_boot offset_image = 0x010000 Image[offset_image: offset_image + len(bin_main)] = bin_main offset_image = 0x0BC000 Image[offset_image: offset_image + len(bin_back)] = bin_back offset_image = 0x0FC000 Image[offset_image: offset_image + len(main_header)] = main_header offset_image = 0x0FE000 Image[offset_image: offset_image + len(back_header)] = back_header return bytearray(Image), main_header, back_header def GenerateImage_SLCP101_p460(path_boot: Path, path_main: Path, path_back: Path): """ 叠光适配器-460平台版本 镜像生成 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"SLCP101"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_boot = IntelHex.file_IntelHex_to_Bin(path_boot.read_text(), len_max=0x00C000) bin_main = IntelHex.file_IntelHex_to_Bin(path_main.read_text(), len_max=0x024000) bin_back = IntelHex.file_IntelHex_to_Bin(path_back.read_text(), len_max=0x024000) encrypt_main = file_upgrade.file_encryption(bin_main) encrypt_back = file_upgrade.file_encryption(bin_back) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_main.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") md5_ctx = hashlib.md5() md5_ctx.update(bin_back) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_back)) config['hex_name'] = list(path_back.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (back_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Merge Image generated successfully.") print(f"Main File:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") print(f"Back File:") print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 组装镜像 Image = [0xFF] * 0x058000 offset_image = 0 Image[offset_image: offset_image + len(bin_boot)] = bin_boot offset_image = 0x00C000 Image[offset_image: offset_image + len(bin_main)] = bin_main offset_image = 0x030000 Image[offset_image: offset_image + len(bin_back)] = bin_back offset_image = 0x054000 Image[offset_image: offset_image + len(main_header)] = main_header offset_image = 0x056000 Image[offset_image: offset_image + len(back_header)] = back_header return bytearray(Image), main_header, back_header def GenerateImage_SLCP102_p460(path_boot: Path, path_main: Path, path_back: Path): """ 叠光适配器-460平台版本 镜像生成 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"SLCP102"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_boot = IntelHex.file_IntelHex_to_Bin(path_boot.read_text(), len_max=0x00C000) bin_main = IntelHex.file_IntelHex_to_Bin(path_main.read_text(), len_max=0x024000) bin_back = IntelHex.file_IntelHex_to_Bin(path_back.read_text(), len_max=0x024000) encrypt_main = file_upgrade.file_encryption(bin_main) encrypt_back = file_upgrade.file_encryption(bin_back) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_main.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") md5_ctx = hashlib.md5() md5_ctx.update(bin_back) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_back)) config['hex_name'] = list(path_back.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (back_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Merge Image generated successfully.") print(f"Main File:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") print(f"Back File:") print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 组装镜像 Image = [0xFF] * 0x058000 offset_image = 0 Image[offset_image: offset_image + len(bin_boot)] = bin_boot offset_image = 0x00C000 Image[offset_image: offset_image + len(bin_main)] = bin_main offset_image = 0x030000 Image[offset_image: offset_image + len(bin_back)] = bin_back offset_image = 0x054000 Image[offset_image: offset_image + len(main_header)] = main_header offset_image = 0x056000 Image[offset_image: offset_image + len(back_header)] = back_header return bytearray(Image), main_header, back_header def GeneratePackage_DLSY001_p460(path_hex: Path): """ 叠光优化器-460平台版本 生成升级包 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"DLSY001"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_main = IntelHex.file_IntelHex_to_Bin(path_hex.read_text(), len_max=0x024000) encrypt_main = file_upgrade.file_encryption(bin_main) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_hex.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Package generated successfully.") print(f"File name: {path_hex.name}") print(f"File Info:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") # 组装镜像 Image = [0xFF] * (len(main_header) + len(encrypt_main)) offset_image = 0 Image[offset_image: offset_image + len(main_header)] = main_header offset_image += len(main_header) Image[offset_image: offset_image + len(encrypt_main)] = encrypt_main return bytearray(Image), bin_main def GenerateImage_DLSY001_p460(path_boot: Path, path_main: Path, path_back: Path): """ 叠光优化器-460平台版本 镜像生成 """ config = { 'prod_type': [0x45, 0x00], # 产品类型 'method_compress': False, # 文件压缩 'prog_id': list(b"DLSY001"), # 程序识别号 'prog_type': 'app', # 程序类型 'area_code': [0x00, 0x00], # 地区 } bin_boot = IntelHex.file_IntelHex_to_Bin(path_boot.read_text(), len_max=0x00C000) bin_main = IntelHex.file_IntelHex_to_Bin(path_main.read_text(), len_max=0x024000) bin_back = IntelHex.file_IntelHex_to_Bin(path_back.read_text(), len_max=0x024000) encrypt_main = file_upgrade.file_encryption(bin_main) encrypt_back = file_upgrade.file_encryption(bin_back) md5_ctx = hashlib.md5() md5_ctx.update(bin_main) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_main)) config['hex_name'] = list(path_main.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (main_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") md5_ctx = hashlib.md5() md5_ctx.update(bin_back) config["md5"] = list(md5_ctx.digest()) config['file_length'] = ByteConv.conv_int_to_array(len(bin_back)) config['hex_name'] = list(path_back.name.encode())[:64] config['hex_name'] += [0] * (64 - len(config['hex_name'])) if (back_header:=file_upgrade.build_header_new(config)) is None: raise Exception("Header tag oversize. ") print("Merge Image generated successfully.") print(f"Main File:") print(f"\t header_length={len(main_header)}, bin_length={len(bin_main)}[{hex(len(bin_main))}]") print(f"Back File:") print(f"\t header_length={len(back_header)}, bin_length={len(bin_back)}[{hex(len(bin_back))}]") # 组装镜像 Image = [0xFF] * 0x058000 offset_image = 0 Image[offset_image: offset_image + len(bin_boot)] = bin_boot offset_image = 0x00C000 Image[offset_image: offset_image + len(bin_main)] = bin_main offset_image = 0x030000 Image[offset_image: offset_image + len(bin_back)] = bin_back offset_image = 0x054000 Image[offset_image: offset_image + len(main_header)] = main_header offset_image = 0x056000 Image[offset_image: offset_image + len(back_header)] = back_header return bytearray(Image), main_header, back_header