import logging import time import requests import pandas as pd from io import BytesIO import subprocess import globals.global_variable as global_variable import globals.driver_utils as driver_utils # 导入驱动工具模块 from selenium.common.exceptions import TimeoutException, NoSuchElementException, StaleElementReferenceException from appium.webdriver.common.appiumby import AppiumBy from selenium.webdriver.support import expected_conditions as EC class CheckStation: def __init__(self, driver=None, wait=None,device_id=None): """初始化CheckStation对象""" if device_id is None: self.device_id = driver_utils.get_device_id() else: self.device_id = device_id if driver is None or wait is None: self.driver, self.wait = driver_utils.init_appium_driver(self.device_id) else: self.driver = driver self.wait = wait # if driver_utils.grant_appium_permissions(self.device_id): # logging.info(f"设备 {self.device_id} 授予Appium权限成功") # else: # logging.warning(f"设备 {self.device_id} 授予Appium权限失败") # # 确保Appium服务器正在运行,不在运行则启动 # if not driver_utils.check_server_status(4723): # driver_utils.start_appium_server() try: if not driver_utils.check_session_valid(self.driver, self.device_id): logging.warning(f"设备 {self.device_id} 会话无效,尝试重新连接驱动...") self.driver, self.wait = driver_utils.reconnect_driver(self.device_id, self.driver) if not self.driver: logging.error(f"设备 {self.device_id} 驱动重连失败") return False except Exception as inner_e: logging.warning(f"设备 {self.device_id} 检查会话状态时出错: {str(inner_e)}") return False # 检查应用是否成功启动 if driver_utils.is_app_launched(self.driver): logging.info(f"设备 {self.device_id} 沉降观测App已成功启动") else: logging.warning(f"设备 {self.device_id} 应用可能未正确启动") driver_utils.check_app_status(self.driver) # @staticmethod # def get_device_id() -> str: # """ # 获取设备ID,优先使用已连接设备,否则使用全局配置 # """ # try: # # 检查已连接设备 # result = subprocess.run( # ["adb", "devices"], # capture_output=True, # text=True, # timeout=10 # ) # # 解析设备列表 # for line in result.stdout.strip().split('\n')[1:]: # if line.strip() and "device" in line and "offline" not in line: # device_id = line.split('\t')[0] # logging.info(f"使用已连接设备: {device_id}") # global_variable.GLOBAL_DEVICE_ID = device_id # return device_id # except Exception as e: # logging.warning(f"设备检测失败: {e}") # # 使用全局配置 # device_id = global_variable.GLOBAL_DEVICE_ID # logging.info(f"使用全局配置设备: {device_id}") # return device_id def get_measure_data(self): # 模拟获取测量数据 pass # def add_transition_point(self): # # 添加转点逻辑 # print("添加转点") # return True def add_transition_point(self): """添加转点""" try: if not driver_utils.check_session_valid(self.driver, self.device_id): logging.warning(f"设备 {self.device_id} 会话无效,尝试重新连接驱动...") self.driver, self.wait = driver_utils.reconnect_driver(self.device_id, self.driver) if not self.driver: logging.error(f"设备 {self.device_id} 驱动重连失败") return False except Exception as inner_e: logging.warning(f"设备 {self.device_id} 检查会话状态时出错: {str(inner_e)}") return False try: # 查找并点击添加转点按钮 add_transition_btn = self.wait.until( EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/btn_add_ZPoint")) ) add_transition_btn.click() logging.info("已点击添加转点按钮") return True except TimeoutException: logging.error("等待添加转点按钮超时") return False except Exception as e: logging.error(f"添加转点时出错: {str(e)}") return False def get_excel_from_url(self, url): """ 从URL获取Excel文件并解析为字典 Excel只有一列数据(A列),每行是站点值 Args: url: Excel文件的URL地址 Returns: dict: 解析后的站点数据字典 {行号: 值},失败返回None """ try: print(f"正在从URL获取数据: {url}") response = requests.get(url, timeout=30) response.raise_for_status() # 检查请求是否成功 # 使用pandas读取Excel数据,指定没有表头,只读第一个sheet excel_data = pd.read_excel( BytesIO(response.content), header=None, # 没有表头 sheet_name=0, # 只读取第一个sheet dtype=str # 全部作为字符串读取 ) station_dict = {} # 解析Excel数据:使用行号+1作为站点编号,A列的值作为站点值 print("解析Excel数据(使用行号作为站点编号)...") for index, row in excel_data.iterrows(): station_num = index + 1 # 行号从1开始作为站点编号 station_value = str(row[0]).strip() if pd.notna(row[0]) else "" if station_value: # 只保存非空值 station_dict[station_num] = station_value print(f"成功解析Excel,共{len(station_dict)}条数据") return station_dict except requests.exceptions.RequestException as e: print(f"请求URL失败: {e}") return None except Exception as e: print(f"解析Excel失败: {e}") return None def check_station_exists(self, station_data: dict, station_num: int) -> str: """ 根据站点编号检查该站点的值是否以Z开头 Args: station_data: 站点数据字典 {编号: 值} station_num: 要检查的站点编号 Returns: str: 如果站点存在且以Z开头返回"add",否则返回"pass" """ if station_num not in station_data: print(f"站点{station_num}不存在") return "error" value = station_data[station_num] str_value = str(value).strip() is_z = str_value.upper().startswith('Z') result = "add" if is_z else "pass" print(f"站点{station_num}: {value} -> {result}") return result def main_run(self): return self.add_transition_point() def run(self, station_num: int): # last_station_num = 0 url = f"https://database.yuxindazhineng.com/team-bucket/69378c5b4f42d83d9504560d/前测点表/20260309/CDWZQ-2标-龙家沟左线大桥-0-11号墩-平原.xlsx" station_data = self.get_excel_from_url(url) print(station_data) station_quantity = len(station_data) #总站点数量 over_station_num = 0 #已完成的站点数量 over_station_list = [] #已完成的站点列表 while over_station_num < station_quantity: try: # 键盘输出线路编号 station_num_input = input("请输入线路编号:") if not station_num_input.isdigit(): # 检查输入是否为数字 print("输入错误:请输入一个整数") continue station_num = int(station_num_input) # 转为整数 if station_num in over_station_list: print("已处理该站点,跳过") continue # if last_station_num == station_num: # print("输入与上次相同,跳过处理") # continue # last_station_num = station_num result = self.check_station_exists(station_data, station_num) if result == "error": print("处理错误:站点不存在") # 错误处理逻辑,比如记录日志、发送警报等 elif result == "add": print("执行添加操作") # 添加转点 if not self.add_transition_point(): print("添加转点失败") # 可以决定是否继续循环 continue over_station_num += 1 else: # result == "pass" print("跳过处理") over_station_num += 1 over_station_list.append(station_num) # 可以添加适当的延时,避免CPU占用过高 # time.sleep(1) except KeyboardInterrupt: print("程序被用户中断") break except Exception as e: print(f"发生错误: {e}") time.sleep(20) # 错误处理,可以继续循环或退出 print(f"已处理{over_station_num}个站点") # 截图 self.driver.save_screenshot("check_station.png") return True def get_excel_from_url(url): """ 从URL获取Excel文件并解析为字典 Excel只有一列数据(A列),每行是站点值 Args: url: Excel文件的URL地址 Returns: dict: 解析后的站点数据字典 {行号: 值},失败返回None """ try: print(f"正在从URL获取数据: {url}") response = requests.get(url, timeout=30) response.raise_for_status() # 检查请求是否成功 # 使用pandas读取Excel数据,指定没有表头,只读第一个sheet excel_data = pd.read_excel( BytesIO(response.content), header=None, # 没有表头 sheet_name=0, # 只读取第一个sheet dtype=str # 全部作为字符串读取 ) station_dict = {} # 解析Excel数据:使用行号+1作为站点编号,A列的值作为站点值 print("解析Excel数据(使用行号作为站点编号)...") for index, row in excel_data.iterrows(): station_num = index + 1 # 行号从1开始作为站点编号 station_value = str(row[0]).strip() if pd.notna(row[0]) else "" if station_value: # 只保存非空值 station_dict[station_num] = station_value print(f"成功解析Excel,共{len(station_dict)}条数据") return station_dict except requests.exceptions.RequestException as e: print(f"请求URL失败: {e}") return None except Exception as e: print(f"解析Excel失败: {e}") return None if __name__ == "__main__": check_station = CheckStation() check_station.run()