Initial commit

This commit is contained in:
xiaoli 2026-02-26 09:59:27 +08:00
commit e02859a336
60 changed files with 11043 additions and 0 deletions

View File

@ -0,0 +1,75 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
if(NOT DEFINED ENV{ESP_MATTER_PATH})
message(FATAL_ERROR "Please set ESP_MATTER_PATH to the path of esp-matter repo")
endif(NOT DEFINED ENV{ESP_MATTER_PATH})
if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
if("${IDF_TARGET}" STREQUAL "esp32" OR "${IDF_TARGET}" STREQUAL "")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c3")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c3_devkit_m)
elseif("${IDF_TARGET}" STREQUAL "esp32c2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c2_devkit_m)
elseif("${IDF_TARGET}" STREQUAL "esp32h2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32h2_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32s3")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32s3_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c6")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c6_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c61")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c61_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c5")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c5_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32p4")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/hollow)
else()
message(FATAL_ERROR "Unsupported IDF_TARGET")
endif()
endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
set(ESP_MATTER_PATH_RAW "$ENV{ESP_MATTER_PATH}")
string(STRIP "${ESP_MATTER_PATH_RAW}" ESP_MATTER_PATH_RAW)
file(TO_CMAKE_PATH "${ESP_MATTER_PATH_RAW}" ESP_MATTER_PATH)
set(ENV{ESP_MATTER_PATH} "${ESP_MATTER_PATH}")
set(ESP_MATTER_DEVICE_PATH_RAW "$ENV{ESP_MATTER_DEVICE_PATH}")
string(STRIP "${ESP_MATTER_DEVICE_PATH_RAW}" ESP_MATTER_DEVICE_PATH_RAW)
file(TO_CMAKE_PATH "${ESP_MATTER_DEVICE_PATH_RAW}" ESP_MATTER_DEVICE_PATH)
set(ENV{ESP_MATTER_DEVICE_PATH} "${ESP_MATTER_DEVICE_PATH}")
set(PROJECT_VER "2.0" CACHE STRING "Application version")
set(PROJECT_VER_NUMBER 2 CACHE STRING "Application version number")
set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip)
# This should be done before using the IDF_TARGET variable.
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
include(${ESP_MATTER_PATH}/examples/common/cmake_common/components_include.cmake)
include($ENV{ESP_MATTER_DEVICE_PATH}/esp_matter_device.cmake)
set(EXTRA_COMPONENT_DIRS
"${ESP_MATTER_PATH}/examples/common"
"${MATTER_SDK_PATH}/config/esp32/components"
"${ESP_MATTER_PATH}/components"
"${ESP_MATTER_PATH}/device_hal/device"
${extra_components_dirs_append})
project(light)
# WARNING: This is just an example for using key for decrypting the encrypted OTA image
# Please do not use it as is.
if(CONFIG_ENABLE_ENCRYPTED_OTA)
target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT)
endif()
if(CONFIG_IDF_TARGET_ESP32C2)
include(relinker)
endif()
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H;-Wno-overloaded-virtual" APPEND)
idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various
# flags that depend on -Wformat
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND)

View File

@ -0,0 +1,75 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
if(NOT DEFINED ENV{ESP_MATTER_PATH})
message(FATAL_ERROR "Please set ESP_MATTER_PATH to the path of esp-matter repo")
endif(NOT DEFINED ENV{ESP_MATTER_PATH})
if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
if("${IDF_TARGET}" STREQUAL "esp32" OR "${IDF_TARGET}" STREQUAL "")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c3")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c3_devkit_m)
elseif("${IDF_TARGET}" STREQUAL "esp32c2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c2_devkit_m)
elseif("${IDF_TARGET}" STREQUAL "esp32h2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32h2_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32s3")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32s3_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c6")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c6_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c61")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c61_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c5")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c5_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32p4")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/hollow)
else()
message(FATAL_ERROR "Unsupported IDF_TARGET")
endif()
endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
set(ESP_MATTER_PATH_RAW "$ENV{ESP_MATTER_PATH}")
string(STRIP "${ESP_MATTER_PATH_RAW}" ESP_MATTER_PATH_RAW)
file(TO_CMAKE_PATH "${ESP_MATTER_PATH_RAW}" ESP_MATTER_PATH)
set(ENV{ESP_MATTER_PATH} "${ESP_MATTER_PATH}")
set(ESP_MATTER_DEVICE_PATH_RAW "$ENV{ESP_MATTER_DEVICE_PATH}")
string(STRIP "${ESP_MATTER_DEVICE_PATH_RAW}" ESP_MATTER_DEVICE_PATH_RAW)
file(TO_CMAKE_PATH "${ESP_MATTER_DEVICE_PATH_RAW}" ESP_MATTER_DEVICE_PATH)
set(ENV{ESP_MATTER_DEVICE_PATH} "${ESP_MATTER_DEVICE_PATH}")
set(PROJECT_VER "1.0")
set(PROJECT_VER_NUMBER 1)
set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip)
# This should be done before using the IDF_TARGET variable.
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
include(${ESP_MATTER_PATH}/examples/common/cmake_common/components_include.cmake)
include($ENV{ESP_MATTER_DEVICE_PATH}/esp_matter_device.cmake)
set(EXTRA_COMPONENT_DIRS
"${ESP_MATTER_PATH}/examples/common"
"${MATTER_SDK_PATH}/config/esp32/components"
"${ESP_MATTER_PATH}/components"
"${ESP_MATTER_PATH}/device_hal/device"
${extra_components_dirs_append})
project(light)
# WARNING: This is just an example for using key for decrypting the encrypted OTA image
# Please do not use it as is.
if(CONFIG_ENABLE_ENCRYPTED_OTA)
target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT)
endif()
if(CONFIG_IDF_TARGET_ESP32C2)
include(relinker)
endif()
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H;-Wno-overloaded-virtual" APPEND)
idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various
# flags that depend on -Wformat
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND)

View File

