背景
#127 / PR #170 已实现并测试 ImActionChannel、EspActionStreamTransport、时间窗口、幂等与重连语义,但这些组件尚未进入生产运行时:当前没有生产 NotificationIntent 调用方,voicelife_runtime 未装配 IM 组件,esp32s3-dev 的 im 仍为 disabled。
本 Issue 负责把已有设备侧动作通道接入真实运行时,不重新设计 Gateway 或跨入口动作状态模型。
目标
形成并在真机上验证以下生产调用链:
TimingTask 已提交的到点通知事件
→ NotificationIntent 映射与 SubmitNotification
→ NotificationSubmission.actionStream
→ ExtractActionWindow
→ ImActionChannel::Run
→ TimingTask 动作执行
→ ReminderActionResult HTTPS 回传
前置条件
范围
1. Runtime 生产装配
2. 通知事件来源
3. 设备凭据
本 Issue 必须落地至少一条可用于真机验收的安全注入路径;完整的设备注册、批量烧录、轮换后台不在本期范围。
4. 网络与 TLS
5. 动作执行与 Profile
非目标
TDD 计划
RED:
GREEN:
REFACTOR:
验收
自动验证
真机与独立 Gateway 验收
Given:
ESP32-S3 使用启用 IM 的有效设备 Profile;
设备凭据通过本 Issue 定义的安全路径注入,并已在 Gateway 注册;
Wi-Fi、DNS、系统时间与 TLS 信任链正常;
[IM] Gateway 服务进程装配与可部署性 #152 Gateway 通过固定 HTTPS 地址运行,公众号测试账号已绑定。
When:
真机 TimingTask 产生并提交一个强提醒到点事件;
Runtime 提交 NotificationIntent,Gateway 完成一次真实公众号投递;
用户在 H5 选择“推迟 10 分钟”;
SSE 在动作有效期内主动断开一次,然后恢复;
设备执行命令并回传结果。
Then:
风险与回退
TLS、网络或凭据异常时 IM Adapter fail closed,本地提醒继续运行;
Profile 可把 im 切回 disabled;
Gateway 故障只影响远端投递与动作闭环,不得修改或回滚设备本地事实;
未确认命令在窗口结束后自然到期,不通过人工改库恢复。
Refs #95 , #127 , #152 , #170 , #214
背景
#127 / PR #170 已实现并测试
ImActionChannel、EspActionStreamTransport、时间窗口、幂等与重连语义,但这些组件尚未进入生产运行时:当前没有生产NotificationIntent调用方,voicelife_runtime未装配 IM 组件,esp32s3-dev的im仍为disabled。本 Issue 负责把已有设备侧动作通道接入真实运行时,不重新设计 Gateway 或跨入口动作状态模型。
目标
形成并在真机上验证以下生产调用链:
前置条件
范围
1. Runtime 生产装配
voicelife_runtime的生产组合根中装配 IM 运行时依赖,而不是在测试或示例入口旁路启动;EspActionStreamTransport、EspHttpTransport、EspClock、设备凭据 Provider 与 TimingTask-backed Action Executor;main/Runtime 不引用 fake、mock 或测试 fixture;im=disabled仍是可用回退路径,禁用后本地日程与语音提醒不受影响。2. 通知事件来源
NotificationIntent唯一触发源,不使用启动时合成事件、mock scenario 或轮询数据库拼装事实;NotificationIntent的 Mapper/Adapter,保留eventId、correlationId、deviceId、reminderTriggerId、提醒强度和发生时间;eventId,不得造成重复 Gateway Delivery;actionStream,Runtime 也不得建立 SSE;actionStream时调用ExtractActionWindow与Run。3. 设备凭据
ImCredentialProvider,提供与设备身份一致的deviceId和设备 Token;本 Issue 必须落地至少一条可用于真机验收的安全注入路径;完整的设备注册、批量烧录、轮换后台不在本期范围。
4. 网络与 TLS
https://origin,通知提交、SSE 和结果回传不得降级为明文 HTTP;skip verify、接受任意证书或把临时自签名例外带入生产 Profile;Last-Event-ID恢复,但Last-Event-ID不替代ReminderActionResult;correlationId追踪通知提交、SSE 命令、执行结果和重连,且不记录 Authorization、Action token 或完整敏感 URL。5. 动作执行与 Profile
ImActionExecutor到 TimingTask Application Port 的映射;deviceId、reminderTriggerId、命令有效期和动作参数;operationId在重放、重连和设备任务重启场景下保持幂等;ReminderActionResult,未回传成功的结果可安全重试;esp32s3-devProfile 的 IM Adapter,并为 Gateway origin、凭据引用和 TLS 信任配置提供可检查的 Profile 校验;非目标
TDD 计划
RED:
SubmitNotification;operationId被执行两次。GREEN:
REFACTOR:
验收
自动验证
voicelife_runtime实际引用并启动 IM Adapter,而非只验证组件可编译;operationId幂等与 Result 重试;python3 scripts/firmware.py build esp32s3-dev通过;./scripts/run_checks.sh通过;真机与独立 Gateway 验收
Given:
When:
NotificationIntent,Gateway 完成一次真实公众号投递;Then:
operationId本地只执行一次;nextTriggerAt;ReminderActionResult后关闭当前动作流;correlationId串联 TimingTask 事件、通知提交、Delivery、Action、SSE 与 Result;风险与回退
im切回disabled;Refs #95, #127, #152, #170, #214