feat: 设备身份改为「名称 + 指纹」——更换 IP 自动认领,分组/任务引用自动同步
背景:设备池原先拿 serial(IP)当身份。设备一换 IP(DHCP 重新分配)旧记录就成了连不上的
僵尸条目(表现为"断联·自动重连中"但设备并没关机),分组与 serial 模式的任务还吊着死地址。
2026-09-11 实际发生:.70 变成 .71、.72 消失,平台两个条目永远连不上。
实现
- **设备名称必填且唯一**:加入设备必须填名称;库层面用部分唯一索引兜底
(ux_device_name / ux_device_fingerprint,WHERE 非空 → 兼容历史空值),管理页可改名
- **设备指纹**(ro.serialno):网络设备添加/确认/扫描/采集型号时自动读取;
身份三层拆分——名称(人可读,稳定)、指纹(机器识别,稳定)、serial(当前地址,可变)
- **自动认领**:添加或确认设备时指纹命中池中已有记录 → 迁移原记录到新地址
(名称/型号/备注/启用状态/添加时间全保留),不新增条目
- **人工认领** `POST /api/devices/pool/relocate`:旧地址已断联、指纹没采过时的兜底——
人工指认"这条就是那台,现在在 X",迁移并同步引用
- **引用同步**:认领/迁址时把 device_group.serials 与 task_job.target.serial 的旧地址
换成新地址。⚠️ 必须同时改**内存**:分组/任务在 TaskManager 里另有内存副本且调度用内存对象,
只改库不重启不生效 → device_pool 迁址后回调 TaskManager.sync_device_serial
(装配层用 set_move_hook 注册;device_pool 不能反向 import task_manager,会循环依赖)
- **前端**:待连接池新增「识别」列(指纹命中时提示"≈ 名称(原 IP)",按钮变「认领为 X」);
设备池新增「名称/指纹」列与「改名/换地址」操作;断联设备表也加「换地址」(用户看到断联就在这里)
- 添加设备接口改用 adb_connect_light(单次短超时),避免不可达 IP 让请求卡 30s+;重名校验提前到 adb 之前
文档:API.md §6 重写(设备身份/认领/新接口)、DATA_MODEL.md(新列 + v5/v6 迁移 + 唯一索引)、
ARCHITECTURE.md §4.0(身份三层与引用同步的内存坑)、DEPLOY.md 排查表加"断联但没关机"条目
自测(全通过):名称必填/唯一/改名/重名拒绝(含库层面约束);指纹采集(真实读到 .71 的
gy7lskwkkvj7c6b6);自动认领(指纹命中→迁址+保留名称+带指纹+未命中不误判);人工认领
(迁址+名称保留+分组与任务引用同步);浏览器验证设备池/断联表/待连接池三个界面
This commit is contained in:
@@ -845,17 +845,19 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<span id="discovery-status" class="text-muted"></span>
|
||||
</div>
|
||||
<table class="table table-hover table-sm" style="margin-top:8px">
|
||||
<thead><tr><th>serial</th><th>来源</th><th>首次发现</th><th>最近发现</th><th>在线</th><th>操作</th></tr></thead>
|
||||
<tbody id="tb-discovery"><tr><td colspan="6" class="empty">尚未扫描</td></tr></tbody>
|
||||
<thead><tr><th>serial</th><th>识别</th><th>来源</th><th>首次发现</th><th>最近发现</th><th>在线</th><th>操作</th></tr></thead>
|
||||
<tbody id="tb-discovery"><tr><td colspan="7" class="empty">尚未扫描</td></tr></tbody>
|
||||
</table>
|
||||
<div class="help">扫描局域网/Tailscale 网段中开放 adb 5555 的设备进入<b>待连接池</b>;
|
||||
<b>确认后才加入正式设备池</b>(不自动连接、不参与任务调度)。未授权设备(手机未接受 RSA 弹窗)不会出现。</div>
|
||||
<b>确认后才加入正式设备池</b>(不自动连接、不参与任务调度)。未授权设备(手机未接受 RSA 弹窗)不会出现。<br>
|
||||
<b>「识别」列</b>:平台按<b>设备指纹</b>认出这台其实就是池中某台设备换了 IP —— 确认后自动<b>认领</b>:
|
||||
迁移原记录(名称/型号/备注全保留),并把分组与任务里的旧地址一并换成新地址。新设备则必须填名称。</div>
|
||||
<!-- 正式池断联设备:仍在设备池(不删除、不进待连接池),自动重连中 -->
|
||||
<div style="margin-top:10px">
|
||||
<div style="font-size:12.5px;font-weight:600;margin-bottom:6px">设备池断联设备
|
||||
<span class="text-muted" style="font-weight:400">(仍在设备池内,扫描线程每轮自动重连;也可手动立即重连)</span></div>
|
||||
<table class="table table-hover table-sm">
|
||||
<thead><tr><th>serial</th><th>型号</th><th>备注</th><th>状态</th><th>操作</th></tr></thead>
|
||||
<thead><tr><th>serial</th><th>名称</th><th>型号</th><th>状态</th><th>操作</th></tr></thead>
|
||||
<tbody id="tb-pool-offline"><tr><td colspan="5" class="empty">全部在线</td></tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -863,8 +865,9 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
<div class="toolbar">
|
||||
<input type="text" id="devpool-serial" class="form-control" style="width:220px;font-family:monospace"
|
||||
placeholder="serial,如 100.100.10.20:5555" onkeydown="if(event.key==='Enter')addPoolDev()">
|
||||
<input type="text" id="devpool-name" class="form-control" style="width:150px"
|
||||
placeholder="备注名(可选)" onkeydown="if(event.key==='Enter')addPoolDev()">
|
||||
<input type="text" id="devpool-name" class="form-control" style="width:170px"
|
||||
placeholder="设备名称(必填·唯一)" title="设备在平台里的标识;分组、任务目标、日志都用它认设备"
|
||||
onkeydown="if(event.key==='Enter')addPoolDev()">
|
||||
<button class="btn btn-primary" onclick="addPoolDev()">添加设备</button>
|
||||
<button class="btn" onclick="reconnectPoolDevices()" title="并发 adb connect 池内全部设备">一键重连</button>
|
||||
<button class="btn" onclick="refreshPoolModels()" title="采集池内在线设备的型号(getprop)">采集型号</button>
|
||||
@@ -876,14 +879,18 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14
|
||||
</div>
|
||||
<table class="table table-hover table-sm" style="margin-top:8px">
|
||||
<thead><tr>
|
||||
<th>serial</th><th>名称</th><th>型号</th><th>在线</th><th>状态</th><th>添加时间</th><th>操作</th>
|
||||
<th>serial</th><th>名称</th><th>型号</th><th>在线</th><th>状态</th>
|
||||
<th title="设备指纹(ro.serialno):采集到之后,设备换 IP 才能被自动认领">指纹</th>
|
||||
<th>添加时间</th><th>操作</th>
|
||||
</tr></thead>
|
||||
<tbody id="tb-devpool"></tbody>
|
||||
</table>
|
||||
<div class="help">
|
||||
新增设备流程:手机开 USB 调试 → 连上后「adb 终端」执行 <code>tcpip 5555</code> 转网络调试 →
|
||||
Tailscale 上线(同一账号)→ 在此添加 <code>IP:5555</code>(自动尝试连接)→
|
||||
任务运行时 u2 自动推送 atx-agent。<b>停用 = 不参与任务调度</b>,删除 = 从池中移除(不影响其他系统)。
|
||||
任务运行时 u2 自动推送 atx-agent。<b>停用 = 不参与任务调度</b>,删除 = 从池中移除(不影响其他系统)。<br>
|
||||
<b>设备名称必填且唯一</b>:它是设备在平台里的身份(分组/任务/日志都按名称认设备);
|
||||
设备换了 IP 时用「换地址」把记录迁过去,分组与任务的引用会自动同步,不用重新配。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user