@ -0,0 +1,414 @@
# ESP32-C6 Matter + ESP-NOW 混合固件开发进度(单色灯 + 双色温灯)
## 1. 项目目标(来自《项目制作需求》)
- 基于 ESP32候选C3/C6开发 Matter + ESP-NOW 混合固件。
- 支持两类灯:
- 单色灯:开关 + 调光(白光)。
- 双色温灯:开关 + 调光 + 调色温(暖/冷)。
- 开发阶段Wi-Fi commissioning通过 Wi-Fi 完成配网)。
- 最终目标Wi-Fi 完成配网、Thread 实现本地 mesh 控制(混合网络模式)。
- 需要 OTA、QR 码生成、VID/PID/DAC 相关出厂数据与认证准备支持。
- 交付:双版本(或可配置)源码仓库 + Factory/OTA 固件 + 烧录/QR 脚本 + 测试报告 + 技术文档。
## 1.1 关键硬性约束与解决方案
- 量产遥控器固件不变,且 ESP-NOW 固定信道为 `channel=1`
- **问题**:若使用 Matter-over-Wi-FiWi-Fi STA 信道会被路由器决定,与 ESP-NOW 固定 ch1 冲突。
- **解决方案**:利用 ESP32-C6 的**双射频**能力:
- **Wi-Fi 2.4GHz 射频**:专用于 ESP-NOW固定 channel 1不连接路由器做 STA
- **802.15.4 射频**:专用于 Matter over Thread与 Wi-Fi 射频完全独立)
- **BLE**:用于 Matter commissioning配网阶段
- 结论:单芯片 ESP32-C6 可实现 ESP-NOW + Matter 共存,无需依赖路由器信道。
## 1.2 需求对齐清单(当前工程状态)
| 需求项 | 状态 | 备注 |
| --- | --- | --- |
| ESP-NOW 代码功能 100% 保持 | 部分 | 已按遥控器协议实现 RX/配对/命令映射,但信道冲突仍未解决为“量产可用”方案 |
| Matter clusters: OnOff / LevelControl | 已完成 | 双 endpoint 已跑通 |
| Matter clusters: Groups / Scenes | 已完成(已验证) | 已在 App 上验证可创建/应用场景 |
| ColorControl双色温 | 已完成(开发态) | 当前实现为 ColorTemperature已确认硬件为 SK6812 RGBW 模块,调色温方向正常 |
| ESP-NOW 组播/广播组命令→所有控制器同步→Matter 状态更新 | 已完成(已稳定) | 控制器能处理 cmd 并更新 Matter 属性;组控一致性/延迟表现正常,无需再测试 |
| QR 码配网Apple/Google/Alexa/RainMaker | 部分 | iOS Home 已验证Google/Alexa/RainMaker 未做系统性验证 |
| OTAHTTP 远程服务器) | 已完成 | 已实现 HTTP OTA从远程服务器下载固件可通过 Matter shell 命令触发,已验证升级后 App version 变更 |
| Matter 标准 OTA | 暂停 | 采用 HTTP OTA远程服务器方案不再推进标准 Matter OTA |
| 断电重置(如 3 次开关机) | 已完成(已稳定) | 已实现并验证3 次重启触发 Matter 工厂重置(含 5 秒确认窗);已测试稳定,无需再测 |
| 交付:源码/编译说明/bin/脚本/测试报告 | 进行中 | 文档与脚本需要补齐并固化 |
## 1.4 当前进度总览(已完成 vs 未完成)
### 1.4.1 已完成
- HTTP OTA远程服务器下载固件shell 命令触发),并验证升级成功后 `App version` 变更2.0 → 2.1
- Matter clusters: Groups / Scenes 已在 App 上验证可创建/应用场景
- 分区表调整为双 OTA`ota_0`/`ota_1`/`otadata`),固件大小可容纳 OTA 升级
- OTA 触发命令已接入 Matter shell`matter esp ota <http://url>`
- 已可在 Windows 上稳定完成 build/flash/monitor含 GN/Pigweed 环境)
- 断电重置(工厂重置):已实现并验证 3 次重启触发 factory reset含 5 秒确认窗),重置后进入可重新配网状态
- 修复断电计数不生效问题:将 NVS key 缩短到 15 字符以内并加入兼容读取逻辑
- ESP-NOW 配对与多设备联调已支持“单遥控器Zone1/Zone2+ APP”控制两台 ESP32-C6 灯具;并修复“电源重启触发配对时未及时广播配对 beacon”的问题提升遥控器绑定成功率
### 1.4.2 未完成(待办)
- 多生态验证Google Home / Alexa / RainMaker 的 commissioning + 控制验证
- 交付物固化:一键环境初始化/构建脚本、烧录脚本、测试报告与完整技术文档
## 3. 已完成的关键里程碑
### 3.1 构建与烧录链路打通Windows
- 已实现:`idf.py build` 成功、可 `flash` 到 COM4、可 `monitor` 观察启动日志。
- 已解决的关键构建问题(历史记录):
- `gn command not found`:定位 `gn.exe` 并加入 PATH。
- Pigweed 环境变量缺失:补齐 `_PW_ACTUAL_ENVIRONMENT_ROOT`
- 链接错误 `undefined reference to mbedtls_hkdf`:启用 `CONFIG_MBEDTLS_HKDF_C=y`
- app 分区过小:切换到自定义分区表 `partitions.csv`(双 OTA并设置 flash size=16MB与硬件一致最小 app 分区 `0x1E0000`
- Windows 反斜杠路径导致 CMake `Invalid character escape`CMakeLists 里将 env path 转为 CMake path。
补充构建该工程的关键环境变量PowerShell 会话级别):
- `ESP_MATTER_PATH=D:\ESP-LED\esp-matter-gh`
- `ESP_MATTER_DEVICE_PATH=D:\ESP-LED\esp-matter-gh\device_hal\device\esp32c6_devkit_c`
- `_PW_ACTUAL_ENVIRONMENT_ROOT=D:\ESP-LED\esp-matter-gh\connectedhomeip\connectedhomeip\third_party\pigweed\repo\environment`
- GN 工具路径(将目录加入 PATH
- `...\third_party\pigweed\repo\environment\cipd\packages\pigweed`(包含 `gn.exe`
### 3.2 Matter 双 endpoint 架构(已运行验证)
- 当前固件创建两个 endpoint
- Endpoint 1单色灯OnOff + LevelControl
- Endpoint 2双色温灯OnOff + LevelControl + ColorControl(ColorTemperature))。
- 串口日志已确认:
- `RGB light created with endpoint_id 1`
- `CCT light created with endpoint_id 2`
### 3.3 驱动层对接(已跑通)
- Endpoint 1单色灯LEDC PWM 驱动GPIO4/5/6
- Endpoint 2双色温灯RMT 驱动 SK6812GPIO2
### 3.4 日志报错修复
- 修复启动时 `E data_model: Cluster cannot be NULL.`
- 原因:对不含 ColorControl 的 endpoint 调用 `attribute::get(endpoint, ColorControl...)`
- 处理:先检查 `cluster::get(endpoint, ColorControl::Id)` 是否存在,再读取 ColorMode / Hue / Temp 等属性。
### 3.5 iOS Home / Matter Commissioning + 控制验证(已完成)
- 现状手机端已完成配网Home App 可同时控制两个灯的开关/亮度/CCT 灯)色温。
- 关键修复:为满足 iOS Home 的发现/配网流程,已启用 BLE commissioning
- `CONFIG_BT_ENABLED=y`
- `CONFIG_BT_NIMBLE_ENABLED=y`
- `CONFIG_ENABLE_CHIPOBLE=y`
- 串口日志关键特征(表示 BLE commissioning 正常):
- `Configuring CHIPoBLE advertising ...`
- `CHIPoBLE advertising started`
- `Commissioning window opened`
- 设备启动时可打印 Onboarding Codes用于手动输入/生成二维码):
- MT 串SetupQRCode`MT:Y.K9042C00KA0648G00`
- 11 位码Manual pairing code`34970112332`
- 注意:上述二维码/手动码为开发阶段示例/测试参数(默认 VID/PID 等),量产需替换正式 VID/PID、DAC/CD/工厂数据与每台唯一的 onboarding 信息。
### 3.6 单芯片双射频方案验证成功2026-01-07
- **架构**ESP32-C6 单芯片同时运行:
- **Thread (802.15.4)**Matter 网络层
- **Wi-Fi (channel 1)**ESP-NOW 接收(不连接路由器)
- **BLE**Matter commissioning
- **关键配置**
- `CONFIG_ENABLE_WIFI_STATION=n`:禁用 Matter Wi-Fi STA
- `CONFIG_ENABLE_THREAD=y`:启用 Matter over Thread
- 独立初始化 Wi-Fi 用于 ESP-NOW固定 channel 1
- **验证通过的日志特征**
- `OpenThread started: OK`
- `Wi-Fi channel fixed to 1 for ESP-NOW`
- `ESP-NOW RX initialized`
- `CHIPoBLE advertising started`
- `Server Listening...`
- **固件大小**~2MB含 Thread + Wi-Fi + BLE + ESP-NOW
- **状态**:设备稳定启动,无崩溃
### 3.7 HTTP OTA远程服务器验证成功2026-01-15
- **目标**支持“远程服务器方式”OTAHTTP不依赖 HTTPS/TLS固件体积可控。
- **实现概览**
- 使用 `esp_http_client` + `esp_ota_*` 实现分段下载与写入 OTA 分区。
- 提供 Matter shell 命令触发:`matter esp ota <http://url>`。
- 仅支持 `http://`,拒绝 `https://` 以减小固件体积。
- **验证结果(串口日志特征)**
- `HTTP OTA progress: ... 100%`
- `HTTP OTA upgrade successful! Rebooting in 3 seconds...`
- 重启后:`Loaded app from partition at offset 0x210000`(切换到 ota_1
- 重启后:`App version: 2.1`(已确认版本号随固件更新)
### 3.8 多设备控制联调进展APP + ESP-NOW 遥控器2026-01-15
- **目标**:一台遥控器 + 手机 App 同时控制两台 ESP32-C6 灯具(两块开发板)。
- **实现状态**
- App 侧iOS Home已可同时添加两台设备并分别控制。
- 遥控器侧支持 Zone1/Zone2 独立绑定不同灯具(通过 ESP-NOW 配对流程完成)。
- **配对机制(开发态)**
- 3 次重启:触发 Matter factory reset5 秒确认窗)。
- 5 次重启:进入 ESP-NOW pairing mode5 秒确认窗)。
- 遥控器在目标 Zone 下长按配对键,设备收到 `0xA5` 后退出配对模式。
- **关键修复**
- 修复“电源重启触发配对模式后,因 Wi-Fi 连接状态导致配对 beacon 未及时广播”的问题:进入配对后将主动启动配对 beacon 广播,确保遥控器可发现并完成绑定。
## 4. 当前仍在进行中的问题/待验证点
### 4.1 单色灯输出"白光"的定义与实现已确定RGB 三路混白)
- 当前单色灯硬件接法为 RGB 三路 PWMGPIO4/5/6
- 已做的软件调整:将 RGB 三路占空比设置为 1:1:1同亮度混色以尽量呈现白光。
- 已确认:单色灯即 RGB 三路混白方案(不做单通道白灯条改造)。
- 注意RGB 分立灯珠近距离仍可能看到“三色点”,属于物理结构;可通过扩散罩/导光改善。
### 4.2 双色温灯的“暖/冷”实现已确认SK6812 RGBW
- 已确认:双色温灯硬件为 SK6812 RGBW 模块,采用 RMT 单线驱动。
- 当前实现Matter ColorTemperaturemireds→ 颜色映射 → SK6812 输出;调色温方向已验证正确。
- 注意SK6812 RGBW 的“色温”属于近似实现(需要 RGB 参与补色),效果取决于映射/校准策略。
- 状态:当前效果表现正常,无需再做专项“色温校准/一致性测试”。
### 4.3 Flash 容量提示告警(已解决)
- 现象:启动时提示检测到 16MB但固件镜像头标记为 4MB
- `Detected size(16384k) larger than the size in the binary image header(4096k)`
- 影响:通常可运行,但不利于后续分区与 OTA 风险控制。
- 已处理并确认:将工程 Flash size 配置调整为 16MB`CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y`),已复测确认告警消失。
## 5. 控制器/遥控器ESP-NOW现状梳理已读源码
- 控制器原码路径:`D:\ESP-LED\控制器原码\Ecolight\...`
- 协议ESP-NOWchannel=1
- Pairing beacon magic`0xABCDEF01`4字节
- 命令1字节
- `0x01` Toggle
- `0x02` On
- `0x03` Brightness Up
- `0x04` Brightness Down
- `0x05` Off
- `0xA5` Pairing Confirm
结论:控制器原码与甲方提供的遥控器一致,且该 ESP-NOW 遥控协议可接入当前 Matter 灯固件C6 端作为 ESPNOW 接收端),收到命令后同步更新 Matter 属性。
## 6. VID/PID/DAC/QR 码阶段性策略
- 开发阶段可以使用示例/测试用的 VID/PID/证书链推进开发。
- 后续拿到正式 VID/PID/DAC 后:
- 替换证书与出厂数据。
- 重新生成 QR。
- 通常需要恢复出厂并重新配网(属正常流程)。
## 7. 下一步开发路线图(按阶段)
### 阶段 A功能验证与参数固化短期
- 单色灯明确硬件定义RGB 混白 vs 单路白灯条),固化白光方案。
- 双色温:已确认 SK6812 RGBW固化色温映射与效果参数端点/曲线/gamma/限幅),并确认通道顺序与供电/信号稳定性。
- 建立功能测试用例并记录:
- endpoint 1开/关、亮度
- endpoint 2开/关、亮度、色温
### 阶段 BESP-NOW + Matter 共存(核心)
- 在 C6 Matter 固件中加入 ESPNOW RX
- 接收 1-byte 命令并映射到 endpoint 1/2 的 Matter 属性更新。
- 目标遥控器控制灯Matter 侧状态同步。
- 解决 Wi-Fi channel 与 ESPNOW channel=1 的冲突(以“遥控器固件不变”为前提):
- 方案 1最小改动但依赖环境路由器/热点 2.4G 固定 `channel=1`
- 方案 2推荐量产架构双芯片/双射频解耦ESP-NOW 固定 ch1 与 Matter Wi-Fi 任意信道互不影响)。
- 方案 3与 Addendum 对齐Wi-Fi 用于 commissioning日常控制走 Thread需要 Thread Border Router 环境),从而避免 Wi-Fi 信道对 ESP-NOW 的牵制。
- 性能目标:端到端延迟 < 20ms需要定义测量方法和基准
### 7.2 芯片选型建议C3 vs C6
- 若坚持单芯片承载 Matter含 Groups/Scenes/OTA/多生态)+ 应用逻辑 + ESPNOW更推荐 ESP32-C6。
- 原因内存与资源更充足Matter 生态适配与稳定性更优,且可扩展 Thread满足 Addendum
- 若控制器仍使用 ESP32-C3需要评估以下风险项
- Matter + BLE commissioning + OTA + Groups/Scenes 的 RAM/Flash 压力。
- 与 ESPNOW 同时运行的峰值内存/任务栈/队列占用。
- 当路由器信道不可控且遥控器固件不变时:
- 单芯片方案存在先天信道冲突。
- 需要硬件/架构调整(例如额外加一颗 C3 专做 ESPNOW 固定 ch1C6 专做 Matter/Wi-Fi/Thread通过 UART/SPI 同步状态)。
### 7.3 方案 A双芯片解耦系统架构量产推荐
#### 7.3.1 总体思路
- MCU1ESP-NOW 控制器,建议 ESP32-C3
- 只负责ESP-NOW固定 ch1、遥控器配对/命令接收、组控广播一致性、驱动输出PWM/RMT/恒流等)。
- 不连接路由器(或不承担 Matter Wi-Fi
- MCU2Matter 控制器,建议 ESP32-C6
- 只负责Matter over Wi-Ficommissioning/长久在线/多生态可选Thread、Matter OTA、Groups/Scenes/状态机。
- 通过 UART/SPI 与 MCU1 交换“控制命令/状态变化/诊断”。
补充确认:本项目采用 UART 作为 MCU1↔MCU2 通信方式。
#### 7.3.2 数据流与一致性目标
- 遥控器 → MCU1ESP-NOW RX
- MCU1 先本地执行灯控(保证延迟与体验不变)
- MCU1 同步上报事件给 MCU2用于 Matter 属性更新与组/场景一致性)
- App/Matter → MCU2属性更新/命令)→ MCU2 下发到 MCU1 → MCU1 执行驱动输出 → MCU1 回报最终状态给 MCU2闭环
#### 7.3.3 量产可测的关键指标
- 遥控器端到端延迟(按键到灯输出):目标 < 20 ms MCU1 本地执行为准
- Matter 状态同步延迟(灯输出到 Matter 属性更新可见):给出目标与测量方法(建议 < 200 ms
- 长期稳定性Wi-Fi/Matter 长久在线,不影响 MCU1 的 ESP-NOW 实时性
#### 7.3.4 PCB/硬件接口建议(小改动范围)
- UART
- MCU1_TX -> MCU2_RXGPIO 待定MCU1=____ / MCU2=____
- MCU1_RX <- MCU2_TXGPIO 待定MCU1=____ / MCU2=____
- 可选硬件流控(建议预留焊盘,量产可按稳定性决定是否启用):
- MCU2->MCU1 `RESET_REQ`(请求 MCU1 执行:清码/恢复出厂/重新配对/进入测试)
- MCU1->MCU2 `IRQ_EVT`(有新事件/状态上报,降低轮询开销)
- 电平:两者均为 3.3V TTL无需电平转换
- 调试建议预留测试点TX/RX/GND便于产线与现场抓包
## 8. 测试计划(面向交付物)
### 8.1 遥控器 + ESP-NOW不改固件
- 工厂重置:三次断电/复位触发工厂重置(含 5 秒确认窗)
- 配对:五次断电/复位进入配对模式;遥控器 slot 长按配对
- 单控0x01..0x05 全命令覆盖,重复按键/长按/连发
- 组控:遥控器广播组命令,多个控制器同步输出一致
- 延迟:示波器/逻辑分析仪测量(按键触发到 GPIO/PWM 变化),记录 P50/P95
### 8.2 Matter 多生态MCU2
- Apple Home / Google Home / Alexa至少两项commissioning 演示
- ClustersOnOff/LevelControl/Groups/Scenes双色温含 ColorControl
- OTA升级演示 + 回滚验证
### 8.3 共存与稳定性
- Wi-Fi 长久在线24h/72h期间遥控器控制无明显延迟/无丢包异常
- 异常恢复:
- MCU1 重启不影响 MCU2Matter 仍在线;状态恢复后同步)
- MCU2 重启不影响 MCU1遥控器控制不中断MCU2 恢复后重新拉取状态)
## 9. Matter 功能测试用例(建议用 chip-tool 记录)
### Endpoint 1单色灯开关/调光)
```bash
chip-tool onoff on 1 1
chip-tool onoff off 1 1
chip-tool levelcontrol movetolevelwithonoff 1 1 10 0 0
chip-tool levelcontrol movetolevelwithonoff 1 1 200 0 0
```
### Endpoint 2双色温灯开关/调光/色温)
```bash
chip-tool onoff on 1 2
chip-tool onoff off 1 2
chip-tool levelcontrol movetolevelwithonoff 1 2 20 0 0
chip-tool levelcontrol movetolevelwithonoff 1 2 220 0 0
chip-tool colorcontrol movetocolortemperature 1 2 153 0 0
chip-tool colorcontrol movetocolortemperature 1 2 450 0 0
```
## 10. 风险与注意事项
- ESPNOW channel 固定为 1当路由器信道不可固定到 1 且遥控器固件不可改时,单芯片方案存在先天冲突,需要改架构。
- 单色灯“白光”体验可能受硬件RGB 三色灯珠)限制,软件无法消除近距离三色颗粒。
- 双色温SK6812 RGBW“色温”为近似实现不同亮度下可能存在色偏需要通过端点/曲线/gamma 与 RGB/W 分配进行校准。
- Thread + Wi-Fi 混合网络模式需要明确最终产品拓扑与测试方法。
## 11. MCU 间通信协议草案(方案 A
### 11.1 物理层与链路建议
- UART建议 921600 或 1Mbps8N1
- 帧格式:固定 header + version + flags + type + seq + len + payload + CRC32
- 可靠性建议:
- 带 `seq``ACK`(至少对“状态设置/模式切换/工厂重置”等关键命令)
- 对“按键事件上报”可不必 ACK但需要丢包容忍MCU2 以 MCU1 的最终状态为准)
### 11.1.1 帧格式(建议稿,可直接实现)
- `SOF`2 bytes固定 `0x55 0xAA`
- `VER`1 byte协议版本初版 `0x01`
- `FLAGS`1 byte
- bit0是否需要 ACK
- bit1是否为 ACK 包
- bit2错误包
- bit3..7:预留
- `TYPE`1 byte消息类型
- `SEQ`2 bytes递增序号小端
- `LEN`2 bytespayload 长度小端0..1024 建议上限)
- `PAYLOAD`LEN bytes
- `CRC32`4 bytes对从 `VER``PAYLOAD` 的 CRC32小端
### 11.1.2 ACK/重试/超时(建议稿)
- 对 `FLAGS.need_ack=1` 的包:
- 接收方在成功处理后回 `ACK` 包(`FLAGS.is_ack=1``SEQ` 原样回显,`TYPE`=原 TYPE 或 `TYPE=ACK(0x7F)` 二选一)
- 发送方超时 `T_ACK=50ms` 未收到 ACK重发最多 `N_RETRY=3`
- 连续失败后进入降级策略:记录错误计数并上报 `EVT_DIAG`(或触发重新握手)
- 对 `EVT_KEY_CMD`:可 `need_ack=0`(允许丢);但要求 MCU1 后续用 `EVT_LOCAL_STATE` 做闭环状态同步
### 11.1.3 上电/复位握手(建议稿)
- MCU2 启动后发送 `HELLO`(包含 MCU2 fw_ver/proto_ver/boot_reason
- MCU1 回 `HELLO_RSP`(包含 MCU1 fw_ver/proto_ver、灯型/能力、当前输出状态摘要)
- MCU2 收到后发送 `GET_STATE`(拉取完整状态),并以此刷新 Matter 属性(避免 MCU2 重启后状态漂移)
### 11.2 消息类型(最小集)
- `EVT_KEY_CMD`MCU1→MCU2遥控器命令事件
- 字段cmd(0x01..0x05/扩展)、src_mac、timestamp、group_mode/slot
- `EVT_LOCAL_STATE`MCU1→MCU2MCU1 本地执行后的最终状态
- 字段endpoint/light_id、onoff、level、cct如有、transition_time
- `SET_STATE`MCU2→MCU1来自 Matter 的控制请求
- 字段:目标灯/组、onoff/level/cct、期望渐变时间
- `SET_MODE`MCU2→MCU1模式切换配对、清码、恢复出厂、进入测试模式
- `HEARTBEAT`双向存活与版本信息fw_ver、proto_ver、uptime、heap
建议补充类型:
- `GET_STATE`MCU2→MCU1请求 MCU1 上报完整状态
- `EVT_DIAG`(双向):错误码/计数器CRC 错、丢包、重试次数、WDT、重启原因
### 11.2.1 字段定义建议(便于落地与调试)
- `light_id`1 byte
- `0x01` 单色灯
- `0x02` 双色温灯
- `onoff`1 byte0/1
- `level`1 byte0..254,按 Matter 约定)
- `cct_mireds`2 bytes小端按 Matter ColorTemperatureMireds
- `transition_ms`2 bytes小端
- `timestamp_ms`4 bytes小端MCU1 uptime 毫秒)
### 11.3 一致性原则(避免双写打架)
- MCU1 为“灯输出唯一权威”source of truth for physical output
- MCU2 为“ Matter 属性权威”source of truth for ecosystem state
- MCU2 更新 Matter 属性应以 `EVT_LOCAL_STATE` 为准,而不是以 `EVT_KEY_CMD` 直接推导(防止执行失败/限幅/场景叠加导致不一致)。
## 11.4 PCB 连线清单(方案 AUART
- UART
- MCU1_TX -> MCU2_RXGPIO 待定MCU1=____ / MCU2=____
- MCU1_RX <- MCU2_TXGPIO 待定MCU1=____ / MCU2=____
- 可选硬件流控(建议预留焊盘,量产可按稳定性决定是否启用):
- MCU1_RTS / MCU1_CTS
- MCU2_RTS / MCU2_CTS
- 额外控制/中断线(建议预留):
- MCU2->MCU1 `RESET_REQ`(请求 MCU1 执行:清码/恢复出厂/重新配对/进入测试)
- MCU1->MCU2 `IRQ_EVT`(有新事件/状态上报,降低轮询开销)
- 电平:两者均为 3.3V TTL无需电平转换
- 调试建议预留测试点TX/RX/GND便于产线与现场抓包
## 13. 可对外汇报摘要(可直接发甲方)
本阶段已完成 ESP32-C6 Matter + ESP-NOW 混合固件的核心功能联调:固件已实现双 endpoint单色灯 + 双色温灯)并通过 iOS Home 完成 Matter commissioning 与控制验证;同时接入甲方量产遥控器的 ESP-NOW 协议channel=1、命令 0x01..0x05/0xA5可通过“5 次重启进入配对模式 + 遥控器 Zone 配对”实现一台遥控器Zone1/Zone2分别绑定两台 ESP32-C6 灯具。当前 APPiOS Home与遥控器均可对两台设备进行控制设备支持 HTTP OTA远程服务器下载升级支持双 OTA 分区切换),已验证升级后版本号变化。下一步将推进 Google Home/Alexa/RainMaker 等生态兼容性测试,并固化交付脚本、测试报告与完整技术文档。

View File

