使用背景
通过上位机给设备压测升级,需要升级1000次及以上,因此,通过手动点击串口按钮并选择升级固件再确认升级不太现实。为了解决这个问题,笔者通过pywinauto中的application来自动化识别exe程序界面控件属性,并且模拟人工手动点击。
调用库
1 2 3 4 5
| from pywinauto.application import Application import datetime import time from loguru import logger import serial
|
保存日志
1
| logger.add("串口升级固件10000次_runtime_{time}.log", encoding='utf-8')
|
构建类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Update_Upper_Computer(): def __init__(self, time_sleep, update_count, COM, software_path): self.time_sleep = time_sleep self.update_count = update_count self.com = COM self.software_path = software_path self.update_H3PI_version1 = r"D:\Date\固件\PP_v1.0.1.bin" self.update_H3PI_version2 = r"D:\Date\固件\APP_v1.0.2.bin" self.check_H3PI_version1 = "v1.0.1" self.check_H3PI_version2 = "v1.0.2"
self.update_success_count = 0 self.update_fail_count = 0 self.update_all_count = 0
|
当前时间函数
1 2 3
| def now_time(self): time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') return str(time)
|
读取串口函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| def ser_read(self, ser): '''串口读取''' print('正在读取串口内容!') data = '' while True: data = ser.readline() logger.info(data) print('***********') time1 = time.time() logger.info(time1) t = time.ctime() print(t, ':') print(data) with open('D:/111.txt', 'a') as f: f.writelines(t) f.writelines(':\n') try: f.writelines(data.decode(encoding='utf-8')) except Exception as e: print(e)
|
升级函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| def update_H3PI(self): for i in range(self.update_count): ser = serial.Serial(self.com, 115200, 8, 'N', 1)
command2 = "1005B\n" ser.write(command2.encode('utf-8'))
content = ser.read(1000) print(str(content))
content1 = content.decode('utf-8', 'ignore') logger.info(content1)
ser.close() print(content1) time.sleep(5)
update_firmware_version_path = " " if self.check_H3PI_version1 in content1: print("当前固件版本为" + self.check_H3PI_version1 + ",即将升级固件版本为" + self.check_H3PI_version2) logger.info( "当前固件版本为" + self.check_H3PI_version1 + ",即将升级固件版本为" + self.check_H3PI_version2) update_firmware_version_path = self.update_H3PI_version2 update_firmware_version_check = self.check_H3PI_version2 elif self.check_H3PI_version2 in content1: print("当前固件版本为" + self.check_H3PI_version2 + ",即将升级固件版本为" + self.check_H3PI_version1) logger.info( "当前固件版本为" + self.check_H3PI_version2 + ",即将升级固件版本为" + self.check_H3PI_version1) update_firmware_version_path = self.update_H3PI_version1 update_firmware_version_check = self.check_H3PI_version1 app = Application(backend="uia").start(self.software_path)
dlg = app["H3更新工具"]
combo = dlg.child_window(auto_id="port_comboBox1") time.sleep(5) combo.wait('visible', timeout=5) combo.select(self.com) open_button = dlg.child_window(auto_id="port_open_button1") open_button.click() encrypt_tab = dlg.child_window(title="加密芯片升级") encrypt_tab.select() file_path_box = dlg.child_window(auto_id="encrypt_chip_textBox") file_path_box.set_text(update_firmware_version_path)
update_button = dlg.child_window(auto_id="encrypt_chip_update_button") update_button.click()
time.sleep(self.time_sleep)
app.kill() self.update_all_count = self.update_all_count + 1 time.sleep(5) ser = serial.Serial(self.com, 115200, 8, 'N', 1)
command2 = "1005B\n" ser.write(command2.encode('utf-8')) content = ser.read(1500) content1 = content.decode('utf-8', 'ignore') logger.info(content1) ser.close() if update_firmware_version_check in content1: self.update_success_count = self.update_success_count + 1 print("当前时间:" + self.now_time()) logger.info("当前时间:" + self.now_time()) print("当前升级状态统计:\n升级总次数:" + str(self.update_all_count) + "\n升级成功次数:" + str( self.update_success_count) + "\n升级失败次数:" + str(self.update_fail_count)) logger.info("当前升级状态统计:\n升级总次数:" + str(self.update_all_count) + "\n升级成功次数:" + str( self.update_success_count) + "\n升级失败次数:" + str(self.update_fail_count)) else: print("当前时间:" + self.now_time()) logger.info("当前时间:" + self.now_time()) self.update_fail_count = self.update_fail_count + 1 print("当前升级状态统计:\n升级总次数:" + str(self.update_all_count) + "\n升级成功次数:" + str( self.update_success_count) + "\n升级失败次数:" + str(self.update_fail_count)) logger.info("当前升级状态统计:\n升级总次数:" + str(self.update_all_count) + "\n升级成功次数:" + str( self.update_success_count) + "\n升级失败次数:" + str(self.update_fail_count)) time.sleep(5)
|
主函数
1 2 3 4 5 6 7
| if __name__ == "__main__": a = Update_Upper_Computer(180, 10000, "COM37", r"D:\Program\固件更新工具\升级配置工具 v1.0.0.5 2025.01.09\升级配置工具 v1.0.0.5 2025.01.09.exe")
print(a.com) a.update_H3PI()
|
调试函数
举一反三,如果读者想要模拟控制别的exe运行文件,确不知道相应控件的属性,那么可以通过以下函数来获取。如果需要选择的界面在另一个tabcontrol中,可以先去选中另一个tabcontrol再打印窗口控件信息。
1 2 3 4 5 6 7 8 9 10 11
| from pywinauto.application import Application
app = Application(backend="uia").start( r"D:\Program\固件更新工具\升级配置工具 v1.0.0.5 2025.01.09\升级配置工具 v1.0.0.5 2025.01.09.exe")
dlg = app.window(title_re=".*H3.*")
dlg.print_control_identifiers()
|
本文使用升级工具
下载固件升级工具(仅供学习交流使用!)