java flush 进度条_Response.Flush的使用心得

本文介绍ASP.NET中使用Response.Flush()实现进度显示的方法,并探讨其最小有效数据量阈值。此外,还涉及了多文件上传插件Uploadify的特性和使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Response.Flush的使用心得

很多时候我们写的asp程序会因为做很多操作,所以会花上一分钟甚至几分钟时间。为了使软件使用者能够耐心的等待程序的执行,我们经常会希望有一个进度条来表示程序执行的状态。或者最起码要显示一个类似: “数据载入中”,“正在保存数据” 等的说明性文字。此时我们就会用到Response.flush()。他会将缓冲区中编译完成的数据先发送到客户端。

但是有很多时候,我们发现即使我们使用了Response.Flush(),但是并没有将前面的信息发到客户端来显示。呈献给我们的依然是白屏。经过反复的测试,我得出一个结论(仅代表个人观点,可随意引用,但后果自负)。就是flush的内容至少要有256字节。也就是只有编译产生了至少256字节的数据,才能在执行Response.Flush()以后将信息发到客户端并显示。

时间: 2006-09-27

6b5aa0751a6f1e6a9d0b665a02cc1f46.gif

通过Response.Flush()实现对服务端文件的下载时,会失败,不能正常弹出IE下载框,经过测试发现需要进行如下设置后即可解决. 进入 [工具]--->[Internet选项]--->[安全]--->[可信任站点]  文件下载的自动提示改成启用即可解决问题 当然得把访问的网站加入到信任站点才行.

写程序的人在编写由asp页面生成静态页面html的时候,如果同时生成大量页面,一定遇到过浏览器下方的进度条上显示着3%,6%,10%等缓慢增长的漫长等待过程.在这个等待过程中,你不知道页面已经生成到哪一条记录,只能大眼瞪小眼的等. 如果你知道Response.Flush和Response.Clear,那你就可以不用这样的等待了.每生成一个Html页面,就用Response.write立即返回一条信息,提示该条数据库记录已经生成Html. 这样,在同时生成大量页面的时候,你就不再是孤独的望着一片空

本文实例讲述了ASP.NET网站实时显示时间的方法.分享给大家供大家参考.具体方法如下: 在ASP.NET环境中开发设计网站或网络应用程序时,往往需要实时显示当前日期和时间.这时,通常使用AJAX控件来实现. 需要注意的是,在.NET Framework 2.0版本中,工具箱中是没有AJAX Extensions控件的.而.NET Framework 3.5版本中集成了AJAX. ASP.NET AJAX包括三部分: ①一个扩展客户端JavaScript功能的客户端库或框架: ②一个允许ASP.

c280c8f93ab31963230bd5a3e1838c86.png

先了解了解Uploadify,具体内容如下 Uploadify是一个简单易用的多文件上传方案.作为一个Jquery插件,Uploadify使用简单,并具有高度的定制性. Uploadify特性: Uploadify简单说来,是基于Jquery的一款文件上传插件.它的功能特色总结如下: 1).支持单文件或多文件上传,可控制并发上传的文件数 2).在服务器端支持各种语言与之配合使用,诸如PHP,.NET,Java-- 3).通过参数可配置上传文件类型及大小限制 4).通过参数可配置是否选择文件后自动

用过软件的朋友都知道,进度条是一个优秀软件的重要组成部分. 它的存在能够使用户及时掌握程序的运行进度,确认应用程序正常工作.可是ASP中似乎没有上述标准控件,控制起来也比较麻烦. 那幺如何实现进度条呢? 以下是本人的一些观点(仅供参考) 我们通常在用ASP处理程序(指的是写文件或操作数据库)的时候,会专门用一个页面(*.asp)去处理或控制这些程序,当处理完毕的时候再跳转到显示页面.这时我们就可以通过这些处理页面显示进度条.其方法是根据程序处理的进度依次画一百张同样的图形(如有颜色的矩形),从而

8d314ee543b8495c0c0453ddef957feb.png

ajax应用越来越多,大部分ajax处理都是在前台显示1个"loading...",然后把数据提交给服务器进行处理,处理完毕后显示"处理完毕".我们能否让ajax更加友好点,实时显示服务器处理的进度了?这在一些长时间的请求中尤其重要,比如上传文件.发送邮件.批量处理数据.答案当然是可以的,不然就不会写这个了,对吧,^_^. 存在的问题: 要解决实现上面的功能,需要解决下面几个问题: 1. 服务器如何在处理一部分数据后传递部分response到浏览器. 2.浏览器如何

本文实例讲述了Python实现采用进度条实时显示处理进度的方法.分享给大家供大家参考,具体如下: 前言 在大多数时候,我们的程序会一直进行循环处理.这时候,我们非常希望能够知道程序的处理进度,由此来决定接下来该做些什么.接下来告诉大家如何简单又漂亮的实现这一功能. 如何使用这个类 使用这个类很简单,只需要三步即可完成,如下: process_bar = ShowProcess(max_steps) # 1.在循环前定义类的实体, max_steps是总的步数 for i in range(max

前言 在大多数时候,我们的程序会一直进行循环处理.这时候,我们非常希望能够知道程序的处理进度,由此来决定接下来该做些什么.接下来告诉大家如何简单又漂亮的实现这一功能. 如何使用这个类 使用这个类很简单,只需要三步即可完成,如下: process_bar = ShowProcess(max_steps) # 1.在循环前定义类的实体, max_steps是总的步数 for i in range(max_steps + 1): process_bar.show_process() # 2.显示当前进

response.buffer=true ' 应用缓存技术. dim lostnum ' 防止dmax过大而dstep过小. dim shownum delayshow(dstep,dmax) sub delayshow(dstep,dmax) ' dmax表示要处理多少dmax(步)才能完成全过程,dstep表示已处理的占全过程的大致百分比. dim total ' 显示所有画面. dim dtemp ' 过渡变量. total=100 dtemp=dstep dstep=dstep+lost

一个投票功能模块少不了查看投票结果,用进度条显示各个投票结果可以起到一目了然的效果.以下是我的方法,请大家不吝赐教:  1:做一张图片用于做进度条,只需要很小的一个图片就可以了,如高20px,宽1px. 2:在要显示进度条的单元格中插入image控件,其imageUrl设置为已做好的图片的位置. 3:用一个dataReader对象dr保存取出的各项票数,用一个int 型变量sum保存取出的总票数,各项分别再定义一个double型变量用来保存单项票数除以(/)总票数的结果(小数),再定义一个int

