Skip to content

Commit 5a8cba8

Browse files
authored
feat(Matter): Adds New Matter Humidity Sensor Endpoint (#10703)
* feat(matter): adds matter humidity sensor endpoint
1 parent 3d8014b commit 5a8cba8

File tree

7 files changed

+323
-0
lines changed

7 files changed

+323
-0
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ set(ARDUINO_LIBRARY_Matter_SRCS
176176
libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp
177177
libraries/Matter/src/MatterEndpoints/MatterFan.cpp
178178
libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp
179+
libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp
179180
libraries/Matter/src/Matter.cpp)
180181

181182
set(ARDUINO_LIBRARY_PPP_SRCS
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Copyright 2024 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+
/*
16+
* This example is an example code that will create a Matter Device which can be
17+
* commissioned and controlled from a Matter Environment APP.
18+
* Additionally the ESP32 will send debug messages indicating the Matter activity.
19+
* Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages.
20+
*/
21+
22+
// Matter Manager
23+
#include <Matter.h>
24+
#include <WiFi.h>
25+
26+
// List of Matter Endpoints for this Node
27+
// Matter Humidity Sensor Endpoint
28+
MatterHumiditySensor SimulatedHumiditySensor;
29+
30+
// set your board USER BUTTON pin here - decommissioning button
31+
const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button.
32+
33+
// WiFi is manually set and started
34+
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
35+
const char *password = "your-password"; // Change this to your WiFi password
36+
37+
// Button control - decommision the Matter Node
38+
uint32_t button_time_stamp = 0; // debouncing control
39+
bool button_state = false; // false = released | true = pressed
40+
const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission
41+
42+
// Simulate a humidity sensor - add your preferred humidity sensor library code here
43+
float getSimulatedHumidity() {
44+
// The Endpoint implementation keeps an uint16_t as internal value information,
45+
// which stores data in 1/100th of humidity percent
46+
static float simulatedHumidityHWSensor = 10.0;
47+
48+
// it will increase from 10% to 30% in 0.5% steps to simulate a humidity sensor
49+
simulatedHumidityHWSensor = simulatedHumidityHWSensor + 0.5;
50+
if (simulatedHumidityHWSensor > 30) {
51+
simulatedHumidityHWSensor = 10;
52+
}
53+
54+
return simulatedHumidityHWSensor;
55+
}
56+
57+
void setup() {
58+
// Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node
59+
pinMode(buttonPin, INPUT_PULLUP);
60+
61+
Serial.begin(115200);
62+
63+
// Manually connect to WiFi
64+
WiFi.begin(ssid, password);
65+
// Wait for connection
66+
while (WiFi.status() != WL_CONNECTED) {
67+
delay(500);
68+
Serial.print(".");
69+
}
70+
Serial.println();
71+
72+
// set initial humidity sensor measurement
73+
// Simulated Sensor - it shall initially print 95% and then move to the 10% to 30% humidity range
74+
SimulatedHumiditySensor.begin(95.00);
75+
76+
// Matter beginning - Last step, after all EndPoints are initialized
77+
Matter.begin();
78+
79+
// Check Matter Accessory Commissioning state, which may change during execution of loop()
80+
if (!Matter.isDeviceCommissioned()) {
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+
// waits for Matter Humidity Sensor Commissioning.
88+
uint32_t timeCount = 0;
89+
while (!Matter.isDeviceCommissioned()) {
90+
delay(100);
91+
if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec
92+
Serial.println("Matter Node not commissioned yet. Waiting for commissioning.");
93+
}
94+
}
95+
Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
96+
}
97+
}
98+
99+
void loop() {
100+
static uint32_t timeCounter = 0;
101+
102+
// Print the current humidity value every 5s
103+
if (!(timeCounter++ % 10)) { // delaying for 500ms x 10 = 5s
104+
// Print the current humidity value
105+
Serial.printf("Current Humidity is %.02f%%\r\n", SimulatedHumiditySensor.getHumidity());
106+
// Update Humidity from the (Simulated) Hardware Sensor
107+
// Matter APP shall display the updated humidity percent
108+
SimulatedHumiditySensor.setHumidity(getSimulatedHumidity());
109+
}
110+
111+
// Check if the button has been pressed
112+
if (digitalRead(buttonPin) == LOW && !button_state) {
113+
// deals with button debouncing
114+
button_time_stamp = millis(); // record the time while the button is pressed.
115+
button_state = true; // pressed.
116+
}
117+
118+
if (digitalRead(buttonPin) == HIGH && button_state) {
119+
button_state = false; // released
120+
}
121+
122+
// Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node
123+
uint32_t time_diff = millis() - button_time_stamp;
124+
if (button_state && time_diff > decommissioningTimeout) {
125+
Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
126+
Matter.decommission();
127+
}
128+
129+
delay(500);
130+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"fqbn_append": "PartitionScheme=huge_app",
3+
"requires": [
4+
"CONFIG_SOC_WIFI_SUPPORTED=y",
5+
"CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y"
6+
]
7+
}

libraries/Matter/keywords.txt

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ MatterFan KEYWORD1
1919
FanMode_t KEYWORD1
2020
FanModeSequence_t KEYWORD1
2121
MatterTemperatureSensor KEYWORD1
22+
MatterHumiditySensor KEYWORD1
2223

2324
#######################################
2425
# Methods and Functions (KEYWORD2)
@@ -65,6 +66,8 @@ onChangeMode KEYWORD2
6566
onChangeSpeedPercent KEYWORD2
6667
setTemperature KEYWORD2
6768
getTemperature KEYWORD2
69+
setHumidity KEYWORD2
70+
getHumidity KEYWORD2
6871

6972
#######################################
7073
# Constants (LITERAL1)

libraries/Matter/src/Matter.h

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <MatterEndpoints/MatterEnhancedColorLight.h>
2828
#include <MatterEndpoints/MatterFan.h>
2929
#include <MatterEndpoints/MatterTemperatureSensor.h>
30+
#include <MatterEndpoints/MatterHumiditySensor.h>
3031

3132
using namespace esp_matter;
3233

@@ -60,6 +61,7 @@ class ArduinoMatter {
6061
friend class MatterEnhancedColorLight;
6162
friend class MatterFan;
6263
friend class MatterTemperatureSensor;
64+
friend class MatterHumiditySensor;
6365

6466
protected:
6567
static void _init();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2024 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+
#include <sdkconfig.h>
16+
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
17+
18+
#include <Matter.h>
19+
#include <app/server/Server.h>
20+
#include <MatterEndpoints/MatterHumiditySensor.h>
21+
22+
using namespace esp_matter;
23+
using namespace esp_matter::endpoint;
24+
using namespace chip::app::Clusters;
25+
26+
bool MatterHumiditySensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) {
27+
bool ret = true;
28+
if (!started) {
29+
log_e("Matter Humidity Sensor device has not begun.");
30+
return false;
31+
}
32+
33+
log_d("Humidity Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32);
34+
return ret;
35+
}
36+
37+
MatterHumiditySensor::MatterHumiditySensor() {}
38+
39+
MatterHumiditySensor::~MatterHumiditySensor() {
40+
end();
41+
}
42+
43+
bool MatterHumiditySensor::begin(uint16_t _rawHumidity) {
44+
ArduinoMatter::_init();
45+
46+
// is it a valid percentage value?
47+
if (_rawHumidity > 10000) {
48+
log_e("Humidity Sensor Percentage value out of range [0..100].");
49+
return false;
50+
}
51+
52+
humidity_sensor::config_t humidity_sensor_config;
53+
humidity_sensor_config.relative_humidity_measurement.measured_value = _rawHumidity;
54+
humidity_sensor_config.relative_humidity_measurement.min_measured_value = nullptr;
55+
humidity_sensor_config.relative_humidity_measurement.max_measured_value = nullptr;
56+
57+
// endpoint handles can be used to add/modify clusters.
58+
endpoint_t *endpoint = humidity_sensor::create(node::get(), &humidity_sensor_config, ENDPOINT_FLAG_NONE, (void *)this);
59+
if (endpoint == nullptr) {
60+
log_e("Failed to create Humidity Sensor endpoint");
61+
return false;
62+
}
63+
rawHumidity = _rawHumidity;
64+
setEndPointId(endpoint::get_id(endpoint));
65+
log_i("Humidity Sensor created with endpoint_id %d", getEndPointId());
66+
started = true;
67+
return true;
68+
}
69+
70+
void MatterHumiditySensor::end() {
71+
started = false;
72+
}
73+
74+
bool MatterHumiditySensor::setRawHumidity(uint16_t _rawHumidity) {
75+
if (!started) {
76+
log_e("Matter Humidity Sensor device has not begun.");
77+
return false;
78+
}
79+
// is it a valid percentage value?
80+
if (_rawHumidity > 10000) {
81+
log_e("Humidity Sensor Percentage value out of range [0..100].");
82+
return false;
83+
}
84+
85+
// avoid processing the a "no-change"
86+
if (rawHumidity == _rawHumidity) {
87+
return true;
88+
}
89+
90+
esp_matter_attr_val_t humidityVal = esp_matter_invalid(NULL);
91+
92+
if (!getAttributeVal(RelativeHumidityMeasurement::Id, RelativeHumidityMeasurement::Attributes::MeasuredValue::Id, &humidityVal)) {
93+
log_e("Failed to get Humidity Sensor Attribute.");
94+
return false;
95+
}
96+
if (humidityVal.val.u16 != _rawHumidity) {
97+
humidityVal.val.u16 = _rawHumidity;
98+
bool ret;
99+
ret = updateAttributeVal(RelativeHumidityMeasurement::Id, RelativeHumidityMeasurement::Attributes::MeasuredValue::Id, &humidityVal);
100+
if (!ret) {
101+
log_e("Failed to update Fan Speed Percent Attribute.");
102+
return false;
103+
}
104+
rawHumidity = _rawHumidity;
105+
}
106+
log_v("Humidity Sensor set to %.02f Percent", (float)_rawHumidity / 100.00);
107+
108+
return true;
109+
}
110+
111+
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2024 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+
#pragma once
16+
#include <sdkconfig.h>
17+
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
18+
19+
#include <Matter.h>
20+
#include <MatterEndPoint.h>
21+
22+
class MatterHumiditySensor : public MatterEndPoint {
23+
public:
24+
MatterHumiditySensor();
25+
~MatterHumiditySensor();
26+
// begin Matter Humidity Sensor endpoint with initial float humidity percent
27+
bool begin(double humidityPercent = 0.00) {
28+
if (humidityPercent < 0.0 || humidityPercent > 100.0) {
29+
log_e("Humidity Sensor Percentage value out of range [0..100].");
30+
return false;
31+
}
32+
return begin(static_cast<uint16_t>(humidityPercent * 100.0f));
33+
}
34+
// this will just stop processing Humidity Sensor Matter events
35+
void end();
36+
37+
// set the humidity percent with 1/100th of a percent precision
38+
bool setHumidity(double humidityPercent) {
39+
if (humidityPercent < 0.0 || humidityPercent > 100.0) {
40+
log_e("Humidity Sensor Percentage value out of range [0..100].");
41+
return false;
42+
}
43+
return setRawHumidity(static_cast<uint16_t>(humidityPercent * 100.0f));
44+
}
45+
// returns the reported float humidity percent with 1/100th of precision
46+
double getHumidity() {
47+
return (double)rawHumidity / 100.0;
48+
}
49+
// double conversion operator
50+
void operator=(double humidityPercent) {
51+
setHumidity(humidityPercent);
52+
}
53+
// double conversion operator
54+
operator double() {
55+
return (double)getHumidity();
56+
}
57+
58+
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
59+
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
60+
61+
protected:
62+
bool started = false;
63+
// implementation keeps humidity relative percentage with 1/100th of a percent precision
64+
uint16_t rawHumidity = 0;
65+
// internal function to set the raw humidity value (Matter Cluster)
66+
bool begin(uint16_t _rawHumidity);
67+
bool setRawHumidity(uint16_t _rawHumidity);
68+
};
69+
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

0 commit comments

Comments
 (0)