Skip to content

Latest commit

 

History

History
195 lines (152 loc) · 22.4 KB

AGENTS.md

File metadata and controls

195 lines (152 loc) · 22.4 KB

FastBee-Arduino 项目协作说明

本文件供在本仓库工作的 AI 编程助手使用,也供维护者审核和调整协作约定。适用于仓库根目录及子目录;子目录如有更具体的 AGENTS.md,在该目录范围内遵循其补充要求。用户当前任务中的明确要求优先于本文的默认约定。

工作约定

  • 默认使用简体中文沟通,代码标识符、命令和日志字段保持原文。
  • 开始修改前检查 git status --short,按任务需要阅读相关源码、配置、测试和文档;不要把历史报告当作当前工作区的验证结果。
  • 保留已有未提交修改和其他任务的工作,只修改本次任务相关文件。不要擅自执行 git reset --hard、git checkout --、git clean 或批量清理证据目录。
  • 不要过度优化项目内容。围绕当前需求和已确认的问题做必要修改,优先复用现有实现;避免没有明确收益的重构、抽象、依赖引入及无关优化。
  • 保持项目简洁,不生成无用或重复的文件。优先更新已有文件;本次会话创建且不属于交付内容、也无需保留为验证证据的临时文件,必须在会话结束前删除。清理仅限本次创建且确认不再需要的文件,保留用户文件、其他任务成果、必要的测试及历史验证证据。
  • 项目相关的文件生成(隔离构建目录、工作区快照、临时脚本、草稿和中间产物等)统一放在仓库根目录下,通过 .gitignore 配置过滤不提交;不得在 C:\、D:\ 等仓库外路径散落创建(历史反例如 C:\p11、C:\px-rgb20、D:\project\fastbee-*,已于 2026-10-15 清理)。隔离构建目录和工作区快照以 fastbee- 开头命名,临时产物放入已忽略的 tmp/。
  • “只评估”“只诊断”“审核”按只读任务处理;“修改”“实现”“完善测试”则完成相应实现和验证。已明确授权的常规步骤继续执行,遇到目标设备不明、改动冲突或需要扩大范围时再说明具体阻塞。
  • 用户要求继续完成某份计划时,以该计划及其当前实施记录为工作清单,逐项落实并更新证据;不要只输出方案,也不要把存在实物依赖的项目标成全部完成。
  • 未要求提交或发布时,将结果保留为可审核的本地改动。

项目定位与目录

FastBee-Arduino 是面向 ESP32 系列的零代码 Web 物联网固件,通过“外设配置”定义并初始化硬件资源,通过“外设执行”配置触发器、条件、动作及联动规则,通过 MQTT/MQTTS 与物联网平台通信,通过 Modbus RTU 主站接入现场设备。

固件使用 C++、Arduino 框架和 PlatformIO;Node.js 用于 Web 资源构建及主机测试,不是设备运行时。芯片、Flash、PSRAM、分区和功能裁剪以 platformio.ini 及对应板卡配置为准。

路径 职责与修改入口
src/、include/ 固件实现及对应头文件,按同名模块组织(core、network、peripherals、protocols、screen、security、systems、utils)
src/core/ 框架、外设管理、执行调度、规则和电机控制服务
src/network/、src/network/handlers/ 网络适配、Web 服务和 API 路由
src/protocols/、src/peripherals/ MQTT、Modbus RTU 及外设驱动
src/screen/、src/security/、src/systems/、src/utils/ 屏幕交互、认证、配置存储、日志、健康管理和通用工具
web-src/ HTML、JavaScript、CSS、页面模块和中英文文案源码
data/config/ LittleFS 默认配置,不代表在线设备当前配置
data/www/ 自动生成的 Web 发布资源;源资产例外见下文
partitions/、platformio.ini 分区布局、依赖、构建环境和编译能力
scripts/ 构建、资源生成、部署、验证及诊断入口
test/ 根目录 test_*.cpp Native 主机测试用例(run_tests.cpp 为入口)
test/unit/、test/helpers/、test/mocks/、test/fixtures/ 主机测试、C++ 测试辅助代码、模拟依赖及测试数据
test/browser/ Playwright 离线/设备测试(设备发现辅助在 test/helpers/)
docs/ 公开配置样例、专项设计、改进计划和验收说明
images/ 文档及 README 引用的图片
vendor/ 仓内固化的第三方源码(如 esp-idf-rgb-*),配合 patches/ 维护
managed_components/ ESP-IDF 组件管理器输出,可由 dependencies.lock 恢复,不提交
tmp/ 本地临时产物,不提交
.pio/、node_modules/、dist/、artifacts/ 构建缓存、npm 依赖、发布产物和本地验证证据,不作为业务源码编辑

