Skip to content

Commit

Permalink
Merge branch 'controller/controller_with_thread_br' into 'master'
Browse files Browse the repository at this point in the history
Add Thread border router support in rainmaker + matter controller

See merge request app-frameworks/esp-rainmaker!434
  • Loading branch information
dhrishi committed May 17, 2024
2 parents a2fbfd1 + b2738e0 commit 944a13e
Show file tree
Hide file tree
Showing 24 changed files with 670 additions and 28 deletions.
2 changes: 1 addition & 1 deletion examples/matter/matter_controller/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_
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)
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security;-Wformat=0" APPEND)
24 changes: 24 additions & 0 deletions examples/matter/matter_controller/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,28 @@ This example is expected to be compatible with the Rainmaker iOS app version 3.0
- Single click the BOOT button will toggle the power of the selected remote device. This will also reflect on the phone app.
- Double click the BOOT button will change the selected remote device. The new selected device's node-id will be printed in the device console.

## OpenThread Border Router (OTBR) feature

### Hardware Platform

ESP Thread Border Router DevKit Board, see the [docs](https://github.com/espressif/esp-thread-br#hardware-platforms) for more information about the hardware platform.

### Build

The sdkconfig file `sdkconfig.defaults.otbr` is provided to enable the OTBR feature on the controller.
Build and flash the controller example with the sdkconfig file 'sdkconfig.defaults.otbr'

```
idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.otbr" set-target esp32s3 build
idf.py -p <PORT> erase-flash flash monitor
```

### CLI Command
Use Thread CLI command in device console
> Note: Thread Border Router is not initialized until the Controller has been commissioned and obtained an IP address.
```
matter esp ot_cli <command>
```


> Please refer to the [README in the parent folder](../README.md) for instructions.
4 changes: 3 additions & 1 deletion examples/matter/matter_controller/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
set(ldfragments linker.lf)
idf_component_register(SRCS ./app_main.cpp ./app_matter.cpp ./app_driver.cpp
PRIV_INCLUDE_DIRS ".")
PRIV_INCLUDE_DIRS "."
LDFRAGMENTS "${ldfragments}")

set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H")
28 changes: 28 additions & 0 deletions examples/matter/matter_controller/main/app_matter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
#include <esp_matter_controller_console.h>
#include <matter_controller_device_mgr.h>

#if CONFIG_OPENTHREAD_BORDER_ROUTER
#include <esp_matter_thread_br_cluster.h>
#include <esp_matter_thread_br_console.h>
#include <esp_matter_thread_br_launcher.h>
#include <esp_ot_config.h>
#endif // CONFIG_OPENTHREAD_BORDER_ROUTER

using namespace esp_matter;
using namespace esp_matter::attribute;
using namespace esp_matter::cluster;
Expand Down Expand Up @@ -101,6 +108,20 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
case chip::DeviceLayer::DeviceEventType::PublicEventTypes::kCommissioningComplete:
ESP_LOGI(TAG, "Commissioning complete");
break;
case chip::DeviceLayer::DeviceEventType::kESPSystemEvent:
if (event->Platform.ESPSystemEvent.Base == IP_EVENT &&
event->Platform.ESPSystemEvent.Id == IP_EVENT_STA_GOT_IP) {
#if CONFIG_OPENTHREAD_BORDER_ROUTER
esp_openthread_platform_config_t config = {
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
};
ESP_LOGI(TAG, "Thread border router init");
esp_matter::thread_br_init(&config);
#endif
}
break;
case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged:
if (event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned) {
esp_matter::controller::device_mgr::init(0, on_device_list_update);
Expand All @@ -127,6 +148,10 @@ esp_err_t app_matter_init()
endpoint_t *root_endpoint = esp_matter::endpoint::get(node, 0);
esp_matter::cluster::matter_controller::create(root_endpoint, CLUSTER_FLAG_SERVER);

#if CONFIG_OPENTHREAD_BORDER_ROUTER
cluster::thread_br::create(root_endpoint, CLUSTER_FLAG_SERVER);
#endif

/* Add custom rainmaker cluster */
return rainmaker::init();
}
Expand Down Expand Up @@ -170,6 +195,9 @@ void app_matter_enable_matter_console()
#if CONFIG_ESP_MATTER_CONTROLLER_ENABLE
esp_matter::console::controller_register_commands();
#endif
#if CONFIG_OPENTHREAD_BORDER_ROUTER && CONFIG_OPENTHREAD_CLI
esp_matter::console::thread_br_cli_register_command();
#endif // CONFIG_OPENTHREAD_BORDER_ROUTER && CONFIG_OPENTHREAD_CLI
#else
ESP_LOGI(TAG, "Set CONFIG_ENABLE_CHIP_SHELL to enable Matter Console");
#endif
Expand Down
84 changes: 84 additions & 0 deletions examples/matter/matter_controller/main/esp_ot_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*
* OpenThread Border Router Example
*
* 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 "sdkconfig.h"
#if CONFIG_OPENTHREAD_BORDER_ROUTER
#include "esp_openthread_types.h"

