203 lines
15 KiB
Markdown
Executable File
203 lines
15 KiB
Markdown
Executable File
# Web Console
|
||
|
||
## 宠物卡片与 NFC 上报
|
||
|
||
主页“宠物卡片”区域支持创建多张宠物卡片。`pet_name` 与 `action` 可在卡片中编辑,
|
||
`nfc_id` 为只读字段,只能在“NFC 设备授权”弹窗中使用读卡器当前识别到的实体 NFC
|
||
完成绑定,不能由浏览器或 API 请求直接填写。同一个 NFC UID 最多绑定一张宠物卡片;重新
|
||
绑定时会自动解除旧卡片上的相同 UID。新卡片必须先完成编辑并点击保存,之后才能从
|
||
“NFC 设备绑定”或“关联卡片”入口继续绑定;右侧卡片区域不再直接触发 NFC 绑定。
|
||
|
||
卡片由后端持久化到 `artifacts/server/pet_cards.sqlite3`,网页关闭或服务重启不会丢失。
|
||
同源接口如下:
|
||
|
||
- `GET /api/extension/pets`:读取卡片及发布器状态。
|
||
- `POST /api/extension/pets`:创建卡片,只接受 `pet_name`、`action`。
|
||
- `PUT /api/extension/pets/{pet_id}`:修改宠物名和动作。
|
||
- `DELETE /api/extension/pets/{pet_id}`:删除卡片。
|
||
- `POST /api/extension/pets/{pet_id}/bind-current-nfc`:绑定读卡器中当前在场的 NFC。
|
||
- `POST /api/extension/pets/{pet_id}/unbind`:解除绑定。
|
||
|
||
服务端首次检测到已绑定 NFC 进入读卡区时,后台线程复用当前车辆 MQTT Broker 连接,
|
||
在 1 秒内向固定话题 `n7/pet` 发布 3 帧非保留消息,随后保持静默。只有将 NFC 移出读卡区
|
||
后再次靠近,才会触发下一组 3 帧。消息只包含以下三个字段:
|
||
|
||
```json
|
||
{"pet_name":"团团","nfc_id":"E113B203","action":"摇尾巴"}
|
||
```
|
||
|
||
发布行为独立于网页是否打开。若本次 3 帧中存在 Broker 发布失败,卡片与绑定关系仍会
|
||
保存,前端会显示本次突发发送失败;为避免持续发送,服务不会在 NFC 一直停留时无限重试,
|
||
移开并重新靠近后才会发起下一组 3 帧。
|
||
|
||
Web 控制台是车机端的远程自编排与同步显示界面。网页保留一句话指令和预设功能模式入口,请求通过同源服务发送至车机执行;同时同步显示车机任务、编排结果、设备反馈和 USB 扩展能力。真实 CAN 与硬件执行权限仍由服务端安全门禁控制。
|
||
|
||
当前页面包括:
|
||
|
||
- 自编排和自扩展合并为一个实时界面,登录身份固定为 `user`,不再提供模块切换。
|
||
- AI助手默认展开;左侧控制台、车端设备状态、外设与扩展能力默认收起。四个板块统一通过页面右上角的图标按钮展开或收回,主工作区随面板状态自适应。
|
||
- AI助手支持普通问答、工程能力核对和车控工作。能力问答读取运行时权威目录,高置信度冷热请求走确定性快速控制链,其他问题和复杂车控由 Codex App Server 流式处理;车控结果仍以自然语言和可审计的动作进度呈现。
|
||
- 网页端可输入一句话指令或点击预设模式,车机端同样可发起任务;两端任务与结果统一同步。
|
||
- AI助手语音入口支持双模式:手动点击麦克风按钮会立即以 `manual` 模式录音,不要求唤醒词;浏览器已授权麦克风、助手展开且页面可见时自动进入 `wake` 待机,只有听到“你好,小迪”(兼容无标点与字间停顿)后才展示并继续转录。AudioWorklet 采集后,服务端 SenseVoiceSmall 以节流预览返回未语义清洗的实时文字;静音端点立即停止采音,再由 Silero VAD、幂等 TranscriptAssembler 和理解层生成最终 `assistant_text`。普通问答、未知能力、否定和撤销表达均可回填,`commands` 仅作为受信任车控旁路,不能反向过滤助手输入。
|
||
- 整车数字孪生位于工作区中央,点击或悬停热点可查看车窗、遮阳帘、主/副驾座椅、阅读灯、氛围灯、前大灯和空调的完整状态。
|
||
- 车端设备状态与外设能力板块均可独立隐藏或恢复,面板状态在当前浏览器会话中保留。
|
||
- USB 外设接入后同步显示 GSCU 链路、外设名称、类型、已学习能力和最近一次跨设备联动。
|
||
- 左侧运行日志集中显示网页/车机任务、链路、设备与外设同步事件。
|
||
|
||
UI 只展示可审计的“决策摘要”和“处理轨迹”,不展示模型私有思维过程。
|
||
|
||
## AI助手接口
|
||
|
||
浏览器只使用同源接口,不直接连接 App Server、MCP 或模型服务:
|
||
|
||
- `GET /api/assistant/status`:返回 App Server 状态、可用性和当前会话数。
|
||
- `GET /api/assistant/capabilities`:返回由运行时注册表、模式目录、CAN 绑定和已学习外设共同生成的权威能力快照。`service_surfaces` 只提供语音、手势、NFC、自标定和自修复的状态信息,不代表助手可调用;执行资格以 `assistant_callable` 和服务端校验为准。
|
||
- `POST /api/assistant/stream`:提交 `message`、`conversation_id`、执行模式和当前车型等上下文,返回 `application/x-ndjson`。前端消费 `message.accepted`、`work.*`、`action.*`、`answer.delta`、`control.suggestions`、`answer.completed` 与 `error` 事件,以增量方式展示回复和控制进度。不支持的车控请求可随 `control.suggestions` 返回当前车型可执行的替代指令;前端去重后渲染为按钮卡片,点击会作为新指令沿同一受控链路提交。
|
||
|
||
`POST /api/internal/codex/vehicle-control` 是 App Server MCP 子进程专用的回环接口,要求一次性内部令牌且与原始用户文本绑定,不是浏览器或第三方集成接口。浏览器也不能通过响应内容扩大执行目标、切换执行模式或提交原始 CAN。
|
||
|
||
当前座椅阶段一控制台为无构建静态页面,由 `cognitive_agent.server` 同源提供 API 和资源。运行:
|
||
|
||
```bash
|
||
make dev
|
||
```
|
||
|
||
语音听写首次运行前安装运行时、官方完整精度模型和 Silero VAD:
|
||
|
||
```bash
|
||
python -m pip install -e ".[speech]"
|
||
python tools/install_sensevoice_model.py
|
||
```
|
||
|
||
录音只用于当前请求,不落盘;`captured_text` 保留完整声学结果,`raw_text` 在 `manual` 模式保留完整原文、在 `wake` 模式剥离唤醒词,`assistant_text` 是面向问答的轻清洗会话,`clean_text/control_text` 与结构化 Intent 则保持严格车控语义。前后端通过 `X-Speech-Input-Mode: manual|wake` 显式区分模式;可用 `SPEECH_WAKE_WORD_ENABLED=false` 关闭唤醒门,或用竖线分隔的 `SPEECH_WAKE_WORDS` 配置主唤醒词与别名。远程浏览器必须通过 HTTPS 才能访问麦克风。诊断可设置后端 `SPEECH_DEBUG=1` 并用 `?speechDebug=1` 打开前端日志,默认关闭。
|
||
|
||
Android PAD/模拟器联调使用:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tools\android_pad_dev.ps1
|
||
```
|
||
|
||
脚本会启动已配置的 Pixel Tablet AVD、建立 `adb reverse tcp:8000 tcp:8000`、
|
||
以真实硬件关闭/模拟台架开启的方式启动服务,并在 Android Chrome 中打开
|
||
`http://127.0.0.1:8000`。停止联调环境:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File .\tools\android_pad_dev.ps1 -Stop
|
||
```
|
||
|
||
局域网演示使用:
|
||
|
||
```bash
|
||
make dev-lan
|
||
```
|
||
|
||
其他设备访问启动日志打印的 `http://<LAN-IP>:8000`。页面与后端 API 由同一服务提供,无需单独配置前端地址。
|
||
|
||
自扩展接口统一位于 `/api/extension/*`。红外模块默认使用已验证的 GSCU1B TCP
|
||
模式:Linux 端在 `0.0.0.0:4444` 监听,GSCU1B 作为 TCP Client 主动接入。
|
||
“外设与扩展能力”中的“TCP 设置”可修改监听 IP、端口并立即重启监听,配置持久化到
|
||
`artifacts/tmp/gscu_gateway.json`;同一弹窗可执行查询、学习、取消、发射、读取、
|
||
写入、软重启、WiFi 配网锁、擦除、恢复出厂和原始 JSON 调试动作。模块配置的
|
||
服务器地址必须填写 Linux 的实际局域网 IP,不能填写 `0.0.0.0`。
|
||
|
||
TCP 发射、取消、写入和设置类动作在操作系统确认写入连接后立即返回“已下发”,
|
||
不会因设备不回 ACK 而阻塞前端。固件 1.1.5 的学习动作同样不主动返回 ACK,因此
|
||
前端在学习命令下发后自动读取目标槽位,以实际 `ir_data` 回读确认学习完成;设备查询
|
||
和读取槽位仍等待带 `messageId` 的实际回执。
|
||
学习时可为每个 `1–248` 红外槽位填写信号名称;槽位与名称持久化在本机
|
||
`artifacts/server/gscu_ir_catalog.sqlite3` 数据库中,并在 TCP 动作调试区按槽位号
|
||
升序显示为小卡片。浏览器中已有的旧名称会自动迁移到数据库。单卡片删除操作只删除
|
||
本地目录记录,不会擦除设备红外码;已验证的设备协议仅支持全部擦除。全部擦除会先
|
||
弹出不可恢复确认,设备命令提交成功后才同步清空本地槽位数据库。
|
||
|
||
如需回退 MQTT,可设置 `GSCU_TRANSPORT=mqtt`,通过 `GSCU_MQTT_*`、
|
||
`GSCU_COMMAND_TOPIC` 和 `GSCU_RESPONSE_TOPIC` 指定 Broker 与话题;通过
|
||
`GSCU_TRANSPORT=simulation` 使用演示学习器。MQTT 依赖已包含在核心环境中;
|
||
NFC 串口依赖通过 `ir` 可选依赖安装。自扩展不再需要独立的 `8010` 前端服务。
|
||
|
||
## NFC 玩具识别与红外学习
|
||
|
||
统一页面的“外设与扩展能力”区域提供“感应玩具 NFC”入口。点击后将玩具上的
|
||
NFC 卡片靠近 PCR532/PN532(CH340/CH341 串口)读卡器:新卡可建立或绑定
|
||
玩具档案,并立即进入现有 GSCU1B 红外学习流程;已绑定卡片会自动识别玩具,
|
||
展示全部已学习/待学习动作,并可直接发射已验证动作。
|
||
|
||
安装串口支持并启动:
|
||
|
||
```bash
|
||
python -m pip install -e ".[ir]"
|
||
make dev
|
||
```
|
||
|
||
服务会优先复用本机 `ir-toy-learning` 的 MQTT NFC 桥(默认
|
||
`127.0.0.1:1883`),避免两个进程同时抢占同一个 `COM` 口;桥不可用时再自动选择
|
||
唯一的 CH340/CH341、PN532 或 PCR532 串口。可通过 `NFC_PORT=COM5` 指定串口,
|
||
或用 `NFC_MQTT_HOST`、`NFC_MQTT_PORT` 调整桥地址;`NFC_MQTT_DISABLED=true`
|
||
强制只使用串口,`NFC_DISABLED=true` 可完全禁用读卡线程。
|
||
|
||
首次加载时页面会从 `http://localhost:3001/n7web-profile-bridge.html` 安全迁移旧
|
||
`ir-toy-learning` 浏览器档案,保留工牌 UID、玩具编号、动作名称和 GSCU1B 槽位。
|
||
不同浏览器运行时,旧工作台会把不含红外原始波形的档案元数据同步到本机 MQTT
|
||
保留主题 `toy/ir/profiles`,当前服务同样会自动导入。迁移按档案与槽位幂等合并,
|
||
不会覆盖当前工程中已经建立的能力。NFC UID 与玩具档案的绑定保存在当前浏览器,
|
||
红外波形仍保存在 GSCU1B 的 1–248 号物理槽位。
|
||
|
||
TCP 模式下本服务是服务器,GSCU1B 是客户端:设备配网页中的“TCP服务器”
|
||
必须填写运行本服务的主机地址,“TCP端口”必须与 `GSCU_TCP_PORT` 一致。
|
||
如需绑定指定网卡地址,可设置 `GSCU_TCP_LISTEN_HOST`;网卡晚于服务就绪或
|
||
端口被短暂占用时,监听器会按 `GSCU_TCP_BIND_RETRY_SECONDS`(默认 1 秒)
|
||
自动重试。`/api/extension/health` 的 `listening` 表示服务器已监听,只有收到
|
||
真实设备会话后 `connected`/`peer_connected` 才会变为 `true`。
|
||
|
||
车机与网页同步使用以下同源接口:
|
||
|
||
- `GET /api/vehicle-display-sync`:网页轮询最新车机任务、结果、外设目录与扩展链路状态。
|
||
- `POST /api/requests`:车机执行时附带 `client_type: "head_unit"`;网页控制台附带 `client_type: "web_console"`。两类任务的执行结果都会写入同步快照。
|
||
- `POST /api/extension/display-sync`:车机刚识别 USB 外设时上报 `device` 与 `peripherals` 能力目录,无需等待首次执行。
|
||
- `POST /api/extension/assistant/plan` 和 `/api/extension/vehicle/execute`:联动规划与车端执行结果同样写入同步快照。
|
||
|
||
右上角“能耗监测”入口以独立固定页面展示 7 个当前可控车端设备的实时功率、
|
||
本次监测累计能耗、总功率趋势和分设备趋势。能耗链路优先接收
|
||
`cognitive-agent:power-telemetry` 事件,也兼容调用
|
||
`window.updateDevicePowerTelemetry(payload)` 的现有集成方式;载荷可使用
|
||
`devices.<device>.power_w` 或 `total_power_w`,并可附带 `energy_wh`、
|
||
`trip_energy_kwh` 或 `today_energy_kwh`。累计能耗独立保留,瞬时功率超过 15 秒
|
||
未更新时只会回退到状态估算,不会让已上报的车端累计值消失。每条遥测应显式提供
|
||
`source: "vehicle_power_sensor"`(实测)或 `source: "estimated"`(估算)。
|
||
当前 CAN 状态协议没有独立电流/
|
||
功率电表信号,因此未注入新鲜功率数据的设备会显示带 `≈` 和“状态估算”标签的
|
||
确定性实时估算,绝不标记为车端实测。真实功率通道接入后页面会逐设备自动切换为
|
||
“实测”,无需更换页面或曲线实现。
|
||
|
||
公网入口由后端统一认证,前端不保存密码或 API Key。未认证访问自动进入
|
||
`/login`,主控制台提供退出按钮。固定入口是
|
||
`https://511.kendeji.fun`,应用容器只监听服务器回环地址,再由 Caddy 提供
|
||
HTTPS。部署方式见
|
||
[`deploy/server/README.md`](../../deploy/server/README.md)。
|
||
|
||
页面支持 GPT/本地解析切换、六阶段流水线、主副驾热舒适、五轴位置状态和 3D 座椅孪生、GPT 结构化能力请求、决策与校验轨迹、FunctionConfig、CommandPlan、虚拟帧和 ExecutionReport。真实硬件执行由服务端门禁控制,不是仅靠前端按钮限制;Android 联调脚本会显式关闭真实硬件执行。
|
||
|
||
## 手势资源与安全规则
|
||
|
||
手势模型随当前工程交付,默认位置为:
|
||
|
||
```text
|
||
assets/gesture/gesture_recognizer.task
|
||
../../config/gesture/default.yaml
|
||
```
|
||
|
||
后端提供 `/api/gesture/runtime` 和 `/api/gesture/model`,前端以二进制缓冲区加载模型,避免依赖外部 `seat_gesture_control` 目录。MediaPipe Web、Lucide 和 Three.js 均按固定版本保存在 `vendor/`,运行时不访问外部 CDN;摄像头帧和手部关键点只在当前浏览器中处理。
|
||
|
||
## PAD、PWA 与离线行为
|
||
|
||
- 竖屏 PAD 在 900 CSS px 以下切换为上下布局,横屏保留指令栏与结果区;触控目标最小 48 dp,并处理安全区和动态视口。
|
||
- 顶部连接徽标由 `/api/health` 周期探测驱动;GET 可有限重试,POST 控制请求不自动重试。
|
||
- Service Worker 缓存页面壳、固定版本依赖和按需访问的 3D/手势资源;`/api/requests` 等控制 API 始终走网络且不会写入缓存。
|
||
- 从 Android Chrome 的“安装应用”可进入 standalone PWA;首次完整在线加载后可离线打开控制台壳,实际编排仍要求 Windows 服务可达。
|
||
|
||
模拟台架需要 `COGNITIVE_AGENT_SIMULATED_HARDWARE_ENABLED=true`。选择“模拟台架”后可注入反馈超时、适配器断开、电机堵转、固件不匹配和部分反馈。结果会标记 `simulation=true`、`seat_feedback=simulated_hardware` 和 `physical_can_opened=false`,不会调用真实 CAN、ZLG 或 IAR。
|
||
|
||
安全规则:张掌保持 1 秒激活;动作保持 600 ms 且至少连续 8 帧才执行;换动作不重新锁止;握拳立即停止但不解除激活;3 秒无有效动作自动锁止;单次连续运动最多 1.5 秒;检测到多只手时不执行。自定义映射保存在浏览器 `localStorage`。
|
||
|
||
摄像头仅能在安全来源使用:本机访问 `http://127.0.0.1:8000`,远程访问必须使用 HTTPS。关闭抽屉、页面隐藏或离开页面时会立即停止摄像头轨道。
|