修改原则

  • 固件修改沿用现有 manager/service/driver 分层,同时检查对应头文件、调用方和错误路径。外设访问、资源仲裁及电机动作通过既有服务处理,避免在 Web 路由或页面中绕开它们。
  • 区分“已编译”“用户已启用”和“运行时实际可用”。增加能力时同步检查编译宏、运行时开关、资源预算、API 和 Web 展示,不能只让页面显示为可用。
  • 对具有额外内存开销、且并非所有设备都必需的功能,优先纳入现有“功能配置”,复用 RuntimeFeatureManager、features.json 和资源预算机制,让用户按需启用。新增可选功能默认关闭,保留已有设备的用户选择,避免另建平行开关体系。
  • 功能开关应控制实际资源生命周期:未启用时避免初始化专属资源或启动后台任务,关闭后停止相关任务并安全释放可回收的专属 RAM/PSRAM;需要重启才能生效或无法动态回收的资源应明确说明。资源节省区分估算与实测,运行时关闭不等于减少固件 Flash 体积,Flash 体积优化通过编译期裁剪处理。
  • 修改配置结构、逻辑 ID 或协议字段时保留旧配置兼容;迁移失败不能静默重置用户配置。新增 API 或改变裁剪行为时检查 scripts/device-api-test-matrix.json 及相应契约测试。
  • 修改 Web 页面只编辑 web-src/,再通过构建脚本生成发布资源。data/www/assets/logo.png 与 data/www/assets/favicon.ico 是受 Git 跟踪的源资产例外,隔离构建时必须保留。
  • HTML/JS/CSS 发布资源采用 gzip-only 形式,使用现有清单和资源检查流程;不要直接修改生成的 bundle、.gz 或 Service Worker 清单来修复问题。
  • 界面文案直接以中文硬编码(UTF-8),与现有硬编码文案保持一致;新增或修改文案时检查窄屏布局、加载状态、失败提示和离页后的异步回调。
  • 遵循 .editorconfig 和相邻代码风格,避免顺手格式化无关文件。文本使用 UTF-8;C/C++ 以 .clang-format 为参考。
  • 依赖或底层库补丁通过现有配置及 patches/、补丁脚本维护,不把对 .pio/、node_modules/ 的手工修改作为交付结果。

跨芯片与长期稳定性约束

项目目标是让 ESP32、ESP32-C3、ESP32-C6、ESP32-S3 在各自受支持的硬件、内存配置和声明负载范围内长期稳定运行。资源不足时必须明确拒绝超限配置或进入可恢复的保护状态,不得崩溃、静默丢失配置或伪造业务成功。本文规定开发与验收要求,不代表设备已经通过长期验证。

覆盖范围

正式发布矩阵以 platformio.ini、README.md 和生成的能力矩阵为准;当前包括:

芯片 构建环境
ESP32 esp32-F4R0、esp32-F8R0、esp32-F8R8
ESP32-C3 esp32c3-F4R0
ESP32-C6 esp32c6-F4R0、esp32c6-F8R0
ESP32-S3 esp32s3-F8R0、esp32s3-F8R8、esp32s3-F16R8
  • 环境名中的 F 表示 Flash,R 表示 PSRAM;内部 RAM 还需按芯片和运行时实际可用量评估。部署时核实实际容量、总线模式及初始化结果,不能只按环境名推断内存可用。
  • 跨芯片公共逻辑、内存管理、调度、协议或构建配置变更,应覆盖全部正式构建环境,并按芯片、PSRAM 有无及容量、板卡和业务负载分别记录实机结果。缺少对应硬件或证据时标记“待验证”,不以一台 S3 的结果代表其他组合。
  • 其他容量、厂商自定义板卡及 RGB 专用构建需单独核验配置、资源预算和实机行为,不能直接继承正式环境的通过结论。新增或删除正式环境时同步本表及相关测试清单。
  • 离线浏览器覆盖以 test/browser/offline-device-profiles.json 和实际执行用例为准;检查其与目标矩阵的差异,不能把部分模拟配置通过描述为全部内存组合通过。

