Rainmaker Lights Switch

This commit is contained in:
2025-06-28 05:10:32 -04:00
parent 265ccaa3e3
commit 5510298781
23 changed files with 876 additions and 1 deletions

View File

@@ -19,5 +19,6 @@
"idf.flashType": "UART",
"idf.espIdfPath": "/home/alex/esp/v5.4.1/esp-idf",
"idf.toolsPath": "/home/alex/.espressif",
"idf.pythonInstallPath": "/usr/bin/python3"
"idf.pythonInstallPath": "/usr/bin/python3",
"idf.port": "/dev/ttyS10"
}

View File

@@ -2,3 +2,4 @@
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
COMPONENT_EMBED_TXTFILES := server.crt

View File

@@ -0,0 +1,8 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf:
version: ">=5.0.0"
espressif/esp_rainmaker:
version: ">=1.0"
override_path: '/home/alex/.espressif/esp_rainmaker'

View File

@@ -0,0 +1,13 @@
ARG DOCKER_TAG=latest
FROM espressif/idf:${DOCKER_TAG}
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN apt-get update -y && apt-get install udev -y
RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc
ENTRYPOINT [ "/opt/esp/entrypoint.sh" ]
CMD ["/bin/bash", "-c"]

View File

@@ -0,0 +1,21 @@
{
"name": "ESP-IDF QEMU",
"build": {
"dockerfile": "Dockerfile"
},
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"idf.espIdfPath": "/opt/esp/idf",
"idf.toolsPath": "/opt/esp",
"idf.gitPath": "/usr/bin/git"
},
"extensions": [
"espressif.esp-idf-extension",
"espressif.esp-idf-web"
]
}
},
"runArgs": ["--privileged"]
}

View File

@@ -0,0 +1,55 @@
# 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(DEFINED ENV{RMAKER_PATH})
set(RMAKER_PATH $ENV{RMAKER_PATH})
else()
set(RMAKER_PATH ${CMAKE_CURRENT_LIST_DIR}/../../..)
endif(DEFINED ENV{RMAKER_PATH})
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 "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 "esp32c2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c2_devkit_m)
else()
message(FATAL_ERROR "Unsupported IDF_TARGET")
endif()
endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH})
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($ENV{ESP_MATTER_DEVICE_PATH}/esp_matter_device.cmake)
idf_build_set_property(RAINMAKER_ENABLED 1)
set(EXTRA_COMPONENT_DIRS
"${MATTER_SDK_PATH}/config/esp32/components"
"${ESP_MATTER_PATH}/components"
"${ESP_MATTER_PATH}/device_hal/device"
"${ESP_MATTER_PATH}/examples/common"
"${RMAKER_PATH}/examples/common/app_insights"
"${RMAKER_PATH}/examples/matter/common"
${extra_components_dirs_append})
project(RainMaker_Lights-Switch)
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H" 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,21 @@
# Matter + Rainmaker Switch Example
## What to expect in this example?
- This demonstrates a Matter + RainMaker Switch. Matter is used for commissioning (also known as Wi-Fi provisioning) and local control, whereas RainMaker is used for remote control and OTA upgrades.
- This example uses the BOOT button and RGB LED on the ESP32-C3-DevKitC board to demonstrate a switch.
- To commission the device, scan the QR Code generated by the mfg_tool script using ESP RainMaker app.
- Pressing the BOOT button will send a toggle the power state of switch and send an on/off command to the remote device. This will also reflect on the phone app.
- Toggling the button on the phone app should toggle the LED on your board.
- To test remote control, change the network connection of the mobile.
> Please refer to the [README in the parent folder](../README.md) for instructions.
#### Optimization
TO optimize the DRAM usage, this example uses the following optimizations:
- Disables the chip shell, `CONFIG_ENABLE_CHIP_SHELL=n`, it adds approx 10KB or RAM.
- As this example has two endpoints (Endpoint 0: Root endpoint, Endpoint 1: Extended Color Light), the default dynamic endpoint count is set to 2. This is done by setting `CONFIG_ESP_MATTER_MAX_ENDPOINT_COUNT=2` in the menuconfig.
For more optimizations please refer [esp-matters RAM Flash optimization guide](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/optimizations.html)

