Skip to content

Commit 9168784

Browse files
authored
feat(matter): adds a simple Window Blind example
This example is the simplest possible in order to demonstrate how to control a Window blind.
1 parent c9dc7c0 commit 9168784

File tree

3 files changed

+232
-0
lines changed

3 files changed

+232
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2025 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Matter Simple Window Blinds Example
16+
// This is a minimal example that only controls Lift percentage using a single onGoToLiftPercentage() callback
17+
18+
#include <Matter.h>
19+
#if !CONFIG_ENABLE_CHIPOBLE
20+
// if the device can be commissioned using BLE, WiFi is not used - save flash space
21+
#include <WiFi.h>
22+
#endif
23+
24+
// List of Matter Endpoints for this Node
25+
// Window Covering Endpoint
26+
MatterWindowCovering WindowBlinds;
27+
28+
// CONFIG_ENABLE_CHIPOBLE is enabled when BLE is used to commission the Matter Network
29+
#if !CONFIG_ENABLE_CHIPOBLE
30+
// WiFi is manually set and started
31+
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
32+
const char *password = "your-password"; // Change this to your WiFi password
33+
#endif
34+
35+
// Simple callback - handles window Lift change request
36+
bool onBlindLift(uint8_t liftPercent) {
37+
// This example only uses lift
38+
Serial.printf("Window Covering change request: Lift=%d%%\r\n", liftPercent);
39+
40+
// Returning true will store the new Lift value into the Matter Cluster
41+
return true;
42+
}
43+
44+
void setup() {
45+
Serial.begin(115200);
46+
delay(1000);
47+
Serial.println("\n========================================");
48+
Serial.println("Matter Simple Window Blinds Example");
49+
Serial.println("========================================\n");
50+
51+
// CONFIG_ENABLE_CHIPOBLE is enabled when BLE is used to commission the Matter Network
52+
#if !CONFIG_ENABLE_CHIPOBLE
53+
// We start by connecting to a WiFi network
54+
Serial.print("Connecting to ");
55+
Serial.println(ssid);
56+
WiFi.mode(WIFI_STA);
57+
WiFi.begin(ssid, password);
58+
while (WiFi.status() != WL_CONNECTED) {
59+
delay(500);
60+
Serial.print(".");
61+
}
62+
Serial.println("");
63+
Serial.println("WiFi connected");
64+
Serial.print("IP address: ");
65+
Serial.println(WiFi.localIP());
66+
#endif
67+
68+
// Initialize Window Covering endpoint
69+
// Using ROLLERSHADE type (lift only, no tilt)
70+
WindowBlinds.begin(100, 0, MatterWindowCovering::ROLLERSHADE);
71+
72+
// Set up the onGoToLiftPercentage callback - this handles all window covering changes requested by the Matter Controller
73+
WindowBlinds.onGoToLiftPercentage(onBlindLift);
74+
75+
// Start Matter
76+
Matter.begin();
77+
Serial.println("Matter started");
78+
Serial.println();
79+
80+
// Print commissioning information
81+
Serial.println("========================================");
82+
Serial.println("Matter Node is not commissioned yet.");
83+
Serial.println("Initiate the device discovery in your Matter environment.");
84+
Serial.println("Commission it to your Matter hub with the manual pairing code or QR code");
85+
Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str());
86+
Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str());
87+
Serial.println("========================================");
88+
}
89+
90+
void loop() {
91+
delay(100);
92+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Matter Simple Window Blinds Example
2+
3+
This is a minimal example demonstrating how to create a Matter-compatible window covering device with lift control only. This example uses a single `onGoToLiftPercentage()` callback to handle all window covering lift changes, making it ideal for simple implementations.
4+
5+
## Supported Targets
6+
7+
| SoC | Wi-Fi | Thread | BLE Commissioning | Status |
8+
| --- | ---- | ------ | ----------------- | ------ |
9+
| ESP32 |||| Fully supported |
10+
| ESP32-S2 |||| Fully supported |
11+
| ESP32-S3 |||| Fully supported |
12+
| ESP32-C3 |||| Fully supported |
13+
| ESP32-C5 |||| Fully supported |
14+
| ESP32-C6 |||| Fully supported |
15+
| ESP32-H2 |||| Supported (Thread only) |
16+
17+
### Note on Commissioning:
18+
19+
- **ESP32 & ESP32-S2** do not support commissioning over Bluetooth LE. For these chips, you must provide Wi-Fi credentials directly in the sketch code so they can connect to your network manually.
20+
- **ESP32-C6** Although it has Thread support, the ESP32 Arduino Matter Library has been precompiled using Wi-Fi only. In order to configure it for Thread-only operation it is necessary to build the project as an ESP-IDF component and to disable the Matter Wi-Fi station feature.
21+
- **ESP32-C5** Although it has Thread support, the ESP32 Arduino Matter Library has been precompiled using Wi-Fi only. In order to configure it for Thread-only operation it is necessary to build the project as an ESP-IDF component and to disable the Matter Wi-Fi station feature.
22+
23+
## Features
24+
25+
- Matter protocol implementation for a window covering device
26+
- **Lift control only** (0-100%) - simplified implementation
27+
- **Single `onGoToLiftPercentage()` callback** - handles all window covering lift changes when `TargetPositionLiftPercent100ths` changes
28+
- Matter commissioning via QR code or manual pairing code
29+
- Integration with Apple HomeKit, Amazon Alexa, and Google Home
30+
31+
## Hardware Requirements
32+
33+
- ESP32 compatible development board (see supported targets table)
34+
- Window covering motor/actuator (optional for testing - example simulates movement)
35+
36+
## Software Setup
37+
38+
### Prerequisites
39+
40+
1. Install the Arduino IDE (2.0 or newer recommended)
41+
2. Install ESP32 Arduino Core with Matter support
42+
3. ESP32 Arduino libraries:
43+
- `Matter`
44+
- `Wi-Fi` (only for ESP32 and ESP32-S2)
45+
46+
### Configuration
47+
48+
Before uploading the sketch, configure the following:
49+
50+
1. **Wi-Fi Credentials** (for ESP32 and ESP32-S2 only):
51+
```cpp
52+
const char *ssid = "your-ssid";
53+
const char *password = "your-password";
54+
```
55+
56+
## Expected Output
57+
58+
```
59+
========================================
60+
Matter Simple Window Blinds Example
61+
========================================
62+
63+
Connecting to your-ssid
64+
WiFi connected
65+
IP address: 192.168.1.100
66+
Matter started
67+
68+
========================================
69+
Matter Node is not commissioned yet.
70+
Initiate the device discovery in your Matter environment.
71+
Commission it to your Matter hub with the manual pairing code or QR code
72+
Manual pairing code: 34970112332
73+
QR code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT:Y.K9042C00KA0648G00
74+
========================================
75+
```
76+
77+
When a command is received from the Matter controller:
78+
```
79+
Window Covering change request: Lift=50%
80+
```
81+
82+
## Usage
83+
84+
1. **Commissioning**: Use the QR code or manual pairing code to commission the device to your Matter hub (Apple Home, Google Home, or Amazon Alexa).
85+
86+
2. **Control**: Once commissioned, you can control the window covering lift percentage (0-100%) from your smart home app. The `onGoToLiftPercentage()` callback will be triggered whenever the target lift percentage changes.
87+
88+
## Code Structure
89+
90+
- **`onBlindLift()`**: Callback function that handles window covering lift changes. This is registered with `WindowBlinds.onGoToLiftPercentage()` and is triggered when `TargetPositionLiftPercent100ths` changes. The callback receives the target lift percentage (0-100%).
91+
- **`setup()`**: Initializes WiFi (if needed), Window Covering endpoint with `ROLLERSHADE` type, registers the callback, and starts Matter.
92+
- **`loop()`**: Empty - all control is handled via Matter callbacks.
93+
94+
## Customization
95+
96+
### Adding Motor Control
97+
98+
In the `onBlindLift()` callback, replace the simulation code with actual motor control:
99+
100+
```cpp
101+
bool onBlindLift(uint8_t liftPercent) {
102+
Serial.printf("Moving window covering to %d%%\r\n", liftPercent);
103+
104+
// Here you would control your actual motor/actuator
105+
// For example:
106+
// - Calculate target position based on liftPercent and installed limits (if configured)
107+
// - Move motor to target position
108+
// - When movement is complete, update current position:
109+
// WindowBlinds.setLiftPercentage(finalLiftPercent);
110+
// WindowBlinds.setOperationalState(MatterWindowCovering::LIFT, MatterWindowCovering::STALL);
111+
112+
// For this minimal example, we just return true to accept the command
113+
return true; // Indicate command was accepted
114+
}
115+
```
116+
117+
## Troubleshooting
118+
119+
1. **Device not discoverable**: Ensure WiFi is connected (for ESP32/ESP32-S2) or BLE is enabled (for other chips).
120+
121+
2. **Lift percentage not updating**: Check that `onGoToLiftPercentage()` callback is properly registered and that `setLiftPercentage()` is called when movement is complete to update the `CurrentPosition` attribute.
122+
123+
3. **Commands not working**: Ensure the callback returns `true` to accept the command. If it returns `false`, the command will be rejected.
124+
125+
4. **Motor not responding**: Replace the simulation code in `onBlindLift()` with your actual motor control implementation. Remember to update `CurrentPosition` and set `OperationalState` to `STALL` when movement is complete.
126+
127+
## Notes
128+
129+
- This example uses `ROLLERSHADE` window covering type (lift only, no tilt).
130+
- The example accepts commands but doesn't actually move a motor. In a real implementation, you should:
131+
1. Move the motor to the target position in the callback
132+
2. Update `CurrentPositionLiftPercent100ths` using `setLiftPercentage()` when movement is complete
133+
3. Set `OperationalState` to `STALL` using `setOperationalState(MatterWindowCovering::LIFT, MatterWindowCovering::STALL)` to indicate the device has reached the target position
134+
- **Important**: `onGoToLiftPercentage()` is called when `TargetPositionLiftPercent100ths` changes. This happens when commands are executed or when a Matter controller writes directly to the target position attribute.
135+
- Commands modify `TargetPosition`, not `CurrentPosition`. The application is responsible for updating `CurrentPosition` when the physical device actually moves.
136+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fqbn_append: PartitionScheme=huge_app
2+
3+
requires:
4+
- CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y

0 commit comments

Comments
 (0)