实现约束

  • 内存与容量准入:分别统计内部可按字节访问的 DRAM、最大连续块、任务栈和 PSRAM;PSRAM 余量不能代替内部 RAM 预留。组合预算计入外设、规则、首次执行、日志、Web 响应及网络缓冲峰值,分配失败须可处理。新建、修改、导入和启动加载使用一致的容量校验,超限时保留原有效配置及运行态。
  • 有界调度与积压:队列、缓存、历史、日志、连接数和并发任务均设置容量及回收规则,通信、锁等待和重试有明确超时。沿用既有任务池、总线仲裁和非阻塞调度,避免拖住主循环或长期饿死采集任务;看门狗反映实际任务进展,不能靠盲目喂狗掩盖阻塞。计时逻辑覆盖计数器回绕及 NTP 校时变化。
  • 功能与保护状态:功能生效须满足编译支持、用户启用、依赖就绪、资源预算和初始化成功,并受运行期保护状态约束。临时限流或降级保留用户原有启用意图,显示原因和恢复条件,不因一次资源不足永久关闭规则或删除配置。
  • 断线与外设故障恢复:WiFi、MQTT 和外设通信失败采用有界超时与退避,恢复后验证连接、订阅和业务数据。具备离线运行条件的本地采集及规则继续工作;无响应外设不能阻塞其他任务。过期、结果不明或未获准的电机、继电器等动作不得在恢复后擅自重放。
  • 持久化与 Flash 寿命:配置保存、导入及迁移使用既有事务或原子替换机制,覆盖写入失败、断电和重启恢复;失败时保留可恢复的有效版本。避免每次采样或轮询写 Flash,按需求合并写入、限制频率并轮转日志,文件空间不足时明确报错。
  • 业务数据完整性:采集值保留时间及有效性,缺失、过期或错误读数不能用零值伪装成功;有效的零值仍应正常处理。HTTP 成功需包含完整正文,SSE 心跳不代表业务数据更新,按钮确认或指令入队不代表动作完成。

稳定性验证与发布准入

  • 验证前固定设备身份、固件/Web 摘要、配置版本、启用功能、预期业务及负载范围;按同一套配置和执行模型覆盖无 PSRAM、带 PSRAM、资源受限及组合峰值场景。预期功能依据用户配置确定,不能从故障后的降级状态反推验收目标。
  • 相关变更覆盖重复启停、持续采集与上报、浏览器访问、断网重连、外设超时、分配失败及配置恢复。正常负载长测与超负载/故障注入分开记录;后者预先定义预期错误、恢复时限和输出安全状态,不能把预期注入故障混入正常窗口后忽略失败。
  • 正式长期验收按 scripts/README.md 的 8 小时 Web 功能验收、24 小时及后续 72 小时设备观察流程执行,逐硬件组合核实实际时长、采样覆盖和预期业务持续有效。只读探活不能替代 MQTT/Modbus 数据、规则执行及必要的实物反馈证据;特殊场景有更严格要求时遵循对应计划。
  • 内存、延迟、失败率和重启门槛复用 scripts/device-stability-thresholds.json 及对应验收脚本,按实际硬件条件选择并核验。新增容量分档需有测量依据,不为取得通过结论放宽阈值;报告同时保留内部 RAM、最大连续块、PSRAM、任务栈、积压量及其趋势,缺少相关采样时明确说明覆盖不足。
  • 正常声明负载下的异常重启、OOM/看门狗复位、持续内存泄漏、超阈值下降、正文截断、非预期失败、no-memory 降级或 WebGuard 503 均不得判定为严格稳定性通过。超负载下的保护行为需另外验证拒绝有界、状态可见、恢复后业务正常。
  • 只有本次报告的退出状态、结果字段、时长、覆盖和业务门槛均满足要求,才能对对应组合报告“长期稳定通过”。中断、跳过或不足时长不得判通过;支持续跑的观察须保留原始证据且停机时间不计入有效时长,要求连续运行的窗口不能靠拼接中断前后数据满足。

