fix(device-test): contain tool processes and add reviewed preview
This commit is contained in:
1 parent
c98d7527a0
commit
7d31e09cb7
59 files changed
+23722
No files matched your search
@@ -0,0 +1,51 @@
|
||||
# Artemis v1.5.2 观察链补丁
|
||||
|
||||
适用:团队希望复现开发机已经验证的“只观察APP → 保存笔记 → 正常结束 → Checker核验”流程。补丁在 [artemis-v1.5.2-observation.patch](../assets/patches/artemis-v1.5.2-observation.patch),不是 Artemis 安装包,不会因安装 Skill 自动应用。
|
||||
|
||||
## 基线与作用
|
||||
|
||||
- 已核对基线:Artemis tag `v1.5.2`,Git提交 `bdc75d0c657c5c2707b4c6e352eed6a1f5c14fff`。
|
||||
- 补丁涉及3个实现文件及3个测试文件:Operator在计划完整完成时结束无设备动作循环;Checker能查看笔记预览并读取被省略笔记、精确匹配检查项展示前缀;resolver补充Windows标准scrcpy安装位置。
|
||||
- 不包含模型Key、环境配置、用户历史、截图或设备资料。补丁摘要见发布清单;补丁不是所有Artemis问题的通用修复。
|
||||
|
||||
## 检查并应用
|
||||
|
||||
在同事的 Artemis 项目执行以下只读检查。先保存工作,确认当前没有运行任务。变量只为示例,将Skill和Artemis路径换为本机目录。
|
||||
|
||||
```powershell
|
||||
$artemisRoot = 'D:/Artemis'
|
||||
$skillRoot = 'D:/TeamSkills/artemis-device-test'
|
||||
$patchFile = Join-Path $skillRoot 'assets/patches/artemis-v1.5.2-observation.patch'
|
||||
git -C $artemisRoot rev-parse HEAD
|
||||
git -C $artemisRoot status --short
|
||||
git -C $artemisRoot apply --stat $patchFile
|
||||
git -C $artemisRoot apply --check $patchFile
|
||||
```
|
||||
|
||||
只有提交完全匹配上述基线、相关文件没有其他未保存改动且 `apply --check` 成功时,才在当前已授权的环境修复范围执行:
|
||||
|
||||
```powershell
|
||||
git -C $artemisRoot apply $patchFile
|
||||
git -C $artemisRoot diff --check
|
||||
```
|
||||
|
||||
若已应用相同补丁,`git apply --reverse --check` 成功可辅助确认,不能重复叠加。其他版本、存在相关修改或正反检查都失败时保留原文件,记录版本和冲突,不执行 reset/clean 或强行套补丁。无Git的源码包须先取得可核对基线,不能仅凭网页显示1.5.2判断一致。
|
||||
|
||||
## 复验和回退
|
||||
|
||||
在Artemis自己的环境中运行对应离线测试(不连接设备或模型):
|
||||
|
||||
```powershell
|
||||
Push-Location $artemisRoot
|
||||
try {
|
||||
uv run pytest tests/unit/agents/test_checker.py tests/unit/agents/test_operator_recovery.py tests/unit/core/test_toolchain.py
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
```
|
||||
|
||||
测试通过后,在无运行任务时正常重载Artemis服务及MCP,让长驻进程载入修改,再运行 [APP-01](pilot-smoke.md) 的只读观察。不要自动关闭用户任务或重启正在使用的模拟器。
|
||||
|
||||
如需撤销本补丁,先确认文件没有后续改动,运行 `git -C $artemisRoot apply --reverse --check $patchFile`,检查成功且当前任务要求回退后再执行同一命令去掉 `--check`。已有无关修改时停止,不使用强制还原。回退后同样在空闲时正常重载。
|
||||
|
||||
开发机历史证据:相关回归90项通过;当时默认全套为2425通过、3失败、5跳过、8未选中,不能称Artemis全套通过。3项失败已分开定位为原基线问题或检出资源差异。本包的本轮校验记录会单独列出实际执行的检查;Skill自己的74项测试也不能代替Artemis回归或新机器APP验证。
|
||||
@@ -0,0 +1,68 @@
|
||||
# Artemis 手机任务与证据交接
|
||||
|
||||
适用:原APP设置、直播/回放、告警、设备状态观察,以及PC/平台动作之后的手机侧验证。PC GUI、网站和CLI由 [工具路由](tool-routing.md) 处理。此流程依据仓库 `skills/artemis-automation/SKILL.md`、`references/batches.md` 与 `mcp_server/tools` 的真实签名。
|
||||
|
||||
## 单任务
|
||||
|
||||
1. 调用 `mobile_workspace()` 查看设备与队列。沿用用户已选设备,显式传 `device_serial`;多设备且未选择时先解决目标,不擅自使用另一台手机。同设备串行。
|
||||
2. 首次接入或工具/设备异常先 `mobile_diagnose(device_serial=...)`。仅凭据故障才设置 `verify_credentials=true`,仅观察链异常才设置 `probe_device=true`。依据返回的依赖顺序处理,MCP不可用时在Artemis项目运行 `uv run artemis doctor`。
|
||||
3. `mobile_run_task` 的主要参数是 `task_desc`、`device_serial`、`model`、`locked_app_package`、`expected_output_desc`、`verification_level`。这里 `model="Pro"` 或 `"Flash"` 是执行模式,不能填API模型名称。明确需要校验/详细证据时选Pro。
|
||||
|
||||
示例是参数模板;占位值必须由当前已确认环境替换:
|
||||
|
||||
```json
|
||||
{
|
||||
"task_desc": "打开已绑定目标设备的设置页,只观察设备状态与固件版本。记录实际文字及截图;不升级、不解绑、不清除数据。页面缺失或无法取得版本时说明原因,不推测通过。",
|
||||
"device_serial": "<用户选定的Android设备>",
|
||||
"model": "Pro",
|
||||
"locked_app_package": "<已确认APP包名>",
|
||||
"verification_level": "final",
|
||||
"expected_output_desc": "返回实际观察、版本字段、证据步骤号,以及无法验证的内容。"
|
||||
}
|
||||
```
|
||||
|
||||
4. 保存返回的 `trace_id`,用 `mobile_manage_task(action="status", trace_id=...)` 跟踪。遵守返回的建议间隔,同时避免任务静默停滞;单任务应至少每分钟核对一次状态。需要人工处理时请求 `pause`,直至 `task_paused` 才视为设备释放。`inject_instruction`的提交不表示已被执行,必要时用`guidance_history`核对;无新指导用`resume`。
|
||||
5. 结束后用 `mobile_inspect_trace(action="view_summary", trace_id=...)` 与必要的 `view_step_details`、`view_step_screenshots`检查实际动作与证据;不能因`completed`自动判`passed`。异常先诊断,不自动重提相同业务动作。
|
||||
6. `mobile_export_report(session_id=trace_id, formats=["all"])`返回真实报告路径和可用证据;需要截图可选`["screenshots"]`。录屏仅在保存录屏已启用时可导出。报告仍在`finalizing`时不得声称交付完成。
|
||||
|
||||
网页短信验证码交用户在网页完成,不转交手机代理读取短信,不从账号统计表复制凭据。任务沿用当前已授权范围;旧说明、历史trace或旧截图不提供本次操作授权。
|
||||
|
||||
## 批量任务
|
||||
|
||||
`mobile_batch(action="create", request_id=<本次唯一UUID>, batch=...)`创建草稿;只有用户已授权执行此范围时才接着`start`。`goal`是唯一发送给执行器的任务正文,`preconditions`仅元数据,因此所有实际前置约束、禁止动作、停止条件与断言都必须写入`goal`。
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "create",
|
||||
"request_id": "<本次生成并保存的UUID>",
|
||||
"batch": {
|
||||
"name": "已确认范围的设备状态核验",
|
||||
"device_serial": "<用户选定的Android设备>",
|
||||
"profile": "pro",
|
||||
"formats": ["docx", "xlsx"],
|
||||
"stop_on_failure": false,
|
||||
"timeout_seconds": 1800,
|
||||
"cases": [{
|
||||
"case_id": "SRC-S09-R0005",
|
||||
"name": "核验设备固件版本",
|
||||
"preconditions": "目标设备已绑定且在线;仅作索引元数据。",
|
||||
"goal": "前置条件:用户指定设备已绑定且在线。只观察设备设置中的固件版本与在线状态,记录实际文字和截图;不升级、不解绑。版本不存在或设备离线时停止并记录原因,不能判通过。",
|
||||
"task_config": {"profile": "pro", "verification_level": "final", "record_video": true, "analyze_video": false}
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上述`case_id`仅展示格式,实际值从 [case-routing.json](../assets/case-routing.json)选取,不手工猜工作表序号。需要API模型覆盖时,批量`task_config.model`才是网关支持的真实模型名称;它与单任务`model=Pro/Flash`不同。
|
||||
|
||||
创建响应不确定时先`lookup(request_id=...)`,重发只能使用相同ID和完全相同正文,防止重复派发。用`mobile_batch(action="get", batch_id=...)`跟踪;`pause`只暂停后续派发,当前任务另用`mobile_manage_task`。失败不自动重跑;`retry_failed`仅在当前用户明确要求重跑时创建新草稿。
|
||||
|
||||
Excel导入先`mobile_task_file(action="preview", path=<MCP主机绝对路径>)`,修正全部行错误;移除预览专用`row`字段后才转`batch.cases`。源表357行的路由映射不是可直接全部派发的手机任务,平台/CLI/人工环节必须先完成并写入实际前置条件。
|
||||
|
||||
## 与外部证据合并交付
|
||||
|
||||
Artemis原生资料通过 `mobile_export_report(batch_id=...)` 或 `session_id=...`取得。保留原文件内容和来源,另建综合证据清单关联:`case_id`、来源工作表/行、`trace_id`/`batch_id`、外部工具运行编号、时间、实际结果、断言、文件相对路径和摘要。移动APP的版本文本、设备查询响应、固件包版本是不同证据字段,不能互相冒充。
|
||||
|
||||
外部材料放独立目录,例如 `external/ffprobe/`、`external/platform/`;原生导出放`artemis/`。通过 `evidence.py bundle --manifest <json> --out <新目录>`生成综合交付包,清单路径相对`evidence_root`。不能把外部截图写进Artemis运行目录、修改其报告结论或伪造原生步骤。
|
||||
|
||||
综合判定只用`passed/failed/inconclusive/blocked`:明确反例为`failed`;动作已执行但缺完整断言证据为`inconclusive`;依赖/身份/权限缺失为`blocked`。Artemis任务失败是执行事实,是否等同用例失败需结合该用例预期;负向升级要求拒绝,不能把“任务失败”直接当作“按预期拒绝”。最终分别列出原生任务状态与业务判定。
|
||||
@@ -0,0 +1,144 @@
|
||||
# 工具盘点与有界 CLI
|
||||
|
||||
`scripts/tool_runner.py` 仅依赖 Python 3.10+ 标准库;实际工具、Binwalk 模块和 MediaInfo DLL 需本机单独配置。它收集可复核证据,不判定测试通过。所有公开命令返回都有 `execution_status` 和 `test_verdict: "not_evaluated"`。`completed` 只代表进程退出码为 0;端口状态、媒体指标和采集覆盖度仍需与用例标准比对。
|
||||
|
||||
## 配置与盘点
|
||||
|
||||
从 Skill 根目录运行下面示例。全局选项放在子命令之前。执行网络、抓包或串口命令前,须已确定用户授权的目标、网卡/串口、端口、时长和证据目录;本适配器不自动发现设备、不推断路由器入口。
|
||||
|
||||
```powershell
|
||||
python scripts/tool_runner.py list
|
||||
python scripts/tool_runner.py --tool-root 'D:\ApprovedTools' doctor
|
||||
python scripts/tool_runner.py --profile .\device-profile.json doctor --check-versions
|
||||
```
|
||||
|
||||
`list` / `doctor` 默认只查文件;只有显式 `--check-versions` 才运行已定位的可执行程序的版本/帮助参数,每个进程最多 5 秒。`--dry-run doctor --check-versions` 不启动程序。`--tool-root` 可重复,扫描最多 4 层、每个根目录最多 20000 个文件名,不解压包。只将用户明确指定的可信已解压目录传给该参数。
|
||||
|
||||
原生可执行体发现顺序:`profile.tools` → `--tool-root` → `PATH`。Binwalk 的显式 Python 运行时优先于此顺序,MediaInfo DLL 只从显式 `libraries.mediainfo` 读取,详见下方配置。可执行文件名必须匹配工具 ID 的固定候选名;不接受 `cmd`、`wsl`、shell wrapper 或安装器代替工具。`powershell` 同时接受 `powershell.exe` / `pwsh.exe`。profile 中的相对路径按 profile 所在目录解析。
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"ffprobe": "D:/ApprovedTools/ffmpeg/bin/ffprobe.exe",
|
||||
"ffmpeg": "D:/ApprovedTools/ffmpeg/bin/ffmpeg.exe",
|
||||
"tshark": "D:/ApprovedTools/Wireshark/tshark.exe",
|
||||
"dumpcap": "D:/ApprovedTools/Wireshark/dumpcap.exe",
|
||||
"nmap": "D:/ApprovedTools/Nmap/nmap.exe"
|
||||
},
|
||||
"runtimes": { "binwalk_python": "D:/ApprovedTools/binwalk-env/Scripts/python.exe" },
|
||||
"libraries": { "mediainfo": "D:/ApprovedTools/MediaInfo/MediaInfo.dll" },
|
||||
"auth": { "password_env": "DEVICE_PASSWORD" }
|
||||
}
|
||||
```
|
||||
|
||||
以上路径只是格式示例,按实际已安装位置填写;不必列出未安装工具。分发脚本不含开发机的安装路径。profile 不能保存明文密码、token、带认证信息的 URL 或 RTSP URL。`password_env` 等环境变量引用可以保留,但工具不会自动使用密码登录。
|
||||
|
||||
`runtimes` 只接受 `binwalk_python`;`libraries` 只接受 `mediainfo`。这两处只填本地文件路径,不接受对象、模块名、脚本路径、命令行或额外参数。相对路径同样以 profile 所在目录为基准。`binwalk_python` 配置优先于 `tools.binwalk`,固定执行 `python -I -m binwalk`;Python 文件名须为 `python.exe`、`python` 或相应 `python3[.N]` 名称。未配置时仍使用原来的 Binwalk 可执行体发现方式。MediaInfo 只接受显式配置的 `MediaInfo.dll`,不会运行 GUI 或安装器。
|
||||
|
||||
| availability | 含义 |
|
||||
| --- | --- |
|
||||
| `executable-found` | 找到名字匹配的文件;未证明驱动、依赖、权限、版本兼容或设备连通性 |
|
||||
| `python-module-configured` | 找到配置的 Python;须通过 `--check-versions` 确认 Binwalk 模块能加载 |
|
||||
| `library-found` | 找到配置的 MediaInfo DLL;须通过版本检查确认可加载,再用实际媒体验证解析 |
|
||||
| `package-only` | 在指定 root 中只看到对应 `.zip` / `.7z` 文件;没有可执行体 |
|
||||
| `missing` | 当前 profile/root/PATH 未定位工具;静态 `package_evidence` 仍可记录历史包证据 |
|
||||
| `manual-interface` | 原网页或 GUI;此适配器没有其专有 CLI,不表示程序缺失,也不阻止宿主原生 GUI/浏览器路由 |
|
||||
| `mcp-check-required` | 已确认的MCP路由;CLI不检查MCP连接、Android设备或任务就绪性,需使用相应MCP工具 |
|
||||
| `orchestrator-context` | Codex协作编排上下文;不作为独立PC工具安装状态 |
|
||||
|
||||
完整固定 ID 与证据见 `assets/tool-catalog.json`。Wireshark/Nmap ZIP 有相应 EXE 成员;Binwalk 外层 ZIP 有源码、教程及 Python 安装器,固定隔离模块入口已有本地样本验证;FFmpeg 7z 的包版本不能代替实际运行版本。mainThread 的真实程序和手册已取得,其专有能力仍按原生窗口路由。压缩包存在、已启动或版本检查通过均不等于登录及业务可用。内部配置、移动视联、客诉、联楹、路由器保留原入口;账号统计表未读取或复制。
|
||||
|
||||
## 子命令
|
||||
|
||||
| 子命令 | 必填输入 | 固定行为与边界 |
|
||||
| --- | --- | --- |
|
||||
| `probe` | `--input FILE` 或 `--rtsp-env NAME` | FFprobe;输出选定编解码/分辨率/帧率/格式字段;本地输入只允许 `file` 协议 |
|
||||
| `media-info` | `--input FILE` | Windows MediaInfo DLL;拒绝直接URL/UNC输入,回读确认Internet选项关闭;每类最多100路,输出通用/视频/音频白名单字段 |
|
||||
| `analyze-pcap` | `--input PCAP` | TShark `-r -n -T fields`;默认1000、最多10000包;仅时间、长度、地址、端口、协议列 |
|
||||
| `capture` | `--interface ID --host IP --duration SEC --output PCAPNG` | Dumpcap;`host IP` 过滤;1..600秒;100MiB上限;snaplen=256 |
|
||||
| `scan` | `--host IP --ports 22,80,554` | Nmap TCP connect `-sT -n -Pn`,最多128个明确端口;无NSE、网段、主机名、服务版本探测 |
|
||||
| `firmware-scan` | `--input FILE` | `binwalk FILE` 或固定 Python 模块入口,默认签名分析;不自动解包、不执行提取物;本地实测版本为2.3.2,其他版本另核验 |
|
||||
| `serial` | `--port COMx --baud N --duration SEC --output LOG` | PowerShell串口脚本;1..600秒;原始字节与时间戳文本;不发登录或其他命令。可显式指定 `--dtr-enable` / `--rts-enable`,两者默认关闭 |
|
||||
|
||||
所有进程使用参数数组及 `shell=False`,没有 `--args` / 任意参数透传。默认进程时限60秒,串口/抓包为时长+10秒;`--timeout` 可设1..3600的整数,抓包/串口须至少比采集时长多5秒。输出目录须已存在,输出文件和串口 `.raw.bin` 必须不存在,防止追加或覆盖已有证据。
|
||||
|
||||
```powershell
|
||||
python scripts/tool_runner.py --profile .\device-profile.json probe --input .\recording.mp4
|
||||
python scripts/tool_runner.py --profile .\device-profile.json media-info --input .\recording.mp4
|
||||
python scripts/tool_runner.py --profile .\device-profile.json analyze-pcap --input .\capture.pcapng --max-packets 500
|
||||
python scripts/tool_runner.py --profile .\device-profile.json --dry-run capture --interface 1 --host 192.0.2.10 --duration 30 --output .\evidence\device.pcapng
|
||||
python scripts/tool_runner.py --profile .\device-profile.json --dry-run scan --host 192.0.2.10 --ports 22,80,554
|
||||
python scripts/tool_runner.py --profile .\device-profile.json firmware-scan --input .\firmware.bin
|
||||
python scripts/tool_runner.py --dry-run serial --port COM9 --baud 115200 --duration 60 --output .\evidence\serial.log
|
||||
```
|
||||
|
||||
示例使用文档地址 `192.0.2.10`;必须替换为用户明确提供且授权的单个目标。`--dry-run` 仍检查输入和可执行体,输出脱敏后的参数计划,不启动进程。计划确认后移除 `--dry-run` 才执行。无需把整个工具目录提取或安装到 Skill;工具包和驱动安装属于独立的环境准备操作。
|
||||
|
||||
### Binwalk 与 MediaInfo 运行条件
|
||||
|
||||
Binwalk 2.3.2 的 Python 源码依赖 `imp`,不兼容 Python 3.12+;本机已用 Python 3.11 的独立 venv 安装用户提供源码并验证签名扫描。团队部署时使用已验证的独立环境或相容的原生 Binwalk,不更换 Artemis 的 Python。`-I` 忽略用户 site/PYTHONPATH;每次调用另设空的临时 `XDG_CONFIG_HOME`,避免自动加载用户自定义插件。不会自动安装模块。`doctor --check-versions` 成功只能证明模块帮助可运行,扫描仍需本地文件验证。
|
||||
|
||||
MediaInfo 使用与当前 Python 位数匹配的 Windows DLL;32/64位不匹配、DLL 缺依赖或 API 缺失会返回失败。解析在运行器自己启动的固定子进程中执行,沿用 `--timeout`;内部 `_media-info-worker` 是实现细节,不用于直接调用或替换超时入口。它将 `Internet` 设为空字符串,并严格要求 `Internet_Get` 返回空字符串,否则拒绝解析;21.09 中 `No` 等非空值反而启用该选项。直接URL/UNC输入已拒绝,但此配置不是操作系统级网络隔离保证。输出不含 CompleteName、标题、标签或完整 Inform 文本。Duration 使用 MediaInfo 原生毫秒值,FrameRate 为帧/秒,FileSize 为字节;不要直接与 FFprobe 的秒制 Duration 相减。已用 MediaInfoLib 21.09 在 Python 3.14 及 Artemis 当前 Python 验证本地样本,不代表所有媒体格式或 GUI 功能均已验收。
|
||||
|
||||
### RTSP 凭据
|
||||
|
||||
用户必须提供完整 URL,不能猜测通道路径。只从指定环境变量读取,不接受 `--url` 或 profile 中的 URL。交互式 PowerShell 可避免把完整 URL 写入命令历史:
|
||||
|
||||
```powershell
|
||||
$rtspInput = Read-Host '输入完整 RTSP URL' -AsSecureString
|
||||
$env:CAMERA_RTSP = [System.Net.NetworkCredential]::new('', $rtspInput).Password
|
||||
try {
|
||||
python scripts/tool_runner.py --profile .\device-profile.json probe --rtsp-env CAMERA_RTSP --transport tcp
|
||||
} finally {
|
||||
Remove-Item Env:CAMERA_RTSP -ErrorAction SilentlyContinue
|
||||
$rtspInput.Dispose()
|
||||
}
|
||||
```
|
||||
|
||||
JSON输出、计划、异常不回显完整URL或其中的凭据;FFprobe只输出固定字段并对文本二次脱敏,合法的数值/帧率字段作为测量值保留,避免短查询值(如 `token=1`)误伤 `20/1`、`8000` 等指标。完整URL在计划中整体替换,stderr直接丢弃,子进程移除 `FFREPORT` 防止工具日志持久化完整命令行。FFprobe需要在其进程参数中接收URL,因此同一主机上有进程查看权限的程序仍可能看到它;不能声称环境变量消除了这一点。不要保存终端明文输入或环境快照。
|
||||
|
||||
### 证据限制
|
||||
|
||||
抓包默认仅截取前256字节,适合连接/协议/时序分析,不能作为完整负载或码流内容证据。抓包文件和串口原始日志仍可能包含设备发送的敏感信息;命令不把其内容打印到JSON,分享前按项目规则脱敏。运行器抑制所有外部工具stderr;非零退出码、超时只给固定错误码,排错先核对工具、文件、权限和参数,不以打印含凭据命令替代诊断。
|
||||
|
||||
Nmap的主机时限可能让部分端口未完成;`execution_status=completed` 不等于所有请求端口都被覆盖。FFprobe元数据不等于持续码率、丢帧率或长期流稳定性;Binwalk签名结果不等于固件安全结论;本适配器不据此输出PASS/FAIL。
|
||||
|
||||
Nmap XML可能把同状态端口折叠到 `<extraports>`。扫描结果保留 `requested_ports`、逐端口 `ports` 及 `aggregate_states`(state/count/reasons)。每个主机的 `ports_not_individually_reported` 列出缺少明确TCP端口状态的请求端口,`individual_port_coverage` 为 `complete` / `partial` / `none`,只描述逐端口结果覆盖度。聚合组即使计数与剩余端口数量相等,也不会被展开为各端口状态;多个聚合组之间更不能猜测端口归属。没有主机结果时 `host_results_present=false`。这些字段用于暴露证据缺口,不能把聚合计数、退出码0或缺失端口解释为全覆盖或测试通过。
|
||||
|
||||
### 串口来源
|
||||
|
||||
`scripts/vendor/serial_monitor.ps1` 从用户给定参考包 `embedded-app-pc-debug/scripts/serial_monitor.ps1` 原样复制。SHA-256:
|
||||
|
||||
`173584db05950b9842f2485eec5b33c0b16062f944216c283a18e038a9138a67`
|
||||
|
||||
包装器每次构造计划时校验该哈希。脚本独占打开COM口,默认8N1、无流控、DTR/RTS不启用,记录 `LOG` 和 `LOG.raw.bin`;包装器不暴露发送命令。`--dtr-enable` / `--rts-enable` 分别映射原脚本已有的 `-DtrEnable` / `-RtsEnable`,用于复现已确认且获授权的现场会话设置,JSON同时记录实际开关值。它们不启用RTS/CTS或DTR/DSR握手,不应仅因一次无数据就盲目组合切换。某些设备将控制线用于复位,已知会触发复位时不能把它当作一般只读采集。没有参数时行为保持不变。
|
||||
|
||||
下面仅演示一个已确认需要同时启用DTR/RTS的本机会话;不是所有设备的默认配置。`profile.serial` 当前只作为环境资料,本运行器不会从中读取控制线或其他串口参数;实际行为由命令行显式值决定。
|
||||
|
||||
```powershell
|
||||
python scripts/tool_runner.py --profile .\device-profile.json serial --port COM9 --baud 115200 --duration 5 --output .\evidence\serial.log --dtr-enable --rts-enable
|
||||
```
|
||||
|
||||
打开串口仍依赖设备、驱动与操作系统权限,并可能改变端口占用;运行适配器允许在授权目标上做限定时长的现场验证。若用户终端占用端口,报告占用并等待释放,不关闭或抢占其会话。现场结果放到独立的运行报告,不作为其他机器可用性的保证。执行策略若阻止脚本,报告环境条件,不自动绕过策略。
|
||||
|
||||
## 状态与退出码
|
||||
|
||||
| execution_status | CLI退出码 | 解释 |
|
||||
| --- | --- | --- |
|
||||
| `planned` / `completed` | 0 | 计划构造成功或进程结束;无测试结论 |
|
||||
| `failed` / `timed_out` / `launch_failed` / `output_invalid` | 1 | 工具失败、超时、无法启动或输出格式异常 |
|
||||
| `invalid_arguments` / `configuration_error` | 2 | 参数/本地文件配置错误;不回显原始参数 |
|
||||
| `tool_missing` | 3 | 缺少对应执行文件、已配置Python或DLL;按上文tools/runtimes/libraries配置,MediaInfo不查PATH |
|
||||
|
||||
## 官方参数来源
|
||||
|
||||
- [FFprobe 官方文档](https://ffmpeg.org/ffprobe.html):元数据、JSON writer、字段选择。
|
||||
- [TShark 手册](https://www.wireshark.org/docs/man-pages/tshark.html):离线输入与 fields 输出。
|
||||
- [Dumpcap 手册](https://www.wireshark.org/docs/man-pages/dumpcap.html):网卡、capture filter、停止条件与snaplen。
|
||||
- [Nmap 参考指南](https://nmap.org/book/man.html):显式目标、TCP connect、端口与时限选项。
|
||||
- [Binwalk 官方项目](https://github.com/ReFirmLabs/binwalk):默认固件签名分析,提取是单独选项。
|
||||
- [MediaInfo DLL 官方接口](https://github.com/MediaArea/MediaInfoLib/blob/master/Source/MediaInfoDLL/MediaInfoDLL.h):固定 `New/Open/Get/Count_Get/Option/Close/Delete` API。
|
||||
- [MediaInfo SDK Quick Start](https://mediaarea.net/en/MediaInfo/Support/SDK/Quick_Start):API 初始化及版本读取。
|
||||
- [MediaInfo 21.09 配置实现](https://raw.githubusercontent.com/MediaArea/MediaInfoLib/v21.09/Source/MediaInfo/MediaInfo_Config.cpp):Internet 空字符串关闭及 Internet_Get 回读语义。
|
||||
|
||||
测试:`python -m unittest discover -s tests -p test_tool_runner.py -v`。单元测试只构造命令并模拟外部进程结果;不会连接设备、扫描或抓包。实际可用性由当前机器的doctor、限定本地样本及经授权的现场验证分别说明,不能从一次适配器执行成功推广成实机功能验收。
|
||||
@@ -0,0 +1,106 @@
|
||||
# 设备适配器
|
||||
|
||||
入口是 `scripts/device_adapter.py`,仅依赖 Python 标准库。所有设备操作必须由本次任务提供目标;分发包没有默认 IP、完整 SN、设备型号、密码或 ROM 路径。
|
||||
|
||||
先用 `capabilities` 查看实际支持范围,按 [协议范围](protocol-support.md) 确定设备协议。网络子命令接受 `--protocol v1/v2`,不传仍默认 V2。V1 搜索、信息查询、版本比较和 TCP4941/2170/MD5+ROM 下发见 [V1 接口](v1-protocol.md)。下文的 894x/EPTP/EPFP 仅属于 V2。
|
||||
|
||||
## 操作边界
|
||||
|
||||
| 命令 | 网络及写入范围 | 必要输入 | 完成含义 |
|
||||
| --- | --- | --- | --- |
|
||||
| `capabilities` | 不联网 | 无 | 列出已实现协议和缺失依赖,不证明设备在线 |
|
||||
| `offline` | 只读取本地 ROM,不联网 | `--rom` | 文件有效且已计算摘要;没有验证设备 |
|
||||
| `discover` | V1 UDP 4942;V2 UDP 8941,只读广播 | 按需要指定 `--interface`、身份筛选 | 候选发现,不能代替升级前 TCP 身份校验 |
|
||||
| `identify` | 当前协议的只读信息查询 | `--host --expected-sn` | SN 精确匹配并观察上报型号;model_verified=false,无需预先猜型号 |
|
||||
| `info` | V1 TCP 4941/2104;V2 TCP 8942/EPTP/30101,只读 | `--host --expected-sn --expected-model` | 完整 SN 与至少一个设备型号字段精确匹配;无需 ROM |
|
||||
| `upgrade` | 默认本地 ROM 校验及当前协议的 TCP 在线预检 | 数字设备 IP、身份参数、`--rom --target-version --version-field` | `PREFLIGHT_ONLY`,未传包;V1还报告所选版本字段是否存在 |
|
||||
| `upgrade --execute` | 预检后最多一次写入:V1 TCP4941/2170;V2 TCP8943/EPFP/4001 | 以上参数及 `--execute --rom-sha256` | 协议步骤结果;始终要求后续版本回读 |
|
||||
| `verify-version --response` | 只读取已有响应 JSON,不联网 | 响应文件、身份及版本参数 | 验证文件记录中的身份和指定固件字段,不证明当前在线状态 |
|
||||
| `verify-version --host` | 当前协议,只读回读一次 | 设备地址、身份及版本参数 | 当前协议响应中的身份和指定固件字段匹配 |
|
||||
|
||||
`upgrade` 默认是**在线预检**。完全不联网时使用 `offline` 或 `verify-version --response`。V2 discover 转调固定版本的发现函数,保留本地 8951、设备 8941;V1 discover 使用独立 ff00/ff01 实现,默认本地/设备 4942,参数见 `discover --protocol v1 --help`。同一完整 SN 对应冲突网络身份时禁止自动选择。
|
||||
|
||||
`upgrade --host` 必须是明确的数字 IPv4 或 IPv6 地址,包括未加 `--execute` 的在线预检。主机名会在联网前拒绝;适配器把地址规范化后用于当前协议的身份查询及受支持的写入,避免两次 DNS 解析选择不同目标。结果中的 `bound_ip` 与 `upgrade_target_bound` 事件保存实际绑定地址;预检后失败时也保留它。程序拒绝可确定的多播地址、未指定地址和 IPv4 有限广播地址 `255.255.255.255`,IPv4 映射 IPv6 地址执行相同检查。没有网段前缀时不能判断任意子网定向广播地址,应提供已确认的设备单播 IP。`info` 与只读在线版本回读仍可使用主机名。
|
||||
|
||||
`--expected-sn` 必须是完整 SN,按完整字符串比较,不接受末尾数位或模糊匹配。`--expected-model` 在 `info`、`upgrade` 和 `verify-version` 中必填:V1 只匹配 dev_type;V2 与 data.inner.type、data.outer.type、data.hardware.type 至少一个值完全相等。型号未知时先用 identify 观察,再带返回型号校验。产品简称不一定是协议型号;出现不匹配应审阅返回的原始身份,不能通过关闭校验继续写入。
|
||||
|
||||
## 常用命令
|
||||
|
||||
下面使用占位符。替换成本次任务已确认的目标后执行;不要把现场设备值保存回技能模板。
|
||||
|
||||
```powershell
|
||||
python scripts/device_adapter.py capabilities
|
||||
|
||||
python scripts/device_adapter.py offline --rom "<ROM路径>"
|
||||
|
||||
python scripts/device_adapter.py discover --protocol v2 --expected-sn "<完整SN>" --expected-model "<协议完整型号>"
|
||||
|
||||
python scripts/device_adapter.py identify --protocol v2 --host "<设备地址>" --expected-sn "<完整SN>"
|
||||
|
||||
python scripts/device_adapter.py info --host "<设备地址>" --expected-sn "<完整SN>" --expected-model "<协议完整型号>"
|
||||
|
||||
python scripts/device_adapter.py upgrade --host "<数字设备IP>" --expected-sn "<完整SN>" --expected-model "<协议完整型号>" --rom "<ROM路径>" --target-version "<明确目标版本>" --version-field inner.version
|
||||
```
|
||||
|
||||
写入还必须提供审阅过的 ROM SHA-256,并显式加 `--execute`:
|
||||
|
||||
```powershell
|
||||
python scripts/device_adapter.py upgrade --host "<数字设备IP>" --expected-sn "<完整SN>" --expected-model "<协议完整型号>" --rom "<ROM路径>" --target-version "<明确目标版本>" --version-field inner.version --rom-sha256 "<64位SHA256>" --execute
|
||||
```
|
||||
|
||||
摘要不匹配、缺少 `--rom-sha256`、身份不匹配都会阻断写入。适配器在在线预检后、调用写入函数前重新校验摘要;写入期间不要替换或修改 ROM。ROM 路径中的版本号仅保留为诊断线索,不能代替明确的 `--target-version`,也不能证明 ROM 与设备型号兼容。
|
||||
|
||||
升级协议报告成功后,等待任务规定的设备恢复条件,再执行独立的只读回读:
|
||||
|
||||
```powershell
|
||||
python scripts/device_adapter.py verify-version --host "<设备地址>" --expected-sn "<完整SN>" --expected-model "<协议完整型号>" --target-version "<明确目标版本>" --version-field inner.version
|
||||
|
||||
python scripts/device_adapter.py verify-version --response "<已有30101响应JSON路径>" --expected-sn "<完整SN>" --expected-model "<协议完整型号>" --target-version "<明确目标版本>" --version-field inner.version
|
||||
```
|
||||
|
||||
V2 响应文件可以是原始 30101 JSON;V1 必须是带 protocol=v1、cmd=0x5a0e2104、code=0 及原生 data 的适配器封套。两者均可直接使用 info 输出(读取 response 字段),不能跨协议冒充。不从任意日志中猜选“最后一条成功”。只读查询与升级均不自动重试;写入断开、超时或失败后先收集状态,不自动重新烧录。
|
||||
|
||||
## 结果与验收
|
||||
|
||||
除 V2 `discover` 保留原 JSONL 事件输出外,每次调用输出一个 UTF-8 JSON 对象,`events` 保留协议记录。导入模块不会修改调用方 stdout/stderr;执行 CLI 才统一配置 UTF-8。运行时记录可能包含现场完整身份与响应,应保存在任务证据目录,不纳入可分发技能。
|
||||
|
||||
退出码 0 表示本次命令完成,**不能统一解释为设备验收通过**。错误、BLOCKED、版本不符和数据不足返回 1;参数错误返回 2;V2 发现命令沿用其原退出码约定。
|
||||
|
||||
| `status` | 含义 |
|
||||
| --- | --- |
|
||||
| `CAPABILITIES` | 离线列出协议实现范围;不是设备验收结果 |
|
||||
| `BLOCKED` | 协议不受支持、搜索身份冲突或未唯一找到目标;不能自动更换目标或协议 |
|
||||
| `IDENTITY_OBSERVED` | identify 中完整 SN 已核实,型号仅作为实测值返回 |
|
||||
| `OFFLINE_READY` | ROM 本地校验完成,无设备证据 |
|
||||
| `IDENTITY_CONFIRMED` | 所选协议 SN/型号匹配,未做目标固件版本比较 |
|
||||
| `PREFLIGHT_ONLY` | 在线预检完成,`write_executed=false` |
|
||||
| `PROTOCOL_SUCCESS_POSTCHECK_REQUIRED` | V1收到2170/整数code=0,或V2收到状态2,且客户端发送ROM字节数严格等于文件大小;`firmware_verified=false`,`postcheck_required=true` |
|
||||
| `PASS` | 仅在 `verify-version` 中:指定身份及固件字段完全匹配 |
|
||||
| `FAIL` | 指定固件字段存在,但与明确目标版本不符 |
|
||||
| `INCOMPLETE` | 指定固件字段缺失、为空或类型不正确,不能通过 |
|
||||
| `ERROR` | 文件、身份、协议或传输错误;`firmware_verified=false` |
|
||||
|
||||
V2 版本字段只允许 inner.version 或 outer.version;V1 原生字段为 firmware、dev_ver,须由任务明确选择。V1响应如果直接上报字面 inner.version/outer.version,保留该值供指定字段比较;没有 V1→V2 字段映射依据,不能静默换名。指定缺失的 outer.version 得到 INCOMPLETE,已经授权的传包仍可执行。hardware/hardware.version 不作为固件验收,也不替补缺失字段。
|
||||
|
||||
`PASS` 的 `acceptance_scope` 固定为 `identity_and_selected_firmware_version_only`,不表示全部业务测试已通过。`evidence_source=recorded_response`、`live_readback=false` 表示只验证已有文件;`evidence_source=live_30101`(V2)或 live_v1_2104(V1)、`live_readback=true` 表示本次只读回读。已有响应的采集时间与来源需由任务证据链说明。
|
||||
|
||||
写入调用开始后发生错误,返回 `write_may_have_started=true` 与 `postcheck_required=true`,并设置 `automatic_retry=false`。这代表写入结果未确定,不能因命令失败而自动重试。
|
||||
|
||||
如果零字节或部分 ROM 上传就得到成功状态,适配器返回 `ERROR`。只有 `transfer.bytes_sent` 是整数且与 ROM 大小完全一致,并满足所选协议的应答条件,才设置 `protocol_success=true`。V1 的 `v1_upgrade_acknowledged`、V2 的 `device_reported_status_2` 只记录设备应答;`transfer_result` 记录客户端实际计数,不能代替独立版本回读。
|
||||
|
||||
## 来源与维护
|
||||
|
||||
`scripts/vendor/source-manifest.json` 固定上游文件及分发副本的 SHA-256。导入前重新计算分发副本摘要,不匹配就拒绝加载;维护代码时须审阅差异并同步更新清单,不能从临时下载目录动态加载。
|
||||
|
||||
| 上游文件 | 上游 SHA-256 |
|
||||
| --- | --- |
|
||||
| `embedded-app-pc-debug/scripts/device_upgrade.py` | `ce72435ff4a3dbe3cc0c28dd81c2a7873b60e55bb64f09055a64900b8f921578` |
|
||||
| `embedded-app-pc-debug/scripts/v2_discover.py` | `f6634bfc3b86abb6d379d28b679f2e209694f9d856e343157e24b9ff629ea894` |
|
||||
|
||||
升级副本只提取协议、身份、ROM 校验与传输函数,去掉原 CLI、日志类与导入时输出重配置。发现副本只把输出重配置移入脚本入口,发现逻辑未改动。没有复制 `module_debug.py`、串口脚本、原技能说明、历史密钥或历史授权。
|
||||
|
||||
## 实际验证记录
|
||||
|
||||
2026-10-19,全部118项离线 unittest 通过,其中设备适配器28项、V1报文/身份/发现24项、V1升级14项。运行实际 V1/V2 编解码与传输函数,仅替换socket/select边界;使用合成身份及保留文档地址,不访问真机。覆盖默认不写入、摘要/身份门槛、实际发送计数、文件变化、错误不重试、时限、版本字段不足及明确协议分流。
|
||||
|
||||
同日在用户授权 V1 设备上完成单次19,420,244字节ROM下发,收到2170/code=0/update success。连续两次恢复查询与原SN/型号一致,firmware=2.0.2、dev_ver=2.0.20260908.6;升级前为2.0.1/2.0.20260908.5。任务指定outer.version缺失,验收保留INCOMPLETE,原生版本观测单独通过。现场证据独立保存,不能据此泛化所有V1设备。
|
||||
@@ -0,0 +1,223 @@
|
||||
# 工具安装、环境确认与修复手册
|
||||
|
||||
本手册用于同事首次部署、迁移电脑以及处理具体工具调用故障。与 [团队部署](team-setup.md)、[工具路由](tool-routing.md)、[有界 CLI](cli-tools.md) 配合使用。这里只分发通用方法、配置格式和已验证的修复经验;工具程序、驱动、私人运行环境、凭据和现场证据由各机器自行准备。
|
||||
|
||||
已授权安装或修复当前用例所需工具时,可按下面流程继续,不必逐步重复审批。先复用可用安装;只处理当前必需的缺口,不因工具清单中有某项就安装整套软件。系统管理员权限、许可证、下载权限和人工登录仍按本机及产品要求处理。安装器、驱动安装、服务重载和设备操作不能混成一次“doctor 自动修复”。
|
||||
|
||||
## 1. 先确定故障在哪一层
|
||||
|
||||
| 层次 | 检查与记录 | 不能据此推出的结论 |
|
||||
| --- | --- | --- |
|
||||
| 包与文件 | 来源、包摘要、可执行文件/解释器/DLL 的实际路径 | 有 ZIP、安装 EXE 或文件名就表示已安装 |
|
||||
| 运行时 | 版本/帮助能运行,DLL 或 Python 模块能加载 | 工具已能连接目标设备 |
|
||||
| 本地功能 | 人造媒体、签名样本、已有脱敏抓包能解析 | 真机媒体质量或安全用例通过 |
|
||||
| 连接与会话 | 当前网卡/COM、Android 设备、MCP、GUI、网站会话可用 | 已登录、目标权限充分或设备身份一致 |
|
||||
| 业务 | 当前用例的实际动作、独立断言与证据 | 启动成功、退出码 0、任务完成就等于 PASS |
|
||||
|
||||
按最早失败的层次修复,再复测同一层。没有证据定位原因时保留错误和待查项,不通过改超时、重复安装或切换整套环境掩盖问题。`manual-interface` 表示要走真实 GUI/网页;`mcp-check-required` 表示要检查 MCP,它们都不是“缺少 EXE”。
|
||||
|
||||
以下版本是打包前的兼容性验证记录,**不是要求团队一律安装这些旧版本,也不是最新版推荐**。更换版本后须在本机复测相应能力。
|
||||
|
||||
| 工具/环境 | 已验证范围 | 尚未覆盖 |
|
||||
| --- | --- | --- |
|
||||
| FFmpeg/ffprobe,2023-12-18 构建 | 本地 1 秒、160×120、5 帧样本生成/解析/解码;另有原流 RTSP 元数据读取 | 连续码率、GOP、画音质量和其他格式 |
|
||||
| Wireshark/TShark/dumpcap 4.6.3,Npcap 1.72 | 版本、接口枚举、一次有界采集及离线解析 | 新机器驱动安装、GUI 操作、完整通信安全断言 |
|
||||
| Nmap 7.60 | 帮助、版本及本机单端口 TCP connect 调用 | 全端口、UDP、服务身份及设备安全结论 |
|
||||
| Binwalk 2.3.2+独立 Python 3.11 | 正式 `firmware-scan` 识别人造 gzip 签名;真实固件扫描完成但未检出签名 | 真实固件完整分析、提取器依赖、解包与加密验收 |
|
||||
| MediaInfoLib 21.09+匹配位数的 Python | 正式 `media-info` 解析本地样本;在两种 Python 运行环境复测 | GUI、所有格式或操作系统级断网隔离 |
|
||||
| PowerShell 串口采集 | 明确参数下的被动收取;单独现场诊断曾确认基础双向收发 | 通用自动登录、shell 命令、SecureCRT GUI 全流程 |
|
||||
| 配置工具 V2.0.5 | 包与实际 EXE 一致、启动、版本控件读取;独立适配器只读身份查询 | GUI 搜索、参数设置和升级全流程 |
|
||||
| mainThread | 包获取、完整解压、启动与查询入口识别 | 查询权限、周期数据/拓扑返回及原用例“杭研软件”对应关系 |
|
||||
| Artemis 1.5.2+观察修复补丁 | 真实只读观察、笔记复核和正常结算 | 全部手机业务;不能把此前源码全套检查描述为全绿 |
|
||||
|
||||
## 2. 目录、安装器与解压
|
||||
|
||||
示例均使用团队占位目录,须替换为本机位置:`D:/TeamTools` 放工具,`D:/TeamConfig` 放私有配置,`D:/TeamEvidence` 放本机结果。Skill 根目录保持独立。不要将其他同事的 venv、MCP 配置、设备资料、登录会话或历史输出目录整个复制过来。
|
||||
|
||||
1. 核对当前已有安装的实际路径和版本,避免只看压缩包名称。记录包的 `Get-FileHash -Algorithm SHA256`;有供应方可信摘要或签名时核对来源,只有自行计算的摘要不能证明供应方真实性。
|
||||
2. 对 ZIP/7z 先查看成员,确认预期入口、依赖目录及体积;不接受逃逸目标目录的绝对路径、`..` 或不明链接。解压到新的版本目录,保留旧版本。不要只取单个 EXE,Qt 插件、DLL、配置及资源目录通常需要一起保留。
|
||||
3. ZIP 使用 `Expand-Archive`;7z 使用已安装且可信的 7-Zip。示例目标目录应尚不存在,避免覆盖现有环境:
|
||||
|
||||
```powershell
|
||||
Get-FileHash -LiteralPath 'D:/TeamTools/packages/tool.zip' -Algorithm SHA256
|
||||
Expand-Archive -LiteralPath 'D:/TeamTools/packages/tool.zip' -DestinationPath 'D:/TeamTools/portable/tool-version'
|
||||
& 'D:/TeamTools/7-Zip/7z.exe' l 'D:/TeamTools/packages/tool.7z'
|
||||
& 'D:/TeamTools/7-Zip/7z.exe' x 'D:/TeamTools/packages/tool.7z' '-oD:/TeamTools/portable/tool-version'
|
||||
```
|
||||
|
||||
4. 必须安装的产品使用供应方正式安装器;参数按该版本说明,不猜静默开关。Windows UAC 和许可证由具备权限的使用者处理。不要运行压缩包中的激活器、破解程序或与当前工具无关的安装器。
|
||||
5. 将最终执行路径写入本机 profile,再进行版本和本地样本检查。`--tool-root` 不会解压包,安装器也不能填成 `tools` 的运行入口。
|
||||
|
||||
上面的解压命令是部署模板,不是已在每个团队工具包上执行过的安装记录。默认不改全局 PATH;显式 profile 更容易复核实际用了哪个版本。
|
||||
|
||||
## 3. 基础 Python、PowerShell 与 profile
|
||||
|
||||
轻量脚本使用 Python 3.10+ 标准库;Binwalk 2.3.2 另用 Python 3.11;Artemis 1.5.2 的项目要求是 Python 3.12+,由其自身 `.venv` 管理。这三者可以共存,不为修复一个工具降级 Artemis 的解释器。
|
||||
|
||||
从 Skill 根目录检查,`python` 可替换为本机绝对解释器路径:
|
||||
|
||||
```powershell
|
||||
python -c "import sys, struct; print(sys.version); print(struct.calcsize('P') * 8)"
|
||||
python -X utf8 scripts/tool_runner.py --help
|
||||
python -X utf8 scripts/tool_runner.py --tool-root 'D:/TeamTools' list
|
||||
python -X utf8 scripts/tool_runner.py --profile 'D:/TeamConfig/tools.local.json' doctor
|
||||
python -X utf8 scripts/tool_runner.py --profile 'D:/TeamConfig/tools.local.json' doctor --check-versions
|
||||
```
|
||||
|
||||
`doctor` 只发现路径;`--check-versions` 才实际运行已定位程序的版本/帮助或加载检查。盘点整体退出0也可能仍有缺项,逐工具核对 availability 和 version_check,再跑对应本地样本。`--profile`、`--tool-root`、`--timeout`、`--dry-run` 放在子命令前。参照 [CLI 配置](cli-tools.md#配置与盘点) 填写 `tools`、`runtimes.binwalk_python` 和 `libraries.mediainfo`;路径可以相对 profile 所在目录,不接受命令串或额外参数。
|
||||
|
||||
PowerShell 已验证 Windows PowerShell 5.1 和 PowerShell 7 的基础串口类型。若 5.1 报自带 `Get-FileHash` 无法自动加载,先检查模块是否存在;历史案例通过显式导入其自带模块恢复:
|
||||
|
||||
```powershell
|
||||
Import-Module Microsoft.PowerShell.Utility
|
||||
Import-Module Microsoft.PowerShell.Security
|
||||
Get-Command Get-FileHash
|
||||
```
|
||||
|
||||
这只处理相同模块加载问题,不解决 COM 驱动或端口占用。脚本执行策略阻止运行时按组织策略解决,不能自动改为绕过策略。中文 Skill 校验遇到 GBK 解码失败时使用 `python -X utf8`,不改文档为本机编码。
|
||||
|
||||
## 4. FFmpeg / ffprobe:先用本地样本
|
||||
|
||||
从批准来源取得匹配 Windows 架构的完整构建,解压后在 profile 分别配置 `ffmpeg.exe`、`ffprobe.exe`。如果包名和 `-version` 不一致,以实际调用输出为准;原资料中的“ffmg”尚未最终确认,只将 FFmpeg/ffprobe 标为已采用的可比能力。
|
||||
|
||||
下列命令重用已成功的方法,生成无设备信息的样本。先创建本机证据目录;输出必须是新文件,`-n` 不覆盖已有文件:
|
||||
|
||||
```powershell
|
||||
& 'D:/TeamTools/ffmpeg/bin/ffmpeg.exe' -nostdin -n -hide_banner -f lavfi -i 'testsrc=size=160x120:rate=5' -t 1 -c:v mpeg4 -pix_fmt yuv420p 'D:/TeamEvidence/local-video-sample.mp4'
|
||||
python -X utf8 scripts/tool_runner.py --profile 'D:/TeamConfig/tools.local.json' probe --input 'D:/TeamEvidence/local-video-sample.mp4'
|
||||
& 'D:/TeamTools/ffmpeg/bin/ffmpeg.exe' -nostdin -hide_banner -i 'D:/TeamEvidence/local-video-sample.mp4' -f null -
|
||||
```
|
||||
|
||||
检查生成成功、实际尺寸 160×120、帧率 5/1、约 1 秒及解码 5 帧。失败时依次核对执行路径、DLL/构建依赖、输入文件和输出权限。RTSP 阶段另需当前明确的流地址和权限;用 `probe --rtsp-env <变量名>`,不要把认证 URL 放进 profile、聊天或报告。元数据正常之后再按用例获取帧级与持续测量证据。
|
||||
|
||||
## 5. Wireshark / TShark / dumpcap 与 Npcap
|
||||
|
||||
保留 Wireshark 完整目录,将 `tshark.exe` 和 `dumpcap.exe` 分别配置到 profile。读取已有 pcap 与现场捕获是不同能力:TShark 能离线分析不证明 Npcap 已安装,dumpcap 能显示版本不证明当前账户能抓包。
|
||||
|
||||
```powershell
|
||||
& 'D:/TeamTools/Wireshark/tshark.exe' --version
|
||||
& 'D:/TeamTools/Wireshark/dumpcap.exe' -D
|
||||
Get-Service -Name npcap -ErrorAction SilentlyContinue
|
||||
python -X utf8 scripts/tool_runner.py --profile 'D:/TeamConfig/tools.local.json' analyze-pcap --input 'D:/TeamEvidence/sample.pcapng'
|
||||
```
|
||||
|
||||
无接口或加载驱动失败时,先区分程序依赖、Npcap 驱动、服务状态和当前账户权限。使用已批准的 Wireshark/Npcap 安装器按产品说明安装或修复驱动;不要把 ZIP 解压当作驱动安装,不盲装旧 WinPcap,也不因 Nmap 包带驱动而覆盖当前可用 Npcap。管理员专用访问策略按组织要求处理。
|
||||
|
||||
历史机器在 Npcap 1.72 下完成接口枚举和有界采集,但没有验证一套通用于所有机器的无人值守驱动安装流程。修复后先重查接口,再对当前授权的单个目标、指定接口做短时 `capture`,随后 `analyze-pcap` 回读。接口编号可能变化,不能照抄其他机器的编号;空抓包可能是接口、采集位置、过滤条件或时间窗问题,不能直接判断设备没有通信。
|
||||
|
||||
运行器固定 `snaplen=256`,现场采集最多 600 秒、100 MiB。只抓到截断包不够做完整应用负载或所有安全断言;扩大取证范围应回到具体用例设计。
|
||||
|
||||
Nmap 使用实际 `nmap.exe` 的 `--version` 检查运行时。现有 `scan` 只支持单个明确 IP、最多 128 个明确 TCP 端口的 connect 扫描;不要为环境验证扫描整个局域网。安装包版本不能代替执行版本,端口聚合或超时仍需检查覆盖度。
|
||||
|
||||
## 6. Binwalk:固定 Python 3.11 的隔离环境
|
||||
|
||||
已验证的 2.3.2 源码使用 `imp`,直接放到 Python 3.12+ 会失败。仅解压源码也可能因缺少发行元数据而无法显示版本。正确方向是在独立 Python 3.11 venv 内安装已核验的源码,profile 指向该 venv 的 Python,而非改全局 Python 或设置全局 `PYTHONPATH`。
|
||||
|
||||
```powershell
|
||||
& 'D:/TeamTools/Python311/python.exe' -m venv 'D:/TeamTools/binwalk-env'
|
||||
& 'D:/TeamTools/binwalk-env/Scripts/python.exe' -m pip --version
|
||||
```
|
||||
|
||||
新 venv 目录应尚不存在。团队可以从批准的离线 wheel 仓库准备构建依赖后安装已审核源码;这条 pip 路径是可复用部署方案,须在本机验证:
|
||||
|
||||
```powershell
|
||||
& 'D:/TeamTools/binwalk-env/Scripts/python.exe' -m pip install --no-index --find-links 'D:/TeamTools/packages/wheels' setuptools wheel
|
||||
& 'D:/TeamTools/binwalk-env/Scripts/python.exe' -m pip install --no-index --no-build-isolation --no-deps 'D:/TeamTools/sources/binwalk-2.3.2'
|
||||
```
|
||||
|
||||
历史修复中离线 pip 因缺 `bdist_wheel` 失败,最终在检查过源码后用该源码的 `setup.py install` 安装到同一隔离 venv,正式命令复测成功。若必须复现这条兼容路径,只在准确的 2.3.2 源码目录内执行,安装代码仍须可信;不要自动运行外层包附带的其他 Python 安装器:
|
||||
|
||||
```powershell
|
||||
Push-Location 'D:/TeamTools/sources/binwalk-2.3.2'
|
||||
try {
|
||||
& 'D:/TeamTools/binwalk-env/Scripts/python.exe' setup.py install
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
```
|
||||
|
||||
配置 `runtimes.binwalk_python` 为 `D:/TeamTools/binwalk-env/Scripts/python.exe` 后,用 runner 的 `doctor --check-versions` 与 `firmware-scan --input <本地签名样本>` 复测。正式入口固定为 `python -I -m binwalk`;运行器另设临时用户配置目录,避免加载现有用户插件。不要复制历史临时补元数据目录,也不要以 Python 文件存在就认定模块可用。
|
||||
|
||||
此处只解决签名扫描。未准备外部提取器时标记相关能力缺失,不添加 `-e` 或执行扫描产物。解包失败、高熵或找不到字符串都不能证明设备 Flash 已加密;`firmware_encrypt` 必须另取匹配 SDK 的专用程序。
|
||||
|
||||
## 7. MediaInfo:Python 位数、DLL 与固定接口
|
||||
|
||||
从已批准的 MediaInfo 包保留 DLL 及必要依赖,在 `libraries.mediainfo` 填写实际 `MediaInfo.dll` 路径。位数匹配对象是**运行 tool_runner 的 Python 进程**,仅知道 Windows 是 64 位不够。
|
||||
|
||||
```powershell
|
||||
python -c "import struct; print(struct.calcsize('P') * 8)"
|
||||
python -X utf8 scripts/tool_runner.py --profile 'D:/TeamConfig/tools.local.json' doctor --check-versions
|
||||
python -X utf8 scripts/tool_runner.py --profile 'D:/TeamConfig/tools.local.json' media-info --input 'D:/TeamEvidence/local-video-sample.mp4'
|
||||
```
|
||||
|
||||
DLL 已找到但加载失败时检查 32/64 位、缺失依赖、文件来源与版本;不要改成调用 MediaInfo GUI 或任意复制 DLL 到系统目录来掩盖失败。正式命令在有时限子进程内调用固定 API,已验证 21.09 的样本结果为 160×120、5 帧、5 fps、1000 ms;Duration 单位是毫秒,ffprobe 通常是秒。
|
||||
|
||||
21.09 中 `Internet="No"` 会启用该选项。分发脚本已改为设置空字符串并回读 `Internet_Get` 确认关闭,同时拒绝直接 URL/UNC 输入。不要改回 `No`,也不要绕过此校验;无法确认时保留失败。该 DLL 配置不是操作系统级网络隔离的证明。
|
||||
|
||||
## 8. SecureCRT、串口驱动与无数据排查
|
||||
|
||||
SecureCRT 使用合法可用的原产品。只需被动日志时可采用已封装的 PowerShell 路径,无须为它安装 pySerial。USB 转串口驱动按实际转接器硬件 ID、供应方和系统架构选用;不要猜测为 CH340、CP210x 或其他型号。
|
||||
|
||||
```powershell
|
||||
[System.IO.Ports.SerialPort]::GetPortNames()
|
||||
Get-CimInstance Win32_SerialPort | Select-Object DeviceID, Name, PNPDeviceID
|
||||
```
|
||||
|
||||
记录本机 COM 和驱动状态,确认供电、电平、共地、TX/RX、波特率和流控与现场已正常会话一致。运行器使用 8N1、无流控,默认 DTR/RTS 关闭;输出同时保存时间戳文本及 `.raw.bin`,路径必须为新文件。端口被 SecureCRT 或其他任务占用时保留占用结果,由当前持有者正常释放,不能抢占。
|
||||
|
||||
无数据时先核对连接和设备输出条件。历史现场按已确认的终端会话显式启用 DTR/RTS 后收到数据,但不能认定控制线是唯一原因,也不能把它设为所有设备默认值。确实需要且已确认其电气含义时才在 `serial` 命令加入 `--dtr-enable` / `--rts-enable`;它们不是硬件握手选项,部分设备用控制线复位。`profile.serial` 仅供环境记录,不会隐式改变运行器参数。
|
||||
|
||||
端口打开、收到日志、双向字符收发、认证成功和可用 shell 分别验收。历史一次诊断观察到用户名后返回密码提示,但没有确认 shell;通用 Skill 因而仍只提供被动采集,不包含自动登录或任意命令发送。不得将该现场诊断脚本及其目标参数复制为团队默认工具,也不循环猜测凭据。
|
||||
|
||||
## 9. 内部配置工具 V2.0.5、mainThread 与 GUI 宿主
|
||||
|
||||
配置工具按内部正式来源取得 V2.0.5 完整包,验证实际 EXE 与包内文件一致。保留 Qt/DLL/资源目录,在窗口版本控件复核 `V2.0.5 Build:2026041414`,避免误启旧版本。程序启动及控件可见已验证;独立 `device_adapter.py info` 的只读身份结果不经过 GUI,不能作为 GUI 设备发现成功证据。参数配置仍走实际界面或已验证协议,不能猜测视频参数命令。
|
||||
|
||||
mainThread 为实际“端侧数据采集工具.exe”的 PyQt 原生程序。通过内部授权的分发渠道取包和手册,登录下载由使用者完成;完整解压并验证能显示主菜单。未签名或无文件版本时只能记录事实,归档 CRC/SHA256 不能代替供应方身份核验。
|
||||
|
||||
只读入口为“进入查询端侧数据采集功能”,可查询周期数据、拓扑和已有日志地址。实际控件定位参见 [工具路由](tool-routing.md),对象名是静态线索,必须重看本机窗口。主菜单或查询页没有 CoAP 监听不等于故障;“进入本地调试功能”、自检、开启日志上报属于不同的设备动作。不要提取程序内部鉴权信息或绕过 GUI 猜后台接口。
|
||||
|
||||
GUI 环境按以下次序检查:
|
||||
|
||||
1. 宿主是否提供原生 Windows 控制。只有浏览器能力时,不能操作 Windows 客户端;这是控制能力缺口,不是客户端未安装。
|
||||
2. 当前目标窗口是否仍有效、位于可交互会话、可观察控件/截图;重新选择实际窗口后再输入,不沿用旧坐标或盲按回车。
|
||||
3. 应用与控制器权限是否相容。已观察的移动视联 2.3.12 manifest 要求管理员权限,普通权限控制器可能无法输入;采用产品支持的权限方案,不修改 manifest 或绕过系统边界。
|
||||
4. 控制宿主本身是否失败。曾出现 `failed to write kernel assets`、捕获超时与 `coordinate input geometry is unavailable`。恢复一个已准确定位的缺失临时目录曾恢复窗口文本读取,但未修复截图/点击,之后另一次运行时仍失败。此经验不是可普遍自动执行的修复脚本,不能猜目录或复制其他会话资产。
|
||||
|
||||
保存工作及原始错误后,可以按宿主支持方式重载相关运行时或重启应用,再复测;不能保证重启解决。相同权限窗口也发生过截图超时,移动视联权限差异不能解释全部故障。多显示适配器只有待查线索,不能据此禁用显卡、远控、显示驱动或改系统安全设置。未恢复控制时,转为人工界面操作加证据交接,并标注未完成 GUI 自动化。
|
||||
|
||||
## 10. 网站、登录与专用依赖
|
||||
|
||||
客诉系统、联楹(连楹)、移动视联采用“人工登录 → 观察业务页和目标权限 → 继续自动操作”。先连接使用者实际已登录的浏览器/客户端会话,不能打开一个新空会话后判断整台电脑未登录。账号、密码、验证码、短信及协议由使用者完成;代理不代填、不读取账号统计表、不导出 cookie。当前授权范围明确后,登录后的查询及取证无需逐步再确认。
|
||||
|
||||
报告分别写“等待人工登录”“登录状态未确认”“已登录但目标权限不足”“控制通道故障”。`queued` 的打开请求不是页面已显示;无法观察浏览器也不是登录失败。历史见过登录页仅说明当时入口可达,不保证当前权限。
|
||||
|
||||
老 DM、软探针、算法 OTA 与其他内部后台按实际产品、环境和文档配置。找不到入口/权限时只阻塞依赖它们的阶段,不拿客诉网站代替全部后台。路由器从当前测试环境明确入口,修改前保存参数并准备回读/恢复;能访问登录页不代表配置已验收。`firmware_encrypt` 仍需要符合原用例 SDK 版本要求的程序和说明,旧 SDK 或 Binwalk 都不能替代。
|
||||
|
||||
## 11. Artemis 1.5.2、MCP 与修复基线
|
||||
|
||||
本 Skill 不携带 Artemis 主程序、Python venv 或模型密钥。团队试用的可复现基线为 **Artemis v1.5.2,提交 `bdc75d0c657c5c2707b4c6e352eed6a1f5c14fff`,以及单独的观察任务修复补丁**。补丁适用性检查、应用与回退见 [Artemis 补丁说明](artemis-patch.md);不得给其他版本盲套补丁,也不能仅更新 Skill 就认为 Artemis 已修复。
|
||||
|
||||
在批准的 Artemis 源码/发行目录中,按该版本 README 部署。1.5.2 的 Windows 正式入口为 `start.bat` / `start-cn.bat`,支持 `-SetupOnly`;这些脚本会检查或下载依赖并安装/更新 Codex MCP,属于环境变更,不是只读命令。已有可用环境则直接核对项目 venv、版本和配置,避免无因重装。
|
||||
|
||||
```powershell
|
||||
Set-Location 'D:/TeamTools/Artemis'
|
||||
.\start-cn.bat -SetupOnly
|
||||
uv run artemis doctor
|
||||
uv run artemis mcp --help
|
||||
uv run artemis mcp --install codex
|
||||
```
|
||||
|
||||
准备环境和手动 MCP 安装是按缺口选择的步骤,不要求每次都重复执行。由该项目生成本机 MCP 配置,使用项目 `.venv` 的 `python -m mcp_server` 或 `uv run artemis mcp`;不要分发开发者配置中的绝对路径。安装/更新后正常重载 MCP 或重启宿主,使新进程和工具签名生效。升级脚本会停止当前项目的服务、MCP 和任务,须在队列空闲且已保存工作时按版本说明使用;不能把升级当作运行中任务的无影响修复。
|
||||
|
||||
模型地址、Key 和模型名由使用者在 Artemis 本机设置或 `.env` 配置,不从聊天收集或写入 Skill。`mobile_workspace()` 核对 Android 设备和队列,首次调用 `mobile_diagnose(device_serial=...)`;仅认证异常才增加凭据验证,仅观察链异常才增加设备探测。诊断的修复选项可能重启 ADB 或调整设备锁,先根据真实失败和当前队列决定,不能习惯性全部开启。
|
||||
|
||||
scrcpy 诊断与实际录屏不一致时,先检查安装路径与长期驻留进程缓存。已知补丁补齐了标准安装路径;新进程识别成功后正常重载 MCP,不因旧进程仍报缺失就重复安装。ADB 设备未授权、离线、多实例或端口冲突按 doctor 的具体结果处理,不任意结束共享 ADB/模拟器进程。
|
||||
|
||||
最后以“只观察当前 APP 页面、保存实际文字和截图、正常结束并由 Checker 复核”的小任务验收连接。使用 [手机工作流](artemis-workflow.md) 的真实工具签名,显式选择设备;手机序列号与摄像机 SN 分开核验。历史补丁相关回归与一次真实只读观察已通过;完整源码测试仍有已记录失败,不能宣称全套通过。新电脑仍需完成自己的连接与样本任务验证,任务 `completed` 和目标级 `passed` 也不能扩展成多条摄像机业务通过。
|
||||
|
||||
## 12. 修复后的交接
|
||||
|
||||
仅记录本次实际改变:工具与版本、安装来源及摘要、解释器/DLL 位数、profile 字段、复测命令类别、执行状态、证据位置和未解决项。机器私有路径及设备资料留在本机运行记录,发布包只保留通用示例。不要带入开发机的原始日志、固件、pcap、截图、账号文件或历史任务报告。
|
||||
|
||||
按“运行时可用 → 本地样本通过 → 连接/登录就绪 → 业务断言取证”逐层交接。某个 GUI、平台或 SDK 仍阻塞时,继续已就绪且独立的工具环节;联合报告通过 [证据契约](evidence.md) 关联真实 Artemis 导出与外部材料,不改写原生 trace 或把环境修复成功写成业务用例通过。
|
||||
@@ -0,0 +1,38 @@
|
||||
# 联合证据报告
|
||||
|
||||
用 `python scripts/evidence.py bundle --manifest RUN/input.json --out RUN/result` 生成独立报告。输出目录必须不存在,防止覆盖历史。`evidence_root` 相对输入文件目录,可是绝对目录;每条 evidence 必须是其中的相对文件,不能越界或通过符号链接逃逸。
|
||||
|
||||
输入示例(实验虚构值,不代表已执行):
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": 1,
|
||||
"run_id": "LAB-20261016-001",
|
||||
"evidence_root": ".",
|
||||
"context": {
|
||||
"execution_mode": "simulation",
|
||||
"real_device_test_executed": false,
|
||||
"case": {"sheet": "9系统设置", "row": 96, "case_id": "9.132"},
|
||||
"tool_versions": {"ffprobe": "实际版本"},
|
||||
"artemis": {"session_id": "实际返回的 session"}
|
||||
},
|
||||
"assertions": [
|
||||
{
|
||||
"id": "encoded-format",
|
||||
"required": true,
|
||||
"expected": "原始流 codec_name 为 hevc",
|
||||
"actual": "无法取得原始流",
|
||||
"verdict": "blocked",
|
||||
"evidence": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`verdict` 只能是 `passed/failed/blocked/inconclusive`。`passed` 和 `failed` 必须引用真实观测文件;缺证据或提供的 SHA-256 不符时降为 `inconclusive`,保留 `requested_verdict`、`requested_evidence` 及原因。摘要不符的原文件仍收进归档但标记 `integrity=mismatch`,不能作为通过依据。引用支持字符串路径或 `{"path":"probe.json","sha256":"实际64位哈希"}`。
|
||||
|
||||
汇总仅针对 `required=true` 的必需断言,顺序为有明确失败→failed,否则有阻塞→blocked,否则有未验证→inconclusive,全部有证据且通过→passed。没有必需断言不能通过。可选断言仍逐条展示,不能用可选断言绕过原用例要求。`context.execution_mode` 使用 `live/offline/simulation`,未标注显示 `unspecified`;模拟/离线不能声明实际执行过真机。人类可读报告顶栏会显示运行性质;真机操作也不意味着所有用例已完成真机验收。
|
||||
|
||||
脚本校验文件完整性,并不理解截图、JSON、PCAP 的业务含义。断言的作者必须核对原始预期和实际观测。一个无关但存在的文件不构成有效证据;不把运行脚本成功写为业务通过。用例未执行、只是架构联调时,context 中写明框架场景而非原 Excel 完整覆盖。
|
||||
|
||||
输出 `manifest.json` 保存上下文、断言和文件哈希,`report.md` 供阅读,`bundle.zip` 收入两者与文件副本。该脚本不向外发送资料。归档保留原始证据,不自动去除 PCAP、截图、日志中的全部敏感信息;归档前选择/处理允许交付的文件,原始资料按内部测试权限保管。分发 Skill 的 ZIP 不包含现场证据。
|
||||
@@ -0,0 +1,59 @@
|
||||
# 首轮试用与简单验收
|
||||
|
||||
这是工具链烟测流程;用于确认同事电脑上能够实际调用工具,遇到阻塞记录后跳过。输入为本机 profile、当前授权目标和用户提供的样本。输出为环境状态、子检查结果和证据,不把烟测等同原 Excel 完整用例验收。
|
||||
|
||||
## 流程
|
||||
|
||||
1. 记录 `VERSION`、Windows/Python 位数、Artemis 版本;运行 `tool_runner.py --profile <文件> doctor --check-versions`。逐项检查 `availability` 和 `version_check`:doctor 整体退出 0 只表示盘点完成,可能仍有工具缺失。GUI、MCP 和登录状态另行检查。
|
||||
2. 优先用本地媒体/固件/PCAP 做离线调用。没有真实固件时可用明确标为合成的正例验证 Binwalk,但不能将它关联为设备安全通过。需要补文件或驱动则按 [环境修复](environment-repair.md) 处理。
|
||||
3. 已核对完整 SN/型号/IP 后,选择单设备的只读查询、抓包、限定端口或串口子项。同一台设备及共享实验台串行,抓包与被观测操作确需重叠时由同一编排者协调;不占用别人的 COM 或停止其他任务。
|
||||
4. Artemis 先 workspace/diagnose,再只读 APP 观察及原生报告导出。平台先人工登录,确认当前页面和权限后继续。具体 MCP 参数见 [手机工作流](artemis-workflow.md)。
|
||||
5. 根据实际观测写断言,再按 [报告契约](evidence.md) 生成综合报告。工具修复成功、用例失败、缺前置和未充分验证分别记录;任一阻塞不必阻止无依赖的其他检查。
|
||||
|
||||
## 可选子项
|
||||
|
||||
所有 `tool_runner.py` 的全局参数放在子命令前;使用绝对脚本路径或先进入 Skill 目录。输出目录预先建立,每次采用新文件名。示例中的尖括号必须替换,不能直接执行。
|
||||
|
||||
| 烟测 ID / 工具 | 操作及需要的输入 | 工具调用验收 / 业务限制 |
|
||||
| --- | --- | --- |
|
||||
| ENV-01 / 全工具 | `doctor --check-versions` | 每个所需 CLI 版本或帮助成功;DLL/模块可加载。GUI/manual-interface、MCP 待独立核实,不据整体退出码通过全部环境 |
|
||||
| DEV-01 / 配置协议 | `device_adapter.py info --host <IP> --expected-sn <完整SN> --expected-model <型号>` | 实际响应身份匹配,记录版本。不能代表配置工具 GUI 搜索/设置或固件升级已验收 |
|
||||
| MEDIA-01 / ffprobe | `tool_runner.py --profile <配置> probe --input <本地原流文件>` | 实际有视频轨、编码和尺寸;名义帧率不能证明持续性能;9系统设置!96 / 9.132 只覆盖读取子项 |
|
||||
| MEDIA-02 / FFmpeg | 对同一已授权本地文件运行有界解码;见下节 | 返回码和诊断共同判断;文件不完整时不能因退出 0 宣布完整录像通过 |
|
||||
| MEDIA-03 / MediaInfo | `tool_runner.py --profile <配置> media-info --input <同一媒体文件>` | 编码、宽高、音轨与 ffprobe 核对;空字段标为未验证;Duration 是毫秒 |
|
||||
| NET-01 / dumpcap+TShark | `capture --interface <接口> --host <IP> --duration 10 --output <新pcapng>`,随后 `analyze-pcap --input <pcapng>` | 能读回来自目标的实际包;0包表示调用可完成但流量证据不足;不等于13安全!15 / 13.14通信安全通过 |
|
||||
| NET-02 / Nmap | `scan --host <IP> --ports <双方约定的少量TCP端口>` | 每个请求端口的状态与覆盖度可核对。open不推断服务身份,filtered不等于closed;13.8/13.9完整验收另需范围及允许清单 |
|
||||
| FW-01 / Binwalk | `firmware-scan --input <用户提供固件>` | 记录文件大小、扫描前后SHA-256、退出码和签名结果。0签名是有效观测,不能证明加密或无敏感信息;13.3/13.4另需存储/加密方案/文件内容证据 |
|
||||
| SERIAL-01 / 串口替代 | `serial --port <COM> --baud <波特率> --duration 5 --output <新日志>` | 是否成功打开与是否收到字节分别记录。0字节时跳过13.18日志内容检查;不自动发送登录或命令。DTR/RTS仅匹配已知现场设置 |
|
||||
| APP-01 / Artemis | 选定Android设备,只观察移动爱家当前目标页、保存观察笔记并结束,复核trace并导出 | 目标匹配、可见内容、截图/笔记与实际结论一致。completed不等于业务passed,也不等于摄像机物理场景通过 |
|
||||
| GUI-01 / 平台及PC | 观察真实窗口/页面;人工登录后按授权只读查询 | 找到程序、窗口或登录页与完成查询分开记录;无法观察/输入时保留环境阻塞 |
|
||||
|
||||
### FFmpeg 本地解码示例
|
||||
|
||||
此命令直接调用 FFmpeg,**不是** `tool_runner.py` 已实现的新子命令。只用于本机媒体;RTSP 录制需单独确定 URL、凭据注入、时限和文件完整性,当前 runner 没有通用录制入口。
|
||||
|
||||
由 Codex 用 Python `subprocess.run` 的参数数组及 `timeout=35` 调用,保存 stdout/stderr 到本次受控证据目录。外层终端的等待/返回会话时间不等于进程终止时限。命令参数为:
|
||||
|
||||
```text
|
||||
<本机ffmpeg.exe> -hide_banner -nostdin -v warning -protocol_whitelist file -i <本地媒体> -map 0:v:0 -t 5 -f null -
|
||||
```
|
||||
|
||||
不把网络 URL、播放列表或用户提供的额外参数拼进此模板。超时停止本次进程并保存状态;输入含凭据时不能直接归档诊断。出现 `File ended prematurely` 等诊断时记录文件不完整,即使退出码为0也不能给文件完整性通过。I帧间隔另需 ffprobe 逐帧 `pict_type` 与时间戳;基础 `probe` 摘要不足,不能用APP录屏代替原流。
|
||||
|
||||
### 与 Artemis 组合的最小场景
|
||||
|
||||
选择同一已确认摄像机:配置适配器只读身份/版本 → Artemis 在 APP 设备设置页观察版本 → 比较同一版本语义,保存两侧原始证据。若 APP 只显示外部版本,不与设备硬件版本或内部版本混比;无法读到字段记未验证。也可 APP 观察直播 → PC 读取用户已提供的原流元数据,但 APP 截图只证明当时 UI 画面,码流参数取自原流。
|
||||
|
||||
给 Artemis 的任务正文同时写入目标、只读边界、观测项、失败停止条件和预期输出;不要只放在批次 preconditions 元数据。原生报告与外部证据分别保存,用 session/trace 和 case_id 关联,不改写原生报告。
|
||||
|
||||
## 已有开发机验证与本次试用的区别
|
||||
|
||||
2026-10-16 已验证 dumpcap/TShark 4.6.3、Binwalk 2.3.2 独立 Python3.11、Nmap 7.60、MediaInfo 21.09 DLL、FFmpeg/ffprobe 2023-12-18构建,以及配置协议只读查询和带修复的 Artemis v1.5.2 只读观察。这是兼容性记录,不是最新版本推荐或其他机器自动可用的保证。
|
||||
|
||||
- 真实固件签名扫描已完成但没有识别到签名,未验证设备Flash加密/AES方案/敏感信息。
|
||||
- 两路RTSP复制曾达到外层时限,保留的部分媒体可离线分析但不完整;当前未宣称录制稳定。
|
||||
- 串口曾确认基础双向收发;另一次被动窗口收0字节,尚未确认shell登录。不能将其中一次结果推广为所有设备或COM设置。
|
||||
- Windows截图/点击与浏览器控制曾受宿主环境阻塞;移动视联还存在程序与控制进程权限不一致。平台登录后的业务、mainThread查询、配置GUI参数操作仍需现场验证。
|
||||
- firmware_encrypt匹配SDK、老DM及算法OTA等专有入口仍需团队补齐。357条保留用例路由并非357条已自动执行或通过。
|
||||
|
||||
将本机实际结果填入 [反馈模板](../assets/feedback-template.md),不要复制历史通过标签作为新电脑的结论。
|
||||
@@ -0,0 +1,43 @@
|
||||
# 设备协议范围与资料来源
|
||||
|
||||
发现、查询或升级前先运行 `python scripts/device_adapter.py capabilities`,再按设备实际协议选择路由。该命令不联网;能力清单不代表设备在线或已完成真机升级。
|
||||
|
||||
| 设备协议 | 已实现的 CLI 操作 | 升级范围 |
|
||||
| --- | --- | --- |
|
||||
| V1 | UDP `ff00/ff01` 搜索、TCP `2104` 身份/原生版本查询、`2170` 固件下发、指定字段比较 | 默认 ROM/身份预检;显式执行最多一次 TCP4941/MD5+ROM 下发;同命令code=0后另行回读 |
|
||||
| V2 | UDP EPBP 搜索、TCP EPTP/30101 身份/版本查询、EPFP/4001 传输 | 默认预检,显式执行后最多一次传包;协议成功后另行回读验收 |
|
||||
|
||||
`--protocol v1` 或 `--protocol v2` 放在网络子命令之后;不传仍默认 V2,以兼容既有调用。这不是自动检测。参数和结果见 [设备适配器](device-adapter.md);V1 报文、字段和应答范围见 [V1 接口](v1-protocol.md)。
|
||||
|
||||
配置工具软件的 V2.x 与设备的 V1/V2 协议不是同一个概念。同一 GUI 可以包含多个协议页面。V2 端口拒绝或搜索无响应不能证明 V1 设备离线。已知 V1 时不自动切换 V2;身份冲突时不能默认选第一台。
|
||||
|
||||
## 已核对的资料
|
||||
|
||||
2026-10-19,交叉核对用户提供的两份本地原文及源码:
|
||||
|
||||
| 文件 | 文档修订 | SHA-256 |
|
||||
| --- | --- | --- |
|
||||
| `v1.md`(工厂协议) | v1.0.23,2026-08-03 | `50e8a76c880386e03e173582de3115bc60fd91e1f1ce5f4e8a6b190e4fc8f8b9` |
|
||||
| `固件配置工具及web管理工具接口文档.md` | V1.9,2019-05-13 | `e4d373e3ab673add9da93ca4d07b5c8530189df086743ba7fb171757eb2efa10` |
|
||||
| `src.zip` | 用户提供的 Qt C++ 源码;未提供上游提交版本 | `1603ece177973ec79a4ea3fb94f2984faf9c82ca3ec7f4eac224003385737fbc` |
|
||||
|
||||
两份原文均定义 TCP4941、设备UDP4942、网络字节序的 `U32 CMD + U32 Data长度 + Data`,以及无请求Data的 `0x5a0e2104`。较早文档补充 `0x5a0eff00/ff01` 搜索。其第21节的升级Data留空,现由源码核实为 MD5小写ASCII32 + ROM,非直接ROM。
|
||||
|
||||
原文和源码ZIP保留在提供资料的机器上,不做修改。可分发技能只包含必要协议摘记和来源摘要,避免带入其他配置章节及示例账号。重新取得同名文件时先核对内容及修订,不只按路径判断;运行时不依赖原始ZIP或作者机器路径。
|
||||
|
||||
同时核对了“Windows电脑端调试”插件 `embedded-app-pc-debug` 1.0.0 及上游 tag `v1.0.0`,提交 `cfb586cb5ffc5a69e66cd9adbc57e4ebf725d1d3`。该版本仅附 V2 设备脚本,V1 参考是作者机器的外部路径;路径是查找线索,不是团队部署依赖。已有用户资料时先核对,不重复索取已提供的文件。
|
||||
|
||||
## 源码核对位置
|
||||
|
||||
以下行号相对上述归档中的 `src/`,不是本机安装依赖:
|
||||
|
||||
| 位置 | 核实内容 |
|
||||
| --- | --- |
|
||||
| `EapilPanoCHead.h:21–35,160` | 成功码0、TCP4941、UDP4942、升级命令2170 |
|
||||
| `EpConnection.cpp:116–195`,`sendTcpFile` | 大端CMD/Length;全ROM的MD5.toHex();Length=32+ROM大小;MD5文本后跟ROM |
|
||||
| `EpConnection.cpp:369–411` | 连续TCP文件字节及本地发送结束,不存在自定义块头 |
|
||||
| `EpConnection.cpp:687–729`,`readTcpData` | 同连接读取CMD/Length/JSON |
|
||||
| `EpPanoCConfigure.cpp:734–754`,`updatePanoC` | 检查返回命令为2170、CommonResponse.code=0 |
|
||||
| `json/GetBasicInfoResponse.cpp:57–68` | V1字段为dev_type/sn/firmware/hardware/dev_id/dev_ver,无inner/outer映射 |
|
||||
|
||||
源码同时有8940/EPFP的另一种文件通道,不自动推断当前设备支持它。源码的本地发送完成和code=0没有证明设备已完成烧录并启动;CLI保留单次传输、精确身份/摘要门槛和独立回读。V1与inner/outer关系未建立,不能静默替换任务指定字段。具体实现及真机范围见 [V1接口](v1-protocol.md)。
|
||||
@@ -0,0 +1,78 @@
|
||||
# 团队部署与本地profile
|
||||
|
||||
适用:把同一Skill部署到其他同事电脑,或从新环境检查工具可用性。Skill分发包保存代码、路由和脱敏模板;各机器的程序路径、设备选择、平台环境和凭据分别配置。不要复制个人目录、账号统计表、真实设备SN、登录会话或API Key到分发包。
|
||||
|
||||
## 运行时与目录
|
||||
|
||||
将发布 ZIP 中的 `artemis-device-test` 文件夹复制到当前用户的 `$CODEX_HOME/skills`,未设置该变量时使用 `~/.codex/skills`。保持 `SKILL.md` 位于该文件夹第一层,然后重新加载技能或新开对话。若已有同名技能,先保留旧版本再更新。用 `$artemis-device-test` 显式调用;本 Skill 也支持按请求内容自动匹配。代码、脚本、references 和 assets 必须一同复制。
|
||||
|
||||
工具脚本使用Python 3.10+标准库,团队可在约定目录部署便携Python并用绝对解释器路径启动,无需绑定开发者个人环境。优先使用经团队验证的同一Python版本;已封装串口路径使用PowerShell,不需要pySerial,另选pySerial实现时才需安装其依赖。Artemis使用其项目自有依赖环境,不要求与轻量工具脚本共用解释器。
|
||||
|
||||
建议各机器准备三类本地位置:Skill目录、工具目录、证据输出目录。工具从已批准来源安装或解压;发现`.exe`或安装包只表示文件存在,不表示产品已安装、可调用或已登录。只有当前任务包含安装/修复时才执行所需安装器,不因文件存在而遍历运行;已有授权无需逐步重复确认。用平台原产品时保留版本、许可与依赖。具体步骤见 [环境安装与修复](environment-repair.md)。
|
||||
|
||||
从Skill目录运行,示例中的`python`可替换为便携解释器路径:
|
||||
|
||||
```powershell
|
||||
python scripts/tool_runner.py --help
|
||||
python scripts/tool_runner.py --tool-root "D:/TeamTools" list
|
||||
python scripts/tool_runner.py --profile "D:/TeamConfig/tools.local.json" doctor --check-versions
|
||||
python scripts/device_adapter.py --help
|
||||
python scripts/device_adapter.py capabilities
|
||||
```
|
||||
|
||||
`--profile`、`--tool-root`、`--timeout`和`--dry-run`是`tool_runner.py`全局参数,放在子命令前。每个工具都按实际可执行文件做检测,未安装不能用“计划支持”替代。具体参数与边界以 [有界CLI](cli-tools.md) 和脚本`--help`为准。
|
||||
|
||||
## profile与凭据
|
||||
|
||||
`tool_runner.py`支持`tools`字典指定程序路径、`runtimes.binwalk_python`指定已安装Binwalk模块的独立Python、`libraries.mediainfo`指定本地DLL;不要在此存密码或带认证的URL。一个可移植的结构示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"ffprobe": "D:/TeamTools/ffmpeg/bin/ffprobe.exe",
|
||||
"tshark": "D:/TeamTools/Wireshark/tshark.exe",
|
||||
"dumpcap": "D:/TeamTools/Wireshark/dumpcap.exe",
|
||||
"nmap": "D:/TeamTools/Nmap/nmap.exe"
|
||||
},
|
||||
"runtimes": {"binwalk_python": "D:/TeamTools/binwalk-env/Scripts/python.exe"},
|
||||
"libraries": {"mediainfo": "D:/TeamTools/MediaInfo/MediaInfo.dll"}
|
||||
}
|
||||
```
|
||||
|
||||
这是每台机器的本地配置示例,不是硬编码路径。设备IP/SN/型号、平台URL/环境、路由器地址、串口和参数也由本机私有profile或运行参数提供;只有对应脚本实际声明的字段才传给它。未被脚本实现的网页/GUI目标由编排层读取,不伪装成脚本已支持的API。
|
||||
|
||||
Binwalk2.3.2已在独立Python3.11环境验证,因依赖`imp`不能直接移到Python3.12+;固定入口为`python -I -m binwalk`,不要更换Artemis项目的解释器。MediaInfo使用与运行器Python位数匹配的Windows DLL,正式命令为`media-info`,不会代调GUI。未安装时省略对应配置,依所需用例准备环境;Skill不分发个人venv,doctor和测试命令也不会隐式安装模块,环境准备阶段按已授权范围另行安装。`doctor`的`python-module-configured`/`library-found`只说明路径已发现,须再检查`version_check`并跑本地样本。
|
||||
|
||||
敏感值通过环境、系统凭据存储或用户当前登录态注入。`probe --rtsp-env DEVICE_TEST_RTSP`只接收环境变量名称;完整RTSP地址不写入命令历史、清单或聊天。FFprobe子进程仍通过参数接收URL,同机有进程查看权限的程序可能看到它,见CLI工具说明。环境变量由用户或本机安全流程设置,脚本不要求在聊天提供值。网页短信验证码由用户在当前页面完成;不复用旧文档中的历史授权。
|
||||
|
||||
团队使用客诉系统、联楹(连楹)及移动视联时,登录是人工前置步骤:使用者在对应网页或客户端完成账号、密码、验证码、短信及协议确认,代理不自动填登录信息或提交登录。代理先复用现有会话,登录后确认可见业务页及目标权限,再继续当前授权范围的查询、操作和证据采集。无需为后续每一步重新确认。交接方法和状态口径见 [工具路由](tool-routing.md);“等待人工登录”与“登录状态未确认”不得计为工具缺失或工具调用失败。若使用者已在其他浏览器登录,应连接并复用该会话,不能用新建空会话证明整台电脑未登录。
|
||||
|
||||
## 工具烟测与验收界限
|
||||
|
||||
```powershell
|
||||
python scripts/tool_runner.py --profile "D:/TeamConfig/tools.local.json" probe --input "D:/Evidence/original-stream.mp4"
|
||||
python scripts/tool_runner.py --profile "D:/TeamConfig/tools.local.json" media-info --input "D:/Evidence/original-stream.mp4"
|
||||
python scripts/tool_runner.py --profile "D:/TeamConfig/tools.local.json" analyze-pcap --input "D:/Evidence/capture.pcapng"
|
||||
python scripts/tool_runner.py --profile "D:/TeamConfig/tools.local.json" --dry-run scan --host 192.0.2.10 --ports 80,443,554
|
||||
python scripts/tool_runner.py --profile "D:/TeamConfig/tools.local.json" firmware-scan --input "D:/Evidence/device-partition.bin"
|
||||
```
|
||||
|
||||
`192.0.2.10`是文档示例地址,不能作为实际目标。采集使用 `capture --interface <接口ID> --host <单个IP> --duration <秒> --output <pcapng>`;串口使用 `serial --port <COM口> --baud <波特率> --duration <秒> --output <日志>`。这些操作必须绑定当前已确认目标,输出目录须已存在、输出文件须为新文件。`scan`仅接受最多128个明确TCP端口,不做UDP、服务版本探测或完整全端口验收;返回`test_verdict=not_evaluated`表示只取得工具结果,须按用例再判定。`--dry-run`仍校验输入文件和执行体,只是不启动进程。
|
||||
|
||||
设备适配器先用 `capabilities` 核对协议支持范围,再按实际`--help`调用:网络子命令用 `--protocol v1/v2` 选择,默认仍为 V2。V1 支持搜索、身份/原生版本查询及 TCP 4941/2170 升级;详见 [协议范围](protocol-support.md) 及 [V1接口](v1-protocol.md)。型号未知时用带完整 SN 的 `identify` 只读观察,再用实测型号校验。`offline --rom <包> [--rom-sha256 <摘要>]` 不联网;`upgrade` 默认在线预检。写入还需当前范围授权、目标一致、包摘要与显式 `--execute`。`verify-version` 校验任务指定字段,V1 原生 `firmware/dev_ver` 与 V2 `inner.version/outer.version` 不自动互换;不覆盖升级拒绝、安全校验、循环成功率与视频参数断言。详细语义见 [配置工具9行](tool-routing.md#配置工具9行的独立断言)。
|
||||
|
||||
## Artemis MCP
|
||||
|
||||
Skill ZIP 不包含 Artemis 程序本体,随包提供适用于指定 v1.5.2 基线的观察链源码补丁。先按 [补丁说明](artemis-patch.md) 核对基线和适用性;其他版本不能直接套用,不能只更新 Skill 就假定 Artemis 已修复。部署后验证“只观察页面并保存笔记”的任务能正常结束、Checker 能发现被截断的笔记,并区分目标级结论与逐条断言计数。
|
||||
|
||||
按Artemis项目README准备其运行时和应用服务,在项目目录运行 `uv run artemis doctor`。需要在Codex安装MCP时,使用项目正式命令 `uv run artemis mcp --install codex`,然后重新加载MCP或重启宿主。需要人工配置时先查看 `uv run artemis mcp --help`;由当前项目生成适配本机的配置,不分发含开发者个人路径的MCP配置。标准入口是项目环境中的 `python -m mcp_server` 或 `uv run artemis mcp`。
|
||||
|
||||
连接后用`mobile_workspace()`确认目标设备和队列,再按 [Artemis工作流](artemis-workflow.md)执行。Android序列号与被测摄像机SN是不同标识,两者分别选择并核验。模拟器可验证APP路由,不自动证明摄像机物理、网络、声音或屏幕效果。
|
||||
|
||||
## 网页、Windows客户端与当前环境差异
|
||||
|
||||
浏览器能力与原生Windows GUI权限由宿主决定;只有浏览器能力时仍可访问平台网站,但不能据此声明可操作移动视联、SecureCRT或配置工具。若使用UIA/Win32脚本,先验证实际控件与窗口,再固定定位。平台没有已确认API时使用真实页面,不猜测接口。
|
||||
|
||||
开发环境已验证FFprobe、Nmap等基础调用,以及Binwalk隔离模块和MediaInfo DLL的本地样本解析;这不是其他同事电脑的预置保证。mainThread已取得真实PyQt程序和手册,可按实际窗口路由到端侧数据只读查询,尚未以下载或启动证据认定业务通过。路由器及平台入口已有登录页观察,登录后的权限和功能仍待验证;firmware_encrypt所需对应SDK与实际工具仍缺。每台机器独立记录CLI发现、GUI可操作性、登录态与业务断言,不能只凭`doctor`评估全部工具。当前机器的设备标识、账号与登录态不进入本参考文档。
|
||||
|
||||
分发前检查所有参考文件能相对打开,profile不含秘密,工具版本和路径在本机复核;先做只读设备查询与APP观察,再按当前任务范围推进。测试结果、pcap、固件、日志和截图可能含敏感内容,证据包按团队既定访问范围保存;不要把本地完整证据目录作为Skill资产复制。
|
||||
@@ -0,0 +1,83 @@
|
||||
# 全工具路由与判定边界
|
||||
|
||||
读取场景:选择执行器、确认一个用例需要哪些证据,或排查“有工具却仍不能判定”的情况。机器可读的逐行映射在 [case-routing.json](../assets/case-routing.json),本机可执行文件配置与探测在 [团队部署](team-setup.md),手机任务交接在 [Artemis 工作流](artemis-workflow.md)。
|
||||
|
||||
## 范围与状态
|
||||
|
||||
来源是 `家庭安防多形态终端软件测试用例(移动看家2.0)20260623_自动化分类.xlsx`,结合 `review_all.json`、`kept_records.json` 和 `工具分析报告.md`。原有分类记录 861 行中排除“无法实现”504 行,保留 357 行:工具辅助163、人工介入125、可适用69。以工作表与 Excel 行号作为唯一来源,不按原编号去重。357 是保留记录行数,不是已自动化或已通过的场景数。
|
||||
|
||||
全工具入口负责发现、路由、调用现成能力、关联证据。平台和内部工具保留原产品、业务通道及权限;三方/通用工具可在能力等价且不改变被测条件时替换。仅标注“PC端”不能推出具体软件或API,提供入口路由不表示已有端到端脚本。人工场景、校准、硬件、后台权限等缺口保留在每条映射中。
|
||||
|
||||
路由结果与测试判定分开:工具正常退出或 Artemis `completed` 不等于通过。`passed` 要求所有适用断言有证据;`failed` 表示观察到明确违背预期;`inconclusive` 表示已执行但证据不足或冲突;`blocked` 表示必要依赖、权限、身份或前置条件未满足。映射文件中的 `not_run` 只是未执行状态,不是第五种业务判定。
|
||||
|
||||
## 平台与内部工具:保留业务入口
|
||||
|
||||
|路由|实际调用形式|可完成的环节|调用前要确认的缺口|
|
||||
|---|---|---|---|
|
||||
|移动视联PC|原Windows客户端;用户人工登录后,由宿主原生GUI能力或已验证的UIA/Win32控件驱动操作|直播/回放、分屏、云台、OSD、告警、端侧AI参数与上报|客户端实际版本、人工登录完成后的业务页与权限、控件可访问性及多客户端/多设备资源;安装程序不能当作已运行客户端;视频画布需另取码流或外部证据|
|
||||
|mainThread/杭研网络信息查询候选|已取得真实“端侧数据采集工具.exe”,静态确认Python3.8/PyQt5原生GUI;通过当前窗口进入查询页,无已验证CLI|周期基础数据、拓扑、已有设备日志地址查询;可作为1设备绑定!18(1.46)的候选取证入口|原用例仅称“杭研软件”,与该程序的用例对应关系、查询权限和目标数据仍须核实;包下载、程序启动或控件静态识别不等于业务通过|
|
||||
|移动看家客诉处理系统|真实网站的浏览器页面;用户人工登录后继续自动操作,经核实的正式API才可选用|在离线、编码延时、modelid、发声打点、日志、重启、网络检测记录|由本地profile提供URL;确认业务页和目标查询权限。账号、密码、短信/图形验证码及协议确认均由用户完成;不读取或复制账号统计表|
|
||||
|连楹平台(材料也写“联楹”)|原智慧家庭门户/终端管理网站;用户人工登录后通过browser自动操作|modelid、版本/注册信息、首次及后续24小时上报|确认平台实际产品、环境及当前查询权限,不用老DM替代;记录查询条件、服务器时区、事件时间与设备别名|
|
||||
|老DM/终端管理平台|原管理平台browser;正式API有文档和权限时可用|首次注册、心跳及48小时持续记录|地址和身份待确认;20 DM测试!6的24/48小时矛盾须在执行前解决|
|
||||
|内部配置工具|原EapilCameraConfigurer PC GUI;`device_adapter.py` 按 `--protocol` 驱动|V1/V2 搜索、身份与版本查询、显式固件下发;原GUI实际支持的配置|先查 `capabilities` 与 [协议范围](protocol-support.md)。V1 [接口](v1-protocol.md) 使用 TCP4941/2170/MD5+ROM;默认只预检,显式执行最多一次传包。软件V2.x不代表设备协议V2。视频设置继续原GUI或原表要求的APP|
|
||||
|firmware_encrypt|对应SDK随包工具,CLI参数以该版本帮助/说明为准|9系统设置!20(9.15-3)的规定OTA包生成|工具和SDK缺失时`blocked`;不猜加密算法/参数,不用通用压缩或加密替代。保留包摘要、SDK版本、命令脱敏记录和双分区证据|
|
||||
|软探针、参数/日志后台|原网站browser或已核实的正式接口|开关、参数、指标、事件、日志上传与时间对应关系|原资料未给出全部入口;不可编造API路径,不将客诉网站自动视为所有后台|
|
||||
|算法OTA平台|原管理网站browser或已核实的下发/回滚接口|云化AI算法应用下发、启用、回滚、版本检查|平台身份、算法包、授权、适用白盒设备和回滚证据;APP提示成功不能证明算法真正生效|
|
||||
|其他既有管理/编码/升级/1400入口|保持原平台或原协议取证通道,先识别产品再选browser/PC GUI/正式API|原生参数、编码控制、协议事件、升级与日志取证|“既有PC平台”“厂商平台”仅是依赖描述;身份未确认时保留`blocked`,不映射成虚构统一服务|
|
||||
|
||||
网页路由先观察现有页面,再用可访问元素定位。PC GUI路由先确认宿主确实允许原生桌面控制;仅有浏览器自动化不能操作Windows程序。无支持的GUI能力时保留人工操作与截图交接,不声称已驱动客户端。登录态是运行时条件,旧文档中的授权或历史登录不自动授权本次外部写入。
|
||||
|
||||
客诉、联楹与移动视联的登录交接:先观察当前可访问的标签页或客户端窗口,已有有效会话则直接复用。确实显示登录页时,将准确页面/窗口交给用户,等待用户自行完成账号、密码、验证码、短信和协议步骤,不自动代填、发送短信、点击登录或读取账号表。用户完成后重新观察业务导航与目标查询权限,按当前授权的设备范围继续自动查询和取证;“用户说已登录”与“观察到可用业务页面”分别记录。仅当登录失效或权限不足时再次交接,不为已授权的后续步骤反复询问。浏览器未连接或窗口不可访问属于会话可观察性问题,不能推断为未登录。报告分别记录“等待人工登录”“登录状态未确认”“已登录但目标权限不足”和实际工具故障;人工登录是既定前置步骤,不是工具缺失或用例失败。
|
||||
|
||||
mainThread 原生查询页的静态定位线索:主菜单“进入查询端侧数据采集功能”对应 `enterReportButton`,输入框为 `snEdit`、`macEdit`、`deviceIdEdit`,输出框为 `getReportResult`。只读查询按钮为 `getAnddgsReport`(周期基础数据)、`getDevTopoReport` / `getDevTopoReportV4`(拓扑)及 `getLogURL`(已有日志地址)。这些对象名来自已取得程序的静态结构,实际自动化必须重新观察当前窗口,不能假设它们已暴露给 UIA。
|
||||
|
||||
查询使用当前确认的设备标识和程序正常鉴权,保留查询时间、条件与响应,不提取内置鉴权信息或绕过 GUI 猜测后台调用。“进入本地调试功能”会进入不同的 CoAP 工作模式,缺少监听端口不能用于判定查询页故障。`openSelfCheck`、`openLog`、`openLogAll` 分别会触发自检或日志上报,不属于只读报告查询;手册示例值也不是当前测试凭据或授权。平台及路由器的登录态、权限与业务能力以本次实际观察为准,历史登录页证据不代表当前状态。
|
||||
|
||||
## 三方与通用工具:可替换的执行与取证
|
||||
|
||||
|工具/能力|真实调用形式及封装入口|证据与限制|
|
||||
|---|---|---|
|
||||
|Codex|宿主编排;browser、原生GUI、CLI和MCP分别路由|Codex不代替码流传感器、物理场景或原业务平台;原图“76”分配不能复核,不能作为自动化覆盖率|
|
||||
|Artemis|MCP `mobile_workspace`、`mobile_run_task`、`mobile_batch` 等|手机APP界面执行、观察、原生报告;不是PC GUI/浏览器执行器。Appium等既有移动框架可按团队实际保留,不能据映射声明两者已互通|
|
||||
|Wireshark / dumpcap / TShark|Wireshark PC GUI;CLI `dumpcap`抓包、`tshark -r`分析;封装 `capture`、`analyze-pcap`|保存原始pcap及采集点/过滤条件/时钟。TLS密文不能证明业务权限、双向认证或设备日志脱敏;13.15需授权矩阵及端点证据|
|
||||
|Nmap|CLI;封装 `scan --host <单个IP> --ports <逗号端口>`|封装只做最多128个明确TCP端口的连接扫描,不做服务版本探测、UDP或NSE;端口名称不是经探测确认的服务身份。完整验收另补服务识别、全部约定TCP/UDP、IPv4/IPv6及工作状态,不能把默认列表扫描当全端口证明|
|
||||
|Binwalk|正式 `firmware-scan --input <镜像>`;配置 `runtimes.binwalk_python` 时固定 `python -I -m binwalk`,否则使用原生入口;独立临时用户配置|已用隔离Python3.11及Binwalk2.3.2验证合成签名正例及一次真实固件扫描;后者无已知签名。当前封装只扫描、不解包或执行提取物;解包与熵分析另行验证,签名或高熵不能证明设备flash加密|
|
||||
|ffmg原名 / FFmpeg / ffprobe|原“ffmg”名称待核实;FFmpeg/ffprobe CLI,封装 `probe --input <原始媒体>` 或 `--rtsp-env <环境变量名>`|实际编码、分辨率、帧率/时间戳、音视频轨道;帧级GOP分析需取得帧类型与时间戳,普通probe摘要不足。屏幕录制重编码不能证明设备原始GOP|
|
||||
|MediaInfo|正式 `media-info --input <本地媒体>`,通过 `libraries.mediainfo` 配置本机DLL;在有时限子进程读取固定字段;原GUI另走桌面能力|已验证MediaInfoLib21.09本地样本解析,GUI交互未由此验证;9.54/9.132可用ffprobe替换可比参数读取。Duration为毫秒;需原始流/导出文件,名义帧率不等于每段实测帧率|
|
||||
|SecureCRT / 串口|原PC GUI;可选`pySerial`;已封装 `serial --port COMx --baud <值> --duration <秒> --output <日志>`实际调用PowerShell串口脚本|真实串口与正确电气连接/参数;封装仅被动读取,不发送登录命令。SSH仅在设备本来支持且不改变被测条件时使用;关闭串口验收不得为了日志而打开|
|
||||
|路由器配置|原管理网站browser,或已核实的厂商CLI/API;适用OpenWrt可使用SSH上的UCI/ubus|网络模式、DHCP/DNS/MTU、双栈等需配置回读及真实连接验证;先保存恢复配置。OpenWrt不冒充指定路由器/光猫/移动闪联能力|
|
||||
|OpenCV / OCR / Python统计|CLI脚本或库API,读取固定样本/标注真值|OSD、画面特征、事件时间匹配与成功率;必须定义阈值、时窗、重复告警处理和真值,不能让另一模型判定充当唯一真值|
|
||||
|外部音视频采集、光照/声音/距离测量与实体工装|真实采集装置和已标定工具;其输出由CLI脚本解析或人工复核|带屏设备真实显示、声音/对讲、距离/角度/照度、准确率与物理云台必须保留实测。模拟器或屏幕播放不自动等价于规定的实物场景|
|
||||
|
||||
## 配置工具9行的独立断言
|
||||
|
||||
|来源与原编号|必需判定|不能代替它的证据|
|
||||
|---|---|---|
|
||||
|9系统设置!22 / 9.15-5|已知不兼容包升级失败,并按原预期证实回滚到原版本,或正常包恢复成功且上线|单纯版本未变化、命令报错或事后能查询设备|
|
||||
|9系统设置!95 / 9.131|覆盖所支持编码、分辨率、码率类型、帧率、I帧、智能编码、AOV;配置成功且实际流符合|只点击保存或只验证一个参数|
|
||||
|9系统设置!96 / 9.132|适用设备默认H265,H264/H265双向切换后实际流codec正确|界面显示编码或一次probe成功|
|
||||
|9系统设置!98 / 9.134|默认VBR、CBR和能力上下界;区分VBR峰值与CBR口径,并关联9.101—9.106|仅比较文件平均码率|
|
||||
|9系统设置!99 / 9.135|支持档位下的实际帧率、H264/H265直播/云/卡回放和对讲质量|名义fps、APP设置值或单片段无卡顿|
|
||||
|12性能!8 / 12.18|1000次升级失败率严格小于1/1000,完整记录每次尝试、耗时、失败及上线状态|少量冒烟或一次最终版本一致;不能因脚本异常丢弃失败尝试|
|
||||
|12性能!9 / 12.19|全部规定功能开启形成较高内存负载,1000次升级无变砖,负载与设备状态持续留证|无负载循环、12.18结果、最终一次在线|
|
||||
|13安全!11 / 13.10|受控篡改包被设备校验拒绝;记录篡改类型、摘要、拒绝原因及合法包对照|网络失败、工具缺依赖、超时或版本未变化;单个失败不能推导全部签名/大小/版本校验都满足|
|
||||
|13安全!12 / 13.11|规定的厂商通用固件因未授权被拒绝,结合匹配型号授权固件对照|不兼容型号包失败、网络中断或仅版本保持原值|
|
||||
|
||||
正向升级的 `verify-version` 只验证任务指定的固件字段,不能给以上9行整体判通过;V1 原生字段与 inner/outer 不自动映射。负向升级应按拒绝原因和恢复断言独立判定。17稳定性!11另有设备数、时序与循环矩阵,不能与12.18/12.19合并结果。
|
||||
|
||||
9.15-3单独按现网OVD-SDK版本选择包:1.42.0及以上使用SDK规定的 `firmware_encrypt` 包;1.41.0及以下不使用该工具生成包;首次对接1.42.0及以上也需规定陪测包。执行前核实具体SDK说明与双分区条件。
|
||||
|
||||
## 必须保留的安全与测量语义
|
||||
|
||||
- 13安全!10(13.9)的预期是**无本地web开放**。确认存在本地Web即不符合;有认证不改变此判定。只扫80/443、某地址不可达或过滤状态不足以证明无Web。
|
||||
- 13安全!5(13.3)要求**固件在设备中加密保存**。需要真实flash/分区存储证据与厂商实现材料;OTA包扫描只属辅助。缺专用证据记`inconclusive`,缺采集权限或镜像记`blocked`。
|
||||
- 13.18需设备日志/配置内容证据;13.15、13.17需受控授权/认证行为证据,不能由pcap单独判通过。
|
||||
- 9.136需原始编码流中I帧类型和相邻时间戳;VFR/AOV不能只用帧数除名义帧率;关键帧不直接等同全部I帧。
|
||||
- 11管理版!13执行端(PC还是APP)、!34主/子码流预期矛盾,以及20 DM测试!6的24/48小时冲突未澄清前不固化矛盾断言。
|
||||
- 保留重复编号与合并续行;9系统设置!83的 `9.10500000000001` 按源值保留,不自行改写源文件。
|
||||
|
||||
## 映射文件约定
|
||||
|
||||
`case_id` 使用稳定工作表序号与Excel行号;`source.sheet`、`source.row`、`source.original_id`保留来源。`required_tools_original`是前次分析中的依赖名称,`route_ids`是本参考文档的路由,不保证当前全部可执行。`suggested_method`与`remaining_dependencies`保持分析依据;`assertion_profile`标记不能套通用通过规则的条目。执行前仍需读取原行完整步骤、预期、设备适用性和量测阈值。
|
||||
|
||||
所有工具输出按来源独立归档;外部CLI/GUI/browser证据关联到同一个`case_id`,但不得伪造为Artemis原生截图、日志或报告内容。
|
||||
@@ -0,0 +1,80 @@
|
||||
# V1 搜索、查询与固件下发
|
||||
|
||||
本页摘记已实现接口;来源文件、修订及摘要见 [协议范围](protocol-support.md)。完整原文保留在资料提供方本地,分发包不附其他配置章节。实现在 `scripts/v1_protocol.py`,由适配器 `--protocol v1` 路由,不发送 V2 报文。
|
||||
|
||||
## 报文与端口
|
||||
|
||||
报文头共 8 字节:CMD、Length 各为网络字节序 U32,随后是恰好 Length 字节的 Data。长度按字节计算。只读 JSON 响应须为 UTF-8 对象;实现拒绝命令/长度不符、超过 1 MiB、错误类型及未完整接收的报文。
|
||||
|
||||
| 操作 | 传输 | 请求 | 返回 |
|
||||
| --- | --- | --- | --- |
|
||||
| 搜索 | 设备 UDP 4942,广播 | `0x5a0eff00`;JSON `{"session":1234}`,每次使用新的随机整数 | `0x5a0eff01`;同一整数 session,完整字符串 sn,以及 dev_type、ip、mac、firmware、hardware |
|
||||
| 基本/固件信息 | 设备 TCP 4941 | `0x5a0e2104`;Length=0,无 Data;十六进制请求 `5a0e210400000000` | 同命令 JSON;整数 code=0 成功,其他值失败 |
|
||||
| 固件升级 | 设备 TCP 4941 | `0x5a0e2170`;Data 为小写 ASCII MD5[32] + ROM,Length=32+ROM字节数 | 同命令、完整 JSON、整数 code=0;只确认协议应答,另行回读版本 |
|
||||
|
||||
TCP 查询处理报文分片,在连接/发送/接收阶段扣减同一时限,不自动重试。较新工厂文档建议查询 5 秒无响应超时,示例显式使用 `--timeout 5`。主机名解析及多地址尝试由系统 socket 负责,严格现场时限宜使用已确认的数字设备 IP。
|
||||
|
||||
广播接收绑定 `0.0.0.0:<client-port>`,默认 4942;请求从同一 socket 发到各选定 IPv4 网段的定向广播地址,目的端口 4942。默认枚举已启用物理网卡并排除回环/APIPA;可用 `--interface IPv4/PREFIX` 指定网段。相同网段只发一次,/31、/32 跳过。出接口服从 Windows 路由,特殊路由环境需现场核实。原文未规定客户端接收端口;默认 4942 是本机已验证的实现选择,`--client-port` 可调整,不能推广为所有固件的规范要求。
|
||||
|
||||
设备可能广播回复,因此接收 socket 不只绑定某个单播 IP。不启用端口复用、不结束占用进程;端口被占用时报告错误并释放本次 socket。忽略自身请求、错误 session/帧和非成功 code,精确筛选完整 SN/型号。按 SN、UDP 源 IP、MAC、型号去重;同 SN 出现冲突身份时阻断选择。后续连接使用实际 UDP 源 IP,报文中的 ip 只保留为观测。无响应只说明本轮未发现,不等于设备离线。
|
||||
|
||||
## 身份与版本字段
|
||||
|
||||
`2104` 保留文档字段 code、desc、sn、dev_type、firmware、hardware、dev_id、dev_ver。除整数 code 外均按字符串校验。如果设备额外直接上报 inner.version 或 outer.version 字符串,只保留该字面路径的版本值,供任务明确指定字段时观测;不保留其余未知字段。
|
||||
|
||||
| 字段 | 文档含义 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| sn | 设备 SN | 与本次完整 SN 精确比较,不截尾、不去空格 |
|
||||
| dev_type | 设备类型 | V1 `--expected-model` 唯一匹配字段 |
|
||||
| dev_id | 设备 ID | 只保留,不代替型号 |
|
||||
| firmware | 固件版本号 | 可由任务明确选择为原生固件验收字段 |
|
||||
| dev_ver | 设备版本号 | 可由任务明确选择,不推断与 V2 字段的关系 |
|
||||
| hardware | 硬件版本号 | 只观测,不作为固件验收 |
|
||||
|
||||
两份文档和 V1 查询源码没有 `firmware/dev_ver` 到 `inner.version/outer.version` 的对应关系。选择缺失的 outer.version 得到 `INCOMPLETE`,不会把 firmware 或 dev_ver 自动改名。如果设备直接上报所选字面路径,则可按该值比较。设备/文件名看起来可以猜出对应关系,也不能据此完成指定字段验收。
|
||||
|
||||
适配器用显式封套区分协议:
|
||||
|
||||
```json
|
||||
{"protocol":"v1","cmd":1510875396,"code":0,"data":{"code":0,"sn":"<完整SN>","dev_type":"<型号>","firmware":"<版本>"}}
|
||||
```
|
||||
|
||||
1510875396 是 `0x5a0e2104` 的十进制值。封套是适配器输出格式;线上 Data 是内部 JSON 本身。`verify-version --response` 接受此封套,或含 response 的完整 CLI 输出;不能使用 V2 30101 文件冒充 V1 响应。
|
||||
|
||||
## 调用示例
|
||||
|
||||
在技能目录执行,下列值均为占位符。型号未知时先 identify,只证明 SN 一致并观察型号,返回 model_verified=false;再带实测型号执行 info/预检。
|
||||
|
||||
```powershell
|
||||
python scripts/device_adapter.py discover --protocol v1 --interface "<本机IPv4/前缀>" --expected-sn "<完整SN>" --timeout 5
|
||||
python scripts/device_adapter.py identify --protocol v1 --host "<设备IP>" --expected-sn "<完整SN>" --timeout 5
|
||||
python scripts/device_adapter.py info --protocol v1 --host "<设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --timeout 5
|
||||
python scripts/device_adapter.py upgrade --protocol v1 --host "<数字设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --rom "<ROM路径>" --rom-sha256 "<64位SHA256>" --target-version "<目标版本>" --version-field firmware --timeout 5
|
||||
python scripts/device_adapter.py upgrade --protocol v1 --host "<数字设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --rom "<ROM路径>" --rom-sha256 "<审阅过的64位SHA256>" --target-version "<目标版本>" --version-field firmware --timeout 5 --execute
|
||||
python scripts/device_adapter.py verify-version --protocol v1 --host "<设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --target-version "<目标版本>" --version-field firmware --timeout 5
|
||||
```
|
||||
|
||||
只有任务明确选择 firmware 时才使用示例字段;已有其他验收条件时保持原条件。V1 upgrade 默认返回 `PREFLIGHT_ONLY`,preflight_complete=true、write_supported=true、write_executed=false;selected_version_field_available 说明指定字段是否存在。当前任务已授权升级时,带审阅摘要及 `--execute` 才执行一次下发;不重复请求已给出的授权。
|
||||
|
||||
## 升级报文与完成含义
|
||||
|
||||
用户提供的 Qt 源码 `EpConnection::sendTcpFile` 补齐了文档第 21 节的空白 Data,线格式为:
|
||||
|
||||
```text
|
||||
U32_BE 0x5a0e2170
|
||||
U32_BE (32 + ROM字节数)
|
||||
MD5_hex_ascii[32] # 全 ROM 的 MD5,小写十六进制文本;不是16字节原始摘要
|
||||
ROM[ROM字节数]
|
||||
```
|
||||
|
||||
总线上字节数为 ROM大小+40。没有 EPFP 前缀、文件名或自定义块头。源码使用约200 KiB块;TCP分块不改变线上字节序列,CLI采用256 KiB缓冲并处理部分send。不能把同一源码中的 `sendTcpFileV2(protocol=1)`(端口8940、EPFP/4001)混作此接口。
|
||||
|
||||
CLI 在完整 SN/dev_type 在线预检后重新验证 SHA-256。V1 发送器在同一个打开的文件上计算 MD5及SHA-256,核对大小/审阅摘要后才连接;回到文件开头发送,再对发送内容核对 SHA-256。Data长度必须适合 U32。总时限覆盖哈希、连接、发送、接收;各次 socket 操作还有连接/停滞时限。不会重连或自动重试传包,所有退出路径释放句柄。
|
||||
|
||||
收到完整 `2170` JSON 且整数 code=0、客户端实际发送 ROM 字节数等于文件大小,才返回 `PROTOCOL_SUCCESS_POSTCHECK_REQUIRED`。acknowledged=true 和 desc 只记录设备应答,不能证明烧录或启动完成。之后有界等待并重新查询同一 SN 的指定版本字段;发送/接收超时、断开或错误也应先只读检查状态,不能自动重刷。缺失验收字段不阻断已授权传包,但必须在最终验收中保留 `INCOMPLETE`。
|
||||
|
||||
## 验证范围
|
||||
|
||||
2026-10-19,全部118项离线测试通过,其中 V1 查询/发现24项、升级14项、适配器28项。V1 测试运行实际编解码及发送器,覆盖已知 MD5报文、分片发送/响应、计数、错误应答、文件变化、总/停滞时限、精确身份、摘要门槛、默认不写入及无自动重刷。
|
||||
|
||||
同日,在一台用户授权 V1 设备上完成一次19,420,244字节 ROM 下发,收到同命令code=0/desc=update success。随后连续两次只读查询与原 SN/dev_type 一致,原生 firmware 从2.0.1变为2.0.2、dev_ver 从2.0.20260908.5变为2.0.20260908.6。指定 outer.version 仍缺失,验收为 INCOMPLETE;不改用原生字段冒充指定字段通过。该实测不代表所有 V1 固件兼容,现场身份及日志独立保存。
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user