#if CONFIG_OPENTHREAD_RADIO_NATIVE
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_NATIVE, \
}
#elif CONFIG_OPENTHREAD_RADIO_SPINEL_UART
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_UART_RCP, \
.radio_uart_config = { \
.port = (uart_port_t)1, \
.uart_config = \
{ \
.baud_rate = 460800, \
.data_bits = UART_DATA_8_BITS, \
.parity = UART_PARITY_DISABLE, \
.stop_bits = UART_STOP_BITS_1, \
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \
.rx_flow_ctrl_thresh = 0, \
.source_clk = UART_SCLK_DEFAULT, \
}, \
.rx_pin = GPIO_NUM_17, \
.tx_pin = GPIO_NUM_18, \
}, \
}
#else
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_SPI_RCP, \
.radio_spi_config = { \
.host_device = SPI2_HOST, \
.dma_channel = 2, \
.spi_interface = \
{ \
.mosi_io_num = 11, \
.sclk_io_num = 12, \
.miso_io_num = 13, \
}, \
.spi_device = \
{ \
.cs_ena_pretrans = 2, \
.input_delay_ns = 100, \
.mode = 0, \
.clock_speed_hz = 2500 * 1000, \
.spics_io_num = 10, \
.queue_size = 5, \
}, \
.intr_pin = 8, \
}, \
}
#endif // CONFIG_OPENTHREAD_RADIO_SPINEL_UART OR CONFIG_OPENTHREAD_RADIO_SPINEL_SPI

#define HOST_BAUD_RATE 115200

#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 // CONFIG_OPENTHREAD_BORDER_ROUTER
31 changes: 31 additions & 0 deletions examples/matter/matter_controller/main/linker.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[mapping:CHIP]
archive: libCHIP.a
entries:
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
* (extram_bss)
else:
* (default)

[mapping:esp_matter]
archive: libesp_matter.a
entries:
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
* (extram_bss)
else:
* (default)

[mapping:openthread_bss]
archive: libopenthread.a
entries:
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
* (extram_bss)
else:
* (default)

[mapping:openthread_br]
archive: libopenthread_br.a
entries:
if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y:
* (extram_bss)
else:
* (default)
8 changes: 8 additions & 0 deletions examples/matter/matter_controller/partitions_br.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 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,
otadata, data, ota, , 0x2000
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, 0x20000, 3000K,
fctry, data, nvs, 0x320000, 0x6000
2 changes: 1 addition & 1 deletion examples/matter/matter_controller/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ CONFIG_MBEDTLS_HKDF_C=y
# Enable controller
CONFIG_ESP_MATTER_CONTROLLER_ENABLE=y
CONFIG_ESP_MATTER_COMMISSIONER_ENABLE=n
CONFIG_CONTROLLER_CUSTOM_CLUSTER_ENABLE=y
CONFIG_ESP_MATTER_CONTROLLER_CUSTOM_CLUSTER_ENABLE=y

# Increase stack size
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
Expand Down
85 changes: 85 additions & 0 deletions examples/matter/matter_controller/sdkconfig.defaults.otbr
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# ESP Thread Border Router DevKits use 4MB flash
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y

# SPIRAM
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_QUAD=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=512
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y
CONFIG_ESP_MATTER_MEM_ALLOC_MODE_EXTERNAL=y
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y

# Enable Openthread Border Router, but don't run matter over Thread
CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n
CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_BORDER_ROUTER=y
CONFIG_ENABLE_MATTER_OVER_THREAD=n

#LwIP config for OpenThread
CONFIG_LWIP_IPV6_AUTOCONFIG=y
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
CONFIG_LWIP_MULTICAST_PING=y
CONFIG_LWIP_IPV6_FORWARD=y
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
CONFIG_LWIP_NETIF_STATUS_CALLBACK=y

# mbedTLS
CONFIG_MBEDTLS_HARDWARE_AES=y
CONFIG_MBEDTLS_HARDWARE_MPI=y
CONFIG_MBEDTLS_HARDWARE_SHA=y
CONFIG_MBEDTLS_CMAC_C=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y
CONFIG_MBEDTLS_ECJPAKE_C=y
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
CONFIG_MBEDTLS_HKDF_C=y

