import requests import time from concurrent.futures import ThreadPoolExecutor, as_completed from main import DeviceAutomation import globals.apis as apis import random from datetime import datetime, timedelta ## --- 配置区 --- API_URL = "http://your-api-server.com/api/tasks" # 替换为真实的接口地址 MAX_WORKERS = 3 # 最大并发线程数,建议根据网络带宽调整 TIME_FILE_PATH = r"D:\uploadInfo\time.txt" # 电脑D盘下的路径 def parse_time_config(): """ 解析 D:\time.txt 文件 返回格式: { "用户名": "16:40:20", ... } """ time_map = {} if not os.path.exists(TIME_FILE_PATH): print(f"⚠️ 未找到配置文件: {TIME_FILE_PATH}") return time_map try: with open(TIME_FILE_PATH, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if not line: continue # 使用正则匹配用户名、时间、状态 # 兼容 wangshun 16:40:20 true 和 cdwzq3liangchaoyong 15:06:35 true match = re.search(r'(\w+)\s+(\d{2}:\d{2}:\d{2})\s+true', line) if match: username = match.group(1) scheduled_time = match.group(2) time_map[username] = scheduled_time except Exception as e: print(f"❌ 解析 time.txt 失败: {e}") return time_map def get_remote_tasks(): """ 从接口获取数据 """ try: # 1. 先获取本地文件中的配置 local_times = parse_time_config() if not local_times: print("❌ time.txt 中没有有效的 true 任务或文件为空") return {} # 2. 从服务器获取账户 accounts = apis.get_accounts_from_server("68ef0e02b0138d25e2ac9918") if not accounts: print("❌ 未从服务器获取到账户信息,终止流程") return {} # filtered_accounts = [account for account in accounts if account.get('is_ok') == 1] # # print("✅ 获取账户信息成功", filtered_accounts) # # current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # # 从原始 accounts 数据中筛选有 device_ip 和 device_port 且不为 None 的账户 # device_dict = {} # for account in filtered_accounts: # device_ip = account.get('device_ip') # device_port = account.get('device_port') # # 检查 device_ip 和 device_port 是否都存在且不为 None # if device_ip and device_port: # # 拼接为 ip:port 格式 # key = f"{device_ip}:{device_port}" # # 添加当前时间 # # device_dict[key] = current_time # # 获取当前时间的 datetime 对象 # current_datetime = datetime.now() # # 生成1-2小时的随机时间 # random_hours = random.uniform(1, 2) # # 计算未来时间(datetime 对象可以加 timedelta) # future_datetime = current_datetime + timedelta(hours=random_hours) # # 将 datetime 对象格式化为字符串 # time_str = future_datetime.strftime("%Y-%m-%d %H:%M:%S") # # 添加时间字符串到字典 # device_dict[key] = time_str # # 结果 # print(device_dict) # return device_dict device_dict = {} today_str = datetime.now().strftime("%Y-%m-%d") for account in accounts: # 条件1: 接口返回 is_ok == 1 if account.get('is_ok') != 1: continue username = account.get('username') # 假设接口中用户名的 key 是 username device_ip = account.get('device_ip') device_port = account.get('device_port') # 条件2: 用户名在 time.txt 中且状态为 true (已经在 local_times 过滤过) if username in local_times and device_ip and device_port: key = f"{device_ip}:{device_port}" # 拼接成完整的 YYYY-MM-DD HH:MM:SS full_time_str = f"{today_str} {local_times[username]}" device_dict[key] = full_time_str print(f"✅ 匹配成功,待执行任务详情: {device_dict}") return device_dict # # 模拟数据供测试 # return { # "192.168.1.45:5555": "2026-02-03 10:20:00", # "192.168.1.100:5556": "2026-02-03 10:20:20", # "192.168.31.12:5557": "2026-02-03 10:21:00" # } except Exception as e: print(f"❌ 获取接口任务失败: {e}") return {} def run_task(address, target_time): """ 单个线程的任务包装器 """ # 格式化账号/设备名:确保带上端口号 device_address = address print(f"🕒 [等待/启动] 设备: {device_address} | 预定时间: {target_time}") # 解析目标时间 target_datetime = datetime.strptime(target_time, "%Y-%m-%d %H:%M:%S") current_datetime = datetime.now() # 计算等待时间 wait_seconds = (target_datetime - current_datetime).total_seconds() # 如果需要等待 if wait_seconds > 0: print(f"⏳ [等待中] 设备: {device_address} | 等待时间: {wait_seconds:.2f}秒") time.sleep(wait_seconds) print(f"▶️ [开始执行] 设备: {device_address} | 当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") else: print(f"▶️ [开始执行] 设备: {device_address} | 当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") try: # 创建DeviceAutomation实例并执行上传逻辑 automation = DeviceAutomation(device_address) result = automation.handle_app_state() return f"✅ {device_address} 完成: {result}" except Exception as e: return f"❌ {device_address} 报错: {str(e)}" def monitor_center(): """调度中心""" tasks_data = get_remote_tasks() if not tasks_data: print("📭 接口未返回任何任务,程序退出。") return print(f"🗂️ 发现 {len(tasks_data)} 个待处理账号,开始建立线程池...") # 使用线程池并发执行 with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: # 提交所有任务 future_to_device = { executor.submit(run_task, acc, t): acc for acc, t in tasks_data.items() } # 实时打印完成情况 for future in as_completed(future_to_device): print(future.result()) if __name__ == "__main__": print("🚀 自动化调度程序启动...") monitor_center() print("🏁 所有并发任务处理序列结束。")