Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions examples/stateful_light_switch/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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.16)

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})

set(PROJECT_VER "1.0")
set(PROJECT_VER_NUMBER 1)

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(${ESP_MATTER_PATH}/examples/common/cmake_common/components_include.cmake)

set(EXTRA_COMPONENT_DIRS
"${ESP_MATTER_PATH}/examples/common"
"${MATTER_SDK_PATH}/config/esp32/components"
"${ESP_MATTER_PATH}/components"
${extra_components_dirs_append})

project(stateful_light_switch)
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)
87 changes: 87 additions & 0 deletions examples/stateful_light_switch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Stateful Light Switch

A composite Matter device that combines:
- **Dimmable Light (0x0101)**: Server clusters for On/Off and Level Control, controls local WS2812 LED
- **Dimmer Switch (0x0104)**: Client clusters for sending commands to bound devices

Both device types are on a single endpoint, allowing the device to act as both a controllable light and a switch controller.

## Hardware Requirements

- ESP32-C6 development board
- WS2812 RGB LED on **GPIO 8** (used as white light only)
- Button on **GPIO 9**

## Device Functionality

### Matter Clusters

| Cluster | Role | Purpose |
|---------|------|---------|
| On/Off | Server | Receives on/off commands, controls local LED |
| On/Off | Client | Sends on/off commands to bound devices |
| LevelControl | Server | Receives brightness commands, controls LED brightness |
| LevelControl | Client | Sends brightness commands to bound devices |
| Binding | Server | Stores bindings to remote devices |

### Button Operations

| Press Pattern | Action | Description |
|--------------|--------|-------------|
| **Single Short Press** | Toggle | Toggles local LED on/off and sends Toggle command to bound devices |
| **Hold** | Dim Up | Increases brightness gradually. Sends Move command to bound devices at start, Stop on release |
| **Short Press + Hold** | Dim Down | Decreases brightness gradually. Press briefly, then hold within 1.5s to dim down |

### LED Behavior

- LED brightness follows the LevelControl CurrentLevel attribute (0-254)
- LED turns off completely when On/Off attribute is OFF
- LED can be controlled locally or remotely from a Matter controller (e.g., Home Assistant)

## Building and Flashing

```bash
cd examples/stateful_light_switch
idf.py set-target esp32c6
idf.py build flash monitor
```

## Post Commissioning Setup

### Bind a Light to the Switch

After commissioning both devices, update the light's ACL and the switch's binding:

1. Update light's ACL to allow switch access:
```
chip-tool accesscontrol write acl '[{"privilege": 5, "authMode": 2, "subjects": [112233, <switch_node_id>], "targets": null}]' <light_node_id> 0
```

2. Add binding on switch to control the light:
```
chip-tool binding write binding '[{"node": <light_node_id>, "endpoint": 1, "cluster": 6}, {"node": <light_node_id>, "endpoint": 1, "cluster": 8}]' <switch_node_id> 1
```

Note: Cluster 6 = On/Off, Cluster 8 = Level Control

## Console Commands

If console is enabled (`CONFIG_ENABLE_CHIP_SHELL=y`):

### Send commands to bound devices
```
matter esp bound invoke <local_endpoint_id> <cluster_id> <command_id> [parameters]
```

Examples:
- Toggle: `matter esp bound invoke 0x1 0x6 0x2`
- On: `matter esp bound invoke 0x1 0x6 0x1`
- Off: `matter esp bound invoke 0x1 0x6 0x0`

## Troubleshooting

### "failed to notify the bound cluster changed"
This error appears when no devices are bound to the switch. It is expected behavior and will disappear once you configure bindings.

### Brightness changes from controller don't work
Ensure the device is commissioned and the controller has proper ACL access. The device processes attribute updates in the PRE_UPDATE callback.
11 changes: 11 additions & 0 deletions examples/stateful_light_switch/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(SRC_DIRS_LIST "." "${ESP_MATTER_PATH}/examples/common/app_reset")

if (CONFIG_DYNAMIC_PASSCODE_COMMISSIONABLE_DATA_PROVIDER)
list(APPEND SRC_DIRS_LIST "custom_provider")
endif()


idf_component_register(SRC_DIRS ${SRC_DIRS_LIST}
PRIV_INCLUDE_DIRS "." "${ESP_MATTER_PATH}/examples/common/utils" "${ESP_MATTER_PATH}/examples/common/app_reset")

target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H")
39 changes: 39 additions & 0 deletions examples/stateful_light_switch/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
menu "Example Configuration"

visible if CUSTOM_COMMISSIONABLE_DATA_PROVIDER

config DYNAMIC_PASSCODE_COMMISSIONABLE_DATA_PROVIDER
bool "Enable Dynamic Passcode Commissionable Data Provider"
depends on CUSTOM_COMMISSIONABLE_DATA_PROVIDER
default y

config DYNAMIC_PASSCODE_PROVIDER_DISCRIMINATOR
int "Discriminator in Dynamic Passcode Commissionable Data Provider"
depends on DYNAMIC_PASSCODE_COMMISSIONABLE_DATA_PROVIDER
default 3840
range 0 4095
help
Fixed discriminator in custom dynamic passcode commissionable data provider

config DYNAMIC_PASSCODE_PROVIDER_ITERATIONS
int "Iterations in Dynamic Passcode Commissionable Data Provider"
depends on DYNAMIC_PASSCODE_COMMISSIONABLE_DATA_PROVIDER
default 10000
range 1000 100000
help
Fixed iterations in custom dynamic passcode commissionable data provider

config DYNAMIC_PASSCODE_PROVIDER_SALT_BASE64
string "Base64-Encoded Salt in Dynamic Passcode Commissionable Data Provider"
depends on DYNAMIC_PASSCODE_COMMISSIONABLE_DATA_PROVIDER
default "0NHS09TV1tfY2drb3N3e36ChoqOkpaanqKmqq6ytrq8="
help
Fixed salt in custom dynamic passcode commissionable data provider. It should be a Base64-Encoded string.

config SUBSCRIBE_TO_ON_OFF_SERVER_AFTER_BINDING
bool "Enable subscribe to on/off server after binding"
default n
help
"Enables auto subscription to on/off server from client on change in binding"

endmenu
Loading