工具与本地验证

以下命令从项目根目录执行。使用 Node.js 20+、Python 3 和 PlatformIO;本机 python 可能指向旧版本,执行 Python 脚本前确认解释器,优先使用已配置的 PlatformIO 虚拟环境或脚本支持的 FASTBEE_PYTHON。Native 测试还需要可用的主机 C++ 工具链。

需要首次安装或恢复锁定依赖时执行;已有可用依赖时不必重复安装:

npm ci
npm ci --prefix test/browser
npx --prefix test/browser playwright install chromium

按改动范围选择检查,命令定义以当前 package.json、test/browser/package.json 和脚本为准:

断点续跑原则(2026-10-15 约定):测试链、部署流程和其他多步骤脚本在某一步报错时,修复该处问题后从失败步骤继续执行,不要每次从头全量重跑(如 npm test 失败于 test:contracts,就修复后先单独重跑对应脚本/套件,确认绿后再视需要补跑后续段;部署四台设备失败于第二台,就修复后从第二台继续,不重复已成功的第一台)。全量重跑只用于最终整体验证或失败根因不明的场合。

场景 入口 验证范围
纯文档修改 node scripts/check-utf8-text.js AGENTS.md,将文件参数替换为实际改动路径 编码;另检查链接和 diff,不要求固件编译
日常代码回归 npm test 静态门禁、契约与主机单元测试;包含 Web 资源生成
定向单元回归 npm run test:unit 或对应测试脚本 受影响逻辑,不能自动替代其他相关门禁
C++ Native npm run test:native 主机编译与 Native 用例,不连接设备
主机加 Native npm run test:regression 主机门禁和 Native 回归
指定固件环境 npm run test:firmware -- esp32s3-F16R8 固件、LittleFS 构建及当前产物校验,不烧录
Web 发布资源 node scripts/build-web-assets.js --env=esp32s3-F16R8 生成目标环境的 data/www/,不上传
浏览器用例收集 npm run test:e2e:collect 检查用例能否解析,不证明界面功能通过
离线浏览器回归 npm run test:e2e:offline 本地模拟服务上的交互及布局,不代表实机结果
默认构建回归 powershell -NoProfile -ExecutionPolicy Bypass -File scripts/test-all.ps1 默认启用 static/native/build:主机回归、Native 和九个正式固件环境构建;不含独立 artifacts 阶段及完整离线浏览器矩阵

表中的 esp32s3-F16R8 只是示例,必须按实际改动选择目标环境。npm run test:firmware 不带环境参数会运行全部正式环境。npm run test:e2e、test:e2e:device 属于设备测试入口,不能当作默认离线测试执行。

发布前应补齐产物与浏览器检查:在 PowerShell 中执行 ./scripts/test-all.ps1 -Checks static,native,build,artifacts,并单独执行 npm run test:e2e:offline。这些检查仍属于本地验证;设备检查、部署和实物验收按本次发布范围及授权另行执行,不能以默认命令通过代替全部发布验收。

逻辑和行为变更应补充能覆盖原问题的测试,并检查 scripts/validate-test-coverage.js 的登记要求。修改芯片宏、驱动、库或分区时执行相关固件构建;跨芯片改动和发布验证按影响范围扩展矩阵。仅文字调整使用文档检查即可。

构建与共享资源

  • 同一工作区的 PlatformIO、Host/Native 回归、Web 资源生成,以及同一设备的串口读写和部署需串行安排;共享构建或设备操作使用 scripts/firmware-build-lock.ps1。锁被占用时等待,不删除锁文件或终止其他任务的进程。
  • deploy.ps1、test-all.ps1 和 Native/固件测试入口已接入锁;直接运行 npm test、Web 构建或其他未包锁命令时,在外层获取同一把锁。Web 构建自身的发布锁不能代替整个构建/部署流程的协调。
  • deploy.ps1 入口固定 ~/.platformio/penv/Scripts 到 PATH 最前并清除 PYTHONHOME/PYTHONPATH(penv 环境守卫),防止旧版 mingw64/Git 运行时抢占导致 pio 子进程随机失败;主机单元测试由 scripts/run-unit-tests.js 做同样的编译器运行时前置。
  • 多个任务正在修改源码时,正式构建应固定源码、配置和测试输入并保留摘要。构建期间输入变化,产物不能作为该次发布的有效证据。

