优化quart接口。优化添加设备逻辑。
This commit is contained in:
@@ -4,12 +4,10 @@ import socket
|
||||
import threading
|
||||
import time
|
||||
import subprocess
|
||||
from typing import Dict, Optional
|
||||
|
||||
from typing import Dict
|
||||
import tidevice
|
||||
import wda
|
||||
from tidevice import Usbmux, ConnectionType
|
||||
|
||||
from Entity.DeviceModel import DeviceModel
|
||||
from Entity.Variables import WdaAppBundleId, wdaFunctionPort
|
||||
from Module.FlaskSubprocessManager import FlaskSubprocessManager
|
||||
@@ -71,31 +69,33 @@ class DeviceInfo:
|
||||
LogManager.method_info("进入主循环", "listen", udid="system")
|
||||
print("[Listen] 开始监听设备上下线...")
|
||||
|
||||
last_broadcast = 0.0 # 用来做“心跳全量同步”的时间戳
|
||||
|
||||
while True:
|
||||
try:
|
||||
usb = Usbmux().device_list()
|
||||
online = {d.udid for d in usb if d.conn_type == ConnectionType.USB}
|
||||
except Exception as e:
|
||||
LogManager.warning(f"[device_list] 异常:{e}", udid="system")
|
||||
time.sleep(1)
|
||||
continue
|
||||
print("[Listen] device_list 出错,本轮视为无设备,防止状态脏死")
|
||||
usb = []
|
||||
online = set()
|
||||
|
||||
with self._lock:
|
||||
known = set(self._models.keys())
|
||||
|
||||
# 1. 新设备
|
||||
# ---------- 1. 新设备 ----------
|
||||
now = time.time()
|
||||
for udid in online:
|
||||
self._last_seen[udid] = time.time()
|
||||
self._last_seen[udid] = now
|
||||
if udid not in known:
|
||||
try:
|
||||
self._add_device(udid)
|
||||
except Exception as e:
|
||||
# 单设备异常不能干掉整个循环
|
||||
LogManager.warning(f"[Add] 处理设备 {udid} 异常: {e}", udid=udid)
|
||||
print(f"[Add] 处理设备 {udid} 异常: {e}")
|
||||
|
||||
# 2. 可能离线的设备
|
||||
now = time.time()
|
||||
# ---------- 2. 可能离线设备 ----------
|
||||
for udid in list(known):
|
||||
if udid not in online:
|
||||
last = self._last_seen.get(udid, 0)
|
||||
@@ -106,6 +106,15 @@ class DeviceInfo:
|
||||
LogManager.method_error(f"移除失败:{e}", "listen", udid=udid)
|
||||
print(f"[Remove] 移除失败 {udid}: {e}")
|
||||
|
||||
# ---------- 3. 心跳:每 5 秒强制同步一次到 Flask ----------
|
||||
if now - last_broadcast > 5.0:
|
||||
try:
|
||||
self._manager_send()
|
||||
except Exception as e:
|
||||
print(f"[Listen] 周期同步到 Flask 失败: {e}")
|
||||
else:
|
||||
last_broadcast = now
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
# ==========================
|
||||
@@ -216,7 +225,6 @@ class DeviceInfo:
|
||||
|
||||
# 给 WDA 一点启动缓冲时间
|
||||
time.sleep(2.0)
|
||||
|
||||
for _ in range(max_retry):
|
||||
# 设备已移除就不再尝试
|
||||
with self._lock:
|
||||
|
||||
@@ -469,20 +469,38 @@ async def passAnchorData():
|
||||
needReply = data.get("needReply", False)
|
||||
# 获取打招呼数据
|
||||
ev.prologueList = data.get("prologueList", [])
|
||||
|
||||
needTranslate = data.get("needTranslate", False)
|
||||
|
||||
# 添加主播数据
|
||||
addModelToAnchorList(acList)
|
||||
# 启动线程,执行脚本
|
||||
|
||||
failed_ids = []
|
||||
# 启动线程,执行脚本(单个设备异常不影响其它设备)
|
||||
for udid in idList:
|
||||
manager = ScriptManager()
|
||||
event = threading.Event()
|
||||
# 启动脚本
|
||||
thread = threading.Thread(target=manager.safe_greetNewFollowers,
|
||||
args=(udid, needReply, isComment, needTranslate, event,))
|
||||
# 添加到线程管理
|
||||
ThreadManager.add(udid, thread, event)
|
||||
try:
|
||||
manager = ScriptManager()
|
||||
event = threading.Event()
|
||||
thread = threading.Thread(
|
||||
target=manager.safe_greetNewFollowers,
|
||||
args=(udid, needReply, isComment, needTranslate, event,),
|
||||
)
|
||||
ThreadManager.add(udid, thread, event)
|
||||
except Exception as e:
|
||||
failed_ids.append(udid)
|
||||
LogManager.error(f"[passAnchorData] 设备 {udid} 启动脚本失败: {e}")
|
||||
|
||||
# 如果所有设备都失败,可以考虑返回错误码
|
||||
if failed_ids and len(failed_ids) == len(idList):
|
||||
return ResultData(
|
||||
data="",
|
||||
code=1001,
|
||||
message=f"所有设备启动失败: {failed_ids}"
|
||||
).toJson()
|
||||
|
||||
# 部分失败也算整体成功,只是记录一下
|
||||
if failed_ids:
|
||||
LogManager.warning(f"[passAnchorData] 部分设备启动失败: {failed_ids}")
|
||||
|
||||
return ResultData(data="").toJson()
|
||||
except Exception as e:
|
||||
LogManager.error(e)
|
||||
@@ -493,6 +511,7 @@ async def followAndGreetUnion():
|
||||
try:
|
||||
LogManager.method_info("关注打招呼", "关注打招呼(联盟号)")
|
||||
data: Dict[str, Any] = await request.get_json()
|
||||
|
||||
# 设备列表
|
||||
idList = data.get("deviceList", [])
|
||||
# 主播列表
|
||||
@@ -503,29 +522,45 @@ async def followAndGreetUnion():
|
||||
|
||||
# 是否需要回复
|
||||
needReply = data.get("needReply", True)
|
||||
|
||||
needTranslate = data.get("needTranslate", False)
|
||||
|
||||
|
||||
|
||||
|
||||
# 获取打招呼数据
|
||||
ev.prologueList = data.get("prologueList", [])
|
||||
|
||||
# 添加主播数据
|
||||
addModelToAnchorList(acList)
|
||||
# 启动线程,执行脚本
|
||||
|
||||
failed_ids = []
|
||||
|
||||
# 启动线程,执行脚本(单个设备异常不影响其它设备)
|
||||
for udid in idList:
|
||||
manager = ScriptManager()
|
||||
event = threading.Event()
|
||||
# 启动脚本
|
||||
thread = threading.Thread(target=manager.safe_followAndGreetUnion,
|
||||
args=(udid, needReply, needTranslate, event))
|
||||
# 添加到线程管理
|
||||
ThreadManager.add(udid, thread, event)
|
||||
try:
|
||||
manager = ScriptManager()
|
||||
event = threading.Event()
|
||||
thread = threading.Thread(
|
||||
target=manager.safe_followAndGreetUnion,
|
||||
args=(udid, needReply, needTranslate, event),
|
||||
)
|
||||
ThreadManager.add(udid, thread, event)
|
||||
except Exception as e:
|
||||
failed_ids.append(udid)
|
||||
LogManager.error(f"[followAndGreetUnion] 设备 {udid} 启动脚本失败: {e}")
|
||||
|
||||
# 如果所有设备都失败,可以返回错误码
|
||||
if failed_ids and len(failed_ids) == len(idList):
|
||||
return ResultData(
|
||||
data="",
|
||||
code=1001,
|
||||
message=f"所有设备启动失败: {failed_ids}",
|
||||
).toJson()
|
||||
|
||||
# 部分失败也算整体成功,只是记录一下
|
||||
if failed_ids:
|
||||
LogManager.warning(f"[followAndGreetUnion] 部分设备启动失败: {failed_ids}")
|
||||
|
||||
return ResultData(data="").toJson()
|
||||
|
||||
except Exception as e:
|
||||
LogManager.error(e)
|
||||
LogManager.error(f"[followAndGreetUnion] 接口级异常: {e}")
|
||||
return ResultData(data="", code=1001).toJson()
|
||||
|
||||
# 获取私信数据
|
||||
@@ -824,64 +859,6 @@ async def getDeviceNetStatus():
|
||||
|
||||
return ResultData(data=value, code=200).toJson()
|
||||
|
||||
@app.route('/test', methods=['POST'])
|
||||
def test():
|
||||
import wda
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
# 设备的UDID
|
||||
udid = "00008110-000120603C13801E"
|
||||
|
||||
# 连接到设备
|
||||
client = wda.USBClient(udid)
|
||||
session = client.session()
|
||||
|
||||
# 设置Appium的截图深度
|
||||
session.appium_settings({"snapshotMaxDepth": 15})
|
||||
|
||||
# 获取当前屏幕截图
|
||||
screenshot = session.screenshot()
|
||||
screenshot = cv2.imdecode(np.frombuffer(screenshot, np.uint8), cv2.IMREAD_COLOR)
|
||||
|
||||
# 读取大图和小图
|
||||
large_image = screenshot # 这里使用截图作为大图
|
||||
template = cv2.imread(r'E:\python\Scrcpy_test\open-cv-tk\insert_comment.png', 0) # 0 表示以灰度模式读取
|
||||
|
||||
# 检查图像是否成功加载
|
||||
if template is None:
|
||||
print("小图加载失败,请检查路径")
|
||||
exit()
|
||||
|
||||
# 获取模板的宽度和高度
|
||||
w, h = template.shape[::-1]
|
||||
|
||||
# 使用模板匹配方法
|
||||
result = cv2.matchTemplate(large_image, template, cv2.TM_CCOEFF_NORMED)
|
||||
|
||||
# 设定阈值
|
||||
threshold = 0.8
|
||||
loc = np.where(result >= threshold)
|
||||
|
||||
# 遍历所有匹配点
|
||||
if loc[0].size > 0: # 检查是否有匹配点
|
||||
for pt in zip(*loc[::-1]): # 将坐标转换为 (x, y) 格式
|
||||
cv2.rectangle(large_image, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 2)
|
||||
print(f"找到匹配区域,坐标:{pt},尺寸:{(w, h)}")
|
||||
else:
|
||||
print("未找到匹配区域,请检查模板和大图的内容,或调整阈值")
|
||||
|
||||
# 保存结果
|
||||
cv2.imwrite('matched_result.png', large_image)
|
||||
|
||||
# 显示结果
|
||||
cv2.imshow('Matched Result', large_image)
|
||||
cv2.waitKey(0)
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
# 关闭会话
|
||||
session.close()
|
||||
|
||||
# 获取ai配置
|
||||
@app.route("/getAiConfig", methods=['GET'])
|
||||
def getAiConfig():
|
||||
|
||||
Reference in New Issue
Block a user