View File

@@ -0,0 +1,67 @@
# This is the CMakeCache file.
# For build in directory: /home/alex/github/ESP-Nodes/RainMaker_Lights-Switch/build
# It was generated by CMake: /home/alex/.espressif/tools/cmake/3.30.2/bin/cmake
# You can edit this file to change values found and used by cmake.
# If you do not want to change any of the values, simply exit the editor.
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
# KEY is the name of a variable in the cache.
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
########################
# EXTERNAL cache entries
########################
//Value Computed by CMake.
CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=/home/alex/github/ESP-Nodes/RainMaker_Lights-Switch/build/CMakeFiles/pkgRedirects
//No help, variable specified on the command line.
ESP_PLATFORM:UNINITIALIZED=1
//No help, variable specified on the command line.
PYTHON_DEPS_CHECKED:UNINITIALIZED=1
//No help, variable specified on the command line.
SDKCONFIG:UNINITIALIZED=/home/alex/github/ESP-Nodes/RainMaker_Lights-Switch/sdkconfig
########################
# INTERNAL cache entries
########################
//This is the directory where this CMakeCache.txt was created
CMAKE_CACHEFILE_DIR:INTERNAL=/home/alex/github/ESP-Nodes/RainMaker_Lights-Switch/build
//Major version of cmake used to create the current loaded cache
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
//Minor version of cmake used to create the current loaded cache
CMAKE_CACHE_MINOR_VERSION:INTERNAL=30
//Patch version of cmake used to create the current loaded cache
CMAKE_CACHE_PATCH_VERSION:INTERNAL=2
//Path to CMake executable.
CMAKE_COMMAND:INTERNAL=/home/alex/.espressif/tools/cmake/3.30.2/bin/cmake
//Path to cpack program executable.
CMAKE_CPACK_COMMAND:INTERNAL=/home/alex/.espressif/tools/cmake/3.30.2/bin/cpack
//Path to ctest program executable.
CMAKE_CTEST_COMMAND:INTERNAL=/home/alex/.espressif/tools/cmake/3.30.2/bin/ctest
//Path to cache edit program executable.
CMAKE_EDIT_COMMAND:INTERNAL=/home/alex/.espressif/tools/cmake/3.30.2/bin/cmake-gui
//Name of external makefile project generator.
CMAKE_EXTRA_GENERATOR:INTERNAL=
//Name of generator.
CMAKE_GENERATOR:INTERNAL=Ninja
//Generator instance identifier.
CMAKE_GENERATOR_INSTANCE:INTERNAL=
//Name of generator platform.
CMAKE_GENERATOR_PLATFORM:INTERNAL=
//Name of generator toolset.
CMAKE_GENERATOR_TOOLSET:INTERNAL=
//Source directory with the top level CMakeLists.txt file for this
// project
CMAKE_HOME_DIRECTORY:INTERNAL=/home/alex/github/ESP-Nodes/RainMaker_Lights-Switch
//number of local generators
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
//Path to CMake installation.
CMAKE_ROOT:INTERNAL=/home/alex/.espressif/tools/cmake/3.30.2/share/cmake-3.30

View File

@@ -0,0 +1 @@
# This file is generated by cmake for dependency checking of the CMakeCache.txt file

View File

@@ -0,0 +1,4 @@
CMake Error at CMakeLists.txt:12 (message):
Please set ESP_MATTER_PATH to the path of esp-matter repo

View File

@@ -0,0 +1 @@
-- Configuring incomplete, errors occurred!

View File

@@ -0,0 +1,9 @@
set(PRIV_REQUIRES_LIST device esp_matter esp_matter_console esp_matter_rainmaker app_reset
esp_rainmaker app_insights app_matter)
idf_component_register(SRCS ./app_main.cpp ./app_matter_switch.cpp ./app_driver.cpp
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES ${PRIV_REQUIRES_LIST})
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H")

View File

