From 538efe3b8c37ac8d0bdb1106911669f03a47f0c4 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Mon, 9 Dec 2024 19:30:05 -0300 Subject: [PATCH] feat(matter): adds new Temperature Sensor Matter Endpoint (#10698) * feat(matter): adds new temperature sensor matter endpoint * feat(matter): commentaries review and fixes * feat(matter): commentaries review and fixes * feat(matter): commentaries review and fixes * feat(matter): commentaries review and fixes * feat(matter): commentaries review and fixes * feat(matter): commentaries review and fixes * feat(matter): general commentaries and code review * feat(matter): keeping arduino style for local variables (lower case) * feat(matter): applies a generic temperature unit to the implementation and example * fix(matter): fixed problem with begin(float) implementation * fix(matter): fixed begin(float) initiallization * feat(matter): updated matter temperature keywords with new api * ci(pre-commit): Apply automatic fixes * fix(matter): fixed code spell ci errors in matter temperature sensor --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- CMakeLists.txt | 1 + .../MatterTemperatureSensor.ino | 94 ++++++++++++++++++ .../examples/MatterTemperatureSensor/ci.json | 7 ++ libraries/Matter/keywords.txt | 3 + libraries/Matter/src/Matter.h | 2 + .../MatterTemperatureSensor.cpp | 99 +++++++++++++++++++ .../MatterEndpoints/MatterTemperatureSensor.h | 63 ++++++++++++ 7 files changed, 269 insertions(+) create mode 100644 libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino create mode 100644 libraries/Matter/examples/MatterTemperatureSensor/ci.json create mode 100644 libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp create mode 100644 libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e4991d558d8..eba1a3fd824 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,6 +175,7 @@ set(ARDUINO_LIBRARY_Matter_SRCS libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp libraries/Matter/src/MatterEndpoints/MatterFan.cpp + libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp libraries/Matter/src/Matter.cpp) set(ARDUINO_LIBRARY_PPP_SRCS diff --git a/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino b/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino new file mode 100644 index 00000000000..216406d6082 --- /dev/null +++ b/libraries/Matter/examples/MatterTemperatureSensor/MatterTemperatureSensor.ino @@ -0,0 +1,94 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * This example is an example code that will create a Matter Device which can be + * commissioned and controlled from a Matter Environment APP. + * Additionally the ESP32 will send debug messages indicating the Matter activity. + * Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages. + */ + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Matter Temperature Sensor Endpoint +MatterTemperatureSensor SimulatedTemperatureSensor; + +// WiFi is manually set and started +const char *ssid = "your-ssid"; // Change this to your WiFi SSID +const char *password = "your-password"; // Change this to your WiFi password + +// Simulate a temperature sensor - add your preferred temperature sensor library code here +float getSimulatedTemperature() { + // The Endpoint implementation keeps an int16_t as internal value information, + // which stores data in 1/100th of any temperature unit + static float simulatedTempHWSensor = -10.0; + + // it will increase from -10C to 10C in 0.5C steps to simulate a temperature sensor + simulatedTempHWSensor = simulatedTempHWSensor + 0.5; + if (simulatedTempHWSensor > 10) { + simulatedTempHWSensor = -10; + } + + return simulatedTempHWSensor; +} + +void setup() { + Serial.begin(115200); + + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + + // set initial temperature sensor measurement + // Simulated Sensor - it shall initially print -25 degrees and then move to the -10 to 10 range + SimulatedTemperatureSensor.begin(-25.00); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + + // Check Matter Accessory Commissioning state, which may change during execution of loop() + if (!Matter.isDeviceCommissioned()) { + Serial.println(""); + Serial.println("Matter Node is not commissioned yet."); + Serial.println("Initiate the device discovery in your Matter environment."); + Serial.println("Commission it to your Matter hub with the manual pairing code or QR code"); + Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str()); + Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str()); + // waits for Matter Temperature Sensor Commissioning. + uint32_t timeCount = 0; + while (!Matter.isDeviceCommissioned()) { + delay(100); + if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec + Serial.println("Matter Node not commissioned yet. Waiting for commissioning."); + } + } + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +void loop() { + Serial.printf("Current Temperature is %.02f \r\n", SimulatedTemperatureSensor.getTemperature()); + // update the temperature sensor value every 5 seconds + // Matter APP shall display the updated temperature + delay(5000); + SimulatedTemperatureSensor.setTemperature(getSimulatedTemperature()); +} diff --git a/libraries/Matter/examples/MatterTemperatureSensor/ci.json b/libraries/Matter/examples/MatterTemperatureSensor/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/MatterTemperatureSensor/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=huge_app", + "requires": [ + "CONFIG_SOC_WIFI_SUPPORTED=y", + "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y" + ] +} diff --git a/libraries/Matter/keywords.txt b/libraries/Matter/keywords.txt index 4668054d12e..60ffc546bd6 100644 --- a/libraries/Matter/keywords.txt +++ b/libraries/Matter/keywords.txt @@ -18,6 +18,7 @@ MatterEndPoint KEYWORD1 MatterFan KEYWORD1 FanMode_t KEYWORD1 FanModeSequence_t KEYWORD1 +MatterTemperatureSensor KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -62,6 +63,8 @@ setMode KEYWORD2 getMode KEYWORD2 onChangeMode KEYWORD2 onChangeSpeedPercent KEYWORD2 +setTemperature KEYWORD2 +getTemperature KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/Matter/src/Matter.h b/libraries/Matter/src/Matter.h index 06edf32288f..1b35d876705 100644 --- a/libraries/Matter/src/Matter.h +++ b/libraries/Matter/src/Matter.h @@ -26,6 +26,7 @@ #include #include #include +#include using namespace esp_matter; @@ -58,6 +59,7 @@ class ArduinoMatter { friend class MatterColorLight; friend class MatterEnhancedColorLight; friend class MatterFan; + friend class MatterTemperatureSensor; protected: static void _init(); diff --git a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp new file mode 100644 index 00000000000..4a43650f924 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.cpp @@ -0,0 +1,99 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +using namespace esp_matter; +using namespace esp_matter::endpoint; +using namespace chip::app::Clusters; + +bool MatterTemperatureSensor::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + bool ret = true; + if (!started) { + log_e("Matter Temperature Sensor device has not begun."); + return false; + } + + log_d("Temperature Sensor Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + return ret; +} + +MatterTemperatureSensor::MatterTemperatureSensor() {} + +MatterTemperatureSensor::~MatterTemperatureSensor() { + end(); +} + +bool MatterTemperatureSensor::begin(int16_t _rawTemperature) { + ArduinoMatter::_init(); + + temperature_sensor::config_t temperature_sensor_config; + temperature_sensor_config.temperature_measurement.measured_value = _rawTemperature; + temperature_sensor_config.temperature_measurement.min_measured_value = nullptr; + temperature_sensor_config.temperature_measurement.max_measured_value = nullptr; + + // endpoint handles can be used to add/modify clusters + endpoint_t *endpoint = temperature_sensor::create(node::get(), &temperature_sensor_config, ENDPOINT_FLAG_NONE, (void *)this); + if (endpoint == nullptr) { + log_e("Failed to create Temperature Sensor endpoint"); + return false; + } + rawTemperature = _rawTemperature; + setEndPointId(endpoint::get_id(endpoint)); + log_i("Temperature Sensor created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterTemperatureSensor::end() { + started = false; +} + +bool MatterTemperatureSensor::setRawTemperature(int16_t _rawTemperature) { + if (!started) { + log_e("Matter Temperature Sensor device has not begun."); + return false; + } + + // avoid processing the a "no-change" + if (rawTemperature == _rawTemperature) { + return true; + } + + esp_matter_attr_val_t temperatureVal = esp_matter_invalid(NULL); + + if (!getAttributeVal(TemperatureMeasurement::Id, TemperatureMeasurement::Attributes::MeasuredValue::Id, &temperatureVal)) { + log_e("Failed to get Temperature Sensor Attribute."); + return false; + } + if (temperatureVal.val.i16 != _rawTemperature) { + temperatureVal.val.i16 = _rawTemperature; + bool ret; + ret = updateAttributeVal(TemperatureMeasurement::Id, TemperatureMeasurement::Attributes::MeasuredValue::Id, &temperatureVal); + if (!ret) { + log_e("Failed to update Fan Speed Percent Attribute."); + return false; + } + rawTemperature = _rawTemperature; + } + log_v("Temperature Sensor set to %.02f Degrees", (float)_rawTemperature / 100.00); + + return true; +} + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ diff --git a/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h new file mode 100644 index 00000000000..826abac9a2a --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterTemperatureSensor.h @@ -0,0 +1,63 @@ +// Copyright 2024 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#include +#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL + +#include +#include + +class MatterTemperatureSensor : public MatterEndPoint { +public: + MatterTemperatureSensor(); + ~MatterTemperatureSensor(); + // begin Matter Temperature Sensor endpoint with initial float temperature + bool begin(double temperature = 0.00) { + return begin(static_cast(temperature * 100.0f)); + } + // this will stop processing Temperature Sensor Matter events + void end(); + + // set the reported raw temperature + bool setTemperature(double temperature) { + // stores up to 1/100th of a degree precision + int16_t rawValue = static_cast(temperature * 100.0f); + return setRawTemperature(rawValue); + } + // returns the reported float temperature with 1/100th of a degree precision + double getTemperature() { + return (double)rawTemperature / 100.0; + } + // double conversion operator + void operator=(double temperature) { + setTemperature(temperature); + } + // double conversion operator + operator double() { + return (double)getTemperature(); + } + + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. + bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val); + +protected: + bool started = false; + // implementation keeps temperature in 1/100th of a degree, any temperature unit + int16_t rawTemperature = 0; + // internal function to set the raw temperature value (Matter Cluster) + bool setRawTemperature(int16_t _rawTemperature); + bool begin(int16_t _rawTemperature); +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */