130 lines
5.3 KiB
Python
130 lines
5.3 KiB
Python
# coding=utf-8
|
|
import sys
|
|
import os
|
|
import time
|
|
import asyncio
|
|
import uiautomator2 as u2
|
|
import cv2
|
|
|
|
# Add project root to sys.path
|
|
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../"))
|
|
sys.path.append(project_root)
|
|
|
|
try:
|
|
from Apps.YeLiTe.Kit import detect_cards_cv, draw_rectangles, take_screenshot, get_image_content_md5
|
|
from Apps.YeLiTe.Config import Setting
|
|
except ImportError as e:
|
|
print(f"Import Error: {e}")
|
|
sys.exit(1)
|
|
|
|
async def run_verification():
|
|
print(">>> [Step 0] 连接设备...")
|
|
try:
|
|
d = u2.connect()
|
|
info = d.info
|
|
print(f"设备已连接: {info.get('productName', 'Unknown Device')}")
|
|
except Exception as e:
|
|
print(f"设备连接失败: {e}")
|
|
return
|
|
|
|
# 这里我们假设已经在列表页,或者直接启动
|
|
# 为了保险,尝试回到桌面重新进? 不,用户说“获取第一屏场站列表”,假设用户已经准备好了环境,或者我们手动进一下
|
|
# 为了全自动化,我们调用 Opener 进一下
|
|
# 但是 Opener 可能会重启微信,有点慢。
|
|
# 我们先判断当前包名,如果是微信,就默认在列表页(或者由用户手动滑到列表页)
|
|
# 用户指令暗示是交互式的:"获取第一屏...你去点击一下...停止程序"
|
|
# 所以我们假设当前就在列表页
|
|
|
|
current_app = d.app_current()
|
|
print(f"当前前台应用: {current_app.get('package')}")
|
|
if "com.tencent.mm" not in current_app.get('package', ''):
|
|
print("警告:微信似乎不在前台,请确保手机显示的是【驿来特】小程序列表页")
|
|
print("给你 5 秒钟调整手机屏幕...")
|
|
time.sleep(5)
|
|
else:
|
|
print("检测到微信在前台,准备截图...")
|
|
time.sleep(2) # 稍微等一下稳定
|
|
|
|
# 1. 获取第一屏场站列表,然后截图
|
|
timestamp = int(time.time())
|
|
list_screenshot_path = os.path.join(project_root, "Output", f"verify_step1_list_{timestamp}.jpg")
|
|
print(f"\n>>> [Step 1] 截图列表页: {list_screenshot_path}")
|
|
d.screenshot(list_screenshot_path)
|
|
|
|
# 2. 绿框标注,标识模拟点击点
|
|
print("\n>>> [Step 2] 识别卡片并标注...")
|
|
# 使用配置中的排除比例
|
|
cards = detect_cards_cv(list_screenshot_path, top_ratio=Setting.SAFE_EXCLUDE_RATIO, bottom_ratio=Setting.BOTTOM_SAFE_EXCLUDE_RATIO)
|
|
|
|
if not cards:
|
|
print("!!! [Error] 未检测到任何场站卡片,测试终止")
|
|
print(f"请检查截图: {list_screenshot_path}")
|
|
return
|
|
|
|
print(f"检测到 {len(cards)} 个卡片区域")
|
|
|
|
# 在图上绘制绿框和红点
|
|
debug_img = cv2.imread(list_screenshot_path)
|
|
if debug_img is None:
|
|
print("读取截图失败")
|
|
return
|
|
|
|
first_card = cards[0]
|
|
# 计算点击点:中心点
|
|
click_x = int((first_card[0] + first_card[2]) / 2)
|
|
click_y = int((first_card[1] + first_card[3]) / 2)
|
|
|
|
# 绘制所有卡片
|
|
for i, box in enumerate(cards):
|
|
# 绿框
|
|
cv2.rectangle(debug_img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), (0, 255, 0), 2)
|
|
# 标号
|
|
cv2.putText(debug_img, str(i+1), (int(box[0]), int(box[1])+30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
|
|
|
|
# 绘制第一个卡片的点击点 (实心红圆)
|
|
cv2.circle(debug_img, (click_x, click_y), 15, (0, 0, 255), -1)
|
|
# 绘制同心圆
|
|
cv2.circle(debug_img, (click_x, click_y), 25, (0, 0, 255), 2)
|
|
|
|
marked_path = os.path.join(project_root, "Output", f"verify_step2_marked_{timestamp}.jpg")
|
|
cv2.imwrite(marked_path, debug_img)
|
|
print(f">>> 已生成标注图 (绿框+红点): {marked_path}")
|
|
print(f">>> 模拟点击目标: 第 1 个卡片, 坐标 ({click_x}, {click_y})")
|
|
|
|
# 计算点击前的 MD5
|
|
before_md5 = get_image_content_md5(list_screenshot_path, top_ratio=Setting.SAFE_EXCLUDE_RATIO, bottom_ratio=Setting.BOTTOM_SAFE_EXCLUDE_RATIO)
|
|
|
|
# 3. 你去点击一下,等一会
|
|
print(f"\n>>> [Step 3] 执行点击操作...")
|
|
# 使用 shell input tap
|
|
cmd = f"input tap {click_x} {click_y}"
|
|
print(f"执行命令: {cmd}")
|
|
d.shell(cmd)
|
|
|
|
print(">>> 点击完成,等待 5 秒让页面跳转...")
|
|
await asyncio.sleep(5)
|
|
|
|
# 4. 再继续截图,判断是否进入
|
|
after_screenshot_path = os.path.join(project_root, "Output", f"verify_step4_after_{timestamp}.jpg")
|
|
print(f"\n>>> [Step 4] 截图当前页面: {after_screenshot_path}")
|
|
d.screenshot(after_screenshot_path)
|
|
|
|
after_md5 = get_image_content_md5(after_screenshot_path, top_ratio=Setting.SAFE_EXCLUDE_RATIO, bottom_ratio=Setting.BOTTOM_SAFE_EXCLUDE_RATIO)
|
|
|
|
print("\n>>> [Step 5] 结果验证")
|
|
print("-" * 30)
|
|
print(f"点击前 MD5: {before_md5}")
|
|
print(f"点击后 MD5: {after_md5}")
|
|
|
|
if before_md5 != after_md5:
|
|
print(">>> [SUCCESS] 判定结果: 成功进入详情页! (MD5发生变化)")
|
|
else:
|
|
print(">>> [FAILURE] 判定结果: 未进入详情页 (MD5未变化)")
|
|
print("可能原因: 1. 点击无效 2. 页面加载极慢 3. 已经是详情页(误判)")
|
|
print("-" * 30)
|
|
|
|
if __name__ == "__main__":
|
|
loop = asyncio.new_event_loop()
|
|
asyncio.set_event_loop(loop)
|
|
loop.run_until_complete(run_verification())
|