@@ -0,0 +1,67 @@
/*
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 <stdlib.h>
#include <string.h>
#include <device.h>
#include <button_gpio.h>
#include <esp_matter.h>
#include <led_driver.h>
#include <esp_rmaker_core.h>
#include <esp_rmaker_standard_params.h>
#include <app_matter_switch.h>
#include <app_priv.h>
static const char *TAG = "app_driver";
extern uint16_t switch_endpoint_id;
static bool g_power = DEFAULT_POWER;
/* Do any conversions/remapping for the actual value here */
esp_err_t app_driver_switch_set_power(led_driver_handle_t handle, bool val)
{
g_power = val;
return led_driver_set_power(handle, val);
}
static void app_driver_button_toggle_cb(void *handle, void *usr_data)
{
ESP_LOGI(TAG, "Toggle button pressed");
app_matter_send_command_binding(!g_power);
}
esp_err_t app_driver_light_set_defaults()
{
return app_driver_switch_set_power((led_driver_handle_t)esp_matter::endpoint::get_priv_data(switch_endpoint_id),
DEFAULT_POWER);
}
app_driver_handle_t app_driver_light_init()
{
/* Initialize led */
led_driver_config_t config = led_driver_get_config();
led_driver_handle_t handle = led_driver_init(&config);
return (app_driver_handle_t)handle;
}
app_driver_handle_t app_driver_button_init(void *user_data)
{
/* 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, user_data);
return (app_driver_handle_t)handle;
}

View File

@@ -0,0 +1,119 @@
/*
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_err.h>
#include <esp_log.h>
#include <nvs_flash.h>
#include <app_reset.h>
#include <esp_rmaker_core.h>
#include <esp_rmaker_standard_params.h>
#include <esp_rmaker_standard_devices.h>
#include <esp_rmaker_ota.h>
#include <esp_rmaker_schedule.h>
#include <esp_rmaker_scenes.h>
#include <app_insights.h>
#include <app_matter.h>
#include <app_matter_switch.h>
#include <app_priv.h>
static const char *TAG = "app_main";
static app_driver_handle_t switch_handle;
/* Callback to handle commands received from the RainMaker cloud */
static esp_err_t write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param,
const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx)
{
if (ctx) {
ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src));
}
const char *param_name = esp_rmaker_param_get_name(param);
if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) {
app_matter_send_command_binding(val.val.b);
}
return ESP_OK;
}
extern "C" void app_main()
{
/* Initialize NVS. */
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);
/* Initialize drivers for light and button */
switch_handle = app_driver_light_init();
app_driver_switch_set_power(switch_handle, DEFAULT_POWER);
app_driver_handle_t button_handle = app_driver_button_init(switch_handle);
app_reset_button_register(button_handle);
/* Initialize Matter */
app_matter_init(app_attribute_update_cb,app_identification_cb);
app_matter_rmaker_init();
/* Create Data Model for esp-matter */
app_matter_switch_create(switch_handle);
/* Matter start */
esp_matter::client::set_request_callback(app_matter_client_command_callback, NULL, NULL);
app_matter_start(app_event_cb);
app_matter_send_command_binding(DEFAULT_POWER);
/* Initialize the ESP RainMaker Agent.
* Create Lightbulb device and its parameters.
* */
esp_rmaker_config_t rainmaker_cfg = {
.enable_time_sync = false,
};
esp_rmaker_node_t *node = esp_rmaker_node_init(&rainmaker_cfg, "ESP RainMaker Device", "Switch");
if (!node) {
ESP_LOGE(TAG, "Could not initialise node.");
vTaskDelay(5000 / portTICK_PERIOD_MS);
abort();
}
esp_rmaker_device_t *switch_device = esp_rmaker_switch_device_create(SWITCH_DEVICE_NAME, NULL, DEFAULT_POWER);
esp_rmaker_device_add_cb(switch_device, write_cb, NULL);
esp_rmaker_node_add_device(node, switch_device);
/* Enable OTA */
esp_rmaker_ota_config_t ota_config = {
.server_cert = ESP_RMAKER_OTA_DEFAULT_SERVER_CERT,
};
esp_rmaker_ota_enable(&ota_config, OTA_USING_PARAMS);
/* Enable timezone service which will be require for setting appropriate timezone
* from the phone apps for scheduling to work correctly.
* For more information on the various ways of setting timezone, please check
* https://rainmaker.espressif.com/docs/time-service.html.
*/
esp_rmaker_timezone_service_enable();
/* Enable scheduling. */
esp_rmaker_schedule_enable();
/* Enable Scenes */
esp_rmaker_scenes_enable();
/* Enable Insights. Requires CONFIG_ESP_INSIGHTS_ENABLED=y */
app_insights_enable();
/* Pre start */
ESP_ERROR_CHECK(app_matter_rmaker_start());
/* Enable Matter diagnostics console*/
app_matter_enable_matter_console();
// RainMaker start is deferred after Matter commissioning is complete
// and BLE memory is reclaimed, so that MQTT connect doesnt fail.
}