import json import os import threading import PySimpleGUI as sg import telnetlib import time import queue import logging from datetime import datetime import re # ============== 全局配置 ============== DATA_FILE = 'pyremote_config.json' PROJECTS_FILE = 'projects_config.json' END_STR = "ROUTER_MPU /home\x1b[m # " LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' ENCODING = 'utf-8' BUFFER_SIZE = 4096 CHUNK_SIZE = 10 CHUNK_DELAY = 0.15 COMMAND_DELAY = 0.5 MAX_PORTS = 2 AUTO_OPERATION_SUCCESS_STR = "Close watchdog" BOOT_STRING = r"Press\s*['\"]?Ctrl\+T['\"]?\sto\sskip\s*boot" SUCCESS_PATTERNS = { "watchdog -close": r"Close watchdog", "ifconfig eth0": r"Set eth IpAddr:.?Mask:.?Gateway:", "ftp -get": r"Ftp get .? success", "flash -w": r"Flash write .? ret=0" } ERROR_PATTERNS = [ r"error", r"fail", r"invalid", r"not found", r"timeout", r"unrecognized" ] # ============== 日志配置 ============== def setup_logger(): logger = logging.getLogger('RemoteControl') logger.setLevel(logging.DEBUG) file_handler = logging.FileHandler('remote_control.log') file_handler.setFormatter(logging.Formatter(LOG_FORMAT)) console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter(LOG_FORMAT)) logger.addHandler(file_handler) logger.addHandler(console_handler) return logger logger = setup_logger() # ============== 项目管理类 ============== class ProjectManager: def __init__(self): self.last_modified = {} self.projects = self.load_projects() def load_projects(self): default = {"projects": []} if not os.path.exists(PROJECTS_FILE): return default try: with open(PROJECTS_FILE, 'r', encoding='utf-8') as f: projects = json.load(f) if not isinstance(projects, dict) or "projects" not in projects: logger.warning("项目配置文件格式错误,使用默认结构") return default for project in projects["projects"]: if "name" in project: self.last_modified[project["name"]] = datetime.now() return projects except Exception as e: logger.error(f"加载项目配置失败: {e}") return default def save_projects(self): try: with open(PROJECTS_FILE, 'w', encoding='utf-8') as f: json.dump(self.projects, f, indent=4, ensure_ascii=False) for project in self.projects["projects"]: if "name" in project: self.last_modified[project["name"]] = datetime.now() return True except Exception as e: logger.error(f"保存项目配置失败: {e}") return False def add_or_update_project(self, name, commands, auto_operation=False, index=None): project = { "name": name, "commands": commands, "auto_operation": auto_operation, "bios_commands": [], "rbos_commands": [], "initrd_commands": [], "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } if index is None: # 添加新项目 if "projects" not in self.projects: self.projects["projects"] = [] self.projects["projects"].append(project) else: # 更新项目 if 0 <= index < len(self.projects["projects"]): # 保留原有升级指令 for key in ["bios_commands", "rbos_commands", "initrd_commands"]: project[key] = self.projects["projects"][index].get(key, []) self.projects["projects"][index] = project self.last_modified[name] = datetime.now() return self.save_projects() def update_upgrade_commands(self, index, upgrade_type, commands): if 0 <= index < len(self.projects["projects"]): project = self.projects["projects"][index] project_name = project["name"] if upgrade_type in ["bios", "rbos", "initrd"]: project[f"{upgrade_type}_commands"] = commands self.last_modified[project_name] = datetime.now() return self.save_projects() return False def get_upgrade_commands(self, index, upgrade_type): if 0 <= index < len(self.projects["projects"]): project = self.projects["projects"][index] if upgrade_type in ["bios", "rbos", "initrd"]: return project.get(f"{upgrade_type}_commands", []) return [] def delete_project(self, index): if 0 <= index < len(self.projects["projects"]): project_name = self.projects["projects"][index]["name"] del self.projects["projects"][index] if project_name in self.last_modified: del self.last_modified[project_name] return self.save_projects() return False def import_export_projects(self, file_path, action='import'): try: if action == 'import': with open(file_path, 'r', encoding='utf-8') as f: imported = json.load(f) if not isinstance(imported, dict) or "projects" not in imported: logger.error("导入的项目文件格式不正确") return False self.projects = imported self.last_modified = {} for project in self.projects["projects"]: if "name" in project: self.last_modified[project["name"]] = datetime.now() return self.save_projects() else: # export with open(file_path, 'w', encoding='utf-8') as f: json.dump(self.projects, f, indent=4, ensure_ascii=False) return True except Exception as e: action_str = "导入" if action == 'import' else "导出" logger.error(f"{action_str}项目失败: {e}") return False def get_project_commands(self, index): if 0 <= index < len(self.projects["projects"]): return self.projects["projects"][index].get("commands", []) return [] def get_project_last_modified(self, name): return self.last_modified.get(name, datetime.min) # ============== 指令执行类 ============== class CommandExecutor: def __init__(self, port_id): self.port_id = port_id self.tn = None self.is_connected = False self.log_queue = queue.Queue() self.lock = threading.Lock() self.stop_event = threading.Event() self.pause_event = threading.Event() self.last_response = "" self.expected_prompt = END_STR self.current_command_index = -1 self.current_command = "" self.total_commands = 0 self.log_file = None self.log_file_path = "" self.auto_mode = False self.boot_string_detected = False self.auto_completed = False self.auto_operation_callback = None self.command_success = False self.retry_count = 0 self.project_index = -1 self.project_name = "" self.project_manager = None self.max_retries = 3 self.retry_delay = 1 self.max_retry_delay = 30 self.upgrade_type = "" self.max_attempts = 10 self.timeout = 30 def set_project_manager(self, manager): self.project_manager = manager def set_log_file(self, file_path): self.log_file_path = file_path try: if self.log_file: self.log_file.close() self.log_file = open(file_path, 'a', encoding=ENCODING) return True except Exception as e: self.log_queue.put(f"打开日志文件失败: {str(e)}") return False def log_to_file(self, message): if self.log_file: try: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] self.log_file.write(f"[{timestamp}] [Port {self.port_id}] {message}\n") self.log_file.flush() except Exception as e: self.log_queue.put(f"日志写入失败: {str(e)}") def connect(self, host, port): try: with self.lock: self.tn = telnetlib.Telnet(host, port, timeout=10) self.is_connected = True self.log_queue.put(f"端口 {self.port_id} 已连接到 {host}:{port}") self.log_to_file(f"Connected to {host}:{port}") self.read_until_prompt(timeout=3) self.boot_string_detected = False self.auto_completed = False return True except Exception as e: self.log_queue.put(f"端口 {self.port_id} 连接失败: {str(e)}") return False def disconnect(self): with self.lock: if self.tn: try: self.tn.close() except: pass self.is_connected = False self.log_queue.put(f"端口 {self.port_id} 连接已断开") self.log_to_file("Disconnected") if self.log_file: try: self.log_file.close() except: pass self.log_file = None def send(self, content): if not self.is_connected: self.log_queue.put(f"端口 {self.port_id} 错误:未连接到设备") return False try: with self.lock: self.current_command = content encoded_content = content.encode(ENCODING) for i in range(0, len(encoded_content), CHUNK_SIZE): if self.stop_event.is_set(): self.log_queue.put(f"端口 {self.port_id} 发送已中止") return False while self.pause_event.is_set(): time.sleep(0.1) if self.stop_event.is_set(): return False chunk = encoded_content[i:i+CHUNK_SIZE] self.tn.write(chunk) log_msg = f"发送分块: {chunk.decode(ENCODING, errors='replace')}" self.log_queue.put(log_msg) self.log_to_file(log_msg) time.sleep(CHUNK_DELAY) self.tn.write(b"\r\n") self.log_queue.put(f"端口 {self.port_id} 发送回车符") self.log_to_file("Sent ENTER") self.log_queue.put(f"端口 {self.port_id} 完整发送: {content.strip()}") self.log_to_file(f"Sent: {content.strip()}") return True except Exception as e: self.log_queue.put(f"端口 {self.port_id} 发送命令失败: {str(e)}") self.log_to_file(f"Send error: {str(e)}") return False def read_until_prompt(self, timeout=5): if not self.is_connected: return "" try: response = self.tn.read_until(self.expected_prompt.encode(ENCODING), timeout=timeout) decoded_response = response.decode(ENCODING, errors='replace') if decoded_response.endswith(self.expected_prompt): decoded_response = decoded_response[:-len(self.expected_prompt)].rstrip() self.last_response = decoded_response if decoded_response.strip(): self.log_queue.put(f"端口 {self.port_id} 响应: {decoded_response}") self.log_to_file(f"Response: {decoded_response}") return decoded_response except Exception as e: error_msg = f"端口 {self.port_id} 接收响应失败: {str(e)}" self.log_queue.put(error_msg) self.log_to_file(error_msg) return "" def execute_commands(self, commands, max_retries=None, retry_delay=None): if not self.is_connected: self.log_queue.put(f"端口 {self.port_id} 错误:未连接到设备") return False max_retries = max_retries or self.max_retries retry_delay = retry_delay or self.retry_delay self.stop_event.clear() self.pause_event.clear() self.total_commands = len(commands) self.log_queue.put(f"端口 {self.port_id} 开始执行 {self.total_commands} 条命令 (最大重试: {max_retries})") self.log_to_file(f"Starting execution of {self.total_commands} commands (max_retries={max_retries})") try: for idx, cmd in enumerate(commands): if self.stop_event.is_set(): self.log_queue.put(f"端口 {self.port_id} 命令执行已中止") self.log_to_file("Execution aborted") return False self.current_command_index = idx self.retry_count = 0 self.command_success = False while not self.command_success: if self.stop_event.is_set(): return False while self.pause_event.is_set(): time.sleep(0.1) if self.stop_event.is_set(): return False if cmd.strip(): if not self.send(cmd): return False response = self.read_until_prompt(timeout=15) self.command_success = self.check_command_success(cmd, response) if not self.command_success: self.retry_count += 1 if self.retry_count < max_retries: current_delay = min(retry_delay * (2 ** self.retry_count), self.max_retry_delay) self.log_queue.put( f"端口 {self.port_id} 命令执行失败,正在重试 ({self.retry_count}/{max_retries}): {cmd}" f" (等待 {current_delay:.1f}秒)" ) self.log_to_file( f"Command failed, retrying ({self.retry_count}/{max_retries}): {cmd}" f" (delay={current_delay:.1f}s)" ) time.sleep(current_delay) continue else: self.log_queue.put( f"端口 {self.port_id} 命令执行失败: {cmd},已达到最大重试次数({max_retries})" ) self.log_to_file(f"Command failed after {max_retries} retries: {cmd}") self.pause_event.set() while self.pause_event.is_set(): time.sleep(0.1) if self.stop_event.is_set(): return False if self.command_success: delay_remaining = COMMAND_DELAY while delay_remaining > 0: if self.stop_event.is_set(): return False if self.pause_event.is_set(): time.sleep(0.1) continue time.sleep(0.1) delay_remaining -= 0.1 self.log_queue.put(f"端口 {self.port_id} 命令执行完成") self.log_to_file("Execution completed") self.current_command_index = -1 return True except Exception as e: error_msg = f"端口 {self.port_id} 命令执行失败: {str(e)}" self.log_queue.put(error_msg) self.log_to_file(error_msg) return False def check_command_success(self, command, response): for cmd_key, pattern in SUCCESS_PATTERNS.items(): if cmd_key in command and re.search(pattern, response, re.IGNORECASE): return True for pattern in ERROR_PATTERNS: if re.search(pattern, response, re.IGNORECASE): return False if "ping" in command and "100% packet loss" in response: return False return bool(response.strip()) def stop_execution(self): self.stop_event.set() self.log_queue.put(f"端口 {self.port_id} 正在停止执行...") self.log_to_file("Stopping execution") def pause_execution(self): if not self.pause_event.is_set(): self.pause_event.set() self.log_queue.put(f"端口 {self.port_id} 执行已暂停") self.log_to_file("Execution paused") return True return False def resume_execution(self): if self.pause_event.is_set(): self.pause_event.clear() self.log_queue.put(f"端口 {self.port_id} 执行已继续") self.log_to_file("Execution resumed") return True return False def get_execution_status(self): return { "port_id": self.port_id, "is_connected": self.is_connected, "is_running": not self.stop_event.is_set() and not self.pause_event.is_set(), "is_paused": self.pause_event.is_set(), "is_stopped": self.stop_event.is_set(), "current_command": self.current_command.strip(), "current_index": self.current_command_index, "total_commands": self.total_commands, "log_file_path": self.log_file_path, "boot_string_detected": self.boot_string_detected, "auto_completed": self.auto_completed, "command_success": self.command_success, "retry_count": self.retry_count, "project_index": self.project_index, "project_name": self.project_name, "upgrade_type": self.upgrade_type } def detect_boot_string_and_auto_operation(self): """检测引导字符串并执行自动操作(修复版)""" if not self.is_connected or self.auto_completed: return False try: self.log_queue.put(f"端口 {self.port_id} 开始检测引导字符串...") self.log_to_file("Starting boot string detection") # 重置状态 self.boot_string_detected = False self.auto_completed = False # 第一步:检测引导字符串 start_time = time.time() while time.time() - start_time < self.timeout: if self.stop_event.is_set(): self.log_queue.put(f"端口 {self.port_id} 检测已中止") return False # 读取设备响应 response = self.read_until_prompt(timeout=1) # 使用正则检测引导字符串 if re.search(BOOT_STRING, response, re.IGNORECASE): self.boot_string_detected = True self.log_queue.put(f"端口 {self.port_id} 检测到引导字符串") self.log_to_file("Detected boot string") break time.sleep(0.5) if not self.boot_string_detected: self.log_queue.put(f"端口 {self.port_id} 未检测到引导字符串") self.log_to_file("Boot string not detected") return False # 第二步:发送Ctrl+T self.log_queue.put(f"端口 {self.port_id} 发送 Ctrl+T") if not self.send_ctrl_t(): self.log_queue.put(f"端口 {self.port_id} Ctrl+T发送失败") self.log_to_file("Failed to send Ctrl+T") return False # 第三步:等待6秒 self.log_queue.put(f"端口 {self.port_id} 等待6秒...") self.log_to_file("Waiting 6 seconds...") time.sleep(6) # 第四步:发送watchdog命令 self.log_queue.put(f"端口 {self.port_id} 发送 watchdog -close") self.log_to_file("Sending watchdog -close") self.send("watchdog -close") # 第五步:验证命令执行结果 watchdog_response = self.read_until_prompt(timeout=10) if re.search(AUTO_OPERATION_SUCCESS_STR, watchdog_response, re.IGNORECASE): self.auto_completed = True self.log_queue.put(f"端口 {self.port_id} watchdog命令执行成功") self.log_to_file("Watchdog command succeeded") return True else: self.log_queue.put(f"端口 {self.port_id} watchdog命令执行失败") self.log_to_file(f"Watchdog command failed, response: {watchdog_response}") return False except Exception as e: self.log_queue.put(f"端口 {self.port_id} 自动操作失败: {str(e)}") self.log_to_file(f"Auto operation failed: {str(e)}") return False def perform_auto_operation(self, callback=None): """执行自动操作(带重试机制)""" self.auto_operation_callback = callback # 尝试自动操作 success = False for attempt in range(1, self.max_attempts + 1): self.log_queue.put( f"端口 {self.port_id} 开始自动操作尝试 ({attempt}/{self.max_attempts})" ) self.log_to_file(f"Starting auto operation attempt {attempt}/{self.max_attempts}") success = self.detect_boot_string_and_auto_operation() if success: break # 计算指数退避延迟 delay = min(2 ** attempt, self.max_retry_delay) self.log_queue.put( f"端口 {self.port_id} 自动操作失败,正在重试 ({attempt}/{self.max_attempts}) " f"等待 {delay}秒..." ) self.log_to_file(f"Retrying in {delay} seconds...") time.sleep(delay) # 执行回调(如果有) if success and self.auto_operation_callback: self.log_queue.put(f"端口 {self.port_id} 触发自动升级回调") self.log_to_file("Triggering auto operation callback") self.auto_operation_callback() return success def send_ctrl_t(self): """发送Ctrl+T组合键(简化版)""" if not self.is_connected: return False try: with self.lock: if not self.tn: return False # 简化Ctrl+T序列 - 直接发送控制字符 # Ctrl+T的ASCII码是20(0x14) self.tn.write(b"\x14") # 添加回车确保命令被执行 self.tn.write(b"\r") self.log_queue.put(f"端口 {self.port_id} 已发送 Ctrl+T") self.log_to_file("Sent Ctrl+T") return True except Exception as e: error_msg = f"端口 {self.port_id} 发送Ctrl+T失败: {str(e)}" self.log_queue.put(error_msg) self.log_to_file(error_msg) return False # ============== GUI 界面类 ============== class RemoteControlApp: def __init__(self): self.project_manager = ProjectManager() self.default_data = self.load_default_data() self.executors = {} self.window = None for port_id in range(1, MAX_PORTS + 1): executor = CommandExecutor(port_id) executor.set_project_manager(self.project_manager) self.executors[port_id] = executor self.setup_gui() self.running = True def load_default_data(self): default_data = { "IP1": "192.168.1.200", "port1": "1000", "IP2": "71.19.2.130", "port2": "1260", "FTP_IP": "71.19.0.120", "芯片名称": "Hi1260SV100", "发送信息": "", "board_local_ip": "71.19.0.53", "interval": "1", "start_addr": "", "end_addr": "", "文件FTP路径": "", "log_dir": os.getcwd() } if os.path.exists(DATA_FILE): try: with open(DATA_FILE, 'r') as f: data = json.load(f) default_data.update({k: data[k] for k in default_data if k in data}) except Exception as e: logger.error(f"加载默认配置失败: {e}") with open(DATA_FILE, 'w') as f: json.dump(default_data, f) return default_data def save_config(self): try: values = self.window.read()[1] if self.window else {} config = {k: values.get(k, self.default_data[k]) for k in self.default_data} with open(DATA_FILE, 'w') as f: json.dump(config, f) self.default_data = config return True except Exception as e: logger.error(f"保存配置失败: {e}") return False def create_project_buttons(self): layout = [] projects = self.project_manager.projects["projects"] if not projects: layout.append([sg.Text("没有项目,请添加新项目", text_color='red')]) for i, project in enumerate(projects): row = [ sg.Button(project["name"], key=f'-PROJECT-{i}-', size=(20,1), tooltip=f"创建于: {project['created_at']}\n命令数: {len(project['commands'])}"), sg.Text('○', font=('Arial', 12), text_color='gray', tooltip="自动操作状态: ○未执行 ●已检测到引导字符串 ✓已完成", key=f'-AUTO-INDICATOR-{i}-') ] layout.append(row) layout.append([ sg.Button("添加新项目", key='-ADD-PROJECT-', button_color=('white', 'purple')), sg.Button("导入项目", key='-IMPORT-PROJECTS-'), sg.Button("导出项目", key='-EXPORT-PROJECTS-'), sg.Button("生成模板", key='-CREATE-TEMPLATE-') ]) return layout def create_port_selection_dialog(self, title, port_ids): layout = [ [sg.Text(title)], *[[sg.Checkbox(f"端口 {port_id}", key=f'-PORT-{port_id}-', default=True)] for port_id in port_ids], [sg.Button("确定"), sg.Button("取消")] ] return sg.Window("选择端口", layout, modal=True) def create_project_function_window(self, index): if index >= len(self.project_manager.projects["projects"]): return None project = self.project_manager.projects["projects"][index] project_name = project["name"] upgrade_types = [ ("一键升级", "base", 'green'), ("BIOS升级", "bios", 'blue'), ("RBOS升级", "rbos", 'blue'), ("INITRD升级", "initrd", 'blue') ] layout = [ [sg.Text(f"项目: {project_name}", font=("Arial", 12, "bold"))] ] for text, upgrade_type, color in upgrade_types: layout.append([ sg.Button(text, size=(12, 1), key=f'-{upgrade_type.upper()}-UPGRADE-{index}-', button_color=('white', color)), sg.Button("✎", size=(2, 1), key=f'-EDIT-{upgrade_type.upper()}-{index}-', button_color=('white', 'gray'), tooltip=f"编辑{text}指令") ]) layout.extend([ [sg.Button("自动操作", size=(12, 1), key=f'-AUTO-{index}-', button_color=('white', 'purple'), tooltip="执行自动操作进入Shell环境并触发升级")], [sg.Button("编辑项目", key=f'-EDIT-{index}-', button_color=('white', 'orange'))], [sg.Button("删除项目", key=f'-DELETE-{index}-', button_color=('white', 'red'))], [sg.Button("关闭", key='-CLOSE-')] ]) return sg.Window(f"项目功能 - {project_name}", layout, modal=True, finalize=True) def edit_upgrade_commands(self, index, upgrade_type): """编辑指定项目的升级命令""" project = self.project_manager.projects["projects"][index] title = f"{upgrade_type.upper()}升级指令" if upgrade_type != "base" else "基础升级指令" if upgrade_type == "base": commands = project.get("commands", []) else: commands = project.get(f"{upgrade_type}_commands", []) layout = [ [sg.Text(f"{title}:")], [sg.Multiline(key='-UPGRADE-COMMANDS-', size=(60, 10), default_text='\n'.join(commands), tooltip="每行一个命令,命令将按顺序执行")], [sg.Button("保存并执行", key='-SAVE-EXECUTE-'), sg.Button("保存", key='-SAVE-'), sg.Button("取消", key='-CANCEL-')] ] window = sg.Window(title, layout, modal=True, finalize=True) while True: event, values = window.read() if event in (sg.WINDOW_CLOSED, '-CANCEL-'): break commands = [cmd.strip() for cmd in values['-UPGRADE-COMMANDS-'].split('\n') if cmd.strip()] if event in ('-SAVE-', '-SAVE-EXECUTE-'): if upgrade_type == "base": success = self.project_manager.add_or_update_project( project["name"], commands, project.get("auto_operation", False), index) else: success = self.project_manager.update_upgrade_commands(index, upgrade_type, commands) if success: sg.popup(f"{title}保存成功") if event == '-SAVE-EXECUTE-': # 保存后立即执行升级 self.handle_upgrade_event(f'-{upgrade_type.upper()}-UPGRADE-{index}-', index, upgrade_type) break else: sg.popup("操作失败,请查看日志") window.close() return True def handle_auto_event(self, event, index): """处理项目功能窗口中的自动操作按钮""" # 创建端口选择对话框 port_layout = [ [sg.Text("选择执行自动操作的端口:")], *[[sg.Checkbox(f"端口 {port_id}", key=f'-PORT-{port_id}-', default=True)] for port_id in self.executors], [ sg.Text("超时时间(秒):", size=(10, 1)), sg.Input(key='-TIMEOUT-', default_text="60", size=(5, 1)), sg.Text("重试次数:", size=(8, 1)), sg.Input(key='-RETRIES-', default_text="5", size=(5, 1)) ], [sg.Button("确定", key='-OK-'), sg.Button("取消", key='-CANCEL-')] ] port_window = sg.Window("选择端口", port_layout, modal=True) port_event, port_values = port_window.read() port_window.close() if port_event != '-OK-' or not any(port_values.values()): return selected_ports = [port_id for port_id in self.executors if port_values[f'-PORT-{port_id}-']] if not selected_ports: sg.popup("请至少选择一个端口") return # 获取配置参数 try: timeout = int(port_values.get('-TIMEOUT-', 60)) max_retries = int(port_values.get('-RETRIES-', 5)) except ValueError: sg.popup("无效的超时或重试次数设置,使用默认值") timeout = 60 max_retries = 5 # 设置日志文件 log_dir = self.default_data["log_dir"] timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") project_name = self.project_manager.projects["projects"][index]["name"] project_name_safe = re.sub(r'[\\/*?:"<>|]', "", project_name) # 创建升级类型选择对话框 upgrade_types = [ ("一键升级", "base"), ("BIOS升级", "bios"), ("RBOS升级", "rbos"), ("INITRD升级", "initrd") ] upgrade_layout = [ [sg.Text("请选择升级类型:")], *[[sg.Radio(text, "UPGRADE_TYPE", key=f'-TYPE-{upgrade_type}-', default=(i == 0))] for i, (text, upgrade_type) in enumerate(upgrade_types)], [sg.Button("确定", key='-UPGRADE-OK-'), sg.Button("取消", key='-UPGRADE-CANCEL-')] ] upgrade_window = sg.Window("选择升级类型", upgrade_layout, modal=True) upgrade_event, upgrade_values = upgrade_window.read() upgrade_window.close() if upgrade_event != '-UPGRADE-OK-': return # 确定选择的升级类型 selected_upgrade_type = None for _, upgrade_type in upgrade_types: if upgrade_values[f'-TYPE-{upgrade_type}-']: selected_upgrade_type = upgrade_type break if not selected_upgrade_type: sg.popup("请选择升级类型") return # 为每个端口设置日志文件 for port_id in selected_ports: executor = self.executors[port_id] log_file = os.path.join( log_dir, f"{project_name_safe}_auto_{selected_upgrade_type}_port{port_id}_{timestamp}.log" ) executor.set_log_file(log_file) executor.timeout = timeout executor.max_attempts = max_retries executor.project_index = index executor.project_name = project_name executor.upgrade_type = selected_upgrade_type # 在新线程中执行自动操作和升级 threading.Thread( target=self._execute_auto_with_upgrade, args=(index, selected_upgrade_type, selected_ports), daemon=True ).start() def _execute_auto_with_upgrade(self, index, upgrade_type, port_ids): """执行自动操作并在成功后触发升级""" for port_id in port_ids: executor = self.executors[port_id] self.window['-STATUS-'].update(f"端口 {port_id} 开始执行自动操作...") # 执行自动操作(进入Shell环境) success = executor.perform_auto_operation() if success: self.window['-STATUS-'].update(f"端口 {port_id} 自动操作成功,开始升级...") # 获取升级命令 if upgrade_type == "base": commands = self.project_manager.get_project_commands(index) else: commands = self.project_manager.get_upgrade_commands(index, upgrade_type) # 执行升级命令 upgrade_success = executor.execute_commands(commands, max_retries=3, retry_delay=1) status = "成功" if upgrade_success else "失败" self.window['-STATUS-'].update(f"端口 {port_id} {upgrade_type.upper()}升级{status}") else: self.window['-STATUS-'].update(f"端口 {port_id} 自动操作失败,无法执行升级") def handle_upgrade_event(self, event, index, upgrade_type): project = self.project_manager.projects["projects"][index] project_name = project["name"] if upgrade_type == "base": commands = self.project_manager.get_project_commands(index) upgrade_type_name = "一键升级" else: commands = self.project_manager.get_upgrade_commands(index, upgrade_type) upgrade_type_name = f"{upgrade_type.upper()}升级" if not commands: sg.popup(f"未配置{upgrade_type.upper()}升级指令,请先配置") self.edit_upgrade_commands(index, upgrade_type) return port_window = self.create_port_selection_dialog( f"选择执行 {project_name} {upgrade_type_name} 的端口:", list(self.executors.keys()) ) port_event, port_values = port_window.read() port_window.close() if port_event != "确定" or not any(port_values.values()): sg.popup("请至少选择一个端口") return selected_ports = [port_id for port_id in self.executors if port_values[f'-PORT-{port_id}-']] log_dir = self.default_data["log_dir"] timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") project_name_safe = re.sub(r'[\\/*?:"<>|]', "", project_name) for port_id in selected_ports: log_file = os.path.join(log_dir, f"{project_name_safe}_{upgrade_type_name}_port{port_id}_{timestamp}.log") executor = self.executors[port_id] executor.set_log_file(log_file) executor.project_index = index executor.project_name = project_name executor.upgrade_type = upgrade_type threading.Thread( target=self.execute_upgrade, args=(index, upgrade_type, selected_ports), daemon=True ).start() def execute_upgrade(self, index, upgrade_type, port_ids): if upgrade_type == "base": commands = self.project_manager.get_project_commands(index) upgrade_type_name = "一键升级" else: commands = self.project_manager.get_upgrade_commands(index, upgrade_type) upgrade_type_name = f"{upgrade_type.upper()}升级" if not commands: for port_id in port_ids: self.executors[port_id].log_queue.put(f"错误:{upgrade_type_name}没有配置命令") return self.window['-CURRENT-COMMAND-'].update("") self.window['-COMMAND-PROGRESS-'].update("0/0") threads = [] for port_id in port_ids: executor = self.executors[port_id] thread = threading.Thread( target=self._execute_upgrade_on_port, args=(executor, commands, port_id, upgrade_type_name), daemon=True ) thread.start() threads.append(thread) for thread in threads: thread.join(timeout=300) self.window['-STATUS-'].update(f"{upgrade_type_name}任务已完成") def _execute_upgrade_on_port(self, executor, commands, port_id, upgrade_type_name): self.window['-STATUS-'].update(f"端口 {port_id} 开始{upgrade_type_name}...") success = executor.execute_commands(commands, max_retries=3, retry_delay=1) status = "成功" if success else "失败" self.window['-STATUS-'].update(f"端口 {port_id} {upgrade_type_name}{status}") def setup_gui(self): sg.theme('LightBlue1') # 输出区域 output = sg.Multiline( size=(80, 20), key='-OUTPUT-', autoscroll=True, background_color='#f0f0f0', text_color='black' ) # 状态信息区域 status_info = [ sg.Text("当前命令: ", size=(10,1)), sg.Text("无", key='-CURRENT-COMMAND-', size=(40,1), text_color='blue'), sg.Text("进度: ", size=(5,1)), sg.Text("0/0", key='-COMMAND-PROGRESS-', size=(10,1)), sg.Text("状态: ", size=(5,1)), sg.Text("", key='-COMMAND-STATUS-', size=(10,1), text_color='green'), sg.Text("项目: ", size=(5,1)), sg.Text("无", key='-PROJECT-NAME-STATUS-', size=(20,1), text_color='purple'), sg.Text("升级类型: ", size=(8,1)), sg.Text("无", key='-UPGRADE-TYPE-STATUS-', size=(15,1), text_color='red') ] # 项目列表区域 projects_frame = sg.Frame("项目列表", [ [sg.Column( self.create_project_buttons(), scrollable=True, vertical_scroll_only=True, size=(700, 100), key='-PROJECTS-COLUMN-' )] ], key='-PROJECTS-FRAME-') # 执行控制区域 control_buttons = [ sg.Button('暂停执行', key='-PAUSE-EXECUTION-', button_color=('white', 'orange'), size=(10,1)), sg.Button('继续执行', key='-RESUME-EXECUTION-', button_color=('white', 'green'), size=(10,1)), sg.Button('停止执行', key='-STOP-EXECUTION-', button_color=('white', 'red'), size=(10,1)), sg.Button('跳过命令', key='-SKIP-COMMAND-', button_color=('white', 'blue'), size=(10,1)), sg.Button('Go Shell', key='-GO-SHELL-', button_color=('white', 'purple'), size=(10,1), tooltip="执行自动操作:发送Ctrl+T,等待6秒后发送watchdog -close") ] # 端口连接区域 port_layouts = [] for port_id in range(1, MAX_PORTS + 1): port_layout = [ sg.Text(f'端口 {port_id} IP:', size=(8,1)), sg.Input(key=f"IP{port_id}", default_text=self.default_data[f"IP{port_id}"], size=(15,1)), sg.Text('端口:', size=(5,1)), sg.Input(key=f"port{port_id}", default_text=self.default_data[f"port{port_id}"], size=(8,1)), sg.Button(f'连接{port_id}', key=f'-CONNECT-{port_id}-', button_color=('white', 'green')), sg.Button(f'断开{port_id}', key=f'-DISCONNECT-{port_id}-', button_color=('white', 'red')), sg.Text('●', key=f'-STATUS-LIGHT-{port_id}-', text_color='red', font=('Arial', 12)), sg.Text("未连接", key=f'-CONNECTION-STATUS-{port_id}-'), sg.Text('○', key=f'-AUTO-STATUS-{port_id}-', text_color='gray', font=('Arial', 12), tooltip="自动操作状态: ○未执行 ●已检测到引导字符串 ✓已完成") ] port_layouts.append(port_layout) # 日志保存区域 log_layout = [ sg.Text('日志目录:', size=(8,1)), sg.Input(key='log_dir', default_text=self.default_data["log_dir"], size=(40,1)), sg.FolderBrowse('浏览', key='-LOG-BROWSE-'), sg.Button('设置日志目录', key='-SET-LOG-DIR-') ] # 主布局 layout = [ *port_layouts, [projects_frame], status_info, [sg.Frame("执行控制", [control_buttons], key='-CONTROL-FRAME-')], [sg.Text("发送信息:", size=(8,1)), sg.Input(key='发送信息', size=(50, 1), default_text=self.default_data["发送信息"])], [sg.Button('ROUTER_MPU下发送'), sg.Button('Shell下发送'), sg.Text('每隔', size=(3,1)), sg.Input(key='interval', default_text=self.default_data["interval"], size=(5,1)), sg.Text("秒", size=(2,1)), sg.Button('定时发送'), sg.Button("停止定时发送")], [sg.Button('接收1s')], [sg.Button("使用说明", button_color=('white', 'blue'))], [sg.Text('起始地址:', size=(8,1)), sg.Input(key='start_addr', default_text=self.default_data["start_addr"], size=(12,1)), sg.Text('结束地址:', size=(8,1)), sg.Input(key='end_addr', default_text=self.default_data["end_addr"], size=(12,1)), sg.Button('dump寄存器')], log_layout, [output], [sg.StatusBar("就绪", key='-STATUS-', size=(50, 1))] ] self.window = sg.Window('远程单板连接工具 (多端口)', layout, finalize=True, resizable=True) self.update_status_lights() self.update_auto_status() def handle_go_shell(self): """处理Go Shell按钮点击事件(增强版)""" # 选择端口对话框 port_layout = [ [sg.Text("选择执行 Go Shell 操作的端口:")], *[[sg.Checkbox(f"端口 {port_id}", key=f'-PORT-{port_id}-', default=True)] for port_id in self.executors], [ sg.Text("超时时间(秒):", size=(10, 1)), sg.Input(key='-TIMEOUT-', default_text="60", size=(5, 1)), sg.Text("重试次数:", size=(8, 1)), sg.Input(key='-RETRIES-', default_text="5", size=(5, 1)) ], [sg.Button("确定", key='-OK-'), sg.Button("取消", key='-CANCEL-')] ] port_window = sg.Window("选择端口", port_layout, modal=True) port_event, port_values = port_window.read() port_window.close() if port_event == '-OK-': selected_ports = [port_id for port_id in self.executors if port_values[f'-PORT-{port_id}-']] if not selected_ports: sg.popup("请至少选择一个端口") return # 获取配置参数 try: timeout = int(port_values.get('-TIMEOUT-', 60)) max_retries = int(port_values.get('-RETRIES-', 5)) except ValueError: sg.popup("无效的超时或重试次数设置,使用默认值") timeout = 60 max_retries = 5 # 设置日志文件 log_dir = self.default_data["log_dir"] timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") for port_id in selected_ports: executor = self.executors[port_id] log_file = os.path.join(log_dir, f"go_shell_port{port_id}_{timestamp}.log") executor.set_log_file(log_file) # 设置自动操作的参数 executor.timeout = timeout executor.max_attempts = max_retries # 在新线程中执行自动操作 threading.Thread( target=self._execute_go_shell_on_port, args=(executor, port_id), daemon=True ).start() def _execute_go_shell_on_port(self, executor, port_id): """在单个端口上执行Go Shell操作""" self.window['-STATUS-'].update(f"端口 {port_id} 开始执行 Go Shell 操作...") # 执行自动操作(不关联项目) success = executor.perform_auto_operation() if success: self.window['-STATUS-'].update(f"端口 {port_id} Go Shell 操作成功") sg.popup_notify(f"端口 {port_id} Go Shell 操作成功", display_duration_in_ms=3000) else: self.window['-STATUS-'].update(f"端口 {port_id} Go Shell 操作失败") sg.popup_error(f"端口 {port_id} Go Shell 操作失败,请检查日志") def update_status_lights(self): for port_id, executor in self.executors.items(): color = 'green' if executor.is_connected else 'red' status = "已连接" if executor.is_connected else "未连接" self.window[f'-STATUS-LIGHT-{port_id}-'].update(text_color=color) self.window[f'-CONNECTION-STATUS-{port_id}-'].update(status) def update_auto_status(self): for port_id, executor in self.executors.items(): if executor.auto_completed: self.window[f'-AUTO-STATUS-{port_id}-'].update('✓', text_color='green') elif executor.boot_string_detected: self.window[f'-AUTO-STATUS-{port_id}-'].update('●', text_color='red') else: self.window[f'-AUTO-STATUS-{port_id}-'].update('○', text_color='gray') def update_output(self): output_text = self.window['-OUTPUT-'].get() updated = False for port_id, executor in self.executors.items(): while not executor.log_queue.empty(): try: message = executor.log_queue.get_nowait() output_text += message + '\n' updated = True except queue.Empty: break if updated: self.window['-OUTPUT-'].update(output_text) def update_status(self): for port_id, executor in self.executors.items(): status = executor.get_execution_status() if port_id == 1: # 只显示第一个端口的状态 if status["current_command"]: self.window['-CURRENT-COMMAND-'].update(status["current_command"]) if status["current_index"] >= 0 and status["total_commands"] > 0: progress_text = f"{status['current_index'] + 1}/{status['total_commands']}" self.window['-COMMAND-PROGRESS-'].update(progress_text) self.window['-COMMAND-STATUS-'].update( "成功" if status["command_success"] else "失败", text_color='green' if status["command_success"] else 'red' ) self.window['-PROJECT-NAME-STATUS-'].update(status["project_name"] or "无") upgrade_type = status["upgrade_type"] self.window['-UPGRADE-TYPE-STATUS-'].update( upgrade_type.upper() if upgrade_type else "无", text_color='red' if upgrade_type else None ) color = 'green' if status["is_connected"] else 'red' self.window[f'-STATUS-LIGHT-{port_id}-'].update(text_color=color) self.window[f'-CONNECTION-STATUS-{port_id}-'].update( "已连接" if status["is_connected"] else "未连接" ) self.update_auto_status() # 更新按钮状态(基于第一个端口) if self.executors[1].is_connected: status1 = self.executors[1].get_execution_status() if status1["is_running"]: self.window['-PAUSE-EXECUTION-'].update(disabled=False) self.window['-RESUME-EXECUTION-'].update(disabled=True) self.window['-STOP-EXECUTION-'].update(disabled=False) self.window['-SKIP-COMMAND-'].update(disabled=True) elif status1["is_paused"]: self.window['-PAUSE-EXECUTION-'].update(disabled=True) self.window['-RESUME-EXECUTION-'].update(disabled=False) self.window['-STOP-EXECUTION-'].update(disabled=False) self.window['-SKIP-COMMAND-'].update(disabled=False) else: self.window['-PAUSE-EXECUTION-'].update(disabled=True) self.window['-RESUME-EXECUTION-'].update(disabled=True) self.window['-STOP-EXECUTION-'].update(disabled=True) self.window['-SKIP-COMMAND-'].update(disabled=True) def refresh_project_list(self): self.window['-PROJECTS-COLUMN-'].update(visible=False) self.window['-PROJECTS-COLUMN-'].update(self.create_project_buttons()) self.window['-PROJECTS-COLUMN-'].update(visible=True) def run(self): last_status_update = time.time() while True: event, values = self.window.read(timeout=100) if event == sg.WINDOW_CLOSED: break self.update_output() current_time = time.time() if current_time - last_status_update > 0.5: self.update_status() last_status_update = current_time # 事件处理 if event.startswith('-CONNECT-'): port_id = int(event.split('-')[2]) ip_key = f"IP{port_id}" port_key = f"port{port_id}" if values[ip_key] and values[port_key]: if self.executors[port_id].connect(values[ip_key], int(values[port_key])): self.window['-STATUS-'].update(f"端口 {port_id} 已连接") self.update_status_lights() elif event.startswith('-DISCONNECT-'): port_id = int(event.split('-')[2]) self.executors[port_id].disconnect() self.window['-STATUS-'].update(f"端口已断开") self.update_status_lights() elif event.startswith('-EDIT-'): parts = event.split('-') if len(parts) >= 4: try: upgrade_type = parts[2].lower() index = int(parts[3]) self.edit_upgrade_commands(index, upgrade_type) except (ValueError, IndexError): logger.error(f"解析编辑事件失败: {event}") elif event == '-SET-LOG-DIR-': if 'log_dir' in values and values['log_dir']: self.default_data["log_dir"] = values['log_dir'] self.save_config() sg.popup(f"日志目录已设置为: {values['log_dir']}") elif event == '-ADD-PROJECT-': self.edit_project_window() self.refresh_project_list() elif event.startswith('-PROJECT-'): index = int(event.split('-')[2]) project_window = self.create_project_function_window(index) if project_window: while True: win_event, win_values = project_window.read() if win_event in (sg.WINDOW_CLOSED, '-CLOSE-'): break if win_event.startswith('-EDIT-'): parts = win_event.split('-') if len(parts) >= 4: upgrade_type = parts[2].lower() self.edit_upgrade_commands(index, upgrade_type) elif win_event == f'-AUTO-{index}-': self.handle_auto_event(win_event, index) elif win_event == f'-EDIT-{index}-': self.edit_project_window(index) self.refresh_project_list() # 在事件处理部分添加对自动操作按钮的处理 elif event.startswith('-AUTO-'): parts = event.split('-') if len(parts) >= 3: try: index = int(parts[2]) self.handle_auto_event(event, index) except ValueError: pass elif win_event == f'-DELETE-{index}-': if self.project_manager.delete_project(index): sg.popup("项目删除成功") self.refresh_project_list() break else: sg.popup("项目删除失败") project_window.close() elif event == '-IMPORT-PROJECTS-': file_path = sg.popup_get_file("选择项目配置文件", file_types=(("JSON Files", "*.json"),)) if file_path and self.project_manager.import_export_projects(file_path, 'import'): sg.popup("项目导入成功") self.refresh_project_list() else: sg.popup("项目导入失败") elif event == '-EXPORT-PROJECTS-': file_path = sg.popup_get_file("保存项目配置文件", save_as=True, file_types=(("JSON Files", "*.json"),)) if file_path and self.project_manager.import_export_projects(file_path, 'export'): sg.popup("项目导出成功") else: sg.popup("项目导出失败") elif event == '-CREATE-TEMPLATE-': self.create_template_file() sg.popup("模板文件已生成: projects_template.json") # 执行控制 elif event == '-PAUSE-EXECUTION-': for executor in self.executors.values(): if executor.get_execution_status()["is_running"]: executor.pause_execution() self.window['-STATUS-'].update("执行已暂停") elif event == '-RESUME-EXECUTION-': for executor in self.executors.values(): if executor.get_execution_status()["is_paused"]: executor.resume_execution() self.window['-STATUS-'].update("执行已继续") elif event == '-STOP-EXECUTION-': for executor in self.executors.values(): executor.stop_execution() self.window['-STATUS-'].update("执行已停止") elif event == '-SKIP-COMMAND-': for executor in self.executors.values(): if executor.get_execution_status()["is_paused"]: executor.command_success = True executor.resume_execution() self.window['-STATUS-'].update("已跳过当前命令") elif event == '-GO-SHELL-': self.handle_go_shell() # 其他功能 elif event in ('ROUTER_MPU下发送', 'Shell下发送'): if self.save_config() and values["发送信息"]: for executor in self.executors.values(): if executor.is_connected: executor.send(values["发送信息"]) executor.read_until_prompt() elif event == '定时发送': if self.save_config() and values["发送信息"] and values["interval"]: try: interval = float(values["interval"]) if interval <= 0: raise ValueError("间隔必须大于0") threading.Thread( target=self.periodic_send, args=(values["发送信息"], interval), daemon=True ).start() except Exception as e: sg.popup(f"无效的间隔: {str(e)}") elif event == "停止定时发送": for executor in self.executors.values(): executor.stop_execution() elif event == '接收1s': for executor in self.executors.values(): if executor.is_connected: executor.read_until_prompt(timeout=1) elif event == 'dump寄存器': if values["start_addr"] and values["end_addr"]: for executor in self.executors.values(): if executor.is_connected: executor.send(f"dump {values['start_addr']} {values['end_addr']}") executor.read_until_prompt() elif event == '使用说明': self.show_help() self.running = False for executor in self.executors.values(): executor.disconnect() self.window.close() def periodic_send(self, message, interval): while not self.executors[1].stop_event.is_set(): for executor in self.executors.values(): if executor.is_connected: executor.send(message) executor.read_until_prompt() time.sleep(interval) def create_template_file(self): template = { "projects": [ { "name": "示例项目", "commands": [ "watchdog -close", "ifconfig eth0 71.19.0.53 255.255.255.0 71.19.0.1", "ftp -get ftp://user:pass@71.19.0.120/firmware.bin /home/firmware.bin", "flash -w /home/firmware.bin" ], "auto_operation": True, "bios_commands": ["bios_update_command1", "bios_update_command2"], "rbos_commands": ["rbos_update_command1", "rbos_update_command2"], "initrd_commands": ["initrd_update_command1", "initrd_update_command2"], "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } ] } try: with open('projects_template.json', 'w', encoding='utf-8') as f: json.dump(template, f, indent=4, ensure_ascii=False) return True except Exception as e: logger.error(f"生成模板失败: {e}") return False def show_help(self): help_text = f"""=== 远程单板连接工具使用说明 (多端口) === 1. 多端口连接管理: - 支持同时连接 {MAX_PORTS} 个端口 - 每个端口独立显示连接状态(红:未连接, 绿:已连接) - 每个端口独立保存日志文件 2. 项目功能: - 点击项目名称打开功能窗口 - 一键升级:执行项目基础指令 - BIOS/RBOS/INITRD升级:执行特定升级指令 - 自动操作:执行引导字符串检测和自动操作 3. 升级功能: - 每种升级类型有独立的指令配置 - 点击"✎"按钮编辑对应升级类型的指令 - 支持分段发送和响应验证 - 可配置最大重试次数和重试延迟 - 在状态栏显示当前升级类型 4. Go Shell功能: - 自动检测引导字符串(支持多种变体) - 发送Ctrl+T组合键 - 等待6秒后发送watchdog -close命令 - 可配置超时时间和重试次数 5. 执行控制: - 暂停/继续/停止当前执行 - 跳过当前失败的命令 - 实时显示命令执行状态 6. 日志管理: - 每个端口独立日志文件 - 可设置日志保存目录 7. 其他功能: - 定时发送命令 - 寄存器dump - 项目导入导出 """ sg.popup(help_text, title="使用说明", font=("Arial", 10), non_blocking=True) # ============== 主程序入口 ============== if __name__ == "__main__": try: app = RemoteControlApp() app.run() except Exception as e: logger.exception("应用程序崩溃") sg.popup_error(f"应用程序发生致命错误: {str(e)}") 这是我的代码: 请帮我分析代码,并帮我整理一份功能以及操作说明以及安装依赖
最新发布
07-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值