回滚:撤销‘优化开关与渐变的无缝衔接’修改
原因:该修改导致配网场景下的灯效渐变异常(持续闪烁)。 范围:还原 application/ws63/user_main/spotlight/spotlight_main.c 的相关改动;同时移除本次提交新增的 docs/ 与 logs/ 资源文件。 说明:仍保留上一笔‘修复灯光渐变与状态保持逻辑’提交,不影响‘未指定字段保持不变’与‘关灯态只更新目标不推进渐变’的修复。
@@ -254,20 +254,14 @@ static void *fade_task(const char *arg)
|
|||||||
fade_ctx.fade_completed = false;
|
fade_ctx.fade_completed = false;
|
||||||
|
|
||||||
if (fade_ctx.is_closing_fade) {
|
if (fade_ctx.is_closing_fade) {
|
||||||
// 若在收尾时已被“开灯”抢占,则跳过关断动作,避免“先黑一下”的突变
|
|
||||||
if (g_device_control.on) {
|
|
||||||
e_printf("[fade_task] Close-fade preempted by OPEN, skip turning off\r\n");
|
|
||||||
fade_ctx.is_closing_fade = false;
|
|
||||||
// 保持当前PWM与占空,后续由OPEN流程接管渐变
|
|
||||||
} else {
|
|
||||||
// 关灯渐变完成:不更新g_device_control.brightness_local,保持原有目标亮度
|
// 关灯渐变完成:不更新g_device_control.brightness_local,保持原有目标亮度
|
||||||
fade_ctx.is_closing_fade = false;
|
fade_ctx.is_closing_fade = false;
|
||||||
update_pwm_output(false, 0, 0);
|
update_pwm_output(false, 0, 0);
|
||||||
g_device_control.duty_cw = 0;
|
g_device_control.duty_cw = 0;
|
||||||
g_device_control.duty_ww = 0;
|
g_device_control.duty_ww = 0;
|
||||||
|
// 注意:这里不更新 g_device_control.brightness_local,保持之前的亮度值
|
||||||
e_printf("[fade_task] Close light fade completed, PWM turned off, brightness_local preserved: %d\r\n",
|
e_printf("[fade_task] Close light fade completed, PWM turned off, brightness_local preserved: %d\r\n",
|
||||||
g_device_control.brightness_local);
|
g_device_control.brightness_local);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 正常渐变完成:正常更新所有值
|
// 正常渐变完成:正常更新所有值
|
||||||
g_device_control.duty_ww = device_control.duty_ww;
|
g_device_control.duty_ww = device_control.duty_ww;
|
||||||
@@ -673,10 +667,10 @@ static void cancel_current_light_fade(void)
|
|||||||
// 竞态保护:先拉低标志再停计时器,避免回调自重启
|
// 竞态保护:先拉低标志再停计时器,避免回调自重启
|
||||||
fade_ctx.timer_active = false;
|
fade_ctx.timer_active = false;
|
||||||
uapi_timer_stop(fade_ctx.timer_handle);
|
uapi_timer_stop(fade_ctx.timer_handle);
|
||||||
// 标记为非渐变态,清除“关灯渐变”标记与完成态,避免旧渐变在回调里误触发收尾关断
|
// 如果我打断了渐变,则将当前值更新到目标值不然下次计算会异常
|
||||||
fade_ctx.is_fading = false;
|
// g_device_control.cct_local = fade_ctx.current_cct;
|
||||||
fade_ctx.is_closing_fade = false;
|
// g_device_control.brightness_local = fade_ctx.current_brightness;
|
||||||
fade_ctx.fade_completed = false;
|
// memset(&fade_ctx, 0, FADE_CTRL_DATA_SIZE(fade_ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算校验和
|
// 计算校验和
|
||||||
@@ -945,16 +939,12 @@ int set_light(light_ctrl_source_e source,
|
|||||||
int32_t brightness_local_target, int32_t cct_local_target)
|
int32_t brightness_local_target, int32_t cct_local_target)
|
||||||
{
|
{
|
||||||
bool was_on = g_device_control.on;
|
bool was_on = g_device_control.on;
|
||||||
// 记录调用前是否处于“关灯渐变中”,用于开灯时做无缝反向
|
|
||||||
bool was_closing_fade = (fade_ctx.is_fading && fade_ctx.is_closing_fade);
|
|
||||||
int32_t curr_brightness_before_cancel = fade_ctx.current_brightness;
|
|
||||||
int32_t curr_cct_before_cancel = fade_ctx.current_cct;
|
|
||||||
|
|
||||||
struct fade_ctx_t tmp_fade_ctx = {0};
|
struct fade_ctx_t tmp_fade_ctx = {0};
|
||||||
if (fade_ctx.is_fading) {
|
if (fade_ctx.is_fading) {
|
||||||
|
bool closing_fade_active = fade_ctx.is_closing_fade;
|
||||||
bool suppress_cancel = false;
|
bool suppress_cancel = false;
|
||||||
// 在关灯渐变过程中,属性/模式变更不应打断关灯过程
|
// 在关灯渐变过程中,属性/模式变更不应打断关灯过程
|
||||||
if (fade_ctx.is_closing_fade) {
|
if (closing_fade_active) {
|
||||||
if (source == APP_CHANGE_LIGHT_BRIGHTNESS_CCT || source == APP_CHANGE_LIGHT_MODE || source == APP_CLOSE_LIGHT) {
|
if (source == APP_CHANGE_LIGHT_BRIGHTNESS_CCT || source == APP_CHANGE_LIGHT_MODE || source == APP_CLOSE_LIGHT) {
|
||||||
suppress_cancel = true; // 允许继续关灯渐变;再次关灯请求可复用或稍后重启
|
suppress_cancel = true; // 允许继续关灯渐变;再次关灯请求可复用或稍后重启
|
||||||
}
|
}
|
||||||
@@ -968,21 +958,12 @@ int set_light(light_ctrl_source_e source,
|
|||||||
g_device_control.on = true;
|
g_device_control.on = true;
|
||||||
|
|
||||||
if (DEV_POWER_ON == source || (APP_OPEN_LIGHT == source && !was_on)) {
|
if (DEV_POWER_ON == source || (APP_OPEN_LIGHT == source && !was_on)) {
|
||||||
// 若之前处于关灯渐变中,被“开灯”打断,则沿用渐变中的即时亮度作为起点,实现无缝反向
|
// 开机或关灯→开灯:从0开始渐变
|
||||||
if (was_closing_fade) {
|
|
||||||
fade_ctx.current_brightness = curr_brightness_before_cancel;
|
|
||||||
fade_ctx.current_cct = g_device_control.cct_local; // 使用当前目标色温
|
|
||||||
fade_ctx.is_closing_fade = false;
|
|
||||||
e_printf("[set_light] 开灯打断关灯渐变: brightness=%d->%d, cct=%d\n",
|
|
||||||
fade_ctx.current_brightness, g_device_control.brightness_local, fade_ctx.current_cct);
|
|
||||||
} else {
|
|
||||||
// 真正的关→开或上电开灯:从0开始渐变
|
|
||||||
fade_ctx.current_brightness = 0;
|
fade_ctx.current_brightness = 0;
|
||||||
fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值
|
fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值
|
||||||
e_printf("[set_light] 开灯渐变设置: brightness=0->%d, cct=%d\n",
|
e_printf("[set_light] 开灯渐变设置: brightness=0->%d, cct=%d\n",
|
||||||
g_device_control.brightness_local, fade_ctx.current_cct);
|
g_device_control.brightness_local, fade_ctx.current_cct);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
brightness_local_target = g_device_control.brightness_local;
|
brightness_local_target = g_device_control.brightness_local;
|
||||||
// 色温不进行变化,只改变亮度
|
// 色温不进行变化,只改变亮度
|
||||||
|
|||||||
@@ -1,290 +0,0 @@
|
|||||||
# 调试模式(Wi‑Fi Console + HTTP OTA)需求与设计说明
|
|
||||||
|
|
||||||
- 文档版本:v1.1
|
|
||||||
- 更新时间:2025-10-26
|
|
||||||
- 适用机型/平台:WS63(LiteOS/Harmony 适配),本仓库版本 SR_Light_Hilink_14.2.1.312_20250714
|
|
||||||
- 文档目的:沉淀“仅 Wi‑Fi、按需开启”的远程 Debug 能力(TCP Console + HTTP OTA),在不影响现网业务下,实现快速问题定位与在线升级。本文给出明确的需求、行为规格、接口契约、资源预算、测试与风控。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 背景与目标
|
|
||||||
|
|
||||||
设备组装后无物理串口;现场需要远程获取日志与执行命令,并可在线推送固件进行升级。现有工程具备 SOC_LOG、DIAG、UPG 能力,本文在不改动业务使用打印宏与模块的前提下,定义一套“仅 Wi‑Fi、调试模式下启用”的远程调试与 OTA 方案。
|
|
||||||
|
|
||||||
目标:
|
|
||||||
- 纯 Wi‑Fi:仅用 TCP Console 与 HTTP OTA,不使用 BLE/USB/AP/mDNS。
|
|
||||||
- 调试模式准入:仅当扫描到 SSID=`EK_HF_DEBUG` 时进入;平时不暴露任何端口与广播。
|
|
||||||
- 类串口体验:双向交互(收发),支持历史日志回溯与实时回显。
|
|
||||||
- OTA 直装:写入并校验通过后立即安装(可重启)。
|
|
||||||
- 低侵入:常态仅维护内存日志环形缓冲;调试行为可在高负载期延后;禁止 AP 模式。
|
|
||||||
|
|
||||||
不做:
|
|
||||||
- 不开启 UDP syslog;不做 mDNS/DNS‑SD;不引入 HTTPS/TLS 与口令认证。
|
|
||||||
|
|
||||||
## 2. 术语与缩写
|
|
||||||
|
|
||||||
- Debug 模式:本文所述仅在现场触发后短时开放的“调试窗口”。
|
|
||||||
- TCP Console:类串口的 TCP 字节流服务。
|
|
||||||
- HTTP OTA:通过 HTTP 推送固件包分片并安装。
|
|
||||||
- Ring Buffer:内存日志环形缓冲,常态写入,调试时可读取。
|
|
||||||
|
|
||||||
## 3. 需求清单(用户决策映射)
|
|
||||||
|
|
||||||
1) 仅启用 TCP Console 与 HTTP OTA;UDP 日志不启用,且所有 Debug 功能只在 Debug 模式开启时可用。
|
|
||||||
2) 常态始终维护日志 Ring Buffer(仅内存,不外发),用于 Debug 时回溯。
|
|
||||||
3) 不做服务发现(mDNS/DNS‑SD)。
|
|
||||||
4) 唯一入口=扫描到 SSID `EK_HF_DEBUG`:
|
|
||||||
- 若设备当前“未连接任何 Wi‑Fi”(STA 未关联),则直接连接该热点(开放式,无密码),以确保与调试主机处于同一网段后进入 Debug 模式。
|
|
||||||
- 若设备已连接 Wi‑Fi,则不切换网络,仅把“扫描命中”视作触发信号而进入 Debug 模式,避免打断云业务。
|
|
||||||
- 禁止开启 AP 模式。
|
|
||||||
5) 不需要共享口令、不做 SSID 校验后缀,入口完全开放(按风险提示执行)。
|
|
||||||
6) 多设备场景:进入 Debug 模式后,设备以 UDP 广播帧周期发布自身识别信息(复用 HiLink 设备信息字段)以便工具端筛选目标设备。
|
|
||||||
7) Debug 窗口:若进入后的 5 分钟内“从未有主机连接”(Console 或 OTA 任一)则退出 Debug 模式并关闭端口与广播。
|
|
||||||
8) 端口由本方案指定(见 §6)。
|
|
||||||
9) 不启用 IP 白名单/黑名单。
|
|
||||||
10) 背景扫描允许在“高流量周期”暂停/延后。
|
|
||||||
|
|
||||||
## 4. 总体架构与模块
|
|
||||||
|
|
||||||
组件划分(逻辑):
|
|
||||||
- DebugManager(状态机)
|
|
||||||
- 维护状态 Closed/Debug、计时器、端口启停与广播调度。
|
|
||||||
- WifiScanner(被动扫描或等效)
|
|
||||||
- 周期扫描,命中 SSID 触发 Debug;在高负载时延后。
|
|
||||||
- TcpConsoleServer(2323/tcp)
|
|
||||||
- 行缓冲命令模式 + RAW 透传模式;与 DIAG 虚拟 shell 对接;镜像实时日志。
|
|
||||||
- HttpOtaServer(8070/tcp)
|
|
||||||
- `prepare`/`chunk`/`commit`/`status` 路由;调用 UPG uapi;commit 通过即安装。
|
|
||||||
- LogRingBuffer(内存环形,常态写入)
|
|
||||||
- 通过 DIAG 通道 TX hook 或用户打印注册接口镜像日志到环形缓冲;Debug 时提供 tail/dump 出口。
|
|
||||||
- UdpAnnouncer(37501/udp 广播,仅 Debug)
|
|
||||||
- 发布设备识别信息(did/model/sn/ip/fw 等)。
|
|
||||||
- LoadMonitor(高负载守门)
|
|
||||||
- 采样 CPU/LWIP 队列/吞吐量,给扫描与广播提供延后/降频依据。
|
|
||||||
|
|
||||||
## 5. 状态机与时序
|
|
||||||
|
|
||||||
状态:
|
|
||||||
- Closed(默认):
|
|
||||||
- TcpConsole/HttpOta/Announcer 均关闭;Ring Buffer 持续写入。
|
|
||||||
- WifiScanner 以固定周期被动扫描 SSID。
|
|
||||||
- Debug(触发进入):
|
|
||||||
- 立即开启 2323/tcp 与 8070/tcp,并启动 37501/udp 广播。
|
|
||||||
- 启动“5 分钟首联计时器”。若 5 分钟内从未有主机建立 Console 或 OTA 连接,则自动回到 Closed。
|
|
||||||
- 一旦出现首个连接,首联计时器停止;Debug 模式默认保持,直至手工 `debug off` 或设备重启(可选:实现“断开后闲置 5 分钟退出”的拓展策略,默认关闭)。
|
|
||||||
|
|
||||||
触发(唯一):
|
|
||||||
- WifiScanner 扫描结果出现 SSID = `EK_HF_DEBUG`:
|
|
||||||
- 若未联网:尝试连接该 SSID(无密码),DHCP 成功后进入 Debug。
|
|
||||||
- 若已联网:不切换,仅作为信号进入 Debug。
|
|
||||||
|
|
||||||
扫描策略:
|
|
||||||
- 周期:默认 120 s/次;优先采用被动扫描。目标是整个扫描总时长 ≤1.5 s;具体信道驻留时长受驱动能力限制,可按平台实际尽量控制。
|
|
||||||
- 高负载抑制:CPU>60% 或 LWIP 队列>80% 或近 10 s 吞吐>阈值 → 跳过本轮并记录;连续跳过 3 次后强制进行“快速扫描”(仅当前信道与相邻)。若无法直接获取上述指标,可退化为基于 I/O 速率与任务执行时长的启发式延后/降频。
|
|
||||||
|
|
||||||
## 6. 端口与协议
|
|
||||||
|
|
||||||
- TCP Console:`2323/tcp`
|
|
||||||
- 单连接优先。并发连接时:保持首个连接为“前台会话”,后续连接返回“忙碌”并断开。
|
|
||||||
- 编码:UTF‑8;行终止 CR/LF;单行上限 512 字节(可配)。
|
|
||||||
- 模式:默认命令模式;支持 `raw on/off` 切换透传模式(不解析 CR/LF)。
|
|
||||||
- 历史日志:提供 `log tail N` / `log dump S` 指令(见 §7)。
|
|
||||||
|
|
||||||
- HTTP OTA:`8070/tcp`
|
|
||||||
- `POST /ota/prepare` Content‑Type: application/json
|
|
||||||
- 入参:`{"length": <uint32>, "sha256": "<可选hex>"}`
|
|
||||||
- 行为:调用 `uapi_upg_prepare()`;返回 200/错误码。
|
|
||||||
- `PUT /ota/chunk?offset=<uint32>` Content‑Type: application/octet-stream
|
|
||||||
- 要求 4 字节对齐;`offset + len <= length`。
|
|
||||||
- 行为:`uapi_upg_write_package_sync(offset, buf, len)`;返回 200/错误码。
|
|
||||||
- `POST /ota/commit`
|
|
||||||
- 行为:`uapi_upg_verify_file()` → 成功则 `uapi_upg_request_upgrade(reset=true)` 立刻安装并重启;返回 200(可能随即断开)。
|
|
||||||
- `GET /ota/status`
|
|
||||||
- 返回:`{"status":"NONE|UPDATING|SUCC|FAIL", "progress":<0-100 可选>}`。
|
|
||||||
- `status` 源自 `uapi_upg_get_status()` 的聚合状态。
|
|
||||||
- 若编译开启并注册 `uapi_upg_register_progress_callback()`,则返回 `progress`;否则仅返回状态。
|
|
||||||
|
|
||||||
- 设备广播(仅 Debug):`37501/udp`(广播地址/子网广播)
|
|
||||||
- 间隔:进入 Debug 后前 10 秒每秒 1 次;之后每 30 秒 1 次,直至 Debug 结束。
|
|
||||||
- 载荷(JSON 示例):
|
|
||||||
```json
|
|
||||||
{"t":"ekhf.debug.presence.v1","pid":"<productId>","did":"<deviceId>","model":"<model>",
|
|
||||||
"sn":"<sn>","mac":"<xx:xx:xx:xx:xx:xx>","ip":"<a.b.c.d>","fw":"<version>",
|
|
||||||
"uptime":12345,"ports":{"console":2323,"ota":8070},"window_sec_left":270}
|
|
||||||
```
|
|
||||||
|
|
||||||
实现备注:
|
|
||||||
- Console/HTTP 服务需基于 lwIP socket/netconn 自行实现最小可用服务器(单连接 Console、最小路由 HTTP)。
|
|
||||||
- 端口共存与冲突:若系统中已启用如 `hfnet_start_assis(ASSIS_PORT)` 等服务,需确保与 2323/8070 端口不冲突;必要时在 Debug 模式启用时暂时关闭或改口。
|
|
||||||
|
|
||||||
## 7. 日志 Ring Buffer(常态写入,仅 Debug 可读)
|
|
||||||
|
|
||||||
- 源:通过 DIAG 通道 TX hook 或用户打印注册接口,对 `SOC_LOG` 与 `osal_printk/print_str` 输出进行镜像,写入环形缓冲(生产者无阻塞拷贝)。
|
|
||||||
- 容量:建议 128 KB(可调 128–512 KB)。
|
|
||||||
- 条目:时间戳(ms)、等级、模块、线程/CPU 与文本;按行存储,超过行长进行切分。
|
|
||||||
- 读取(Console 指令):
|
|
||||||
- `log tail <N>`:输出最近 N 行;
|
|
||||||
- `log dump <S>`:输出最近 S 秒内日志;
|
|
||||||
- `log level <ERR|WARN|INFO|DBG>`:调节“实时镜像到 Console”的等级(不影响 ring 的写入)。
|
|
||||||
- 限速:Console 推送上限 100 KB/s(可配)。
|
|
||||||
|
|
||||||
## 8. 资源与负载策略
|
|
||||||
|
|
||||||
- 扫描预算:≤1.5 s/120 s;高负载时延后;连续跳过 3 次后进行快速扫描。
|
|
||||||
- Console 与 OTA:非阻塞 socket;后台任务优先级低于业务任务;拥塞时降速/丢弃输出,不反压业务。
|
|
||||||
- 广播预算:仅 Debug 模式广播;高负载时自动将间隔提升至 60 s。
|
|
||||||
- 负载指标退化:若无法采集 CPU%/LWIP 队列等指标,允许使用基于 I/O 速率和任务运行时长的启发式降频/延后策略。
|
|
||||||
|
|
||||||
## 9. 安全与合规
|
|
||||||
|
|
||||||
- 入口完全开放(按照用户要求):
|
|
||||||
- 无密码 SSID;Console/HTTP 无鉴权;无 IP 白名单/黑名单。
|
|
||||||
- 风险:同网段任何人可在 Debug 窗口内接入;因此 Debug 模式仅在现场触发、短时使用,且 5 分钟内无人接入即退出。
|
|
||||||
- 数据:OTA 包整体仍由 UPG 在本地执行完整性校验(头/整包/镜像哈希与签名链,具体以现有 UPG 配置为准)。
|
|
||||||
|
|
||||||
## 10. 配置项(默认值)
|
|
||||||
|
|
||||||
| 项目 | 键名(建议) | 默认 |
|
|
||||||
|---|---|---|
|
|
||||||
| 扫描周期 | `DBG_SCAN_PERIOD_S` | 120 |
|
|
||||||
| 信道驻留 | `DBG_SCAN_DWELL_MS` | 100 |
|
|
||||||
| 高负载 CPU 阈值 | `DBG_CPU_BUSY_PCT` | 60 |
|
|
||||||
| 高负载 LWIP 队列阈值 | `DBG_LWIP_Q_BUSY_PCT` | 80 |
|
|
||||||
| Console 端口 | `DBG_CONSOLE_PORT` | 2323 |
|
|
||||||
| OTA 端口 | `DBG_OTA_PORT` | 8070 |
|
|
||||||
| 广播端口 | `DBG_BROADCAST_PORT` | 37501 |
|
|
||||||
| Ring 容量(KB) | `DBG_RING_KB` | 128 |
|
|
||||||
| Console 实时流上限(KB/s) | `DBG_CONSOLE_RATE_KBPS` | 100 |
|
|
||||||
| 首联超时(s) | `DBG_FIRST_CONN_TIMEOUT_S` | 300 |
|
|
||||||
|
|
||||||
> 注:以上均为实现时的可配置参数,本文档不强制其持久化方式(编译宏 / NV)。
|
|
||||||
|
|
||||||
## 11. 与现有代码的对接点(不改变业务调用)
|
|
||||||
|
|
||||||
0) 前置依赖与初始化:
|
|
||||||
- Kconfig:启用升级模块(`MIDDLEWARE_SUPPORT_UPDATE=y`)。
|
|
||||||
- 启动阶段调用 `ws63_upg_init()` 完成 `uapi_upg_init()` 初始化(见 `middleware/chips/ws63/update/common/upg_common_porting.c`)。
|
|
||||||
- Console/HTTP 服务需新增(基于 lwIP socket/netconn)。
|
|
||||||
|
|
||||||
1) Console 入站命令执行:
|
|
||||||
- 入口:`diag_debug_cmd_proc(uint8_t *data, uint32_t len)`
|
|
||||||
- 参考:`middleware/chips/ws63/dfx/dfx_system_init.c` 中 `cmd_shell_proc()` 用法。
|
|
||||||
|
|
||||||
2) 日志输出镜像与 Ring 写入:
|
|
||||||
- 通过 DIAG 通道 TX hook 做 tee:先走原 UART 输出,再写入 Ring Buffer;或使用平台暴露的用户打印注册入口实现镜像;
|
|
||||||
- 保持原 UART 输出不变,同时镜像一份至 Console 与 Ring Buffer。
|
|
||||||
|
|
||||||
3) OTA 调用序列(HTTP 路由对应):
|
|
||||||
- `prepare` → `uapi_upg_prepare(upg_prepare_info_t*)`;
|
|
||||||
- `chunk` → `uapi_upg_write_package_sync(offset, buf, len)`;
|
|
||||||
- `commit` → `uapi_upg_verify_file()` → `uapi_upg_request_upgrade(reset=true)`(立即安装与重启);
|
|
||||||
- `status` → `uapi_upg_get_status()`;
|
|
||||||
- 参考:`middleware/utils/update/storage/upg_storage.c`、`middleware/utils/update/common/upg_verify.c`、`middleware/utils/update/local_update/upg_process.c`。
|
|
||||||
|
|
||||||
4) Wifi 扫描/连接:
|
|
||||||
- 复用现有 Wi‑Fi 管理接口(参照 `application/samples/wifi/*` 示例)实现被动扫描(或等效)与条件连接;不得影响现有 STA 工作。
|
|
||||||
|
|
||||||
5) 端口共存:
|
|
||||||
- 若使用 `hfnet_start_assis(ASSIS_PORT)` 等调试服务,需在 Debug 模式启用时避免与 2323/8070 端口冲突(可在进入 Debug 时停止该服务或调整端口)。
|
|
||||||
|
|
||||||
## 12. 错误码与返回(建议)
|
|
||||||
|
|
||||||
Console:
|
|
||||||
- `BUSY`(已占用,拒绝并断开)
|
|
||||||
- `ERR_BAD_CMD` / `ERR_ARGS` / `ERR_TOO_LONG`
|
|
||||||
|
|
||||||
HTTP OTA:
|
|
||||||
- 400 `ERR_INVALID_ARGS`(length/offset/对齐错误)
|
|
||||||
- 409 `ERR_STATE`(未 prepare 先 chunk;重复 commit 等)
|
|
||||||
- 413 `ERR_TOO_LARGE`(包长超出 FOTA 区)
|
|
||||||
- 416 `ERR_RANGE`(offset 越界)
|
|
||||||
- 422 `ERR_VERIFY_FAILED`(校验失败)
|
|
||||||
- 500 `ERR_INTERNAL`
|
|
||||||
|
|
||||||
## 13. 典型交互示例
|
|
||||||
|
|
||||||
1) Console:
|
|
||||||
```
|
|
||||||
$ nc <dev-ip> 2323
|
|
||||||
> help\r\n
|
|
||||||
< ...(回显各命令)
|
|
||||||
> log tail 200\r\n
|
|
||||||
< 最近200行历史日志...
|
|
||||||
> raw on\r\n (进入透传)
|
|
||||||
```
|
|
||||||
|
|
||||||
2) OTA:
|
|
||||||
```
|
|
||||||
# 1) 准备
|
|
||||||
curl -sS -X POST http://<dev-ip>:8070/ota/prepare \
|
|
||||||
-H 'Content-Type: application/json' -d '{"length": 1048576}'
|
|
||||||
|
|
||||||
# 2) 分片写入(举例 4KB 步进)
|
|
||||||
offset=0; while read -r -d '' -n 4096 chunk; do \
|
|
||||||
curl -sS -X PUT "http://<dev-ip>:8070/ota/chunk?offset=${offset}" \
|
|
||||||
--data-binary @<(printf "%s" "$chunk"); \
|
|
||||||
offset=$((offset+4096)); done < <(dd if=fw.bin bs=4096 status=none)
|
|
||||||
|
|
||||||
# 3) 提交并安装(设备可能立即断开并重启)
|
|
||||||
curl -sS -X POST http://<dev-ip>:8070/ota/commit
|
|
||||||
```
|
|
||||||
|
|
||||||
3) 广播(工具侧监听):
|
|
||||||
```
|
|
||||||
tcpdump -n -vv -s0 udp port 37501
|
|
||||||
```
|
|
||||||
|
|
||||||
## 14. 测试计划(验收标准)
|
|
||||||
|
|
||||||
触发:
|
|
||||||
- 未联网→现场开启 `EK_HF_DEBUG` 热点:设备自动连接并进入 Debug;5 分钟内无连接则退出。
|
|
||||||
- 已联网→现场开启同名热点:设备不切换,仅进入 Debug;5 分钟内无连接则退出。
|
|
||||||
|
|
||||||
Console:
|
|
||||||
- 命令回显正常;`log tail 200`、`log dump 60` 正确输出;`raw on` 8KB 循环透传校验正确;并发第二连接被拒绝。
|
|
||||||
|
|
||||||
OTA:
|
|
||||||
- `prepare→chunk→commit` 正常;commit 后立即安装/重启;重启后版本信息与日志中可见升级结果;错误 offset/越界/校验失败分别返回 400/416/422。
|
|
||||||
- `GET /ota/status`:在未初始化/未 prepare/写入中/完成/失败各阶段返回符合 `NONE|UPDATING|SUCC|FAIL` 映射;启用进度回调时返回合理 `progress`。
|
|
||||||
|
|
||||||
稳定性:
|
|
||||||
- 高负载下扫描延后生效;广播间隔自动增大;Console/OTA 不阻塞业务(无明显时延抖动)。
|
|
||||||
|
|
||||||
端口与并发:
|
|
||||||
- 与 `ASSIS_PORT` 等服务共存/冲突验证;Console 并发连接第二路返回 `BUSY` 并断开。
|
|
||||||
|
|
||||||
限速:
|
|
||||||
- Console 实时推送限速 100KB/s 验证(长流量压测下不反压业务)。
|
|
||||||
|
|
||||||
回归:
|
|
||||||
- Debug 退出后端口与广播确实关闭;常态 Ring Buffer 持续工作且占用符合预算。
|
|
||||||
|
|
||||||
## 15. 风险与缓解
|
|
||||||
|
|
||||||
- 开放式入口风险:同网段内任意主机可接入 Debug。缓解:仅在现场触发;5 分钟无人连即退出;记录接入来源到 Ring;可后续加“口令开关”。
|
|
||||||
- 扫描扰动:被动扫描+高负载抑制;扫描时间受限;必要时频率可进一步降低。
|
|
||||||
- OTA 失败风险:UPG 既有校验链与回退策略(AB/整包/差分由现配置决定);失败保留当前运行分区。
|
|
||||||
|
|
||||||
## 16. 交付与实施建议(不改变业务逻辑)
|
|
||||||
|
|
||||||
开发任务拆解(建议):
|
|
||||||
1) DebugManager/LoadMonitor/状态机与计时器骨架。
|
|
||||||
2) WifiScanner:被动扫描与条件连接;高负载抑制策略。
|
|
||||||
3) TcpConsoleServer(需新增):基于 lwIP 单连接、行缓冲/RAW 模式、命令桥接、实时日志镜像、历史日志指令。
|
|
||||||
4) HttpOtaServer(需新增):最小路由 `/ota/prepare|chunk|commit|status` 与 UPG uapi 串接、错误码与进度上报。
|
|
||||||
5) LogRingBuffer:通过 DIAG TX hook/用户打印注册入口做日志 tee;读口;限速。
|
|
||||||
6) UdpAnnouncer:JSON 载荷、节流与停止逻辑。
|
|
||||||
7) 集成与测试:按 §14 验收标准逐项打勾。
|
|
||||||
|
|
||||||
端口冲突处理:
|
|
||||||
- 若存在既有调试/辅助服务占用端口,进入 Debug 模式时进行协调(停服或改口),退出时恢复。
|
|
||||||
|
|
||||||
## 17. 变更记录
|
|
||||||
|
|
||||||
- 2025-10-26:v1.1 调整为可落地实现版本:
|
|
||||||
- 明确 Console/HTTP 需基于 lwIP 实现;新增端口冲突与共存说明。
|
|
||||||
- 日志镜像改为 DIAG TX hook/用户打印注册入口;Ring 默认容量建议为 128KB。
|
|
||||||
- `GET /ota/status` 状态与进度对齐 `uapi_upg_get_status` 与进度回调。
|
|
||||||
- 扫描策略放宽为目标约束,并提供负载指标不可用时的启发式退化方案。
|
|
||||||
- 2025-10-26:初版(按“纯 Wi‑Fi + SSID 触发 + 无认证 + 5 分钟首联退出 + 无 AP/mDNS/UDP syslog”的决策输出)。
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 94 KiB |
BIN
logs/screen.png
|
Before Width: | Height: | Size: 99 KiB |
BIN
logs/screen2.png
|
Before Width: | Height: | Size: 101 KiB |
BIN
logs/tap1.png
|
Before Width: | Height: | Size: 65 KiB |
BIN
logs/tap2.png
|
Before Width: | Height: | Size: 65 KiB |
BIN
logs/tap3.png
|
Before Width: | Height: | Size: 65 KiB |