# MDNS platform
CONFIG_USE_MINIMAL_MDNS=n
CONFIG_ENABLE_EXTENDED_DISCOVERY=y
CONFIG_MDNS_MULTIPLE_INSTANCE=y

# Enable chip shell
CONFIG_ENABLE_CHIP_SHELL=y
CONFIG_ESP_MATTER_CONSOLE_TASK_STACK=4096

# Increase Stack size
CONFIG_CHIP_TASK_STACK_SIZE=10240
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192

# Wi-Fi Settings
CONFIG_ENABLE_WIFI_STATION=y
CONFIG_ENABLE_WIFI_AP=n

# Enable Controller and disable commissioner
CONFIG_ESP_MATTER_CONTROLLER_ENABLE=y
CONFIG_ESP_MATTER_COMMISSIONER_ENABLE=n
CONFIG_ESP_MATTER_CONTROLLER_CUSTOM_CLUSTER_ENABLE=y
CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n

# Use a custom partition table
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_br.csv"

# Disable chip test build
CONFIG_BUILD_CHIP_TESTS=n

# Disable OTA Requestor
CONFIG_ENABLE_OTA_REQUESTOR=n

# Use compact attribute storage mode
CONFIG_ESP_MATTER_NVS_USE_COMPACT_ATTR_STORAGE=y

# Disable route hook for matter since OTBR has already initialize the route hook
CONFIG_ENABLE_ROUTE_HOOK=n

CONFIG_OPENTHREAD_CLI=y

# Use USB Jtag Console
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,4 @@ idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
# idf_build_set_property(C_COMPILE_OPTIONS "-Os;-DLWIP_IPV6_SCOPES=0" 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)
idf_build_set_property(CXX_COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security;-Wformat=0" APPEND)
34 changes: 33 additions & 1 deletion examples/matter/matter_controller_with_touchscreen/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Matter + Rainmaker Controller With Touchscreen Example

- This example demonstrates a Matter + RainMaker Controller which running on [ESP32-S3-BOX](https://github.com/espressif/esp-box) or [ESP32-S3-LCD-EV-BOARD](https://github.com/espressif/esp-dev-kits/tree/master/esp32-s3-lcd-ev-board). Matter is used for commissioning (also known as Wi-Fi provisioning) and local control, whereas RainMaker is used for remote control.
- Thread Border Router support by integrating an ESP32-H2.

## Usage

Expand All @@ -10,7 +11,7 @@

### [Generating the factory nvs binary](../README.md#generating-the-factory-nvs-binary)

### Building the example
### Building the example (without OpenThread Border Router)

```
$ idf.py set-target esp32s3
Expand All @@ -23,6 +24,37 @@ $ idf.py flash monitor
>> - Please use ESP-IDF [v5.2](https://github.com/espressif/esp-idf/tree/v5.2).
>> - If the board is ESP32-S3-LCD-EV-BOARD, set-target command should be `idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.lcdboard" set-target esp32s3`, remember to select board at the same time.
### Building the example (with OpenThread Border Router)

Build ot_rcp example in `${IDF_PATH}/examples/openthread/ot_rcp`.

Prepare a ESP32-H2 board (flashed ot_rcp example) to connect ESP32-S3-BOX / ESP32-S3-BOX-3 / S3-LCD-EV-BOARD via UART.

| BOX / BOX-3 | ESP32-H2 |
|------------ |----------|
| GND | GND |
| 3V3 | 3V3 |
| GPIO41 | RX |
| GPIO38 | TX |

| S3-LCD-EV-BOARD | ESP32-H2 |
|-----------------|----------|
| GND | GND |
| 3V3 | 3V3 |
| GPIO0 | RX |
| GPIO4 | TX |

Build the example with the sdkconfig file 'sdkconfig.defaults.otbr' to enable the OTBR feature on the controller.

```
$ idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.otbr" set-target esp32s3
$ idf.py build
$ idf.py flash monitor
```
> If the board is ESP32-S3-LCD-EV-BOARD, set-target command should be `idf.py -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.lcdboard;sdkconfig.defaults.otbr" set-target esp32s3`, remember to check the board selection (default ESP32-S3-BOX-3) at the same time.
> Note: Thread Border Router is not initialized until the Controller has been commissioned and obtained an IP address.
### Commissioning

To commission the Controller with touchscreen, scan the QR Code shown on the screen using ESP RainMaker app.
Expand Down
Loading

0 comments on commit 944a13e

Please sign in to comment.