import configparser from typing import Dict, Union from icmplib import ping, ICMPLibError from PySide6.QtCore import QThread, Signal class DeviceMonitorThread(QThread): connect_success = Signal(str, int) # 成功信号:设备名称(str) + 延迟毫秒数(int) connect_failed = Signal(str) # 失败信号:设备名称(str) state_result = Signal(str, int) # 全局状态(str: normal/warning/error) + 异常设备数量(int) check_finished = Signal() # 本轮检测结束 def __init__(self, config_path = "config/monitor_config.ini", parent=None): super().__init__(parent) # 初始化你的原有配置参数,完全不变 self.config_path = config_path self.ping_timeout_ms = 2000 self.ping_count = 2 self.check_interval = 10 # 默认检测间隔10秒 self.warning_delay = 30 # 默认的警告的网络延迟(单位: ms) self.is_stop = False # 线程停止标志位 self.force_check = False # 立即检测标志 def _ping_device(self, ip: str, timeout_ms: int = 2000) -> Union[int, None]: """设备连接状态检测""" try: response = ping( ip, count=self.ping_count, timeout=timeout_ms / 1000, privileged=False, interval=0.1 ) if response.is_alive: return int(response.avg_rtt) return None except ICMPLibError as e: print(f"IP[{ip}] ICMP异常: {str(e)}") return None except Exception as e: print(f"IP[{ip}] 未知异常: {str(e)}") return None def _read_device_config(self) -> Dict[str, str]: """读取ini配置文件""" device_dict = {} config = configparser.ConfigParser() try: config.read(self.config_path, encoding="utf-8") for section in config.sections(): if "ip" in config[section]: device_ip = config[section]["ip"].strip() device_dict[section] = device_ip except FileNotFoundError: print(f"配置文件[{self.config_path}]不存在,请检查路径!") except Exception as e: print(f"读取配置文件失败: {str(e)}") return device_dict def run(self) -> None: """网络设备检测""" print("✅ 设备检测线程已启动") self.is_stop = False # 重置停止标志位 while True: # 线程退出 if self.is_stop: break # 批量检测所有设备 device_dict = self._read_device_config() check_result = {} # 所有设备的检测结果 if not device_dict: print("设备检测线程: 未读取到任何设备配置!") else: for device_name, device_ip in device_dict.items(): if self.is_stop: break delay_ms = self._ping_device(device_ip, self.ping_timeout_ms) if delay_ms is not None: self.connect_success.emit(device_name, delay_ms) # 发送成功信号 else: self.connect_failed.emit(device_name) # 发送失败信号 check_result[device_name] = delay_ms # 本轮检测完成 self.check_finished.emit() # 设备状态统计 self._calc_device_state(check_result) # 等待指定间隔后,继续下一次检测 # self.msleep(self.check_interval * 1000) sleep_total_ms = self.check_interval * 1000 sleep_slice_ms = 200 # 每次休眠200ms sleep_count = int(sleep_total_ms / sleep_slice_ms) for _ in range(sleep_count): if self.is_stop: # 每次休眠后检测退出标志 break if self.force_check: self.force_check = False break self.msleep(sleep_slice_ms) # ============ 设备状态统计 ============ def _calc_device_state(self, check_result:dict): offline_count = 0 # 离线设备数 delay_warn_count = 0# 延迟超30ms的设备数 # 遍历结果统计 for delay in check_result.values(): if delay is None: offline_count += 1 elif delay >= self.warning_delay: delay_warn_count += 1 # 按优先级判定全局状态 if offline_count > 0: # 设备异常 → error + 离线(异常)数量 self.state_result.emit("error", offline_count) elif delay_warn_count > 0: # 全部在线但有延迟超标 → warning + 延迟超标数量 self.state_result.emit("warning", delay_warn_count) else: # 全部在线且延迟都<30ms → normal + 0 self.state_result.emit("normal", 0) # ============ 修改检测间隔 ============ def set_check_interval(self, interval: int): """ 修改检测时间间隔 :param interval: 间隔秒数(int) """ if isinstance(interval, int) and interval >= 3: self.check_interval = interval # ============ 修改警告延迟 ============ def set_warning_delay(self, delay:int): if isinstance(delay, int) and delay >= 1: self.warning_delay = delay # ============ 停止检测线程============ def stop_thread(self): self.is_stop = True self.wait() print("设备检测线程已退出") # ============ 立即检测============ def force_immediate_check(self): """马上执行新一轮设备检测""" self.force_check = True