功能配置
“功能配置”页面控制已经编译进固件的模块。配置保存于 LittleFS /config/features.json,点击“保存并重启”后生效。
生效条件
compiled AND userEnabled AND budgetPassed AND NOT runtimeDisabled| 字段 | 含义 |
|---|---|
compiled | 有效实现已包含;单独开启保留宏不证明能力已实现 |
userEnabled | 用户在本页开启 |
budgetPassed | 内部判定:启动时 DRAM/PSRAM 预算通过 |
runtimeDisabled | 运行期内存保护临时停用该功能,不等同于用户关闭 |
active | 兼容字段:准入门控通过,不代表实例已初始化或设备实际可用 |
activeMeaning / admissionState | 新候选明示 admission_only,以及预算/网络/依赖等准入原因 |
instanceState | 被动 owner 观察;初始化或服务生命周期,未取得快照为 unobserved |
instanceObserved / instanceScope | 初始化、服务生命周期、命令执行活动或静态资源适用范围;均不是物理健康 |
instanceReason | 未编译、无独立 owner、观察者未建立、同步未就绪、忙锁等固定原因;不触发初始化 |
initializedInstances | 仅初始化/未初始化状态返回明确数量;未知、忙锁、待清理时不返回 |
locked | 编译或分区不支持,运行时不能开启 |
deferred | 网络依赖功能,等待网络就绪后初始化 |
bundleRequired | 是否为强制组合成员;未实现的可选 otaFs 不锁定 OTA 固件升级父项 |
内存不足的功能会跳过初始化并记录 [BUDGET] 日志;/api/system/status 对应值为 no-memory。重启后才会重新评估,不要通过反复开关尝试“挤出”内存。
上方公式是简化示意;实际还逐级检查依赖与网络就绪。需要重启的 ioExpander/i2cSensors 使用本次启动快照,保存意图不立即替换快照;缺失或循环依赖拒绝准入。新页面区分“待保存”“重启后启用/停用”“已准入 · 实例状态未确认”,附属能力降级显示在父行。新字段属于 2026-10-01 后续候选,未部署的旧设备不自动获得这些行为。
Flash/RAM 均为静态估算;摘要 resourceAccounting=static_estimate、instanceMemoryMeasured=false。free8KB/最大连续块是独立系统堆指标,不是某一功能的实测占用。关闭选项不能据此宣称已经释放估算 RAM;其余功能观测和实机资源测量仍待完成。
新候选在主准入状态下单独显示“驱动已初始化 × N”“驱动未初始化”“实例观测忙”或“实例清理待重试”。unobserved 不等于 0 个实例;busy 不沿用上次数量;cleanup_pending 说明资源仍保留,需按该驱动的安全维护流程处理,不自动重试危险动作。已初始化也不证明真实模块应答、物理负载动作、网络连通或全部内存释放。观察不会为了查询创建驱动/互斥或触发硬件读写。
状态未覆盖的服务继续明确未知;不得把三个驱动的观测推广成所有功能已实测。43 项本地主机/Node 行为测试通过,当前候选完整构建、设备端显示和实机资源收益仍独立验收。
2026-10-03 的 r18 后继主仓增量进一步接入 OLED/LCD、LCD1602、红外、RF 学习、规则 manager、屏幕任务、DS18B20、NeoPixel 和 TM1637,尚待统一测试,未部署。这批代码不属于 r18 冻结输入,早期 43 项通过不能作为本批通过。服务范围只显示实际 owner 的“实例已分配/运行中/已停止/退出中”,不返回或沿用驱动初始化数量;“已停止”仍可能保留对象、缓存或延迟清理资源。RuleScript 只报告 manager 对象存在(allocated),不根据规则启用数量声称正在执行。屏幕请求停止后保留任务时显示退出中;后台未编入或同步条件缺失时保持未知。IR/RF/TM1637 缺锁时拒绝无锁启动,正常业务获取 owner 可重试分配,状态查询不分配或修复。
DS18B20 从 SensorDriver 真实对象容器读取状态,采样失败但对象仍保留时显示“已分配”,不代表探头存在或读数新鲜。TM1637 和 NeoPixel 也只以实际对象保留证明分配;原驱动应答/初始化与实际显示仍须单独验收。NeoPixel 分配中显示忙、删除过程中显示退出中,查询不读取可被替换的灯带对象、不触发灯珠输出。关闭配置不会把仍保留的对象错误显示成停止。
| 功能键 | r18 后继主仓观察覆盖 |
|---|---|
ds1302、rfid、ethernet、ioExpander、i2cSensors、lcd1602 | 已接线真实初始化快照;不等于当前设备已部署或完成物理验收 |
lcd、irRemote、rfLearn、screenPanel | 已接线实际 owner 生命周期;四项均为本批新增,待测试 |
ruleScript | 实际静态 manager 对象存在;只报告 allocated |
ds18b20、sevenSegment、neopixel | 实际分配 owner 观察;不报告驱动 initialized,三项均待测试 |
mdns | r19 后继:同步后的实际 begin/end 后台状态,不调用健康检查/网络查询,待测试 |
fileLogging | r19 后继:原日志锁下的实际 ring/任务槽,观察不写盘也不清理,待测试 |
userAdmin | r19 后继:真实可选用户路由对象的构造/析构,不借常驻认证服务推断,待测试 |
webServer、modbus、ota、logViewer、ble、cellular | r19 后继:实际动态管理器构造/析构的 owner_lifetime;不证明服务运行,待测试 |
mqtts | r19 后继:实际 WiFiClientSecure 和蜂窝 software TLS/QSSL 的 transport_allocation;只证明对象分配,待测试 |
lcdGb2312、deviceControl | static_resource/no_dedicated_instance,无独立常驻运行对象;不是瞬态请求不耗内存 |
commandScript | r19 后继:实际 execute 入口的 execution_activity;running=当前执行中,idle=当前无执行,待测试 |
otaFs | 未实现文件系统 OTA writer;旧宏/配置键仍保留,有效 compiled=false/implementation_missing |
2026-10-04 的 r19 后继主仓代码中,28 项分为 17 项实际 owner 实例观察、6 项动态管理器寿命观察、1 项 TLS 传输对象分配观察、1 项实际执行活动、2 项无独立实例的静态资源、1 项未实现 otaFs。本批尚未统一测试/部署,分类不是全部服务运行/实物验收。尚未正常创建的已接线 owner 显示 observer_not_registered;缺锁显示 synchronization_unavailable;忙锁显示 observation_busy;不一致快照显示 invalid_snapshot。编译未包含且没有观察者时显示 not_compiled。页面保持用户意图/重启/降级主状态优先,未知不能解释为 0 个实例,也不按静态 RAM 估算声称已释放内存。
动态管理器显示“管理器已创建/销毁中/未创建”。构造、销毁和重叠替换通过静态身份槽观察,不访问可能销毁的对象;构造未完成或并发变更时显示忙,槽容量或身份耗尽保持未知。该状态不能证明 Web 正在监听、Modbus 正在轮询、OTA 写入成功、蓝牙已广播或蜂窝已联网;服务运行和硬件资源归还仍单独验证。
MQTTS 显示“TLS 对象已分配/释放中/未分配”,包括尚未选中的蜂窝 TLS 对象;不证明当前连接、TLS 握手或证书认证成功。WiFi 和蜂窝对象按实际分配/删除路径记录,查询不创建 TLS 或发送网络请求。蜂窝两种 TLS 后端都不可用时拒绝 MQTTS,不再回退普通 Client;此路径可能在实例建立前失败并显示 -11。未标记为可信 TLS provider 的外部 Client 进入 MQTT 客户端安全校验时返回 -15(MQTTS_TRANSPORT_UNAVAILABLE),实例销毁后该实例错误不一定保留。不能用单一错误码判断所有 TLS provider 缺失路径。这些保护为待统一验证的新代码,尚无设备部署结论。
文件日志禁用但缓冲/任务仍保留时显示退出中;查询只归还互斥,不会顺便 flush 或释放 ring。排队 worker 和成功写盘是不同事实。mDNS 查询仅观察已同步的静态启动状态,不保留可能悬空的 DNSManager 指针;running 不证明域名或网络可达。用户管理只报告路由对象分配,不证明 Web 正在监听。命令执行的 idle 不代表代码、对象或全部 RAM 已释放,并发/提前失败退出保持一致计数,溢出时保持未知。
文件系统 OTA 当前没有 writer,启用旧 FASTBEE_ENABLE_OTA_FS 宏不能获得该能力;分区发布声明和旧用户意图继续兼容,没有新增刷写入口。只有规则/命令脚本和日志查看/文件日志是强制组合,未实现 otaFs 不禁用现有固件 OTA 父功能。两项静态资源显示“无独立实例”,不能解释为不占 Flash/RAM;全部设备启停/真实内存/恢复/长稳仍单独验收。
菜单遵循同一能力状态:设备配置、网络配置、功能配置等核心管理菜单始终显示;可选功能菜单只在 compiled !== false 且 active === true 时显示。已编译但未启用的功能不会显示对应菜单,未编译功能在本页锁定并标注“未编译入固件”。
运行时内存降级
2026-10-04 的 r19 后继代码进入 SEVERE 后暂停 MQTTS、Modbus、外设执行 Worker/定时器、脚本和高内存可选外设,优先保留网络与 Web 管理入口。MQTTS 不自动改为 MQTT;持续 CRITICAL 的 MQTT 停止也是本次启动暂停,不再写入 enabled=false。用户协议、端口、凭据及外设/规则配置保持原值。该修复尚待统一测试/部署,旧版本的行为不能据此倒推为已修复。
内存恢复后只按已确认、已启用的安全配置尝试重建;请求排队、堆不足或实例未就绪仍保留暂停/待重试状态,不连接明文备用。memoryDegradation.mqttsPaused 表示 TLS 暂停;兼容字段 mqttsDowngraded 固定为 false。旧磁盘降密标记继续保留,只有明确的原 mqtts 和合法原端口才能安全重建;缺元数据不猜测。旧版本已保存的 MQTT 禁用标记不会自动清除,须用户在协议配置页明确保存并启用。
出厂默认
发布环境共享统一功能基线,但 OTA、红外等硬件能力由具体环境覆盖。出厂只保证 Web 服务和 mDNS 管理入口开启,其余功能按需启用:
| 分组 | 功能键 | 默认 | 依赖/说明 |
|---|---|---|---|
| 网络 | webServer、mdns | 开启 | 禁用 Web 会失去管理入口;AP 配置模式仍保留入口 |
| 外设 | lcd、neopixel、sevenSegment、ds18b20 | 关闭 | 需要对应硬件 |
| 外设 | screenPanel | 关闭 | 仅 ESP32-S3:支持的 SPI/RGB 显示与可选 I2C 触摸,见设备屏幕 |
| 外设 | lcdGb2312、i2cSensors、rfid、irRemote、rfLearn、ds1302、lcd1602 | 关闭 | 依赖 LCD、I2C、SPI、RMT 或三线接口 |
| 协议 | modbus、mqtts | 关闭 | MQTTS 依赖 MQTT;Modbus 需要 UART/RS485 |
| 自动化 | ruleScript、commandScript | 关闭 | commandScript 依赖 ruleScript |
| 系统 | deviceControl、ota、logViewer、fileLogging、userAdmin | 关闭 | OTA 还需要 A/B 分区;文件功能受构建宏控制 |
| 网络扩展 | ethernet、cellular、ble | 关闭 | W5500、EC801E-CN 或 BLE 硬件;BLE 暂不属于发布路径 |
具体编译状态以页面和 /api/features/status 返回为准。esp32s3-F8R8 关闭红外/RF 学习以避免 RMT/库冲突,esp32s3-F16R8 保持启用;4MB 环境的 ota 因分区限制锁定。
当前 esp32-F4R0、esp32c3-F4R0、esp32c6-F4R0 和 esp32c6-F8R0 环境不编译 Ethernet/Cellular;功能页应显示“未编译入固件”并锁定开关,相关可选菜单不会出现。
经典 esp32-F4R0 和 esp32c3-F4R0 的 4 MB Flash 应用分区有限,面板发布目标明确设为 screenPanel=false、screenUi=false、remoteResources=false。经典 ESP32 仍编译 pointHistory=true;C3 为满足单个 0x330000 应用槽进一步设置 pointHistory=false,但实时采集、Modbus、外设执行和普通 Web 保留。不能在功能页打开未编译的模块;支持 PSRAM 且连接匹配显示硬件的 ESP32-S3 更适合设备屏幕。设备屏幕只面向 ESP32-S3;ESP32-C6 与经典 ESP32、C3 均不提供设备屏幕能力。最终能力以发布清单、实际 BIN 和设备 /api/system/capabilities 为准。
esp32s3-F16R8 是完整面板的目标环境,已编入 screenPanel、screenUi、pointHistory 和 remoteResources。这些编译能力不等于任意屏板已经通过实体兼容验收:微雪 Rev4 的 ST7701/GT911 代码已接入,但当前实屏仍自动漂移并出现横向、纵向卷边,物理显示验收未通过。S3 芯片资源也不会自动带来显示控制器兼容性。SPI 预算不含 RGB565 单帧额外的 460,800 字节 PSRAM。
设备屏幕资源口径
| 指标 | 规划值 | 使用方式 |
|---|---|---|
| Flash 估算 | 约 80 KiB | 用于功能页评估,最终差值以发布 BIN 为准 |
| RAM 估算 | 69,632 B(约 68 KiB) | 包含 snapshot/stripe、任务栈和运行对象 |
| 内部 DRAM 启动门槛 | 20 KiB | 只表示必须保留的内部 8-bit DRAM 余量,不是总 RAM |
| 大缓冲 | 约 48 KiB | 优先 PSRAM;无 PSRAM 时要求内部连续完整分配 |
预算不通过时功能状态应为 no-memory,菜单不应出现,已有配置仍保留。即使预算通过,也必须继续观察最大连续块、网络/TLS 峰值和长时间运行情况。
操作步骤
- 进入 Web → 功能配置。
- 先确认“编译状态”和硬件依赖,再打开需要的功能。
- 关闭父功能时,依赖它的子功能会自动关闭(如
lcd→lcdGb2312)。 - 点击保存并重启;仅保存配置不会立即初始化驱动。
- 重启后先核对准入原因,再查看对应驱动诊断、有效数据或实际读回;
active=true和健康监控本身不证明外设可用。
功能开关只影响运行时初始化,不会减少固件文件大小;要缩减 Flash,必须在 platformio.ini 中关闭对应编译宏并重新构建 Web 资源。
API
GET /api/features/status
返回功能数组和资源摘要:
{
"success": true,
"data": {
"features": [
{
"key": "modbus",
"compiled": true,
"userEnabled": false,
"active": false,
"activeMeaning": "admission_only",
"admissionState": "user_disabled",
"instanceState": "unobserved",
"instanceObserved": false,
"instanceScope": "owner_lifetime",
"instanceReason": "observer_not_registered",
"flashKB": 20,
"ramB": 1024,
"deferred": true
}
],
"summary": {
"totalFlashKB": 300,
"activeFlashKB": 0,
"activeRamB": 0,
"resourceAccounting": "static_estimate",
"instanceMemoryMeasured": false,
"free8KB": 80,
"largest8KB": 40
}
}
}POST /api/features/config
只更新配置,不重启:
{
"features": {
"modbus": { "enabled": true },
"mqtts": { "enabled": false }
}
}POST /api/features/estimate
按提交的开关估算 Flash/RAM,不保存配置。
POST /api/features/apply
保存配置并延时重启;客户端应先读到成功响应,再轮询 /api/health。
注意事项
2026-10-01 20:04 后续候选还为 ioExpander 提供真实 provider 初始化快照:最多四个实例,使用外设管理器已有锁零等待观察,不访问 I2C 或改变输出。忙锁显示 busy;任一实例清理未完成显示 cleanup_pending 且不返回数量;用户关闭功能但实例仍保留时继续显示。首次初始化失败不算初始化实例,数据失鲜与实例存在分开。25 项扩大回归及 9 项真实锁/Provider 模拟测试通过,不是现场接线、内存回收或长期稳定性证明;该代码不属于 r5。
2026-10-01 后续候选将 i2cSensors 缓存接入实际实例观察:正常业务创建缓存后才注册,查询不创建驱动/互斥、不访问 I2C;采样锁忙返回 busy,不返回旧数量。只统计该功能组已初始化实例,不混入其他通用传感器。功能准入关闭但实例仍在时如实保留显示;初始化失败/读失败/释放后按实际缓存状态更新。
本地 10 项生产缓存/驱动模拟回归通过,包括 1000 次被动查询、并发采样、失败/释放及容量边界;不是 MCU 内存回收、物理读数或长稳证明。该后续代码不在早先 r4 镜像中,完整新候选门禁另记。
- 未编译功能不会因修改
features.json而出现。 - 网络依赖功能在启动早期显示
deferred属正常行为。 - Web 页面、日志接口和定制文件 API 在低内存时可能返回
503,按Retry-After退避。 features.json保存完整的用户期望状态;旧版稀疏配置会在首次成功加载时保留已有选择并自动补全。迁移设备时使用配置导入/导出,不要手改运行中的文件。