View File

@@ -0,0 +1,167 @@
/*
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 <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <string.h>
#include <led_driver.h>
#include <esp_matter_rainmaker.h>
#include <platform/ESP32/route_hook/ESP32RouteHook.h>
#include <esp_matter_console.h>
#include <app_matter_switch.h>
#include <esp_rmaker_standard_params.h>
#include <esp_rmaker_core.h>
#include <esp_matter_client.h>
#include <lib/core/Optional.h>
#include <app_matter.h>
#include <app_priv.h>
using namespace esp_matter;
using namespace esp_matter::attribute;
using namespace esp_matter::cluster;
using namespace esp_matter::endpoint;
using namespace chip::app::Clusters;
static const char *TAG = "app_matter";
uint16_t switch_endpoint_id;
esp_err_t app_matter_send_command_binding(bool power)
{
client::request_handle_t req_handle;
req_handle.type = esp_matter::client::INVOKE_CMD;
req_handle.command_path.mClusterId = OnOff::Id;
if (power == true) {
req_handle.command_path.mCommandId = OnOff::Commands::On::Id;
} else {
req_handle.command_path.mCommandId = OnOff::Commands::Off::Id;
}
lock::chip_stack_lock(portMAX_DELAY);
esp_err_t err = client::cluster_update(switch_endpoint_id, &req_handle);
lock::chip_stack_unlock();
return err;
}
esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id,
uint8_t effect_variant, void *priv_data)
{
ESP_LOGI(TAG, "Identification callback: type: %d, effect: %d", type, effect_id);
return ESP_OK;
}
esp_err_t app_attribute_update_cb(attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data)
{
return ESP_OK;
}
void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
{
switch (event->Type) {
case chip::DeviceLayer::DeviceEventType::PublicEventTypes::kCommissioningComplete:
ESP_LOGI(TAG, "Commissioning complete");
break;
case chip::DeviceLayer::DeviceEventType::PublicEventTypes::kBLEDeinitialized:
ESP_LOGI(TAG, "BLE deinitialized and memory reclaimed");
// Starting RainMaker after Matter commissioning is complete
// and BLE memory is reclaimed, so that MQTT connect doesn't fail.
esp_rmaker_start();
break;
default:
break;
}
}
static void send_command_success_callback(void *context, const ConcreteCommandPath &command_path,
const chip::app::StatusIB &status, TLVReader *response_data)
{
ESP_LOGI(TAG, "Send command success");
}
static void send_command_failure_callback(void *context, CHIP_ERROR error)
{
ESP_LOGI(TAG, "Send command failure: err :%" CHIP_ERROR_FORMAT, error.Format());
}
void app_matter_client_command_callback(client::peer_device_t *peer_device, client::request_handle_t *req_handle,
void *priv_data)
{
if (req_handle->type != esp_matter::client::INVOKE_CMD) {
return;
}
char command_data_str[32];
if (req_handle->command_path.mClusterId == OnOff::Id) {
/* RainMaker update */
strcpy(command_data_str, "{}");
const esp_rmaker_node_t *node = esp_rmaker_get_node();
esp_rmaker_device_t *device = esp_rmaker_node_get_device_by_name(node, SWITCH_DEVICE_NAME);
esp_rmaker_param_t *param = esp_rmaker_device_get_param_by_name(device, ESP_RMAKER_DEF_POWER_NAME);
if (req_handle->command_path.mCommandId == OnOff::Commands::Off::Id) {
app_driver_switch_set_power((app_driver_handle_t)priv_data, false);
esp_rmaker_param_update_and_report(param, esp_rmaker_bool(false));
} else if (req_handle->command_path.mCommandId == OnOff::Commands::On::Id) {
app_driver_switch_set_power((app_driver_handle_t)priv_data, true);
esp_rmaker_param_update_and_report(param, esp_rmaker_bool(true));
} else if (req_handle->command_path.mCommandId == OnOff::Commands::Toggle::Id) {
esp_rmaker_param_val_t *param_val = esp_rmaker_param_get_val(param);
app_driver_switch_set_power((app_driver_handle_t)priv_data, !param_val->val.b);
esp_rmaker_param_update_and_report(param, esp_rmaker_bool(!param_val->val.b));
}
} else if (req_handle->command_path.mClusterId == Identify::Id) {
if (req_handle->command_path.mCommandId == Identify::Commands::Identify::Id) {
if (((char *)req_handle->request_data)[0] != 1) {
ESP_LOGE(TAG, "Number of parameters error");
return;
}
sprintf(command_data_str, "{\"0:U16\": %ld}",
strtoul((const char *)(req_handle->request_data) + 1, NULL, 16));
}else {
ESP_LOGE(TAG, "Unsupported command");
return;
}
}else {
ESP_LOGE(TAG, "Unsupported cluster");
return;
}
client::interaction::invoke::send_request(NULL, peer_device, req_handle->command_path, command_data_str,
send_command_success_callback, send_command_failure_callback,
chip::NullOptional);
}
esp_err_t app_matter_switch_create(app_driver_handle_t driver_handle)
{
node_t *node = node::get();
if (!node) {
ESP_LOGE(TAG, "Matter node not found");
return ESP_FAIL;
}
on_off_switch::config_t switch_config;
endpoint_t *endpoint = on_off_switch::create(node, &switch_config, ENDPOINT_FLAG_NONE, driver_handle);
if (!endpoint) {
ESP_LOGE(TAG, "Matter endpoint creation failed");
return ESP_FAIL;
}
cluster::groups::config_t groups_config;
cluster::groups::create(endpoint, &groups_config, CLUSTER_FLAG_SERVER | CLUSTER_FLAG_CLIENT);
switch_endpoint_id = endpoint::get_id(endpoint);
ESP_LOGI(TAG, "Switch created with endpoint_id %d", switch_endpoint_id);
return ESP_OK;
}

