feat(任务): 录制手势改成**纯录制回放**(真手指轨迹)+ 手机端 getevent 录制
用户反馈:录制出来的滑动又被套上滑动那套逻辑(方向/幅度/拟人重新生成),
"导致滑动还是不顺畅"。录制就该是录制——按录下的路径与时间原样重放。
- 新步骤 `gesture`「录制手势」:存完整轨迹点列 `[[x,y,t_ms],…]`,
回放时原样交给设备(`d.swipe_points(points, duration)`),不做任何加工。
与 `swipe` 是两套东西(滑动是参数化的,录制是点列)。
- core/gesture.py(新):
· 手机端录制 `PhoneRecorder`:`getevent` 读**真触屏**设备(自动挑 fts_ts 这类、
排除 uinput/vitural-sar 等合成节点),解析两套协议(BTN_TOUCH / ABS_MT_TRACKING_ID);
**合成的注入事件不会出现在真触屏节点上**(实测),所以录到的只有人手的动作;
· 点列清洗:按 ≥16ms 抽稀但**末点必留**(快划时不能把收尾丢了);
· 回放**一次调用**而不是逐点注入:实测这台设备单次触摸 RPC ≈190ms,
逐点回放 20 点要 3.8 秒——只能让设备自己插值,"时间"由点密度还原。
- 接口:POST /api/gesture/record/{start,stop}(需设备权限;重复开始返回 409)。
- 「录制手势」步骤卡片:录到就回填(手机上录 / 网页上录),显示点数/时长;
**滑动步骤上的「录制手势」按钮已移除**(按用户要求,录制不再走滑动逻辑)。
- 录制前自动唤醒设备:**息屏时 u2 抓 UI 树会从 3 秒退化到 65 秒**(实测),
截图也是黑的——这是本次排查最耗时的坑,已写进文档。
自测:假设备单测(点列/时长/抽稀/失败退回直线,10 项);
无头浏览器 + CDP 真模拟拖动 → 录到 14 点/605ms 并按实际轨迹回填;
手机录制接口起停/重复拦截;
真机回放:用录下的轨迹跑任务 → 步骤 `gesture ok`。
⚠️ 手机端"真手指轨迹"这一段需要人真的去划才能端到端验证(我没有手指)。
文档:TASK_DEV §3.2(两套东西对比 + 三个坑)、步骤表 21 种、API、README。
This commit is contained in:
+35
-2
@@ -10,7 +10,7 @@
|
||||
|
||||
- [1. 核心概念](#1-核心概念)
|
||||
- [2. 通用步骤任务 generic_steps](#2-通用步骤任务-generic_steps)
|
||||
- [3. 20 种步骤全表](#3-20-种步骤全表)(含 [3.1 步骤默认值与动作录制](#31-步骤默认值与动作录制任务--动作配置))
|
||||
- [3. 21 种步骤全表](#3-21-种步骤全表)(含 [3.1 步骤默认值与动作录制](#31-步骤默认值与动作录制任务--动作配置))
|
||||
- [4. 容器步骤与公共参数](#4-容器步骤与公共参数)(含 [4.5 公共巡检](#45-公共巡检任务级独立于步骤画布))
|
||||
- [5. 选择器与元素定位](#5-选择器与元素定位)
|
||||
- [6. 自定义动作](#6-自定义动作)
|
||||
@@ -108,7 +108,7 @@ from .generic import task # 触发 @register_task(当前唯一任务类型)
|
||||
|
||||
---
|
||||
|
||||
## 3. 20 种步骤全表
|
||||
## 3. 21 种步骤全表
|
||||
|
||||
> 参数与默认值以 `tasks/generic/task.py` 为准;前端 `STEP_LIB`(`static/admin/editor.js`)负责在编辑器里呈现这些字段。
|
||||
|
||||
@@ -134,6 +134,39 @@ from .generic import task # 触发 @register_task(当前唯一任务类型)
|
||||
| 18 | `if_el` | 条件判断 | `selector_type`、`selector_value`、`timeout`(3) | `ocr_click`(False) | `then` / `else` | 见 §4.2;条件类型除元素/OCR 外还支持 **屏幕状态**、**前台App** |
|
||||
| 19 | `notify` | 发通知 | — | `title`("")、`message`("")、`level`("info") | — | 推一条**自定义**通知(事件 `task.notify.custom`):标题正文自己写,支持 `{device} {serial} {job} {time} {app} {screen}`;谁收到取决于 webhook 的事件订阅。两者都空则跳过 |
|
||||
| 20 | `stop_self` | 停止本设备 | — | `reason`("") | — | 只停**本设备**的任务(其它设备照跑):置 worker 停止位,后续步骤不再执行,任务记成**被停止而不是失败**(不触发重试) |
|
||||
| 21 | `gesture` | 录制手势 | `points`(录出来的) | `speed`(1.0) | — | **纯录制回放**:把录下的轨迹点列 `[[x,y,t_ms],…]` 按原路径与时长交给设备插值,不做弧线/抖动/手速加工。与「滑动」是两套东西,见 §3.2 |
|
||||
|
||||
### 3.2 录制手势:**纯录制、纯回放**(`core/gesture.py`)
|
||||
|
||||
「滑动」和「录制手势」是**两套东西**,别混:
|
||||
|
||||
| | `swipe` 步骤 | `gesture` 步骤 |
|
||||
|---|---|---|
|
||||
| 存什么 | 方向 + 幅度 + 时长区间 | **完整轨迹点列** `[[x,y,t_ms], …]` |
|
||||
| 回放时 | 每次重新生成(弧线/抖动/本设备手速) | **照录制的路径与时长**,不做任何修饰 |
|
||||
| 适合 | 通用滑动,换设备也能用 | 你亲手划的、要求一模一样的手势 |
|
||||
|
||||
**为什么录制的不能走滑动那套**:滑动是"参数化"的——它按方向+幅度重新生成轨迹并叠
|
||||
拟人抖动,录下来的路径就被丢掉了。要"完全按我划的重放",就只能存点列、回放点列。
|
||||
|
||||
**两个录制来源**(都在「录制手势」步骤的卡片上):
|
||||
|
||||
| 来源 | 做法 | 特点 |
|
||||
|---|---|---|
|
||||
| ● 手机上录 | 点开始后**用手指在真机上划**,后端读 `getevent` 抓真触屏 | 最真实:录的是人手的原始轨迹。合成注入不会出现在真触屏节点上(实测),所以录到的只有人手 |
|
||||
| ● 网页上录 | 在弹窗画面里按住鼠标拖,前端按 8ms/3px 采样 | 不用碰手机,但有鼠标的机械感 |
|
||||
|
||||
要点与坑:
|
||||
|
||||
- **录制前必须唤醒设备**:息屏时 u2 抓 UI 树会从 3 秒退化到 **65 秒**(实测),截图还是黑的。
|
||||
前端在选好设备后会自动调一次亮屏(`/api/device/screen_all`)。
|
||||
- **回放是一次调用**(`d.swipe_points(points, duration)`),不是逐点注入:实测这台设备
|
||||
**单次触摸注入 RPC ≈190ms**,逐点回放 20 个点要 3.8 秒,比录的手势慢一个数量级。
|
||||
所以只能让设备自己插值——"时间"靠**点密度**还原(手指慢的地方采样点更密)。
|
||||
- 回放点数**抽稀到 40 个**(`MAX_REPLAY_POINTS`):这台设备每个点开销大,40 是画质/耗时折中;
|
||||
首尾点一定保留。
|
||||
- 轨迹是**屏幕绝对像素**:换分辨率不同的设备可能偏,同型号/同分辨率最稳。
|
||||
- 点列存在步骤 JSON 里(一条 0.5s 的手势约 25 点 / 400 字节),不新建表。
|
||||
|
||||
### 3.1 步骤默认值与动作录制(任务 → 动作配置)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user