@ -0,0 +1,40 @@
# Light
This example creates a Color Temperature Light device using the ESP
Matter data model.
See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html) for more information about building and flashing the firmware.
## 1. Additional Environment Setup
No additional setup is required.
## 2. Post Commissioning Setup
No additional setup is required.
## 3. Device Performance
### 3.1 Memory usage
The following is the Memory and Flash Usage.
- `Bootup` == Device just finished booting up. Device is not
commissionined or connected to wifi yet.
- `After Commissioning` == Device is conneted to wifi and is also
commissioned and is rebooted.
- device used: esp32c3_devkit_m
- tested on:
[6a244a7](https://github.com/espressif/esp-matter/commit/6a244a7b1e5c70b0aa1bf57254f19718b0755d95)
(2022-06-16)
| | Bootup | After Commissioning |
|:- |:-: |:-: |
|**Free Internal Memory** |108KB |105KB |
**Flash Usage**: Firmware binary size: 1.26MB
This should give you a good idea about the amount of free memory that is
available for you to run your application's code.
Applications that do not require BLE post commissioning, can disable it using app_ble_disable() once commissioning is complete. It is not done explicitly because of a known issue with esp32c3 and will be fixed with the next IDF release (v4.4.2).

View File

@ -0,0 +1,59 @@
CONFIG_IDF_TARGET="esp32c5"
# libsodium
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# NIMBLE
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
# Enable OpenThread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_DNS_CLIENT=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_CLI=n
# Disable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=n
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
# LwIP config for OpenThread
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
# Enable OTA Requestor
CONFIG_ENABLE_OTA_REQUESTOR=y
# Disable STA for ESP32C5
CONFIG_ENABLE_WIFI_STATION=n
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
# ESP32-C5-DevKitC-1 Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=28
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=1
CONFIG_BSP_LED_TYPE_RGB=y
CONFIG_BSP_LED_RGB_GPIO=27
CONFIG_BSP_LED_RGB_BACKEND_RMT=y

View File

@ -0,0 +1,59 @@
CONFIG_IDF_TARGET="esp32c5"
# libsodium
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# NIMBLE
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
# Enable OpenThread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_DNS_CLIENT=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_CLI=n
# Disable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=n
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
# LwIP config for OpenThread
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
# Enable OTA Requestor
CONFIG_ENABLE_OTA_REQUESTOR=y
# Disable STA for ESP32C5
CONFIG_ENABLE_WIFI_STATION=n
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
# ESP32-C5-DevKitC-1 Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=28
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=1
CONFIG_BSP_LED_TYPE_RGB=y
CONFIG_BSP_LED_RGB_GPIO=27
CONFIG_BSP_LED_RGB_BACKEND_RMT=y

View File

@ -0,0 +1,75 @@
CONFIG_IDF_TARGET="esp32c5"
# libsodium
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# NIMBLE
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
# Enable OpenThread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_DNS_CLIENT=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_CLI=n
# Disable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=n
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
# This example use 3 dynamic endpoints: RootNode, light, and secondary network commissioning
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=3
# LwIP config for OpenThread
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
# Enable OTA Requestor
CONFIG_ENABLE_OTA_REQUESTOR=y
# Disable AP
CONFIG_ENABLE_WIFI_STATION=y
CONFIG_ENABLE_WIFI_AP=n
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
# ESP32-C5-DevKitC-1 Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=28
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=1
CONFIG_BSP_LED_TYPE_RGB=y
CONFIG_BSP_LED_RGB_GPIO=27
CONFIG_BSP_LED_RGB_BACKEND_RMT=y
# Firmware size optimization
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y
CONFIG_NEWLIB_NANO_FORMAT=y
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
# Set endpoint id for Thread and Wi-Fi, depending on the secondary network interface endpoint id.
CONFIG_THREAD_NETWORK_ENDPOINT_ID=2
CONFIG_WIFI_NETWORK_ENDPOINT_ID=0

View File

@ -0,0 +1,75 @@
CONFIG_IDF_TARGET="esp32c5"
# libsodium
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# NIMBLE
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
# Enable OpenThread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_DNS_CLIENT=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_CLI=n
# Disable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=n
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
# This example use 3 dynamic endpoints: RootNode, light, and secondary network commissioning
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=3
# LwIP config for OpenThread
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
# Enable OTA Requestor
CONFIG_ENABLE_OTA_REQUESTOR=y
# Disable AP
CONFIG_ENABLE_WIFI_STATION=y
CONFIG_ENABLE_WIFI_AP=n
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
# ESP32-C5-DevKitC-1 Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=28
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=1
CONFIG_BSP_LED_TYPE_RGB=y
CONFIG_BSP_LED_RGB_GPIO=27
CONFIG_BSP_LED_RGB_BACKEND_RMT=y
# Firmware size optimization
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y
CONFIG_NEWLIB_NANO_FORMAT=y
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
# Set endpoint id for Thread and Wi-Fi, depending on the secondary network interface endpoint id.
CONFIG_THREAD_NETWORK_ENDPOINT_ID=2
CONFIG_WIFI_NETWORK_ENDPOINT_ID=0

View File

@ -0,0 +1,59 @@
CONFIG_IDF_TARGET="esp32c6"
# libsodium
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# NIMBLE
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
# Enable OpenThread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_DNS_CLIENT=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_CLI=n
# Disable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=n
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
# LwIP config for OpenThread
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
# Enable OTA Requestor
CONFIG_ENABLE_OTA_REQUESTOR=y
# Disable STA for ESP32C6
CONFIG_ENABLE_WIFI_STATION=n
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
# ESP32-C6-DevKitM-1 Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=9
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=1
CONFIG_BSP_LED_TYPE_RGB=y
CONFIG_BSP_LED_RGB_GPIO=8
CONFIG_BSP_LED_RGB_BACKEND_RMT=y

View File

@ -0,0 +1,75 @@
CONFIG_IDF_TARGET="esp32c6"
# libsodium
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# NIMBLE
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
# Enable OpenThread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_DNS_CLIENT=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_CLI=n
# Disable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=n
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
# LwIP config for OpenThread
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
# Enable OTA Requestor
CONFIG_ENABLE_OTA_REQUESTOR=y
# Disable AP
CONFIG_ENABLE_WIFI_STATION=y
CONFIG_ENABLE_WIFI_AP=n
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
# This example use 3 dynamic endpoints: RootNode, light, and secondary network commissioning
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=3
# ESP32-C6-DevKitM-1 Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=9
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=1
CONFIG_BSP_LED_TYPE_RGB=y
CONFIG_BSP_LED_RGB_GPIO=8
CONFIG_BSP_LED_RGB_BACKEND_RMT=y
# Firmware size optimization
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y
CONFIG_NEWLIB_NANO_FORMAT=y
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
# Set endpoint id for Thread and Wi-Fi, depending on the secondary network interface endpoint id.
CONFIG_THREAD_NETWORK_ENDPOINT_ID=2
CONFIG_WIFI_NETWORK_ENDPOINT_ID=0

View File

@ -0,0 +1,174 @@
CONFIG_IDF_TARGET="esp32c2"
# Compiler options
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
## NimBLE Options
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
CONFIG_BT_NIMBLE_MAX_BONDS=2
CONFIG_BT_NIMBLE_MAX_CCCDS=2
CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=3072
CONFIG_BT_NIMBLE_ROLE_CENTRAL=n
CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=n
CONFIG_BT_NIMBLE_WHITELIST_SIZE=1
CONFIG_BT_NIMBLE_GATT_MAX_PROCS=1
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=10
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE=100
CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=4
CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE=320
CONFIG_BT_NIMBLE_ACL_BUF_COUNT=5
CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=5
CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=3
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
## Controller Options
CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE=3072
CONFIG_BT_LE_LL_RESOLV_LIST_SIZE=1
CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT=1
# Release BT IRAM memory
CONFIG_BT_RELEASE_IRAM=y
# SPI Configuration
CONFIG_SPI_MASTER_ISR_IN_IRAM=n
CONFIG_SPI_SLAVE_ISR_IN_IRAM=n
# Ethernet
CONFIG_ETH_USE_SPI_ETHERNET=n
# Event Loop Library
CONFIG_ESP_EVENT_POST_FROM_ISR=n
# Chip revision
CONFIG_ESP32C2_REV2_DEVELOPMENT=y
# Main XTAL Config
CONFIG_XTAL_FREQ_26=y
CONFIG_XTAL_FREQ_40=n
# ESP Ringbuf
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH=y
# ESP System Settings
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=16
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3072
## Memory protection
CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT=n
# High resolution timer (esp_timer)
CONFIG_ESP_TIMER_TASK_STACK_SIZE=2048
# Wi-Fi
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=n
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=3
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=6
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=6
CONFIG_ESP32_WIFI_IRAM_OPT=n
CONFIG_ESP32_WIFI_RX_IRAM_OPT=n
CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=n
CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=n
CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=n
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
# FreeRTOS
## Kernel
CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
## Port
CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=n
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
# Hardware Abstraction Layer (HAL) and Low Level (LL)
CONFIG_HAL_ASSERTION_DISABLE=y
# LWIP
CONFIG_LWIP_IPV4=n
CONFIG_LWIP_MAX_SOCKETS=5
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16
CONFIG_LWIP_DHCPS=n
CONFIG_LWIP_IPV6_AUTOCONFIG=y
CONFIG_LWIP_MAX_ACTIVE_TCP=5
CONFIG_LWIP_MAX_LISTENING_TCP=5
CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=n
CONFIG_LWIP_TCP_SYNMAXRTX=12
CONFIG_LWIP_TCP_MSL=40000
CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=16000
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=4096
CONFIG_LWIP_TCP_WND_DEFAULT=2440
CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS=y
CONFIG_LWIP_TCP_RTO_TIME=1500
CONFIG_LWIP_MAX_UDP_PCBS=8
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2560
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
# mbedTLS
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y
CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH=y
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=n
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
CONFIG_MBEDTLS_TLS_CLIENT_ONLY=y
CONFIG_MBEDTLS_SSL_PROTO_SSL3=n
CONFIG_MBEDTLS_SSL_PROTO_TLS1=n
CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=n
# ESP-MQTT Configurations
CONFIG_MQTT_PROTOCOL_311=n
# Protocomm
CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=n
CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=n
# SPI Flash driver
CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=n
CONFIG_SPI_FLASH_ROM_IMPL=y
# Websocket
CONFIG_WS_TRANSPORT=n
# Virtual file system
CONFIG_VFS_SUPPORT_DIR=n
CONFIG_VFS_SUPPORT_SELECT=n
CONFIG_VFS_SUPPORT_TERMIOS=n
# Wear Levelling
CONFIG_WL_SECTOR_SIZE_512=y
# CHIP Core
## General Options
CONFIG_MAX_EXCHANGE_CONTEXTS=6
CONFIG_MAX_BINDINGS=6
CONFIG_MAX_PEER_NODES=12
CONFIG_MAX_UNSOLICITED_MESSAGE_HANDLERS=6
CONFIG_ENABLE_CHIP_SHELL=n
CONFIG_DISABLE_IPV4=y
CONFIG_BUILD_CHIP_TESTS=n
## Networking Options
CONFIG_NUM_TCP_ENDPOINTS=1
CONFIG_NUM_UDP_ENDPOINTS=6
## System Options
CONFIG_NUM_TIMERS=24
CONFIG_ENABLE_OTA_REQUESTOR=y
# CHIP Device Layer
## General Options
CONFIG_CHIP_TASK_STACK_SIZE=7168
CONFIG_MAX_EVENT_QUEUE_SIZE=20
## Event Logging Options
CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE=256
CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE=256
CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE=256
# ESP Matter
CONFIG_ESP_MATTER_MAX_DEVICE_TYPE_COUNT=4
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=4

View File

@ -0,0 +1,4 @@
# CMake Utilities
CONFIG_CU_RELINKER_ENABLE=y
CONFIG_CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES=y
CONFIG_CU_RELINKER_CUSTOMIZED_CONFIGURATION_FILES_PATH="../common/relinker/esp32c2_v5.1"

View File

@ -0,0 +1,4 @@
# CMake Utilities
CONFIG_CU_RELINKER_ENABLE=y
CONFIG_CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES=y
CONFIG_CU_RELINKER_CUSTOMIZED_CONFIGURATION_FILES_PATH="../common/relinker/esp32c2_v5.2"

View File

@ -0,0 +1,4 @@
# CMake Utilities
CONFIG_CU_RELINKER_ENABLE=y
CONFIG_CU_RELINKER_ENABLE_CUSTOMIZED_CONFIGURATION_FILES=y
CONFIG_CU_RELINKER_CUSTOMIZED_CONFIGURATION_FILES_PATH="../common/relinker/esp32c2_v5.4"

View File

@ -0,0 +1,14 @@
CONFIG_IDF_TARGET="esp32c3"
# ESP32-C3-DevKitC-02 Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=9
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=1
CONFIG_BSP_LED_TYPE_RGB=y
CONFIG_BSP_LED_RGB_GPIO=8
CONFIG_BSP_LED_RGB_BACKEND_RMT=y

View File

@ -0,0 +1 @@
CONFIG_IDF_TARGET="esp32c5"

View File

@ -0,0 +1,10 @@
CONFIG_IDF_TARGET="esp32c61"
# ESP Ringbuf
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH=y
# FreeRTOS
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n

View File

@ -0,0 +1,21 @@
CONFIG_IDF_TARGET="esp32h2"
# Enable OpenThread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_CLI=n
# Disable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=n
# LwIP config for OpenThread
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
# Disable STA
CONFIG_ENABLE_WIFI_STATION=n

View File

@ -0,0 +1,17 @@
CONFIG_IDF_TARGET="esp32p4"
# Enable BLE Host but use remote controller
CONFIG_BT_NIMBLE_TRANSPORT_UART=n
CONFIG_ESP_ENABLE_BT=y
# Increase main task stack size
CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096
# Do not deinit BLE after commissioning
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n
# ESP32-P4 Function EV Board use ESP32C6 as slave device
CONFIG_SLAVE_IDF_TARGET_ESP32C6=y
# BSP button
CONFIG_BSP_BUTTON_1_GPIO=35

View File

@ -0,0 +1 @@
CONFIG_IDF_TARGET="esp32s3"

View File

@ -0,0 +1,46 @@
# Default to 921600 baud when flashing and monitoring device
CONFIG_ESPTOOLPY_BAUD_921600B=y
CONFIG_ESPTOOLPY_BAUD=921600
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
#enable BT
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
#disable BT connection reattempt
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
#enable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=y
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
# Disable chip tests
CONFIG_BUILD_CHIP_TESTS=n
#enable lwIP route hooks
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# External Platform
CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM=y
CONFIG_CHIP_EXTERNAL_PLATFORM_DIR="../../../../../platform/ESP32_custom"
CONFIG_CHIP_EXTERNAL_PLATFORM_INCLUDE_DIR="../../../../.."
# disable softap by default
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
# Disable DS Peripheral
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
# Enable HKDF in mbedtls
CONFIG_MBEDTLS_HKDF_C=y

View File

@ -0,0 +1,59 @@
# Default to 921600 baud when flashing and monitoring device
CONFIG_ESPTOOLPY_BAUD_921600B=y
CONFIG_ESPTOOLPY_BAUD=921600
CONFIG_ESPTOOLPY_COMPRESSED=y
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
#enable BT
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
#disable BT connection reattempt
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
#enable lwip ipv6 autoconfig
CONFIG_LWIP_IPV6_AUTOCONFIG=y
# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
# Disable chip shell
CONFIG_ENABLE_CHIP_SHELL=n
# Disable chip tests
CONFIG_BUILD_CHIP_TESTS=n
#enable lwIP route hooks
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
# Button
CONFIG_BUTTON_PERIOD_TIME_MS=20
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
# External Platform
CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM=y
CONFIG_CHIP_EXTERNAL_PLATFORM_DIR="../../../../../builds/app-frameworks/platform/ESP32_custom"
CONFIG_CHIP_EXTERNAL_PLATFORM_INCLUDE_DIR="../../../../../builds/app-frameworks/"
# disable softap by default
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
# Disable DS Peripheral
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
# Enable HKDF in mbedtls
CONFIG_MBEDTLS_HKDF_C=y
# ESP32-DevKit Settings
# Buttons
CONFIG_BSP_BUTTONS_NUM=1
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
CONFIG_BSP_BUTTON_1_GPIO=0
CONFIG_BSP_BUTTON_1_LEVEL=0
# LEDs
CONFIG_BSP_LEDS_NUM=0

View File

@ -0,0 +1 @@
CONFIG_ENABLE_CHIP_SHELL=n

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
dependencies:
espressif/button:
component_hash: fccb18c37f1cfe0797b74a53a44d3f400f5fd01f4993b40052dfb7f401915089
dependencies:
- name: espressif/cmake_utilities
registry_url: https://components.espressif.com
require: private
version: '*'
- name: idf
require: private
version: '>=4.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 4.1.5
espressif/cbor:
component_hash: dad9ca860963e930366510a10b422b3125a4fb27b979712ed65efcbcd742de50
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com
type: service
version: 0.6.1~4
espressif/cmake_utilities:
component_hash: 05165f30922b422b4b90c08845e6d449329b97370fbd06309803d8cb539d79e3
dependencies:
- name: idf
require: private
version: '>=4.1'
source:
registry_url: https://components.espressif.com
type: service
version: 1.1.1
espressif/esp-serial-flasher:
component_hash: dcc42a16712a1a636509cf0bf90e14032d7f2141784b533613b267b6aa318d52
dependencies: []
source:
registry_url: https://components.espressif.com
type: service
version: 0.0.11
espressif/esp_delta_ota:
component_hash: 147161b602ef51e9f6649eb6d90c4d4ac3c94228cb264fa0e68be7877180462d
dependencies:
- name: idf
require: private
version: '>=4.3'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.1.4
espressif/esp_diag_data_store:
component_hash: 93f20de81abb791b4482f1bc99afdc24b25c3ee42aacceeb636e9943e677b1c5
dependencies:
- name: idf
require: private
version: '>=5.1'
source:
registry_url: https://components.espressif.com
type: service
version: 1.1.0
espressif/esp_diagnostics:
component_hash: 405803b11fbccfd9c8a26df0b1228081f588ffdb7d1e0c754300e7a2c6241aab
dependencies:
- name: espressif/rmaker_common
registry_url: https://components.espressif.com
require: private
version: ~1.5.0
- name: idf
require: private
version: '>=5.1'
source:
registry_url: https://components.espressif.com
type: service
version: 1.3.0
espressif/esp_encrypted_img:
component_hash: e5a065c140fbc6a69a1de4fa1731b7596cc34a4a50b57913b2dc34c9ad3a0a70
dependencies:
- name: idf
require: private
version: '>=4.4'
source:
registry_url: https://components.espressif.com/
type: service
version: 2.3.0
espressif/esp_insights:
component_hash: 5a394c1eacddff2dbeff840abb0108ad5f54fb076048520b50c3f4a9b59415fe
dependencies:
- name: espressif/cbor
registry_url: https://components.espressif.com
require: private
version: ~0.6
- name: espressif/esp_diag_data_store
registry_url: https://components.espressif.com
require: private
version: 1.1.0
- name: espressif/esp_diagnostics
registry_url: https://components.espressif.com
require: private
version: '>=1.3.0'
- name: espressif/rmaker_common
registry_url: https://components.espressif.com
require: private
version: ~1.5.0
- name: idf
require: private
version: '>=5.1'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.3.1
espressif/esp_rcp_update:
component_hash: 37f535edd527a45faeaad649c0c56af36e5399074e52d83f0990fce466844dde
dependencies:
- name: espressif/esp-serial-flasher
registry_url: https://components.espressif.com
require: private
version: ~0.0.0
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.3.1
espressif/esp_secure_cert_mgr:
component_hash: e8ce8d5ac0ef4ef5df12fdb266190413c4170ad39b394435f0e3115a4fddc6a6
dependencies:
- name: idf
require: private
version: '>=4.3'
source:
registry_url: https://components.espressif.com/
type: service
version: 2.7.2
espressif/jsmn:
component_hash: d80350c41bbaa827c98a25b6072df00884e72f54885996fab4a4f0aebce6b6c3
dependencies:
- name: idf
require: private
version: '>=4.3'
source:
registry_url: https://components.espressif.com
type: service
version: 1.1.0
espressif/json_generator:
component_hash: 45033e1c199b13f1c8c1b544fb7d4e2df6a8e3071ebdcb1b22582b61a7974ff2
dependencies: []
source:
registry_url: https://components.espressif.com/
type: service
version: 1.1.2
espressif/json_parser:
component_hash: d74b81729ad06ec11ff5eb5b1b0d7df1d00e6027fc11471f4b139c70dcf1b1e4
dependencies:
- name: espressif/jsmn
registry_url: https://components.espressif.com
require: private
rules:
- if: idf_version >=5.0
version: ~1.1
source:
registry_url: https://components.espressif.com/
type: service
version: 1.0.3
espressif/led_strip:
component_hash: e8179c56057c243e80a8286c39361eb4bef33e42eb5f7fc841ea877597ca13f7
dependencies: []
source:
registry_url: https://components.espressif.com/
type: service
version: 1.0.0
espressif/mdns:
component_hash: 29e47564b1a7ee778135e17fbbf2a2773f71c97ebabfe626c8eda7c958a7ad16
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 1.9.1
espressif/rmaker_common:
component_hash: 842d2aaf486a24f11827a86b1147ee8ac7e1881f45e3d65a2141aff5bcbf276a
dependencies:
- name: idf
require: private
version: '>=5.1'
source:
registry_url: https://components.espressif.com
type: service
version: 1.5.3
idf:
source:
type: idf
version: 5.5.1
direct_dependencies:
- espressif/button
- espressif/esp_delta_ota
- espressif/esp_encrypted_img
- espressif/esp_insights
- espressif/esp_rcp_update
- espressif/esp_secure_cert_mgr
- espressif/json_generator
- espressif/json_parser
- espressif/led_strip
- espressif/mdns
manifest_hash: c15eaa367fc776fc22627b4c6568183a61ea17ab6b629ec496d666a22ea0947a
target: esp32c6
version: 2.0.0

View File

@ -0,0 +1,14 @@
idf_component_register(SRC_DIRS "."
PRIV_INCLUDE_DIRS "." "../../OTA" "${ESP_MATTER_PATH}/examples/common/utils"
PRIV_REQUIRES app_update esp_http_client
esp_wifi esp_event esp_netif esp_timer nvs_flash
esp_matter esp_matter_console
device button app_reset)
if (CONFIG_ENABLE_SET_CERT_DECLARATION_API)
target_add_binary_data(${COMPONENT_TARGET} "certification_declaration/certification_declaration.der" BINARY)
endif()
target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H")
target_sources(${COMPONENT_LIB} PRIVATE "../../OTA/OtaManager.cpp")

View File

@ -0,0 +1,11 @@
menu "Example Configuration"
config ENABLE_MEMORY_PROFILING
bool "Enable Memory Profiling"
default n
help
Enable this option to include memory profiling features in the example.
This will allow you to monitor memory usage during runtime.
endmenu

View File

@ -0,0 +1,542 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_log.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <esp_matter.h>
#include <app_priv.h>
#include <common_macros.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/ledc.h>
#include <driver/rmt.h>
#include <device.h>
#include <button_gpio.h>
using namespace chip::app::Clusters;
using namespace esp_matter;
static const char *TAG = "app_driver";
extern uint16_t rgb_light_endpoint_id;
extern uint16_t cct_light_endpoint_id;
// Global variables to store current XY color coordinates
static uint16_t current_x = 0;
static uint16_t current_y = 0;
typedef enum {
APP_LIGHT_TYPE_RGB_PWM = 1,
APP_LIGHT_TYPE_SK6812 = 2,
} app_light_type_t;
typedef struct {
app_light_type_t type;
bool power;
uint8_t brightness;
} app_rgb_pwm_light_t;
typedef struct {
app_light_type_t type;
bool power;
uint8_t brightness;
uint32_t temperature_kelvin;
rmt_channel_t rmt_channel;
uint32_t strip_len;
uint8_t *buffer;
} app_sk6812_light_t;
static void kelvin_to_rgb(uint32_t kelvin, uint8_t *out_r, uint8_t *out_g, uint8_t *out_b)
{
if (!out_r || !out_g || !out_b) {
return;
}
if (kelvin < 1000) {
kelvin = 1000;
}
if (kelvin > 40000) {
kelvin = 40000;
}
float temp = (float)kelvin / 100.0f;
float r;
float g;
float b;
if (temp <= 66.0f) {
r = 255.0f;
g = 99.4708025861f * logf(temp) - 161.1195681661f;
if (temp <= 19.0f) {
b = 0.0f;
} else {
b = 138.5177312231f * logf(temp - 10.0f) - 305.0447927307f;
}
} else {
r = 329.698727446f * powf(temp - 60.0f, -0.1332047592f);
g = 288.1221695283f * powf(temp - 60.0f, -0.0755148492f);
b = 255.0f;
}
if (r < 0.0f) r = 0.0f;
if (r > 255.0f) r = 255.0f;
if (g < 0.0f) g = 0.0f;
if (g > 255.0f) g = 255.0f;
if (b < 0.0f) b = 0.0f;
if (b > 255.0f) b = 255.0f;
*out_r = (uint8_t)r;
*out_g = (uint8_t)g;
*out_b = (uint8_t)b;
}
static esp_err_t rgb_pwm_apply(app_rgb_pwm_light_t *light)
{
if (!light) {
return ESP_ERR_INVALID_ARG;
}
const uint32_t max_duty = (1U << 13) - 1;
uint32_t duty = 0;
if (light->power) {
duty = ((uint32_t)light->brightness * max_duty) / 100;
}
const uint32_t white_r_scale = 100;
const uint32_t white_g_scale = 100;
const uint32_t white_b_scale = 100;
uint32_t duty_r = (duty * white_r_scale) / 100;
uint32_t duty_g = (duty * white_g_scale) / 100;
uint32_t duty_b = (duty * white_b_scale) / 100;
if (duty_r > max_duty) duty_r = max_duty;
if (duty_g > max_duty) duty_g = max_duty;
if (duty_b > max_duty) duty_b = max_duty;
// Common-anode RGB module: LED is ON when GPIO is LOW. So invert duty in software.
uint32_t duty_r_inv = max_duty - duty_r;
uint32_t duty_g_inv = max_duty - duty_g;
uint32_t duty_b_inv = max_duty - duty_b;
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty_r_inv);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, duty_g_inv);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1);
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2, duty_b_inv);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_2);
return ESP_OK;
}
static uint32_t ws_t0h_ticks = 0;
static uint32_t ws_t1h_ticks = 0;
static uint32_t ws_t0l_ticks = 0;
static uint32_t ws_t1l_ticks = 0;
static void IRAM_ATTR ws2812_like_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num,
size_t *translated_size, size_t *item_num)
{
if (src == NULL || dest == NULL) {
*translated_size = 0;
*item_num = 0;
return;
}
const rmt_item32_t bit0 = {{{ ws_t0h_ticks, 1, ws_t0l_ticks, 0 }}};
const rmt_item32_t bit1 = {{{ ws_t1h_ticks, 1, ws_t1l_ticks, 0 }}};
size_t size = 0;
size_t num = 0;
const uint8_t *psrc = (const uint8_t *)src;
rmt_item32_t *pdest = dest;
while (size < src_size && num < wanted_num) {
for (int i = 0; i < 8; i++) {
if (*psrc & (1 << (7 - i))) {
pdest->val = bit1.val;
} else {
pdest->val = bit0.val;
}
num++;
pdest++;
}
size++;
psrc++;
}
*translated_size = size;
*item_num = num;
}
static esp_err_t sk6812_apply(app_sk6812_light_t *light)
{
if (!light || !light->buffer) {
return ESP_ERR_INVALID_ARG;
}
uint8_t r = 0;
uint8_t g = 0;
uint8_t b = 0;
uint8_t w = 0;
if (light->power) {
kelvin_to_rgb(light->temperature_kelvin, &r, &g, &b);
const uint32_t scale = light->brightness;
r = (uint8_t)(((uint32_t)r * scale) / 100);
g = (uint8_t)(((uint32_t)g * scale) / 100);
b = (uint8_t)(((uint32_t)b * scale) / 100);
w = 0;
}
// SK6812 RGBW byte order is commonly GRBW
for (uint32_t i = 0; i < light->strip_len; i++) {
uint32_t start = i * 4;
light->buffer[start + 0] = g;
light->buffer[start + 1] = r;
light->buffer[start + 2] = b;
light->buffer[start + 3] = w;
}
esp_err_t ret = rmt_write_sample(light->rmt_channel, light->buffer, light->strip_len * 4, true);
if (ret != ESP_OK) {
return ret;
}
return rmt_wait_tx_done(light->rmt_channel, pdMS_TO_TICKS(100));
}
/* Do any conversions/remapping for the actual value here */
static esp_err_t app_driver_light_set_power(app_driver_handle_t handle, esp_matter_attr_val_t *val)
{
if (!handle) {
return ESP_OK;
}
if (!val) {
return ESP_ERR_INVALID_ARG;
}
app_light_type_t type = ((app_rgb_pwm_light_t *)handle)->type;
if (type == APP_LIGHT_TYPE_RGB_PWM) {
app_rgb_pwm_light_t *h = (app_rgb_pwm_light_t *)handle;
h->power = val->val.b;
return rgb_pwm_apply(h);
}
if (type == APP_LIGHT_TYPE_SK6812) {
app_sk6812_light_t *h = (app_sk6812_light_t *)handle;
h->power = val->val.b;
return sk6812_apply(h);
}
return ESP_ERR_INVALID_ARG;
}
static esp_err_t app_driver_light_set_brightness(app_driver_handle_t handle, esp_matter_attr_val_t *val)
{
if (!handle) {
return ESP_OK;
}
int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS);
if (value < 0) {
value = 0;
}
if (value > 100) {
value = 100;
}
app_light_type_t type = ((app_rgb_pwm_light_t *)handle)->type;
if (type == APP_LIGHT_TYPE_RGB_PWM) {
app_rgb_pwm_light_t *h = (app_rgb_pwm_light_t *)handle;
h->brightness = (uint8_t)value;
return rgb_pwm_apply(h);
}
if (type == APP_LIGHT_TYPE_SK6812) {
app_sk6812_light_t *h = (app_sk6812_light_t *)handle;
h->brightness = (uint8_t)value;
return sk6812_apply(h);
}
return ESP_ERR_INVALID_ARG;
}
static esp_err_t app_driver_light_set_hue(app_driver_handle_t handle, esp_matter_attr_val_t *val)
{
int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE);
(void)value;
return ESP_OK;
}
static esp_err_t app_driver_light_set_saturation(app_driver_handle_t handle, esp_matter_attr_val_t *val)
{
int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION);
(void)value;
return ESP_OK;
}
static esp_err_t app_driver_light_set_temperature(app_driver_handle_t handle, esp_matter_attr_val_t *val)
{
if (!handle) {
return ESP_OK;
}
uint32_t value = REMAP_TO_RANGE_INVERSE(val->val.u16, STANDARD_TEMPERATURE_FACTOR);
app_light_type_t type = ((app_rgb_pwm_light_t *)handle)->type;
if (type == APP_LIGHT_TYPE_SK6812) {
app_sk6812_light_t *h = (app_sk6812_light_t *)handle;
h->temperature_kelvin = value;
return sk6812_apply(h);
}
return ESP_OK;
}
static esp_err_t app_driver_light_set_xy(app_driver_handle_t handle, uint16_t x, uint16_t y)
{
(void)handle;
(void)x;
(void)y;
return ESP_OK;
}
static void app_driver_button_long_press_cb(void *arg, void *data)
{
ESP_LOGW(TAG, "Button LONG PRESS - entering ESP-NOW pairing mode");
app_enter_espnow_pairing_mode();
}
static void app_driver_button_toggle_cb(void *arg, void *data)
{
ESP_LOGI(TAG, "Toggle button pressed");
uint16_t endpoint_id = rgb_light_endpoint_id;
uint32_t cluster_id = OnOff::Id;
uint32_t attribute_id = OnOff::Attributes::OnOff::Id;
attribute_t *attribute = attribute::get(endpoint_id, cluster_id, attribute_id);
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
attribute::get_val(attribute, &val);
val.val.b = !val.val.b;
attribute::update(endpoint_id, cluster_id, attribute_id, &val);
}
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val)
{
esp_err_t err = ESP_OK;
(void)endpoint_id;
if (!driver_handle) {
return ESP_OK;
}
if (cluster_id == OnOff::Id) {
if (attribute_id == OnOff::Attributes::OnOff::Id) {
err = app_driver_light_set_power(driver_handle, val);
}
} else if (cluster_id == LevelControl::Id) {
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
err = app_driver_light_set_brightness(driver_handle, val);
}
} else if (cluster_id == ColorControl::Id) {
if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
err = app_driver_light_set_hue(driver_handle, val);
} else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) {
err = app_driver_light_set_saturation(driver_handle, val);
} else if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) {
err = app_driver_light_set_temperature(driver_handle, val);
} else if (attribute_id == ColorControl::Attributes::CurrentX::Id) {
current_x = val->val.u16;
err = app_driver_light_set_xy(driver_handle, current_x, current_y);
} else if (attribute_id == ColorControl::Attributes::CurrentY::Id) {
current_y = val->val.u16;
err = app_driver_light_set_xy(driver_handle, current_x, current_y);
}
}
return err;
}
esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id)
{
esp_err_t err = ESP_OK;
void *priv_data = endpoint::get_priv_data(endpoint_id);
app_driver_handle_t handle = (app_driver_handle_t)priv_data;
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
/* Setting brightness */
attribute_t *attribute = attribute::get(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id);
if (attribute) {
attribute::get_val(attribute, &val);
err |= app_driver_light_set_brightness(handle, &val);
}
/* Setting color */
cluster_t *color_cluster = cluster::get(endpoint_id, ColorControl::Id);
if (color_cluster) {
attribute = attribute::get(color_cluster, ColorControl::Attributes::ColorMode::Id);
if (attribute) {
attribute::get_val(attribute, &val);
if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation) {
/* Setting hue */
attribute = attribute::get(color_cluster, ColorControl::Attributes::CurrentHue::Id);
if (attribute) {
attribute::get_val(attribute, &val);
err |= app_driver_light_set_hue(handle, &val);
}
/* Setting saturation */
attribute = attribute::get(color_cluster, ColorControl::Attributes::CurrentSaturation::Id);
if (attribute) {
attribute::get_val(attribute, &val);
err |= app_driver_light_set_saturation(handle, &val);
}
} else if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kColorTemperature) {
/* Setting temperature */
attribute = attribute::get(color_cluster, ColorControl::Attributes::ColorTemperatureMireds::Id);
if (attribute) {
attribute::get_val(attribute, &val);
err |= app_driver_light_set_temperature(handle, &val);
}
} else if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kCurrentXAndCurrentY) {
/* Setting XY coordinates */
attribute = attribute::get(color_cluster, ColorControl::Attributes::CurrentX::Id);
if (attribute) {
attribute::get_val(attribute, &val);
current_x = val.val.u16;
}
attribute = attribute::get(color_cluster, ColorControl::Attributes::CurrentY::Id);
if (attribute) {
attribute::get_val(attribute, &val);
current_y = val.val.u16;
}
err |= app_driver_light_set_xy(handle, current_x, current_y);
} else {
ESP_LOGE(TAG, "Color mode not supported");
}
}
}
/* Setting power */
attribute = attribute::get(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id);
if (attribute) {
attribute::get_val(attribute, &val);
err |= app_driver_light_set_power(handle, &val);
}
return err;
}
app_driver_handle_t app_driver_light_init()
{
return app_driver_rgb_light_init();
}
app_driver_handle_t app_driver_rgb_light_init()
{
const int rgb_r_gpio = 4;
const int rgb_g_gpio = 5;
const int rgb_b_gpio = 6;
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_13_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK,
};
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
ESP_LOGE(TAG, "LEDC timer config failed");
return NULL;
}
ledc_channel_config_t ch0 = {
.gpio_num = rgb_r_gpio,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0,
.hpoint = 0,
};
ledc_channel_config_t ch1 = ch0;
ch1.gpio_num = rgb_g_gpio;
ch1.channel = LEDC_CHANNEL_1;
ledc_channel_config_t ch2 = ch0;
ch2.gpio_num = rgb_b_gpio;
ch2.channel = LEDC_CHANNEL_2;
if (ledc_channel_config(&ch0) != ESP_OK || ledc_channel_config(&ch1) != ESP_OK || ledc_channel_config(&ch2) != ESP_OK) {
ESP_LOGE(TAG, "LEDC channel config failed");
return NULL;
}
app_rgb_pwm_light_t *light = (app_rgb_pwm_light_t *)calloc(1, sizeof(app_rgb_pwm_light_t));
if (!light) {
return NULL;
}
light->type = APP_LIGHT_TYPE_RGB_PWM;
light->power = DEFAULT_POWER;
light->brightness = STANDARD_BRIGHTNESS;
rgb_pwm_apply(light);
return (app_driver_handle_t)light;
}
app_driver_handle_t app_driver_cct_light_init()
{
const int sk6812_gpio = 2;
const rmt_channel_t channel = RMT_CHANNEL_0;
const uint32_t strip_len = 8;
rmt_config_t rmt_cfg = RMT_DEFAULT_CONFIG_TX((gpio_num_t)sk6812_gpio, channel);
rmt_cfg.clk_div = 2;
if (rmt_config(&rmt_cfg) != ESP_OK) {
ESP_LOGE(TAG, "RMT config failed");
return NULL;
}
if (rmt_driver_install(rmt_cfg.channel, 0, 0) != ESP_OK) {
ESP_LOGE(TAG, "RMT driver install failed");
return NULL;
}
uint32_t counter_clk_hz = 0;
if (rmt_get_counter_clock(rmt_cfg.channel, &counter_clk_hz) != ESP_OK) {
ESP_LOGE(TAG, "RMT get counter clock failed");
return NULL;
}
// Use WS2812-like timings which work for many SK6812 modules
const float ratio = (float)counter_clk_hz / 1e9f;
ws_t0h_ticks = (uint32_t)(ratio * 350.0f);
ws_t0l_ticks = (uint32_t)(ratio * 1000.0f);
ws_t1h_ticks = (uint32_t)(ratio * 1000.0f);
ws_t1l_ticks = (uint32_t)(ratio * 350.0f);
rmt_translator_init(rmt_cfg.channel, ws2812_like_rmt_adapter);
app_sk6812_light_t *light = (app_sk6812_light_t *)calloc(1, sizeof(app_sk6812_light_t));
if (!light) {
return NULL;
}
light->type = APP_LIGHT_TYPE_SK6812;
light->power = DEFAULT_POWER;
light->brightness = STANDARD_BRIGHTNESS;
light->temperature_kelvin = 4000;
light->rmt_channel = rmt_cfg.channel;
light->strip_len = strip_len;
light->buffer = (uint8_t *)calloc(strip_len * 4, 1);
if (!light->buffer) {
free(light);
return NULL;
}
sk6812_apply(light);
return (app_driver_handle_t)light;
}
app_driver_handle_t app_driver_button_init()
{
/* Initialize button */
button_handle_t handle = NULL;
const button_config_t btn_cfg = {0};
const button_gpio_config_t btn_gpio_cfg = button_driver_get_config();
if (iot_button_new_gpio_device(&btn_cfg, &btn_gpio_cfg, &handle) != ESP_OK) {
ESP_LOGE(TAG, "Failed to create button device");
return NULL;
}
iot_button_register_cb(handle, BUTTON_PRESS_DOWN, NULL, app_driver_button_toggle_cb, NULL);
iot_button_register_cb(handle, BUTTON_LONG_PRESS_START, NULL, app_driver_button_long_press_cb, NULL);
return (app_driver_handle_t)handle;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#pragma once
#include <esp_err.h>
#include <esp_matter.h>
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#include "esp_openthread_types.h"
#endif
/** Standard max values (used for remapping attributes) */
#define STANDARD_BRIGHTNESS 100
#define STANDARD_HUE 360
#define STANDARD_SATURATION 100
#define STANDARD_TEMPERATURE_FACTOR 1000000
/** Matter max values (used for remapping attributes) */
#define MATTER_BRIGHTNESS 254
#define MATTER_HUE 254
#define MATTER_SATURATION 254
#define MATTER_TEMPERATURE_FACTOR 1000000
/** Default attribute values used during initialization */
#define DEFAULT_POWER true
#define DEFAULT_BRIGHTNESS 64
#define DEFAULT_HUE 128
#define DEFAULT_SATURATION 254
typedef void *app_driver_handle_t;
/** Initialize the light driver
*
* This initializes the light driver associated with the selected board.
*
* @return Handle on success.
* @return NULL in case of failure.
*/
app_driver_handle_t app_driver_light_init();
app_driver_handle_t app_driver_rgb_light_init();
app_driver_handle_t app_driver_cct_light_init();
/** Initialize the button driver
*
* This initializes the button driver associated with the selected board.
*
* @return Handle on success.
* @return NULL in case of failure.
*/
app_driver_handle_t app_driver_button_init();
/** Enter ESP-NOW pairing mode
*
* Called from button long press callback to enter ESP-NOW pairing mode.
*/
#ifdef __cplusplus
extern "C" {
#endif
void app_enter_espnow_pairing_mode();
#ifdef __cplusplus
}
#endif
/** Driver Update
*
* This API should be called to update the driver for the attribute being updated.
* This is usually called from the common `app_attribute_update_cb()`.
*
* @param[in] endpoint_id Endpoint ID of the attribute.
* @param[in] cluster_id Cluster ID of the attribute.
* @param[in] attribute_id Attribute ID of the attribute.
* @param[in] val Pointer to `esp_matter_attr_val_t`. Use appropriate elements as per the value type.
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val);
/** Set defaults for light driver
*
* Set the attribute drivers to their default values from the created data model.
*
* @param[in] endpoint_id Endpoint ID of the driver.
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id);
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_NATIVE, \
}
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
{ \
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
}
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
{ \
.storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, \
}
#endif

View File

@ -0,0 +1,6 @@
dependencies:
espressif/cmake_utilities:
version: "^1"
rules: # will add "optional_component" only when all if clauses are True
- if: "idf_version >=5.0"
- if: "target in [esp32c2]"

View File

@ -0,0 +1,10 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
# Thread + Matter + ESP-NOW firmware requires ~2MB, using single factory partition for development
esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
nvs, data, nvs, 0x10000, 0xC000,
otadata, data, ota, 0x1C000, 0x2000,
nvs_keys, data, nvs_keys,0x1E000, 0x1000, encrypted
phy_init, data, phy, 0x1F000, 0x1000,
ota_0, app, ota_0, 0x20000, 0x600000,
ota_1, app, ota_1, 0x620000, 0x600000
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
3 # Thread + Matter + ESP-NOW firmware requires ~2MB, using single factory partition for development
4 esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
5 nvs, data, nvs, 0x10000, 0xC000,
6 otadata, data, ota, 0x1C000, 0x2000,
7 nvs_keys, data, nvs_keys,0x1E000, 0x1000, encrypted
8 phy_init, data, phy, 0x1F000, 0x1000,
9 ota_0, app, ota_0, 0x20000, 0x600000,
10 ota_1, app, ota_1, 0x620000, 0x600000

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
CONFIG_IDF_TARGET="esp32c6"
# Enable Wi-Fi STA for Matter over Wi-Fi (REQUIRED for App control)
CONFIG_ENABLE_WIFI_STATION=y
CONFIG_ENABLE_WIFI_AP=n
# Disable Thread for now (enable later for mesh)
CONFIG_OPENTHREAD_ENABLED=n
# BLE for commissioning
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
# Custom partition
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"

View File

@ -0,0 +1,33 @@
CONFIG_IDF_TARGET="esp32c6"
CONFIG_MBEDTLS_HKDF_C=y
# Custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_DEVICE_SOFTWARE_VERSION_NUMBER=2
# BLE for Matter commissioning
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=n
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_ENABLE_CHIPOBLE=y
# Disable OpenThread - use Wi-Fi for Matter
CONFIG_OPENTHREAD_ENABLED=n
CONFIG_CHIP_ENABLE_OPENTHREAD=n
CONFIG_ENABLE_THREAD=n
CONFIG_ENABLE_CHIP_SHELL=y
# Enable Wi-Fi for Matter AND ESP-NOW
CONFIG_ESP_WIFI_ENABLED=y
CONFIG_ENABLE_WIFI_STATION=y
CONFIG_ENABLE_WIFI_AP=n
CONFIG_ENABLE_OTA_REQUESTOR=y
CONFIG_CHIP_OTA_IMAGE_BUILD=y
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,72 @@
#!/usr/bin/env python3
#
# Copyright (c) 2022 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# TODO: Implement the decode method
CODES = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '-', '.']
RADIX = len(CODES)
BASE38_CHARS_NEEDED_IN_CHUNK = [2, 4, 5]
MAX_BYTES_IN_CHUNK = 3
MAX_ENCODED_BYTES_IN_CHUNK = 5
def encode(bytes):
total_bytes = len(bytes)
qrcode = ''
for i in range(0, total_bytes, MAX_BYTES_IN_CHUNK):
if (i + MAX_BYTES_IN_CHUNK) > total_bytes:
bytes_in_chunk = total_bytes - i
else:
bytes_in_chunk = MAX_BYTES_IN_CHUNK
value = 0
for j in range(i, i + bytes_in_chunk):
value = value + (bytes[j] << (8 * (j - i)))
base38_chars_needed = BASE38_CHARS_NEEDED_IN_CHUNK[bytes_in_chunk - 1]
while base38_chars_needed > 0:
qrcode += CODES[int(value % RADIX)]
value = int(value / RADIX)
base38_chars_needed -= 1
return qrcode
def decode(qrcode):
total_chars = len(qrcode)
decoded_bytes = bytearray()
for i in range(0, total_chars, MAX_ENCODED_BYTES_IN_CHUNK):
if (i + MAX_ENCODED_BYTES_IN_CHUNK) > total_chars:
chars_in_chunk = total_chars - i
else:
chars_in_chunk = MAX_ENCODED_BYTES_IN_CHUNK
value = 0
for j in range(i + chars_in_chunk - 1, i - 1, -1):
value = value * RADIX + CODES.index(qrcode[j])
bytes_in_chunk = BASE38_CHARS_NEEDED_IN_CHUNK.index(chars_in_chunk) + 1
for k in range(0, bytes_in_chunk):
decoded_bytes.append(value & 0xFF)
value = value >> 8
return decoded_bytes

View File

@ -0,0 +1,119 @@
# 烧录与编译说明WindowsESP32-C6
本说明适用于交付目录中的工程与固件:
- 源码:`Deliverable/01_Source/matter-light-c6-wifi`
- 预编译固件:`Deliverable/02_Firmware_Binaries/cct/*`
> 备注:本项目基于 ESP-IDF v5.2+;你当前环境若已安装 Espressif IDF例如 v5.5.1)也可直接使用。
---
## 1. 环境准备
### 1.1 安装/启用 ESP-IDFPowerShell
以你机器上的默认安装路径为例(如不同请替换):
```powershell
# 进入你的 ESP-IDF 目录后执行(不要在命令里写 cd 的话,也可以直接在该目录打开 PowerShell
# 示例C:\Espressif\frameworks\esp-idf-v5.5.1
. "C:\Espressif\frameworks\esp-idf-v5.5.1\export.ps1"
idf.py --version
```
### 1.2 串口与硬件
- 连接 ESP32-C6 开发板(建议 16MB Flash 版本)。
- 在设备管理器确认串口号(如 `COM4`)。
---
## 2. 从源码编译并烧录(推荐,最稳)
在工程目录执行:
```powershell
cd D:\ESP-LED\Deliverable\01_Source\matter-light-c6-wifi
# 清理并编译
idf.py fullclean
idf.py build
# 烧录并监视(将 COM4 替换成你的串口)
idf.py -p COM4 flash monitor
```
停止串口监视:按 `Ctrl+]`
---
## 3. 直接烧录预编译 Factory 固件(无需重新编译)
预编译 Factory 固件路径:
- `Deliverable/02_Firmware_Binaries/cct/factory/bootloader.bin`
- `Deliverable/02_Firmware_Binaries/cct/factory/partition-table.bin`
- `Deliverable/02_Firmware_Binaries/cct/factory/ota_data_initial.bin`
- `Deliverable/02_Firmware_Binaries/cct/factory/light.bin`
烧录地址(来自工程构建输出 `flasher_args.json/flash_args`
- `0x0000` bootloader
- `0x8000` partition-table
- `0x1C000` ota_data_initial
- `0x20000` app (`light.bin`)
### 3.1 使用 `esptool.py` 一次性写入
确保已执行过 `export.ps1`,然后运行:
```powershell
$PORT="COM4" # 替换为你的串口
$BAUD="921600" # 可改成 460800/115200 以提升稳定性
$BASE="D:\ESP-LED\Deliverable\02_Firmware_Binaries\cct\factory"
python -m esptool --chip esp32c6 -p $PORT -b $BAUD `
--before default_reset --after hard_reset `
write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB `
0x0 "$BASE\bootloader.bin" `
0x8000 "$BASE\partition-table.bin" `
0x1c000 "$BASE\ota_data_initial.bin" `
0x20000 "$BASE\light.bin"
```
> 如果你的板子实际是 4MB Flash可把 `--flash_size 16MB` 改为 `4MB`
### 3.2 监视串口日志
```powershell
idf.py -p COM4 monitor
```
---
## 4. OTA 固件文件说明(给服务器/升级用)
OTA 文件路径:
- `Deliverable/02_Firmware_Binaries/cct/ota/light.bin`
说明:
- `light.bin` 用于 OTA 升级包(用于远程 HTTP OTA 场景的下载与升级)。
---
## 5. 常见问题
### 5.1 找不到 `python` / `idf.py`
确保已执行 `export.ps1`,且使用的是同一个 PowerShell 窗口。
### 5.2 串口被占用
关闭其它串口工具(如 Arduino 串口监视器、串口调试助手)。
### 5.3 Flash size 警告
如果日志提示“Detected size larger than size in binary image header”请确认
- 工程配置选择了正确的 Flash size建议 16MB并重新 `idf.py fullclean build`

View File

@ -0,0 +1,85 @@
# QR 码/配网码生成说明Matter Onboarding Codes
本目录已包含一个可直接使用的脚本,用于生成/解析 Matter 的:
- **QR Code 字符串**(以 `MT:` 开头)
- **Manual Pairing Code**11位或21位数字
对应文件:
- `SetupPayload.py`
- `Base38.py`
- 依赖列表:`requirements.setuppayload.txt`
---
## 1. 安装 Python 依赖
在 PowerShell 中进入本目录:
```powershell
cd D:\ESP-LED\Deliverable\03_Flash_and_Tools
python -m pip install -r .\requirements.setuppayload.txt
```
---
## 2. 生成配网码(推荐用法)
### 2.1 生成(仅标准 flow
```powershell
python .\SetupPayload.py generate -d 3840 -p 20202021
```
输出示例:
- `Manualcode : 34970112332`
- `QRCode : MT:...`
### 2.2 生成(带 VID/PID
当 commissioning flow 非 0 时,会把 VID/PID 编进 manual code
```powershell
python .\SetupPayload.py generate -d 3840 -p 20202021 -cf 2 -vid 65521 -pid 32768 -dm 2
```
参数说明:
- `-d` / `--discriminator`0..4095
- `-p` / `--passcode`1..0x5F5E0FE
- `-vid` / `--vendor-id`0..65535
- `-pid` / `--product-id`0..65535
- `-dm` / `--discovery-cap-bitmask`
- 0: SoftAP
- 1: BLE
- 2: OnNetwork
- 默认 4脚本里描述为 OnNetwork不同实现可能有组合值
- `-cf` / `--commissioning-flow`
- 0: Standard
- 1: User-Intent
- 2: Custom
---
## 3. 解析配网码
解析 QR 字符串:
```powershell
python .\SetupPayload.py parse "MT:00000CQM00KA0648G00"
```
解析 Manual pairing code
```powershell
python .\SetupPayload.py parse 34970112332
```
---
## 4. 交付说明(测试数据 vs 量产数据)
当前工程处于开发/演示阶段,通常使用测试用的 VID/PID/证书/配网参数:
- 可以用于演示配网与控制。
- 若后续甲方申请 CSA 认证并进入量产:
- 需要使用正式 VID/PID
- 每台设备需要唯一的出厂数据(如 DAC/证书链、唯一 passcode/discriminator 或出厂注入策略)
- 通常需要重新生成 QR 并恢复出厂重新配网(属正常流程)

View File

@ -0,0 +1,220 @@
#!/usr/bin/env python3
#
# Copyright (c) 2024 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import enum
import Base38
import click
from bitarray import bitarray
from bitarray.util import int2ba, zeros
from construct import BitsInteger, BitStruct, Enum
from stdnum.verhoeff import calc_check_digit
# Format for constructing manualcode
manualcode_format = BitStruct(
'version' / BitsInteger(1),
'vid_pid_present' / BitsInteger(1),
'discriminator' / BitsInteger(4),
'pincode_lsb' / BitsInteger(14),
'pincode_msb' / BitsInteger(13),
'vid' / BitsInteger(16),
'pid' / BitsInteger(16),
'padding' / BitsInteger(7), # this is intentional as BitStruct only takes 8-bit aligned data
)
# Format for constructing qrcode
# qrcode bytes are packed as lsb....msb, hence the order is reversed
qrcode_format = BitStruct(
'padding' / BitsInteger(4),
'pincode' / BitsInteger(27),
'discriminator' / BitsInteger(12),
'discovery' / BitsInteger(8),
'flow' / Enum(BitsInteger(2),
Standard=0, UserIntent=1, Custom=2),
'pid' / BitsInteger(16),
'vid' / BitsInteger(16),
'version' / BitsInteger(3),
)
class CommissioningFlow(enum.IntEnum):
Standard = 0
UserIntent = 1
Custom = 2
class SetupPayload:
def __init__(self, discriminator, pincode, rendezvous=4, flow=CommissioningFlow.Standard, vid=0, pid=0):
self.long_discriminator = discriminator
self.short_discriminator = discriminator >> 8
self.pincode = pincode
self.discovery = rendezvous
self.flow = flow
self.vid = vid
self.pid = pid
def p_print(self):
print('{:<{}} :{}'.format('Flow', 24, self.flow))
print('{:<{}} :{}'.format('Pincode', 24, self.pincode))
print('{:<{}} :{}'.format('Short Discriminator', 24, self.short_discriminator))
if self.long_discriminator:
print('{:<{}} :{}'.format('Long Discriminator', 24, self.long_discriminator))
if self.discovery:
print('{:<{}} :{}'.format('Discovery Capabilities', 24, self.discovery))
if self.vid is not None and self.pid is not None:
print('{:<{}} :{:<{}} (0x{:04x})'.format('Vendor Id', 24, self.vid, 6, self.vid))
print('{:<{}} :{:<{}} (0x{:04x})'.format('Product Id', 24, self.pid, 6, self.pid))
def qrcode_dict(self):
return {
'version': 0,
'vid': self.vid,
'pid': self.pid,
'flow': int(self.flow),
'discovery': self.discovery,
'discriminator': self.long_discriminator,
'pincode': self.pincode,
'padding': 0,
}
def manualcode_dict(self):
return {
'version': 0,
'vid_pid_present': 0 if self.flow == CommissioningFlow.Standard else 1,
'discriminator': self.short_discriminator,
'pincode_lsb': self.pincode & 0x3FFF, # 14 ls-bits
'pincode_msb': self.pincode >> 14, # 13 ms-bits
'vid': 0 if self.flow == CommissioningFlow.Standard else self.vid,
'pid': 0 if self.flow == CommissioningFlow.Standard else self.pid,
'padding': 0,
}
def generate_qrcode(self):
data = qrcode_format.build(self.qrcode_dict())
b38_encoded = Base38.encode(data[::-1]) # reversing
return 'MT:{}'.format(b38_encoded)
def generate_manualcode(self):
CHUNK1_START = 0
CHUNK1_LEN = 4
CHUNK2_START = CHUNK1_START + CHUNK1_LEN
CHUNK2_LEN = 16
CHUNK3_START = CHUNK2_START + CHUNK2_LEN
CHUNK3_LEN = 13
bytes = manualcode_format.build(self.manualcode_dict())
bits = bitarray()
bits.frombytes(bytes)
chunk1 = str(int(bits[CHUNK1_START:CHUNK1_START + CHUNK1_LEN].to01(), 2)).zfill(1)
chunk2 = str(int(bits[CHUNK2_START:CHUNK2_START + CHUNK2_LEN].to01(), 2)).zfill(5)
chunk3 = str(int(bits[CHUNK3_START:CHUNK3_START + CHUNK3_LEN].to01(), 2)).zfill(4)
chunk4 = str(self.vid).zfill(5) if self.flow != CommissioningFlow.Standard else ''
chunk5 = str(self.pid).zfill(5) if self.flow != CommissioningFlow.Standard else ''
payload = '{}{}{}{}{}'.format(chunk1, chunk2, chunk3, chunk4, chunk5)
return '{}{}'.format(payload, calc_check_digit(payload))
@staticmethod
def from_container(container, is_qrcode):
payload = None
if is_qrcode:
payload = SetupPayload(container['discriminator'], container['pincode'],
container['discovery'], CommissioningFlow(container['flow'].__int__()),
container['vid'], container['pid'])
else:
payload = SetupPayload(discriminator=container['discriminator'],
pincode=(container['pincode_msb'] << 14) | container['pincode_lsb'],
vid=container['vid'] if container['vid_pid_present'] else None,
pid=container['pid'] if container['vid_pid_present'] else None)
payload.short_discriminator = container['discriminator']
payload.long_discriminator = None
payload.discovery = None
payload.flow = 2 if container['vid_pid_present'] else 0
return payload
@staticmethod
def parse_qrcode(payload):
payload = payload[3:] # remove 'MT:'
b38_decoded = Base38.decode(payload)[::-1]
container = qrcode_format.parse(b38_decoded)
return SetupPayload.from_container(container, is_qrcode=True)
@staticmethod
def parse_manualcode(payload):
payload_len = len(payload)
if payload_len != 11 and payload_len != 21:
print('Invalid length')
return None
# if first digit is greater than 7 the its not v1
if int(str(payload)[0]) > 7:
print('incorrect first digit')
return None
if calc_check_digit(payload[:-1]) != str(payload)[-1]:
print('check digit mismatch')
return None
# vid_pid_present bit position
is_long = int(str(payload)[0]) & (1 << 2)
bits = int2ba(int(payload[0]), length=4)
bits += int2ba(int(payload[1:6]), length=16)
bits += int2ba(int(payload[6:10]), length=13)
bits += int2ba(int(payload[10:15]), length=16) if is_long else zeros(16)
bits += int2ba(int(payload[15:20]), length=16) if is_long else zeros(16)
bits += zeros(7) # padding
container = manualcode_format.parse(bits.tobytes())
return SetupPayload.from_container(container, is_qrcode=False)
@staticmethod
def parse(payload):
if payload.startswith('MT:'):
return SetupPayload.parse_qrcode(payload)
else:
return SetupPayload.parse_manualcode(payload)
@click.group()
def cli():
pass
@cli.command()
@click.argument('payload')
def parse(payload):
click.echo(f'Parsing payload: {payload}')
SetupPayload.parse(payload).p_print()
@cli.command()
@click.option('--discriminator', '-d', required=True, type=click.IntRange(0, 0xFFF), help='Discriminator')
@click.option('--passcode', '-p', required=True, type=click.IntRange(1, 0x5F5E0FE), help='setup pincode')
@click.option('--vendor-id', '-vid', type=click.IntRange(0, 0xFFFF), default=0, help='Vendor ID')
@click.option('--product-id', '-pid', type=click.IntRange(0, 0xFFFF), default=0, help='Product ID')
@click.option('--discovery-cap-bitmask', '-dm', type=click.IntRange(0, 7), default=4, help='Commissionable device discovery capability bitmask. 0:SoftAP, 1:BLE, 2:OnNetwork. Default: OnNetwork')
@click.option('--commissioning-flow', '-cf', type=click.IntRange(0, 2), default=0, help='Commissioning flow, 0:Standard, 1:User-Intent, 2:Custom')
def generate(passcode, discriminator, vendor_id, product_id, discovery_cap_bitmask, commissioning_flow):
payload = SetupPayload(discriminator, passcode, discovery_cap_bitmask, commissioning_flow, vendor_id, product_id)
print("Manualcode : {}".format(payload.generate_manualcode()))
print("QRCode : {}".format(payload.generate_qrcode()))
if __name__ == '__main__':
cli()

View File

@ -0,0 +1,22 @@
## Python tool to generate and parse Matter onboarding codes
Generates and parses Manual Pairing Code and QR Code
#### example usage:
- Parse
```
./SetupPayload.py parse MT:U9VJ0OMV172PX813210
./SetupPayload.py parse 34970112332
```
- Generate
```
./SetupPayload.py generate --help
./SetupPayload.py generate -d 3840 -p 20202021
./SetupPayload.py generate -d 3840 -p 20202021 --vendor-id 65521 --product-id 32768 -cf 0 -dm 2
```
For more details please refer Matter Specification

View File

@ -0,0 +1,4 @@
bitarray>=2.8.1
click>=8.1.3
construct>=2.10.68
python_stdnum==1.18

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 KiB

48
04_Test_Report/README.md Normal file
View File

@ -0,0 +1,48 @@
# 测试报告说明(截图/视频提交)
本目录用于存放项目验收所需的截图/视频证据。
建议提交内容:
## 1. AppleHome
- 配网演示(扫码/输入码)
- 设备上线后:开关、亮度、(双色温)色温控制
## 2. GoogleHome
- 配网演示
- 基本控制演示
## 3. Alexa
- 配网演示
- 基本控制演示
## 4. RainMaker
- 配网演示
- 基本控制演示
## 5. Remote_Control_and_Group_Control
- 遥控器单控演示(单台设备)
- 遥控器组控/广播命令演示(多台设备同步)
- App 与遥控器同时控制(状态同步)
## 6. OTA_HTTP
- 服务器上放置 `light.bin` 的目录/URL 截图
- 设备端执行 `matter esp ota <url>` 的视频/截图
- 升级前后 `App version` 对比(串口日志/截图)
## 7. Power_Cycle_Reset
- 3 次断电/重启触发 factory reset 的视频/截图
- reset 后进入可重新配网状态的截图
---
## 文件命名建议
建议格式:
- `YYYYMMDD_<场景>_<简述>.mp4`
- `YYYYMMDD_<场景>_<简述>.png`
例如:
- `20260119_AppleHome_Commissioning.mp4`
- `20260119_OTA_HTTP_Upgrade_2.0_to_2.1.mp4`

56
05_Docs/Architecture.md Normal file
View File

@ -0,0 +1,56 @@
# 技术方案与架构说明ESP32-C6 Matter + ESP-NOW
## 1. 总体目标
在 ESP32-C6 单芯片上实现:
- 遥控器侧 ESP-NOW 控制(固定信道 `channel=1`
- Matter 侧生态接入Apple Home 已验证)
- 远程 HTTP OTA 升级
## 2. 网络/射频架构(核心)
为满足“遥控器固件不变 + ESP-NOW 固定信道=1”的约束采用 ESP32-C6 双射频分工:
- **Wi-Fi 2.4GHz 射频**:专用于 ESP-NOW固定 channel=1
- **802.15.4 射频Thread**:用于 Matter 网络承载
- **BLE**:用于 Matter commissioning配网阶段
该架构可避免 Wi-Fi STA 信道由路由器决定导致与 ESP-NOW 冲突的问题。
## 3. Matter 设备模型
- **Endpoint 1单色灯**OnOff + LevelControl
- **Endpoint 2双色温灯**OnOff + LevelControl + ColorControl(ColorTemperature)
- 已验证Groups / Scenes 可创建与应用
## 4. 驱动与硬件接口
- 单色灯LEDC PWMRGB 三路混白)
- 双色温SK6812 RGBWRMT 单线驱动,使用 ColorTemperature 映射实现色温效果
## 5. ESP-NOW 与 Matter 状态同步
- 设备接收遥控器 ESP-NOW 命令0x01..0x05/0xA5映射为灯控动作
- 同步更新 Matter 属性,保证 App 侧状态一致
- 支持多设备联调:遥控器 Zone1/Zone2 + App 同时控制两台灯具
## 6. OTA 方案(交付采用)
交付采用 **HTTP OTA远程服务器下载固件**
- 设备从 HTTP 服务器下载 `light.bin` 并写入 OTA 分区
- 通过 Matter shell 命令触发:`matter esp ota <http://url>`
- 分区表为双 OTA`ota_0/ota_1/otadata`
详细部署说明见:`OTA_HTTP_Deploy_Guide.md`。
## 7. 配网与二维码
- 设备启动可输出 onboarding codesQR 字符串 `MT:...` 与 manual pairing code
- 交付提供 `SetupPayload.py` 工具用于生成/解析配网码
## 8. 工程与交付
- 源码快照:`Deliverable/01_Source/matter-light-c6-wifi`
- 固件 bin`Deliverable/02_Firmware_Binaries/*`
- 烧录说明:`Deliverable/03_Flash_and_Tools/Flash_Guide_CN.md`
- 测试素材目录:`Deliverable/04_Test_Report/`

414
05_Docs/DEV_PROGRESS.md Normal file
View File

@ -0,0 +1,414 @@
# ESP32-C6 Matter + ESP-NOW 混合固件开发进度(单色灯 + 双色温灯)
## 1. 项目目标(来自《项目制作需求》)
- 基于 ESP32候选C3/C6开发 Matter + ESP-NOW 混合固件。
- 支持两类灯:
- 单色灯:开关 + 调光(白光)。
- 双色温灯:开关 + 调光 + 调色温(暖/冷)。
- 开发阶段Wi-Fi commissioning通过 Wi-Fi 完成配网)。
- 最终目标Wi-Fi 完成配网、Thread 实现本地 mesh 控制(混合网络模式)。
- 需要 OTA、QR 码生成、VID/PID/DAC 相关出厂数据与认证准备支持。
- 交付:双版本(或可配置)源码仓库 + Factory/OTA 固件 + 烧录/QR 脚本 + 测试报告 + 技术文档。
## 1.1 关键硬性约束与解决方案
- 量产遥控器固件不变,且 ESP-NOW 固定信道为 `channel=1`
- **问题**:若使用 Matter-over-Wi-FiWi-Fi STA 信道会被路由器决定,与 ESP-NOW 固定 ch1 冲突。
- **解决方案**:利用 ESP32-C6 的**双射频**能力:
- **Wi-Fi 2.4GHz 射频**:专用于 ESP-NOW固定 channel 1不连接路由器做 STA
- **802.15.4 射频**:专用于 Matter over Thread与 Wi-Fi 射频完全独立)
- **BLE**:用于 Matter commissioning配网阶段
- 结论:单芯片 ESP32-C6 可实现 ESP-NOW + Matter 共存,无需依赖路由器信道。
## 1.2 需求对齐清单(当前工程状态)
| 需求项 | 状态 | 备注 |
| --- | --- | --- |
| ESP-NOW 代码功能 100% 保持 | 部分 | 已按遥控器协议实现 RX/配对/命令映射,但信道冲突仍未解决为“量产可用”方案 |
| Matter clusters: OnOff / LevelControl | 已完成 | 双 endpoint 已跑通 |
| Matter clusters: Groups / Scenes | 已完成(已验证) | 已在 App 上验证可创建/应用场景 |
| ColorControl双色温 | 已完成(开发态) | 当前实现为 ColorTemperature已确认硬件为 SK6812 RGBW 模块,调色温方向正常 |
| ESP-NOW 组播/广播组命令→所有控制器同步→Matter 状态更新 | 已完成(已稳定) | 控制器能处理 cmd 并更新 Matter 属性;组控一致性/延迟表现正常,无需再测试 |
| QR 码配网Apple/Google/Alexa/RainMaker | 部分 | iOS Home 已验证Google/Alexa/RainMaker 未做系统性验证 |
| OTAHTTP 远程服务器) | 已完成 | 已实现 HTTP OTA从远程服务器下载固件可通过 Matter shell 命令触发,已验证升级后 App version 变更 |
| Matter 标准 OTA | 暂停 | 采用 HTTP OTA远程服务器方案不再推进标准 Matter OTA |
| 断电重置(如 3 次开关机) | 已完成(已稳定) | 已实现并验证3 次重启触发 Matter 工厂重置(含 5 秒确认窗);已测试稳定,无需再测 |
| 交付:源码/编译说明/bin/脚本/测试报告 | 进行中 | 文档与脚本需要补齐并固化 |
## 1.4 当前进度总览(已完成 vs 未完成)
### 1.4.1 已完成
- HTTP OTA远程服务器下载固件shell 命令触发),并验证升级成功后 `App version` 变更2.0 → 2.1
- Matter clusters: Groups / Scenes 已在 App 上验证可创建/应用场景
- 分区表调整为双 OTA`ota_0`/`ota_1`/`otadata`),固件大小可容纳 OTA 升级
- OTA 触发命令已接入 Matter shell`matter esp ota <http://url>`
- 已可在 Windows 上稳定完成 build/flash/monitor含 GN/Pigweed 环境)
- 断电重置(工厂重置):已实现并验证 3 次重启触发 factory reset含 5 秒确认窗),重置后进入可重新配网状态
- 修复断电计数不生效问题:将 NVS key 缩短到 15 字符以内并加入兼容读取逻辑
- ESP-NOW 配对与多设备联调已支持“单遥控器Zone1/Zone2+ APP”控制两台 ESP32-C6 灯具;并修复“电源重启触发配对时未及时广播配对 beacon”的问题提升遥控器绑定成功率
### 1.4.2 未完成(待办)
- 多生态验证Google Home / Alexa / RainMaker 的 commissioning + 控制验证
- 交付物固化:一键环境初始化/构建脚本、烧录脚本、测试报告与完整技术文档
## 3. 已完成的关键里程碑
### 3.1 构建与烧录链路打通Windows
- 已实现:`idf.py build` 成功、可 `flash` 到 COM4、可 `monitor` 观察启动日志。
- 已解决的关键构建问题(历史记录):
- `gn command not found`:定位 `gn.exe` 并加入 PATH。
- Pigweed 环境变量缺失:补齐 `_PW_ACTUAL_ENVIRONMENT_ROOT`
- 链接错误 `undefined reference to mbedtls_hkdf`:启用 `CONFIG_MBEDTLS_HKDF_C=y`
- app 分区过小:切换到自定义分区表 `partitions.csv`(双 OTA并设置 flash size=16MB与硬件一致最小 app 分区 `0x1E0000`
- Windows 反斜杠路径导致 CMake `Invalid character escape`CMakeLists 里将 env path 转为 CMake path。
补充构建该工程的关键环境变量PowerShell 会话级别):
- `ESP_MATTER_PATH=D:\ESP-LED\esp-matter-gh`
- `ESP_MATTER_DEVICE_PATH=D:\ESP-LED\esp-matter-gh\device_hal\device\esp32c6_devkit_c`
- `_PW_ACTUAL_ENVIRONMENT_ROOT=D:\ESP-LED\esp-matter-gh\connectedhomeip\connectedhomeip\third_party\pigweed\repo\environment`
- GN 工具路径(将目录加入 PATH
- `...\third_party\pigweed\repo\environment\cipd\packages\pigweed`(包含 `gn.exe`
### 3.2 Matter 双 endpoint 架构(已运行验证)
- 当前固件创建两个 endpoint
- Endpoint 1单色灯OnOff + LevelControl
- Endpoint 2双色温灯OnOff + LevelControl + ColorControl(ColorTemperature))。
- 串口日志已确认:
- `RGB light created with endpoint_id 1`
- `CCT light created with endpoint_id 2`
### 3.3 驱动层对接(已跑通)
- Endpoint 1单色灯LEDC PWM 驱动GPIO4/5/6
- Endpoint 2双色温灯RMT 驱动 SK6812GPIO2
### 3.4 日志报错修复
- 修复启动时 `E data_model: Cluster cannot be NULL.`
- 原因:对不含 ColorControl 的 endpoint 调用 `attribute::get(endpoint, ColorControl...)`
- 处理:先检查 `cluster::get(endpoint, ColorControl::Id)` 是否存在,再读取 ColorMode / Hue / Temp 等属性。
### 3.5 iOS Home / Matter Commissioning + 控制验证(已完成)
- 现状手机端已完成配网Home App 可同时控制两个灯的开关/亮度/CCT 灯)色温。
- 关键修复:为满足 iOS Home 的发现/配网流程,已启用 BLE commissioning
- `CONFIG_BT_ENABLED=y`
- `CONFIG_BT_NIMBLE_ENABLED=y`
- `CONFIG_ENABLE_CHIPOBLE=y`
- 串口日志关键特征(表示 BLE commissioning 正常):
- `Configuring CHIPoBLE advertising ...`
- `CHIPoBLE advertising started`
- `Commissioning window opened`
- 设备启动时可打印 Onboarding Codes用于手动输入/生成二维码):
- MT 串SetupQRCode`MT:Y.K9042C00KA0648G00`
- 11 位码Manual pairing code`34970112332`
- 注意:上述二维码/手动码为开发阶段示例/测试参数(默认 VID/PID 等),量产需替换正式 VID/PID、DAC/CD/工厂数据与每台唯一的 onboarding 信息。
### 3.6 单芯片双射频方案验证成功2026-01-07
- **架构**ESP32-C6 单芯片同时运行:
- **Thread (802.15.4)**Matter 网络层
- **Wi-Fi (channel 1)**ESP-NOW 接收(不连接路由器)
- **BLE**Matter commissioning
- **关键配置**
- `CONFIG_ENABLE_WIFI_STATION=n`:禁用 Matter Wi-Fi STA
- `CONFIG_ENABLE_THREAD=y`:启用 Matter over Thread
- 独立初始化 Wi-Fi 用于 ESP-NOW固定 channel 1
- **验证通过的日志特征**
- `OpenThread started: OK`
- `Wi-Fi channel fixed to 1 for ESP-NOW`
- `ESP-NOW RX initialized`
- `CHIPoBLE advertising started`
- `Server Listening...`
- **固件大小**~2MB含 Thread + Wi-Fi + BLE + ESP-NOW
- **状态**:设备稳定启动,无崩溃
### 3.7 HTTP OTA远程服务器验证成功2026-01-15
- **目标**支持“远程服务器方式”OTAHTTP不依赖 HTTPS/TLS固件体积可控。
- **实现概览**
- 使用 `esp_http_client` + `esp_ota_*` 实现分段下载与写入 OTA 分区。
- 提供 Matter shell 命令触发:`matter esp ota <http://url>`。
- 仅支持 `http://`,拒绝 `https://` 以减小固件体积。
- **验证结果(串口日志特征)**
- `HTTP OTA progress: ... 100%`
- `HTTP OTA upgrade successful! Rebooting in 3 seconds...`
- 重启后:`Loaded app from partition at offset 0x210000`(切换到 ota_1
- 重启后:`App version: 2.1`(已确认版本号随固件更新)
### 3.8 多设备控制联调进展APP + ESP-NOW 遥控器2026-01-15
- **目标**:一台遥控器 + 手机 App 同时控制两台 ESP32-C6 灯具(两块开发板)。
- **实现状态**
- App 侧iOS Home已可同时添加两台设备并分别控制。
- 遥控器侧支持 Zone1/Zone2 独立绑定不同灯具(通过 ESP-NOW 配对流程完成)。
- **配对机制(开发态)**
- 3 次重启:触发 Matter factory reset5 秒确认窗)。
- 5 次重启:进入 ESP-NOW pairing mode5 秒确认窗)。
- 遥控器在目标 Zone 下长按配对键,设备收到 `0xA5` 后退出配对模式。
- **关键修复**
- 修复“电源重启触发配对模式后,因 Wi-Fi 连接状态导致配对 beacon 未及时广播”的问题:进入配对后将主动启动配对 beacon 广播,确保遥控器可发现并完成绑定。
## 4. 当前仍在进行中的问题/待验证点
### 4.1 单色灯输出"白光"的定义与实现已确定RGB 三路混白)
- 当前单色灯硬件接法为 RGB 三路 PWMGPIO4/5/6
- 已做的软件调整:将 RGB 三路占空比设置为 1:1:1同亮度混色以尽量呈现白光。
- 已确认:单色灯即 RGB 三路混白方案(不做单通道白灯条改造)。
- 注意RGB 分立灯珠近距离仍可能看到“三色点”,属于物理结构;可通过扩散罩/导光改善。
### 4.2 双色温灯的“暖/冷”实现已确认SK6812 RGBW
- 已确认:双色温灯硬件为 SK6812 RGBW 模块,采用 RMT 单线驱动。
- 当前实现Matter ColorTemperaturemireds→ 颜色映射 → SK6812 输出;调色温方向已验证正确。
- 注意SK6812 RGBW 的“色温”属于近似实现(需要 RGB 参与补色),效果取决于映射/校准策略。
- 状态:当前效果表现正常,无需再做专项“色温校准/一致性测试”。
### 4.3 Flash 容量提示告警(已解决)
- 现象:启动时提示检测到 16MB但固件镜像头标记为 4MB
- `Detected size(16384k) larger than the size in the binary image header(4096k)`
- 影响:通常可运行,但不利于后续分区与 OTA 风险控制。
- 已处理并确认:将工程 Flash size 配置调整为 16MB`CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y`),已复测确认告警消失。
## 5. 控制器/遥控器ESP-NOW现状梳理已读源码
- 控制器原码路径:`D:\ESP-LED\控制器原码\Ecolight\...`
- 协议ESP-NOWchannel=1
- Pairing beacon magic`0xABCDEF01`4字节
- 命令1字节
- `0x01` Toggle
- `0x02` On
- `0x03` Brightness Up
- `0x04` Brightness Down
- `0x05` Off
- `0xA5` Pairing Confirm
结论:控制器原码与甲方提供的遥控器一致,且该 ESP-NOW 遥控协议可接入当前 Matter 灯固件C6 端作为 ESPNOW 接收端),收到命令后同步更新 Matter 属性。
## 6. VID/PID/DAC/QR 码阶段性策略
- 开发阶段可以使用示例/测试用的 VID/PID/证书链推进开发。
- 后续拿到正式 VID/PID/DAC 后:
- 替换证书与出厂数据。
- 重新生成 QR。
- 通常需要恢复出厂并重新配网(属正常流程)。
## 7. 下一步开发路线图(按阶段)
### 阶段 A功能验证与参数固化短期
- 单色灯明确硬件定义RGB 混白 vs 单路白灯条),固化白光方案。
- 双色温:已确认 SK6812 RGBW固化色温映射与效果参数端点/曲线/gamma/限幅),并确认通道顺序与供电/信号稳定性。
- 建立功能测试用例并记录:
- endpoint 1开/关、亮度
- endpoint 2开/关、亮度、色温
### 阶段 BESP-NOW + Matter 共存(核心)
- 在 C6 Matter 固件中加入 ESPNOW RX
- 接收 1-byte 命令并映射到 endpoint 1/2 的 Matter 属性更新。
- 目标遥控器控制灯Matter 侧状态同步。
- 解决 Wi-Fi channel 与 ESPNOW channel=1 的冲突(以“遥控器固件不变”为前提):
- 方案 1最小改动但依赖环境路由器/热点 2.4G 固定 `channel=1`
- 方案 2推荐量产架构双芯片/双射频解耦ESP-NOW 固定 ch1 与 Matter Wi-Fi 任意信道互不影响)。
- 方案 3与 Addendum 对齐Wi-Fi 用于 commissioning日常控制走 Thread需要 Thread Border Router 环境),从而避免 Wi-Fi 信道对 ESP-NOW 的牵制。
- 性能目标:端到端延迟 < 20ms需要定义测量方法和基准
### 7.2 芯片选型建议C3 vs C6
- 若坚持单芯片承载 Matter含 Groups/Scenes/OTA/多生态)+ 应用逻辑 + ESPNOW更推荐 ESP32-C6。
- 原因内存与资源更充足Matter 生态适配与稳定性更优,且可扩展 Thread满足 Addendum
- 若控制器仍使用 ESP32-C3需要评估以下风险项
- Matter + BLE commissioning + OTA + Groups/Scenes 的 RAM/Flash 压力。
- 与 ESPNOW 同时运行的峰值内存/任务栈/队列占用。
- 当路由器信道不可控且遥控器固件不变时:
- 单芯片方案存在先天信道冲突。
- 需要硬件/架构调整(例如额外加一颗 C3 专做 ESPNOW 固定 ch1C6 专做 Matter/Wi-Fi/Thread通过 UART/SPI 同步状态)。
### 7.3 方案 A双芯片解耦系统架构量产推荐
#### 7.3.1 总体思路
- MCU1ESP-NOW 控制器,建议 ESP32-C3
- 只负责ESP-NOW固定 ch1、遥控器配对/命令接收、组控广播一致性、驱动输出PWM/RMT/恒流等)。
- 不连接路由器(或不承担 Matter Wi-Fi
- MCU2Matter 控制器,建议 ESP32-C6
- 只负责Matter over Wi-Ficommissioning/长久在线/多生态可选Thread、Matter OTA、Groups/Scenes/状态机。
- 通过 UART/SPI 与 MCU1 交换“控制命令/状态变化/诊断”。
补充确认:本项目采用 UART 作为 MCU1↔MCU2 通信方式。
#### 7.3.2 数据流与一致性目标
- 遥控器 → MCU1ESP-NOW RX
- MCU1 先本地执行灯控(保证延迟与体验不变)
- MCU1 同步上报事件给 MCU2用于 Matter 属性更新与组/场景一致性)
- App/Matter → MCU2属性更新/命令)→ MCU2 下发到 MCU1 → MCU1 执行驱动输出 → MCU1 回报最终状态给 MCU2闭环
#### 7.3.3 量产可测的关键指标
- 遥控器端到端延迟(按键到灯输出):目标 < 20 ms MCU1 本地执行为准
- Matter 状态同步延迟(灯输出到 Matter 属性更新可见):给出目标与测量方法(建议 < 200 ms
- 长期稳定性Wi-Fi/Matter 长久在线,不影响 MCU1 的 ESP-NOW 实时性
#### 7.3.4 PCB/硬件接口建议(小改动范围)
- UART
- MCU1_TX -> MCU2_RXGPIO 待定MCU1=____ / MCU2=____
- MCU1_RX <- MCU2_TXGPIO 待定MCU1=____ / MCU2=____
- 可选硬件流控(建议预留焊盘,量产可按稳定性决定是否启用):
- MCU2->MCU1 `RESET_REQ`(请求 MCU1 执行:清码/恢复出厂/重新配对/进入测试)
- MCU1->MCU2 `IRQ_EVT`(有新事件/状态上报,降低轮询开销)
- 电平:两者均为 3.3V TTL无需电平转换
- 调试建议预留测试点TX/RX/GND便于产线与现场抓包
## 8. 测试计划(面向交付物)
### 8.1 遥控器 + ESP-NOW不改固件
- 工厂重置:三次断电/复位触发工厂重置(含 5 秒确认窗)
- 配对:五次断电/复位进入配对模式;遥控器 slot 长按配对
- 单控0x01..0x05 全命令覆盖,重复按键/长按/连发
- 组控:遥控器广播组命令,多个控制器同步输出一致
- 延迟:示波器/逻辑分析仪测量(按键触发到 GPIO/PWM 变化),记录 P50/P95
### 8.2 Matter 多生态MCU2
- Apple Home / Google Home / Alexa至少两项commissioning 演示
- ClustersOnOff/LevelControl/Groups/Scenes双色温含 ColorControl
- OTA升级演示 + 回滚验证
### 8.3 共存与稳定性
- Wi-Fi 长久在线24h/72h期间遥控器控制无明显延迟/无丢包异常
- 异常恢复:
- MCU1 重启不影响 MCU2Matter 仍在线;状态恢复后同步)
- MCU2 重启不影响 MCU1遥控器控制不中断MCU2 恢复后重新拉取状态)
## 9. Matter 功能测试用例(建议用 chip-tool 记录)
### Endpoint 1单色灯开关/调光)
```bash
chip-tool onoff on 1 1
chip-tool onoff off 1 1
chip-tool levelcontrol movetolevelwithonoff 1 1 10 0 0
chip-tool levelcontrol movetolevelwithonoff 1 1 200 0 0
```
### Endpoint 2双色温灯开关/调光/色温)
```bash
chip-tool onoff on 1 2
chip-tool onoff off 1 2
chip-tool levelcontrol movetolevelwithonoff 1 2 20 0 0
chip-tool levelcontrol movetolevelwithonoff 1 2 220 0 0
chip-tool colorcontrol movetocolortemperature 1 2 153 0 0
chip-tool colorcontrol movetocolortemperature 1 2 450 0 0
```
## 10. 风险与注意事项
- ESPNOW channel 固定为 1当路由器信道不可固定到 1 且遥控器固件不可改时,单芯片方案存在先天冲突,需要改架构。
- 单色灯“白光”体验可能受硬件RGB 三色灯珠)限制,软件无法消除近距离三色颗粒。
- 双色温SK6812 RGBW“色温”为近似实现不同亮度下可能存在色偏需要通过端点/曲线/gamma 与 RGB/W 分配进行校准。
- Thread + Wi-Fi 混合网络模式需要明确最终产品拓扑与测试方法。
## 11. MCU 间通信协议草案(方案 A
### 11.1 物理层与链路建议
- UART建议 921600 或 1Mbps8N1
- 帧格式:固定 header + version + flags + type + seq + len + payload + CRC32
- 可靠性建议:
- 带 `seq``ACK`(至少对“状态设置/模式切换/工厂重置”等关键命令)
- 对“按键事件上报”可不必 ACK但需要丢包容忍MCU2 以 MCU1 的最终状态为准)
### 11.1.1 帧格式(建议稿,可直接实现)
- `SOF`2 bytes固定 `0x55 0xAA`
- `VER`1 byte协议版本初版 `0x01`
- `FLAGS`1 byte
- bit0是否需要 ACK
- bit1是否为 ACK 包
- bit2错误包
- bit3..7:预留
- `TYPE`1 byte消息类型
- `SEQ`2 bytes递增序号小端
- `LEN`2 bytespayload 长度小端0..1024 建议上限)
- `PAYLOAD`LEN bytes
- `CRC32`4 bytes对从 `VER``PAYLOAD` 的 CRC32小端
### 11.1.2 ACK/重试/超时(建议稿)
- 对 `FLAGS.need_ack=1` 的包:
- 接收方在成功处理后回 `ACK` 包(`FLAGS.is_ack=1``SEQ` 原样回显,`TYPE`=原 TYPE 或 `TYPE=ACK(0x7F)` 二选一)
- 发送方超时 `T_ACK=50ms` 未收到 ACK重发最多 `N_RETRY=3`
- 连续失败后进入降级策略:记录错误计数并上报 `EVT_DIAG`(或触发重新握手)
- 对 `EVT_KEY_CMD`:可 `need_ack=0`(允许丢);但要求 MCU1 后续用 `EVT_LOCAL_STATE` 做闭环状态同步
### 11.1.3 上电/复位握手(建议稿)
- MCU2 启动后发送 `HELLO`(包含 MCU2 fw_ver/proto_ver/boot_reason
- MCU1 回 `HELLO_RSP`(包含 MCU1 fw_ver/proto_ver、灯型/能力、当前输出状态摘要)
- MCU2 收到后发送 `GET_STATE`(拉取完整状态),并以此刷新 Matter 属性(避免 MCU2 重启后状态漂移)
### 11.2 消息类型(最小集)
- `EVT_KEY_CMD`MCU1→MCU2遥控器命令事件
- 字段cmd(0x01..0x05/扩展)、src_mac、timestamp、group_mode/slot
- `EVT_LOCAL_STATE`MCU1→MCU2MCU1 本地执行后的最终状态
- 字段endpoint/light_id、onoff、level、cct如有、transition_time
- `SET_STATE`MCU2→MCU1来自 Matter 的控制请求
- 字段:目标灯/组、onoff/level/cct、期望渐变时间
- `SET_MODE`MCU2→MCU1模式切换配对、清码、恢复出厂、进入测试模式
- `HEARTBEAT`双向存活与版本信息fw_ver、proto_ver、uptime、heap
建议补充类型:
- `GET_STATE`MCU2→MCU1请求 MCU1 上报完整状态
- `EVT_DIAG`(双向):错误码/计数器CRC 错、丢包、重试次数、WDT、重启原因
### 11.2.1 字段定义建议(便于落地与调试)
- `light_id`1 byte
- `0x01` 单色灯
- `0x02` 双色温灯
- `onoff`1 byte0/1
- `level`1 byte0..254,按 Matter 约定)
- `cct_mireds`2 bytes小端按 Matter ColorTemperatureMireds
- `transition_ms`2 bytes小端
- `timestamp_ms`4 bytes小端MCU1 uptime 毫秒)
### 11.3 一致性原则(避免双写打架)
- MCU1 为“灯输出唯一权威”source of truth for physical output
- MCU2 为“ Matter 属性权威”source of truth for ecosystem state
- MCU2 更新 Matter 属性应以 `EVT_LOCAL_STATE` 为准,而不是以 `EVT_KEY_CMD` 直接推导(防止执行失败/限幅/场景叠加导致不一致)。
## 11.4 PCB 连线清单(方案 AUART
- UART
- MCU1_TX -> MCU2_RXGPIO 待定MCU1=____ / MCU2=____
- MCU1_RX <- MCU2_TXGPIO 待定MCU1=____ / MCU2=____
- 可选硬件流控(建议预留焊盘,量产可按稳定性决定是否启用):
- MCU1_RTS / MCU1_CTS
- MCU2_RTS / MCU2_CTS
- 额外控制/中断线(建议预留):
- MCU2->MCU1 `RESET_REQ`(请求 MCU1 执行:清码/恢复出厂/重新配对/进入测试)
- MCU1->MCU2 `IRQ_EVT`(有新事件/状态上报,降低轮询开销)
- 电平:两者均为 3.3V TTL无需电平转换
- 调试建议预留测试点TX/RX/GND便于产线与现场抓包
## 13. 可对外汇报摘要(可直接发甲方)
本阶段已完成 ESP32-C6 Matter + ESP-NOW 混合固件的核心功能联调:固件已实现双 endpoint单色灯 + 双色温灯)并通过 iOS Home 完成 Matter commissioning 与控制验证;同时接入甲方量产遥控器的 ESP-NOW 协议channel=1、命令 0x01..0x05/0xA5可通过“5 次重启进入配对模式 + 遥控器 Zone 配对”实现一台遥控器Zone1/Zone2分别绑定两台 ESP32-C6 灯具。当前 APPiOS Home与遥控器均可对两台设备进行控制设备支持 HTTP OTA远程服务器下载升级支持双 OTA 分区切换),已验证升级后版本号变化。下一步将推进 Google Home/Alexa/RainMaker 等生态兼容性测试,并固化交付脚本、测试报告与完整技术文档。

View File

@ -0,0 +1,123 @@
# 远程 HTTP OTA 部署说明ESP32-C6HTTP OTA
本项目采用“远程服务器 HTTP OTA”方案设备从 HTTP 服务器下载 `light.bin` 并写入 OTA 分区),不依赖 Matter 标准 OTA Provider。
交付目录相关文件:
- OTA 文件:`Deliverable/02_Firmware_Binaries/cct/ota/light.bin`
- 设备端触发命令Matter shell 命令 `matter esp ota <http://...>`
---
## 1. OTA 文件与命名建议
建议按“产品/型号/版本号”组织目录,避免覆盖与混淆。
示例:
```
/ota/
cct/
2.1/
light.bin
sha256.txt
```
- `light.bin`:本次升级包
- `sha256.txt`(建议):文件校验值(用于发布侧校验/人工核对)
> 备注:当前设备端实现为 HTTP OTA非 HTTPS因此建议仅在内网或受控网络环境使用若后续要上公网建议评估签名校验或改为 HTTPS。
---
## 2. 部署方式(最简单:静态 HTTP
任何能提供静态文件下载的 HTTP 服务都可以,例如:
- Nginx
- Apache
- Python 简易 HTTP 服务(仅用于开发/演示)
### 2.1 示例Python 简易 HTTP演示用
在放置 `light.bin` 的目录启动:
```powershell
# Windows PowerShell
python -m http.server 8000
```
访问 URL 示例:
- `http://<PC_IP>:8000/light.bin`
---
## 3. 设备端触发 OTA
### 3.1 触发命令
设备串口进入 Matter shell 后,执行:
```text
matter esp ota http://<SERVER_IP>:<PORT>/path/to/light.bin
```
示例:
```text
matter esp ota http://192.168.1.10:8000/light.bin
```
### 3.2 预期日志特征
升级过程中一般可看到:
- 下载进度0% → 100%
- 写入 OTA 分区成功
- 提示升级成功并延时重启
- 重启后从另一 OTA 分区启动(例如 `Loaded app from partition ...`
- 启动日志中的 `App version` 更新
---
## 4. 版本管理建议
### 4.1 版本号两件事需要一致
- **固件内部版本号**(启动日志里的 `App version`
- **OTA 镜像头版本字段**(用于升级判断与记录)
建议每次发布新固件时同步更新版本号(例如 2.0 → 2.1)。
### 4.2 服务器侧发布策略
- 不覆盖旧版本文件,按版本目录存放
- 用“latest”软链接/重定向(可选)
- 记录每次发布的:版本号、发布时间、文件 SHA256
---
## 5. 常见问题排查
### 5.1 设备提示 404/无法连接
- 检查 URL 是否可在 PC 浏览器直接下载
- 检查服务器与设备是否在同一网段、是否被防火墙拦截
- 确认端口未被占用
### 5.2 下载中断/升级失败
- 检查 Wi-Fi/Thread 网络稳定性(尤其是演示环境)
- 检查固件文件大小是否超出分区容量
- 确认分区表为双 OTA`ota_0/ota_1/otadata`
### 5.3 升级后版本号未变化
- 确认你上传的是新版本 `light.bin`
- 确认构建时已修改工程版本号(例如 `PROJECT_VER` / `PROJECT_VER_NUMBER`
---
## 6. 交付说明(建议写在测试报告里)
建议在测试报告中附:
- 服务器目录与 URL 示例
- 设备执行 `matter esp ota` 的截图/视频
- 升级前后 `App version` 对比截图/视频