View File

@@ -0,0 +1,17 @@
/*
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 <app_priv.h>
esp_err_t app_matter_switch_create(app_driver_handle_t driver_handle);
esp_err_t app_matter_send_command_binding(bool power);
void app_matter_client_command_callback(esp_matter::client::peer_device_t *peer_device, esp_matter::client::request_handle_t *req_handle,
void *priv_data);

View File

@@ -0,0 +1,57 @@
/*
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>
/** Default attribute values used by Rainmaker during initialization */
#define SWITCH_DEVICE_NAME "Matter Switch"
#define DEFAULT_POWER true
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();
/** Initialize the button driver
*
* This initializes the button driver associated with the selected board.
*
* @param[in] user_data Custom user data that will be used in button toggle callback.
*
* @return Handle on success.
* @return NULL in case of failure.
*/
app_driver_handle_t app_driver_button_init(void *user_data);
/** Set LED Power
*
* @param[in] handle Pointer to switch driver handle.
* @param[in] power LED power state.
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
esp_err_t app_driver_switch_set_power(app_driver_handle_t handle, bool power);
esp_err_t app_attribute_update_cb(esp_matter::attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data);
esp_err_t app_identification_cb(esp_matter::identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id,
uint8_t effect_variant, void *priv_data);
void app_event_cb(const ChipDeviceEvent *event, intptr_t arg);

View File

@@ -0,0 +1,7 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf:
version: ">=5.0.0"
espressif/esp_rainmaker:
version: ">=1.0"

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
esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
nvs, data, nvs, 0x10000, 0xC000,
nvs_keys, data, nvs_keys,, 0x1000, encrypted
otadata, data, ota, , 0x2000
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, 0x20000, 0x1E0000,
ota_1, app, ota_1, 0x200000, 0x1E0000,
fctry, data, nvs, , 0x6000,
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 esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
4 nvs, data, nvs, 0x10000, 0xC000,
5 nvs_keys, data, nvs_keys,, 0x1000, encrypted
6 otadata, data, ota, , 0x2000
7 phy_init, data, phy, , 0x1000,
8 ota_0, app, ota_0, 0x20000, 0x1E0000,
9 ota_1, app, ota_1, 0x200000, 0x1E0000,
10 fctry, data, nvs, , 0x6000,

View File

@@ -0,0 +1,11 @@
# 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
esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
nvs, data, nvs, 0x10000, 0xc000,
nvs_keys, data, nvs_keys,, 0x1000, encrypted
otadata, data, ota, , 0x2000
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, 0x20000, 0x1E9000,
reserved, 0x06, , 0x209000, 0x7000,
ota_1, app, ota_1, 0x210000, 0x1E9000,
fctry, data, nvs, 0x3F9000, 0x6000
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 esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
4 nvs, data, nvs, 0x10000, 0xc000,
5 nvs_keys, data, nvs_keys,, 0x1000, encrypted
6 otadata, data, ota, , 0x2000
7 phy_init, data, phy, , 0x1000,
8 ota_0, app, ota_0, 0x20000, 0x1E9000,
9 reserved, 0x06, , 0x209000, 0x7000,
10 ota_1, app, ota_1, 0x210000, 0x1E9000,
11 fctry, data, nvs, 0x3F9000, 0x6000

View File

@@ -0,0 +1,87 @@
# 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 re-attempts
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
# 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"
CONFIG_PARTITION_TABLE_OFFSET=0xC000
CONFIG_PARTITION_TABLE_MD5=y
# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
# mbedtls
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
# Temporary Fix for Timer Overflows
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
# 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
# Disable softap by default
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
# ESP RainMaker
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
CONFIG_ESP_RMAKER_NO_CLAIM=y
CONFIG_ESP_RMAKER_USE_ESP_SECURE_CERT_MGR=y
CONFIG_ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN=y
CONFIG_ESP_RMAKER_DISABLE_USER_MAPPING_PROV=y
# ESP Matter
CONFIG_CHIP_FACTORY_NAMESPACE_PARTITION_LABEL="fctry"
CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER=y
CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER=y
CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER=y
CONFIG_SEC_CERT_DAC_PROVIDER=y
CONFIG_DEVICE_VENDOR_ID=0x131B
CONFIG_DEVICE_PRODUCT_ID=0x2
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
# Enable HKDF in mbedtls
CONFIG_MBEDTLS_HKDF_C=y
# Use compact attribute storage mode
CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y
# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1)
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
# If ESP-Insights is enabled, we need MQTT transport selected
# Takes out manual efforts to enable this option
CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT=y
# Flash optimization
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
# DRAM optimization
CONFIG_ENABLE_CHIP_SHELL=n
CONFIG_ESP_MATTER_MAX_DYNAMIC_ENDPOINT_COUNT=2

View File

@@ -0,0 +1,121 @@
# Bluetooth
CONFIG_BT_ENABLED=y
CONFIG_BT_RELEASE_IRAM=y
CONFIG_BT_NIMBLE_ENABLED=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_MSYS_1_BLOCK_COUNT=10
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE=100
CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=4
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_GATT_MAX_PROCS=1
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=n
CONFIG_BT_NIMBLE_WHITELIST_SIZE=1
## 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
# 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
# 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
# Bypass a bug. Use 26M XTAL Freq
CONFIG_XTAL_FREQ_26=y
## 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
# 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_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_KEEP_PEER_CERTIFICATE=n
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
# 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

View File

@@ -0,0 +1,10 @@
#
# Use partition table which makes use of flash to the fullest
# Can be used for other platforms as well. But please keep in mind that fctry partition address is
# different than default, and the new address needs to be specified to `rainmaker.py claim`
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_4mb_optimised.csv"
# To accomodate security features
CONFIG_PARTITION_TABLE_OFFSET=0xc000