手动包锁示例,try 内替换为本次需要的命令,并检查每条命令的退出码:

. ./scripts/firmware-build-lock.ps1
$taskBuildLock = Enter-FastBeeFirmwareBuildLock -ProjectRoot (Get-Location).Path -Label 'host-regression'
try {
    npm test
    if ($LASTEXITCODE -ne 0) { throw "npm test failed: $LASTEXITCODE" }
}
finally {
    Exit-FastBeeFirmwareBuildLock -Handle $taskBuildLock
}

需要统一构建入口且不烧录时,可执行:

powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy.ps1 -Env esp32s3-F16R8 -BuildOnly

deploy.ps1 不带 -BuildOnly 会进入设备写入流程;执行前必须满足下节的目标核验和配置保留要求。RGB 触屏等专用板卡还需对应板级配置,不能仅凭同为 ESP32-S3 就使用通用构建替代。

设备操作与配置保护

  • 设备测试、烧录、配置导入、重启和外设动作必须处于用户已授权范围。代码修改本身不代表要操作任何已连接设备;已有明确部署授权时,不重复询问相同授权。
  • 每次访问设备前核对连接目标与预期 MAC/芯片身份;网络访问核对当前 STA 地址,串口访问核对当前端口。历史 IP、串口编号和相同构建环境都不能单独证明是同一台设备。
  • 烧录、分区调整或文件系统写入前,再核对 Flash/PSRAM、分区布局及适用时的活动 OTA 槽。只读 API/Web 巡检无需为这项写入预检额外打开串口或让设备进入下载模式。
  • 升级在线设备时,先备份并保留设备身份、网络、认证、MQTT、外设、协议、规则、屏幕布局及非 Web 文件。公开 docs/ 样例和 data/config/ 不能直接覆盖现场配置,不能把另一台设备的备份套用到目标设备。
  • 区分完整固件更新与仅 Web 更新。仅 Web 更新应保留应用固件、启动和分区信息、NVS 及非 Web 文件;写入范围、当前产物摘要和校验结果必须可追溯。普通全量烧录不能默认视为配置保留升级。
  • 设备轮询保持适当间隔,按现有脚本处理超时及限流;不要用高并发重试、无效零值、反复重启或关闭用户功能掩盖异常。
  • 电机、继电器和其他输出遵循现有资源仲裁、行程准入及故障保护。电机提示 TRAVEL_REFERENCE_REQUIRED 时检查参考位置和准入条件,不通过取消保护或自动重试启动来消除提示。
  • .device-config-backups/、Flash 备份、认证 Cookie 和含凭据的日志属于私有材料,不提交、不写入公开样例,也不在回复中输出其敏感内容。

验收与交付

结论 所需证据与边界
本地通过 本次相关测试的退出码、结果和输入版本;不代表设备通过
构建通过 对应环境的实际编译及产物校验;不代表已经写入设备
部署完成 本次目标设备、产物摘要、写入与读回校验;使用部署报告时核实本次 written=true、verified=true 等字段,不能沿用旧报告
设备 API/Web 通过 当前设备的请求、资源和界面证据;按钮响应或寄存器读回不证明物理动作
实物通过 实际触摸、输出动作、测量或现场反馈;电机运动不能仅凭 UI 确认或 Modbus 成功判断
长期稳定通过 对应芯片、内存配置和负载满足上述长期验收的时长、采样、资源及业务门槛;短时恢复或其他硬件的通过不能替代
  • 未执行、缺少硬件、输入变化、观察中断或时长不足时,明确标记“待验证”及原因。
  • 新一轮验证使用独立输出目录,保存输入摘要、日志和报告;脚本支持的同一轮断点续跑可在核对原设备、版本和配置后向原目录追加记录。保留历史失败,不能覆盖失败文件,也不能让后续恢复把整个观察窗口改成通过。
  • 最终交付说明修改了什么、验证了什么、尚缺哪些证据,并给出关键文件及报告路径。涉及既有计划时同步维护对应实施记录,不扩大完成范围。

按任务查阅的文档