From 29acdc6140f9025688433e2d3d03c251e724d937 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 5 Dec 2024 22:44:03 -0300 Subject: [PATCH 01/21] feat(matter): adds new fan endpoint and example --- .../Matter/examples/Matter_Fan/MatterFan.ino | 173 +++++++++++++ libraries/Matter/examples/Matter_Fan/ci.json | 7 + .../Matter/src/MatterEndpoints/MatterFan.cpp | 240 ++++++++++++++++++ .../Matter/src/MatterEndpoints/MatterFan.h | 160 ++++++++++++ 4 files changed, 580 insertions(+) create mode 100644 libraries/Matter/examples/Matter_Fan/MatterFan.ino create mode 100644 libraries/Matter/examples/Matter_Fan/ci.json create mode 100644 libraries/Matter/src/MatterEndpoints/MatterFan.cpp create mode 100644 libraries/Matter/src/MatterEndpoints/MatterFan.h diff --git a/libraries/Matter/examples/Matter_Fan/MatterFan.ino b/libraries/Matter/examples/Matter_Fan/MatterFan.ino new file mode 100644 index 00000000000..8460193c464 --- /dev/null +++ b/libraries/Matter/examples/Matter_Fan/MatterFan.ino @@ -0,0 +1,173 @@ +// 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. + +// Matter Manager +#include +#include + +// List of Matter Endpoints for this Node +// Fan Endpoint - On/Off control + Speed Percent Control + Fan Modes +MatterFan Fan; + +// set your board USER BUTTON pin here - used for toggling on/off +const uint8_t buttonPin = 0; // Set your pin here. Using BOOT Button. C6/C3 use GPIO9. + +// set your board Analog Pin here - used for changing the Fan speed +const uint8_t analogPin = A0; // Analog Pin depends on each board + +// 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 + +void setup() { + // Initialize the USER BUTTON (Boot button) GPIO that will toggle the Fan (on/off) + pinMode(buttonPin, INPUT_PULLUP); + // Initialize the Analog Pin A0 used to read input voltage and to set the Fan speed accordingly + pinMode(analogPin, INPUT); + analogReadResolution(10); // 10 bits resolution reading 0..1023 + + Serial.begin(115200); + while (!Serial) { + delay(100); + } + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + // enable IPv6 + WiFi.enableIPv6(true); + // Manually connect to WiFi + WiFi.begin(ssid, password); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println("\r\nWiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + delay(500); + + // On Boot or Reset, Fan is set at 0% speed, OFF, changing between OFF, ON, SMART and HIGH + Fan.begin(0, MatterFan::FAN_MODE_OFF, MatterFan::FAN_MODE_SEQ_OFF_HIGH); + + // callback functions would control Fan motor + // the Matter Controller will send new data whenver the User APP or Automation request + + // single feature callbacks take place before the generic (all features) callback + // This callback will be executed whenever the speed percent matter attribute is updated + Fan.onChangeSpeedPercent([](uint8_t speedPercent) { + // setting speed to Zero, while the Fan is ON, shall turn the Fan off + if (speedPercent == 0 && Fan.getMode() != MatterFan::FAN_MODE_OFF) { + // ATTR_SET do not update the attribute, just set it to avoid inifinite loop + return Fan.setOnOff(false, Fan.ATTR_SET); + } + // changing the speed to higher than Zero, while the Fan is OFF, shall turn the Fan on + if (speedPercent > 0 && Fan.getMode() == MatterFan::FAN_MODE_OFF) { + // ATTR_SET do not update the attribute, just set it to avoid inifinite loop + return Fan.setOnOff(true, Fan.ATTR_SET); + } + // for other case, just return true + return true; + }); + + // This callback will be executed whenever the fan mode matter attribute is updated + // This will take action when user APP starts the Fan by changing the mode + Fan.onChangeMode([](MatterFan::FanMode_t fanMode) { + // when the Fan is turned on using Mode Selection, while it is OFF, shall start it by setting the speed to 50% + if (Fan.getSpeedPercent() == 0 && fanMode != MatterFan::FAN_MODE_OFF) { + Serial.println("Starting Smart Mode -- set speed to 50%"); + // ATTR_SET do not update the attribute, just set it to avoid inifinite loop + return Fan.setSpeedPercent(50, Fan.ATTR_SET); + } + return true; + }); + + // Generic callback will be executed as soon as a single feature callback is done + // In this example, it will just print status messages + Fan.onChange([](MatterFan::FanMode_t fanMode, uint8_t speedPercent) { + // just report state + Serial.printf("Fan State: Mode %s | %d%% speed.\r\n", Fan.getFanModeString(fanMode), speedPercent); + // returns success + return true; + }); + + // Matter beginning - Last step, after all EndPoints are initialized + Matter.begin(); + // This may be a restart of a already commissioned Matter accessory + if (Matter.isDeviceCommissioned()) { + Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use."); + } +} + +// Builtin Button control +uint32_t button_time_stamp = 0; // debouncing control +bool button_state = false; // false = released | true = pressed +const uint32_t debouceTime = 250; // button debouncing time (ms) +const uint32_t decommissioningTimeout = 10000; // keep the button pressed for 10s to decommission the Matter Fabric + +void loop() { + // 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 Generic Switch 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."); + } + + // A builtin button is used to trigger and send a command to the Matter Controller + // Check if the button has been pressed + if (digitalRead(buttonPin) == LOW && !button_state) { + // deals with button debouncing + button_time_stamp = millis(); // record the time while the button is pressed. + button_state = true; // pressed. + } + + // Onboard User Button is used as a smart button or to decommission it + uint32_t time_diff = millis() - button_time_stamp; + if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { + button_state = false; // released + // builtin button is released - send a click event to the Matter Controller + Fan.toggle(); + Serial.printf("User button released. Setting the Fan %s.\r\n", Fan > 0 ? "ON" : "OFF"); + + // Factory reset is triggered if the button is pressed longer than 10 seconds + if (time_diff > decommissioningTimeout) { + Serial.println("Decommissioning the Generic Switch Matter Accessory. It shall be commissioned again."); + Matter.decommission(); + } + } + + // checks Analog pin and adjust the speed only if it has changed + static int lastRead = 0; + // analog values (0..1023) / 110 => mapped into 10 steps (0..9) + int anaVal = analogRead(analogPin) / 110; + if (lastRead != anaVal) { + // speed percent moves in steps of 10. Range is 10..100 + if (Fan.setSpeedPercent((anaVal + 1) * 10)) { + lastRead = anaVal; + } + } +} diff --git a/libraries/Matter/examples/Matter_Fan/ci.json b/libraries/Matter/examples/Matter_Fan/ci.json new file mode 100644 index 00000000000..556a8a9ee6b --- /dev/null +++ b/libraries/Matter/examples/Matter_Fan/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/src/MatterEndpoints/MatterFan.cpp b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp new file mode 100644 index 00000000000..a2ae858d200 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp @@ -0,0 +1,240 @@ +// 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 esp_matter::cluster; +using namespace chip::app::Clusters; + +// string helper for the FAN MODE +const char *MatterFan::fanModeString[7] = {"OFF", "LOW", "MEDIUM", "HIGH", "ON", "AUTO", "SMART"}; +// bitmap for valid Fan Modes based on order defined in Zap Generated Cluster Enums +const uint8_t MatterFan::fanModeSequence[6] = { + fanSeqModeOffLowMedHigh, fanSeqModeOffLowHigh, fanSeqModeOffLowMedHighAuto, + fanSeqModeOffLowHighAuto, fanSeqModeOffHighAuto, fanSeqModeOffHigh +}; + +// Constructor and Method Definitions +MatterFan::MatterFan() { +} + +MatterFan::~MatterFan() { + end(); +} + +bool MatterFan::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 Fan device has not begun."); + return false; + } + + log_i("===> Fan Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + + if (endpoint_id == getEndPointId() && cluster_id == FanControl::Id) { + //endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + //cluster_t *cluster = cluster::get(endpoint, FanControl::Id); + + //attribute_t *attr_percent_setting = attribute::get(cluster, Attributes::PercentSetting::Id); + //attribute_t *attribute_percent_current = attribute::get(cluster, Attributes::PercentCurrent::Id); + //attribute_t *attr_fan_mode = attribute::get(cluster, Attributes::FanMode::Id); + + switch (attribute_id) { + case FanControl::Attributes::FanMode::Id: + log_d("FanControl Fan Mode changed to %s (%x)", val->val.u8 < 7 ? fanModeString[val->val.u8] : "Unknown", val->val.u8); + if (_onChangeModeCB != NULL) { + ret &= _onChangeModeCB((FanMode_t) val->val.u8); + } + if ( _onChangeCB != NULL) { + ret &= _onChangeCB((FanMode_t) val->val.u8, currentPercent); + } + if (ret == true) { + currentFanMode = (FanMode_t) val->val.u8; + } + break; + case FanControl::Attributes::PercentSetting::Id: + case FanControl::Attributes::PercentCurrent::Id: + log_d("FanControl Percent %s changed to %d", attribute_id == FanControl::Attributes::PercentSetting::Id ? "SETTING" : "CURRENT", val->val.u8); + if (_onChangeSpeedCB != NULL) { + ret &= _onChangeSpeedCB(val->val.u8); + } + if ( _onChangeCB != NULL) { + ret &= _onChangeCB(currentFanMode, val->val.u8); + } + if (ret == true) { + // change setting speed percent + currentPercent = val->val.u8; + setAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, val); + setAttributeVal(FanControl::Id, FanControl::Attributes::PercentCurrent::Id, val); + } + break; + } + } + + return ret; +} + +bool MatterFan::begin(uint8_t percent, FanMode_t fanMode, FanModeSequence_t fanModeSeq) { + ArduinoMatter::_init(); + + // endpoint handles can be used to add/modify clusters. + fan::config_t fan_config; + fan_config.fan_control.fan_mode = fanMode; + fan_config.fan_control.percent_current = percent; + fan_config.fan_control.percent_setting = percent; + fan_config.fan_control.fan_mode_sequence = fanModeSeq; + validFanModes = fanModeSequence[fanModeSeq]; + + endpoint_t *endpoint = fan::create(node::get(), &fan_config, ENDPOINT_FLAG_NONE, (void *)this); + + if (endpoint == nullptr) { + log_e("Failed to create Generic swtich endpoint"); + return false; + } + + currentFanMode = fanMode; + currentPercent = percent; + + setEndPointId(endpoint::get_id(endpoint)); + log_i("Fan created with endpoint_id %d", getEndPointId()); + started = true; + return true; +} + +void MatterFan::end() { + started = false; +} + +bool MatterFan::setMode(FanMode_t newMode, bool performUpdate) { + if (!started) { + log_w("Matter Fan device has not begun."); + return false; + } + // avoid processing the a "no-change" + if (currentFanMode == newMode) { + return true; + } + + // check if the mode is valid based on the sequence used in its creation + if (!(validFanModes & (1 << newMode))) { + log_e("Invalid Fan Mode %s for the current Fan Mode Sequence.", fanModeString[newMode]); + return false; + } + + esp_matter_attr_val_t modeVal = esp_matter_invalid(NULL); + if (!getAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal)) { + log_e("Failed to get Fan Mode Attribute."); + return false; + } + if (modeVal.val.u8 != (uint8_t) newMode) { + modeVal.val.u8 = (uint8_t) newMode; + bool ret; + if (performUpdate) { + ret = updateAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal); + } else { + ret = setAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal); + } + if (!ret) { + log_e("Failed to %s Fan Mode Attribute.", performUpdate ? "update" : "set"); + return false; + } + } + currentFanMode = newMode; + log_d("Fan Mode %s to %s ==> onOffState[%s]", performUpdate ? "updated" : "set", fanModeString[currentFanMode], getOnOff() ? "ON" : "OFF"); + return true; + +} + +// this function will change the Fan Speed by callin the user application callback +// it is up to the application to decide to turn on, off or change the speed of the fan +bool MatterFan::setSpeedPercent(uint8_t newPercent, bool performUpdate) { + if (!started) { + log_w("Matter Fan device has not begun."); + return false; + } + // avoid processing the a "no-change" + if (currentPercent == newPercent) { + return true; + } + + esp_matter_attr_val_t speedVal = esp_matter_invalid(NULL); + if (!getAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, &speedVal)) { + log_e("Failed to get Fan Speed Percent Attribute."); + return false; + } + if (speedVal.val.u8 != newPercent) { + speedVal.val.u8 = newPercent; + bool ret; + if (performUpdate) { + ret = updateAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, &speedVal); + } else { + ret = setAttributeVal(FanControl::Id, FanControl::Attributes::PercentSetting::Id, &speedVal); + ret = setAttributeVal(FanControl::Id, FanControl::Attributes::PercentCurrent::Id, &speedVal); + } + if (!ret) { + log_e("Failed to %s Fan Speed Percent Attribute.", performUpdate ? "update" : "set"); + return false; + } + } + currentPercent = newPercent; + log_d("Fan Speed %s to %d ==> onOffState[%s]", performUpdate ? "updated" : "set", currentPercent, getOnOff() ? "ON" : "OFF"); + return true; +} + +bool MatterFan::setOnOff(bool newState, bool performUpdate) { + if (!started) { + log_w("Matter Fan device has not begun."); + return false; + } + // avoid processing the a "no-change" + if (getOnOff() == newState) { + return true; + } + + esp_matter_attr_val_t modeVal = esp_matter_invalid(NULL); + if (!getAttributeVal(FanControl::Id, FanControl::Attributes::FanMode::Id, &modeVal)) { + log_e("Failed to get Fan Mode Attribute."); + return false; + } + if (modeVal.val.u8 != (uint8_t) newState) { + FanMode_t newMode = newState ? FAN_MODE_ON : FAN_MODE_OFF; + if (!setMode(newMode, performUpdate)) { + return false; + } + } + log_d("Fan State %s to %s :: Mode[%s]|Speed[%d]", performUpdate ? "updated" : "set", getOnOff() ? "ON" : "OFF", fanModeString[currentFanMode], currentPercent); + return true; +} + +bool MatterFan::getOnOff() { + return currentFanMode == FAN_MODE_OFF ? false : true; +} + +bool MatterFan::toggle(bool performUpdate) { + if (getOnOff() == true) { + return setOnOff(false, performUpdate); + } else { + return setOnOff(true, performUpdate); + } +} + + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ \ No newline at end of file diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h new file mode 100644 index 00000000000..1b62c0e5849 --- /dev/null +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -0,0 +1,160 @@ +// 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 +#include + +using namespace chip::app::Clusters::FanControl; + +// Matter Generic Switch Endpoint that works as a single click smart button +class MatterFan : public MatterEndPoint { +public: + // Fan feature constants + static const uint8_t MAX_SPEED = 100; // maximum High speed + static const uint8_t MIN_SPEED = 1; // minimum Low speed + static const uint8_t OFF_SPEED = 0; // speed set by Matter when FAN_MODE_OFF + + // Default Fan Modes: ON, SMART, LOW and OFF + // Other mode will depend on what is the configured Fan Mode Sequence + enum FanMode_t { + FAN_MODE_OFF = (uint8_t) FanModeEnum::kOff, + FAN_MODE_LOW = (uint8_t) FanModeEnum::kLow, + FAN_MODE_MEDIUM = (uint8_t) FanModeEnum::kMedium, + FAN_MODE_HIGH = (uint8_t) FanModeEnum::kHigh, + FAN_MODE_ON = (uint8_t) FanModeEnum::kOn, + FAN_MODE_AUTO = (uint8_t) FanModeEnum::kAuto, + FAN_MODE_SMART = (uint8_t) FanModeEnum::kSmart + }; + + // Menu will always have ON, OFF, HIGH and SMART. + // AUTO will show up only when a AUTO SEQ is CONFIGURED + // LOW and MEDIUM depend on the SEQ MODE configuration + enum FanModeSequence_t { + FAN_MODE_SEQ_OFF_LOW_MED_HIGH = (uint8_t) FanModeSequenceEnum::kOffLowMedHigh, + FAN_MODE_SEQ_OFF_LOW_HIGH = (uint8_t) FanModeSequenceEnum::kOffLowHigh, + FAN_MODE_SEQ_OFF_LOW_MED_HIGH_AUTO = (uint8_t) FanModeSequenceEnum::kOffLowMedHighAuto, + FAN_MODE_SEQ_OFF_LOW_HIGH_AUTO = (uint8_t) FanModeSequenceEnum::kOffLowHighAuto, + FAN_MODE_SEQ_OFF_HIGH_AUTO = (uint8_t) FanModeSequenceEnum::kOffHighAuto, + FAN_MODE_SEQ_OFF_HIGH = (uint8_t) FanModeSequenceEnum::kOffHigh + }; + + MatterFan(); + ~MatterFan(); + virtual bool begin(uint8_t percent = 0, FanMode_t fanMode = FAN_MODE_OFF, FanModeSequence_t fanModeSeq = FAN_MODE_SEQ_OFF_HIGH); + void end(); // this will just stop processing Matter events + + // returns a friendly string for the Fan Mode + static const char *getFanModeString(uint8_t mode) { + return fanModeString[mode]; + } + + // Fan Control of current on off state + bool setOnOff(bool newState, bool performUpdate = true); // sets Fan on/off state + bool getOnOff(); // returns current Fan state + bool toggle(bool performUpdate = true); // toggle Fun on/off state + + // Fan Control of current and last speed percent + bool setSpeedPercent(uint8_t newPercent, bool performUpdate = true); // returns true if successful + uint8_t getSpeedPercent() { // returns current Fan Speed Percent + return currentPercent; + } + + // Fan Control of current and last Fan Mode, which may change the current percent speed + // Turning Fan using setOnOff() or toggle() will change current speed, but not the last setting + bool setMode(FanMode_t newMode, bool performUpdate = true); // returns true if successful + FanMode_t getMode() { // returns current Fan Mode + return currentFanMode; + } + // used to update the state of the Fan using the current Matter Fan internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory() { + if (_onChangeCB != NULL) { + _onChangeCB(currentFanMode, currentPercent); + } + } + + // returns current Fan speed percent + operator uint8_t() { + return getSpeedPercent(); + } + // sets Fan speed percent + void operator=(uint8_t speedPercent) { + setSpeedPercent(speedPercent); + } + + // 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); + + // User Callback for whenever the Fan Mode (state) is changed by the Matter Controller + using EndPointModeCB = std::function; + void onChangeMode(EndPointModeCB onChangeCB) { + _onChangeModeCB = onChangeCB; + } + + // User Callback for whenever the Fan Speed Percentage value [0..100] is changed by the Matter Controller + using EndPointSpeedCB = std::function; + void onChangeSpeedPercent(EndPointSpeedCB onChangeCB) { + _onChangeSpeedCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + +protected: + bool started = false; + uint8_t validFanModes = 0; // bitmap for valid Fan Modes - index of fanModeSequence[] + + // tuning fan off will set the speed to 0, but it won't change the internal mode or speed percent + // therefore, turining it back on will resume the last mode and speed percent + uint8_t currentPercent = 0; // current speed percent + FanMode_t currentFanMode = FAN_MODE_OFF; // current Fan Mode + EndPointModeCB _onChangeModeCB = NULL; + EndPointSpeedCB _onChangeSpeedCB = NULL; + EndPointCB _onChangeCB = NULL; + + // bitmap for Fan Sequence Modes (OFF, LOW, MEDIUM, HIGH, AUTO) + static const uint8_t fanSeqModeOff = 0x01; + static const uint8_t fanSeqModeLow = 0x02; + static const uint8_t fanSeqModeMedium = 0x04; + static const uint8_t fanSeqModeHigh = 0x08; + static const uint8_t fanSeqModeOn = 0x10; + static const uint8_t fanSeqModeAuto = 0x20; + static const uint8_t fanSeqModeSmart = 0x40; + + // bitmap for common modes: ON, OFF, HIGH and SMART + static const uint8_t fanSeqCommonModes = fanSeqModeOff | fanSeqModeOn | fanSeqModeHigh | fanSeqModeSmart; + + static const uint8_t fanSeqModeOffLowMedHigh = fanSeqCommonModes | fanSeqModeLow | fanSeqModeMedium; + static const uint8_t fanSeqModeOffLowHigh = fanSeqCommonModes | fanSeqModeLow; + static const uint8_t fanSeqModeOffLowMedHighAuto = fanSeqCommonModes | fanSeqModeLow | fanSeqModeMedium | fanSeqModeAuto; + static const uint8_t fanSeqModeOffLowHighAuto = fanSeqCommonModes | fanSeqModeLow | fanSeqModeAuto; + static const uint8_t fanSeqModeOffHighAuto = fanSeqCommonModes | fanSeqModeAuto; + static const uint8_t fanSeqModeOffHigh = fanSeqCommonModes; + + // bitmap for valid Fan Modes based on order defined in Zap Generated Cluster Enums + static const uint8_t fanModeSequence[6]; + + // string helper for the FAN MODE + static const char *fanModeString[7]; +}; + +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ From f92791e73cce2699d7d35a01839ac2a43bd6c425 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 5 Dec 2024 22:46:28 -0300 Subject: [PATCH 02/21] feat(matter): adds fan endpoint to matter main structure --- CMakeLists.txt | 1 + libraries/Matter/keywords.txt | 35 ++++++++++++- libraries/Matter/src/Matter.h | 2 + libraries/Matter/src/MatterEndPoint.h | 72 +++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ab001c2d09..27329a8aedd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,7 @@ set(ARDUINO_LIBRARY_Matter_SRCS libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp + libraries/Matter/src/MatterEndpoints/MatterFan.cpp libraries/Matter/src/Matter.cpp) set(ARDUINO_LIBRARY_PPP_SRCS diff --git a/libraries/Matter/keywords.txt b/libraries/Matter/keywords.txt index 39a74e76583..dab7e6fbef5 100644 --- a/libraries/Matter/keywords.txt +++ b/libraries/Matter/keywords.txt @@ -13,6 +13,9 @@ MatterDimmableLight KEYWORD1 MatterColorTemperatureLight KEYWORD1 MatterColorLight KEYWORD1 MatterEndPoint KEYWORD1 +MatterFan KEYWORD1 +FanMode_t KEYWORD1 +FanModeSequence_t KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -30,6 +33,7 @@ decommission KEYWORD2 attributeChangeCB KEYWORD2 setOnOff KEYWORD2 getOnOff KEYWORD2 +toggle KEYWORD2 setBrightness KEYWORD2 getBrightness KEYWORD2 setColorTemperature KEYWORD2 @@ -38,14 +42,23 @@ setColorRGB KEYWORD2 getColorRGB KEYWORD2 setColorHSV KEYWORD2 getColorHSV KEYWORD2 -toggle KEYWORD2 updateAccessory KEYWORD2 onChange KEYWORD2 onChangeOnOff KEYWORD2 onChangeBrightness KEYWORD2 onChangeColorTemperature KEYWORD2 onChangeColorHSV KEYWORD2 - +getAttribute KEYWORD2 +getAttributeVal KEYWORD2 +setAttributeVal KEYWORD2 +updateAttributeVal KEYWORD2 +getFanModeString KEYWORD2 +setSpeedPercent KEYWORD2 +getSpeedPercent KEYWORD2 +setMode KEYWORD2 +getMode KEYWORD2 +onChangeMode KEYWORD2 +onChangeSpeedPercent KEYWORD2 ####################################### # Constants (LITERAL1) @@ -54,3 +67,21 @@ onChangeColorHSV KEYWORD2 MAX_BRIGHTNESS LITERAL1 MAX_COLOR_TEMPERATURE LITERAL1 MIN_COLOR_TEMPERATURE LITERAL1 +ATTR_SET LITERAL1 +ATTR_UPDATE LITERAL1 +MAX_SPEED LITERAL1 +MIN_SPEED LITERAL1 +OFF_SPEED LITERAL1 +FAN_MODE_OFF LITERAL1 +FAN_MODE_LOW LITERAL1 +FAN_MODE_MEDIUM LITERAL1 +FAN_MODE_HIGH LITERAL1 +FAN_MODE_ON LITERAL1 +FAN_MODE_AUTO LITERAL1 +FAN_MODE_SMART LITERAL1 +FAN_MODE_SEQ_OFF_LOW_MED_HIGH LITERAL1 +FAN_MODE_SEQ_OFF_LOW_HIGH LITERAL1 +FAN_MODE_SEQ_OFF_LOW_MED_HIGH_AUTO LITERAL1 +FAN_MODE_SEQ_OFF_LOW_HIGH_AUTO LITERAL1 +FAN_MODE_SEQ_OFF_HIGH_AUTO LITERAL1 +FAN_MODE_SEQ_OFF_HIGH LITERAL1 diff --git a/libraries/Matter/src/Matter.h b/libraries/Matter/src/Matter.h index 4d269474187..47410855c9b 100644 --- a/libraries/Matter/src/Matter.h +++ b/libraries/Matter/src/Matter.h @@ -23,6 +23,7 @@ #include #include #include +#include using namespace esp_matter; @@ -52,6 +53,7 @@ class ArduinoMatter { friend class MatterDimmableLight; friend class MatterColorTemperatureLight; friend class MatterColorLight; + friend class MatterFan; protected: static void _init(); diff --git a/libraries/Matter/src/MatterEndPoint.h b/libraries/Matter/src/MatterEndPoint.h index 02577957e8e..80cc25fe578 100644 --- a/libraries/Matter/src/MatterEndPoint.h +++ b/libraries/Matter/src/MatterEndPoint.h @@ -19,15 +19,87 @@ #include #include +using namespace esp_matter; + // Matter Endpoint Base Class. Controls the endpoint ID and allows the child class to overwrite attribute change call class MatterEndPoint { public: + + enum attrOperation_t { + ATTR_SET = false, + ATTR_UPDATE = true + }; + uint16_t getEndPointId() { return endpoint_id; } + void setEndPointId(uint16_t ep) { endpoint_id = ep; } + + // helper functions for attribute manipulation + attribute_t * getAttribute(uint32_t cluster_id, uint32_t attribute_id){ + if (endpoint_id == 0) { + log_e("Endpoint ID is not set"); + return NULL; + } + endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); + if (endpoint == NULL) { + log_e("Endpoint [%d] not found", endpoint_id); + return NULL; + } + cluster_t *cluster = cluster::get(endpoint, cluster_id); + if (cluster == NULL) { + log_e("Cluster [%d] not found", cluster_id); + return NULL; + } + attribute_t *attribute = attribute::get(cluster, attribute_id); + if (attribute == NULL) { + log_e("Attribute [%d] not found", attribute_id); + return NULL; + } + return attribute; + } + + // get the value of an attribute from its cluster id and attribute it + bool getAttributeVal(uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *attrVal){ + attribute_t *attribute = getAttribute(cluster_id, attribute_id); + if (attribute == NULL) { + return false; + } + if (attribute::get_val(attribute, attrVal) == ESP_OK) { + log_v("GET_VAL Suceess for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return true; + } + log_v("GET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return false; + } + + // set the value of an attribute from its cluster id and attribute it + bool setAttributeVal(uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *attrVal){ + attribute_t *attribute = getAttribute(cluster_id, attribute_id); + if (attribute == NULL) { + return false; + } + if (attribute::set_val(attribute, attrVal) == ESP_OK) { + log_v("SET_VAL Suceess for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return true; + } + log_v("SET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return false; + } + + // update the value of an attribute from its cluster id and attribute it + bool updateAttributeVal(uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *attrVal){ + if (attribute::update(endpoint_id, cluster_id, attribute_id, attrVal) == ESP_OK) { + log_v("Update Suceess for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return true; + } + log_v("Update FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + return false; + } + // this function is called by Matter internal event processor. It could be overwritten by the application, if necessary. virtual bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) = 0; From 0c0940c07124b09184d72b1c3ce39d6819726188 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 5 Dec 2024 22:47:21 -0300 Subject: [PATCH 03/21] feat(matter): few formatting and details in other files --- .../src/MatterEndpoints/MatterColorLight.h | 150 +++++++++--------- .../MatterColorTemperatureLight.h | 1 + 2 files changed, 76 insertions(+), 75 deletions(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h index 13ff0decbc2..ea762f3bdc9 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h @@ -1,75 +1,75 @@ -// 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 MatterColorLight : public MatterEndPoint { -public: - MatterColorLight(); - ~MatterColorLight(); - // default initial state is off, color is red 12% intensity HSV(0, 254, 31) - virtual bool begin(bool initialState = false, espHsvColor_t colorHSV = {0, 254, 31}); - // this will just stop processing Light Matter events - void end(); - - bool setOnOff(bool newState); // returns true if successful - bool getOnOff(); // returns current light state - bool toggle(); // returns true if successful - - bool setColorRGB(espRgbColor_t rgbColor); // returns true if successful - espRgbColor_t getColorRGB(); // returns current RGB Color - bool setColorHSV(espHsvColor_t hsvColor); // returns true if successful - espHsvColor_t getColorHSV(); // returns current HSV Color - - // used to update the state of the light using the current Matter Light internal state - // It is necessary to set a user callback function using onChange() to handle the physical light state - void updateAccessory(); - - operator bool(); // returns current on/off light state - void operator=(bool state); // turns light on or off - - // 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); - - // User Callback for whenever the Light On/Off state is changed by the Matter Controller - using EndPointOnOffCB = std::function; - void onChangeOnOff(EndPointOnOffCB onChangeCB) { - _onChangeOnOffCB = onChangeCB; - } - // User Callback for whenever the HSV Color value is changed by the Matter Controller - using EndPointRGBColorCB = std::function; - void onChangeColorHSV(EndPointRGBColorCB onChangeCB) { - _onChangeColorCB = onChangeCB; - } - - // User Callback for whenever any parameter is changed by the Matter Controller - using EndPointCB = std::function; - void onChange(EndPointCB onChangeCB) { - _onChangeCB = onChangeCB; - } - -protected: - bool started = false; - bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) - espHsvColor_t colorHSV = {0}; // default initial color HSV is black, but it can be changed by begin(bool, espHsvColor_t) - EndPointOnOffCB _onChangeOnOffCB = NULL; - EndPointRGBColorCB _onChangeColorCB = NULL; - EndPointCB _onChangeCB = NULL; -}; -#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ +// 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 MatterColorLight : public MatterEndPoint { +public: + MatterColorLight(); + ~MatterColorLight(); + // default initial state is off, color is red 12% intensity HSV(0, 254, 31) + virtual bool begin(bool initialState = false, espHsvColor_t colorHSV = { 0, 254, 31}); + // this will just stop processing Light Matter events + void end(); + + bool setOnOff(bool newState); // returns true if successful + bool getOnOff(); // returns current light state + bool toggle(); // returns true if successful + + bool setColorRGB(espRgbColor_t rgbColor); // returns true if successful + espRgbColor_t getColorRGB(); // returns current RGB Color + bool setColorHSV(espHsvColor_t hsvColor); // returns true if successful + espHsvColor_t getColorHSV(); // returns current HSV Color + + // used to update the state of the light using the current Matter Light internal state + // It is necessary to set a user callback function using onChange() to handle the physical light state + void updateAccessory(); + + operator bool(); // returns current on/off light state + void operator=(bool state); // turns light on or off + + // 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); + + // User Callback for whenever the Light On/Off state is changed by the Matter Controller + using EndPointOnOffCB = std::function; + void onChangeOnOff(EndPointOnOffCB onChangeCB) { + _onChangeOnOffCB = onChangeCB; + } + // User Callback for whenever the HSV Color value is changed by the Matter Controller + using EndPointRGBColorCB = std::function; + void onChangeColorHSV(EndPointRGBColorCB onChangeCB) { + _onChangeColorCB = onChangeCB; + } + + // User Callback for whenever any parameter is changed by the Matter Controller + using EndPointCB = std::function; + void onChange(EndPointCB onChangeCB) { + _onChangeCB = onChangeCB; + } + +protected: + bool started = false; + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + espHsvColor_t colorHSV = { 0 }; // default initial color HSV is black, but it can be changed by begin(bool, espHsvColor_t) + EndPointOnOffCB _onChangeOnOffCB = NULL; + EndPointRGBColorCB _onChangeColorCB = NULL; + EndPointCB _onChangeCB = NULL; +}; +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ \ No newline at end of file diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h index 723849e354a..522f9ed7b09 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h @@ -57,6 +57,7 @@ class MatterColorTemperatureLight : public MatterEndPoint { void onChangeOnOff(EndPointOnOffCB onChangeCB) { _onChangeOnOffCB = onChangeCB; } + // User Callback for whenever the Light brightness value [0..255] is changed by the Matter Controller using EndPointBrightnessCB = std::function; void onChangeBrightness(EndPointBrightnessCB onChangeCB) { From e679fb6fa71a6d76c279e8b45c90c99877fc08d5 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 5 Dec 2024 22:51:13 -0300 Subject: [PATCH 04/21] fix(matter): fixes example names and files --- .../MatterColorLight.ino} | 0 .../examples/{Matter_ColorLight => MatterColorLight}/ci.json | 0 libraries/Matter/examples/{Matter_Fan => MatterFan}/MatterFan.ino | 0 libraries/Matter/examples/{Matter_Fan => MatterFan}/ci.json | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename libraries/Matter/examples/{Matter_ColorLight/Matter_ColorLight.ino => MatterColorLight/MatterColorLight.ino} (100%) rename libraries/Matter/examples/{Matter_ColorLight => MatterColorLight}/ci.json (100%) rename libraries/Matter/examples/{Matter_Fan => MatterFan}/MatterFan.ino (100%) rename libraries/Matter/examples/{Matter_Fan => MatterFan}/ci.json (100%) diff --git a/libraries/Matter/examples/Matter_ColorLight/Matter_ColorLight.ino b/libraries/Matter/examples/MatterColorLight/MatterColorLight.ino similarity index 100% rename from libraries/Matter/examples/Matter_ColorLight/Matter_ColorLight.ino rename to libraries/Matter/examples/MatterColorLight/MatterColorLight.ino diff --git a/libraries/Matter/examples/Matter_ColorLight/ci.json b/libraries/Matter/examples/MatterColorLight/ci.json similarity index 100% rename from libraries/Matter/examples/Matter_ColorLight/ci.json rename to libraries/Matter/examples/MatterColorLight/ci.json diff --git a/libraries/Matter/examples/Matter_Fan/MatterFan.ino b/libraries/Matter/examples/MatterFan/MatterFan.ino similarity index 100% rename from libraries/Matter/examples/Matter_Fan/MatterFan.ino rename to libraries/Matter/examples/MatterFan/MatterFan.ino diff --git a/libraries/Matter/examples/Matter_Fan/ci.json b/libraries/Matter/examples/MatterFan/ci.json similarity index 100% rename from libraries/Matter/examples/Matter_Fan/ci.json rename to libraries/Matter/examples/MatterFan/ci.json From 2fcdd35dc76ffdc999e5f1647f7cf4cd71927ade Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 5 Dec 2024 23:12:56 -0300 Subject: [PATCH 05/21] feat(matter): change example messages within fan modes --- libraries/Matter/examples/MatterFan/MatterFan.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Matter/examples/MatterFan/MatterFan.ino b/libraries/Matter/examples/MatterFan/MatterFan.ino index 8460193c464..e561a7e33ef 100644 --- a/libraries/Matter/examples/MatterFan/MatterFan.ino +++ b/libraries/Matter/examples/MatterFan/MatterFan.ino @@ -87,7 +87,7 @@ void setup() { Fan.onChangeMode([](MatterFan::FanMode_t fanMode) { // when the Fan is turned on using Mode Selection, while it is OFF, shall start it by setting the speed to 50% if (Fan.getSpeedPercent() == 0 && fanMode != MatterFan::FAN_MODE_OFF) { - Serial.println("Starting Smart Mode -- set speed to 50%"); + Serial.printf("Fan set to %s mode -- speed percentage will go to 50%\r\n", Fan.getFanModeString(fanMode)); // ATTR_SET do not update the attribute, just set it to avoid inifinite loop return Fan.setSpeedPercent(50, Fan.ATTR_SET); } From 6759dd7a2706ca32c105f14e3b06ad1c3d40003e Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 5 Dec 2024 23:39:13 -0300 Subject: [PATCH 06/21] fix(matter): removing commented code lines and fixing log levels --- libraries/Matter/src/MatterEndPoint.h | 6 +++--- libraries/Matter/src/MatterEndpoints/MatterFan.cpp | 7 ------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/libraries/Matter/src/MatterEndPoint.h b/libraries/Matter/src/MatterEndPoint.h index 80cc25fe578..5c352d7ef57 100644 --- a/libraries/Matter/src/MatterEndPoint.h +++ b/libraries/Matter/src/MatterEndPoint.h @@ -72,7 +72,7 @@ class MatterEndPoint { log_v("GET_VAL Suceess for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); return true; } - log_v("GET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + log_e("GET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); return false; } @@ -86,7 +86,7 @@ class MatterEndPoint { log_v("SET_VAL Suceess for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); return true; } - log_v("SET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + log_e("SET_VAL FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); return false; } @@ -96,7 +96,7 @@ class MatterEndPoint { log_v("Update Suceess for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); return true; } - log_v("Update FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); + log_e("Update FAILED! for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32); return false; } diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.cpp b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp index a2ae858d200..4e94e2c9a4c 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp @@ -50,13 +50,6 @@ bool MatterFan::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uin log_i("===> Fan Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); if (endpoint_id == getEndPointId() && cluster_id == FanControl::Id) { - //endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id); - //cluster_t *cluster = cluster::get(endpoint, FanControl::Id); - - //attribute_t *attr_percent_setting = attribute::get(cluster, Attributes::PercentSetting::Id); - //attribute_t *attribute_percent_current = attribute::get(cluster, Attributes::PercentCurrent::Id); - //attribute_t *attr_fan_mode = attribute::get(cluster, Attributes::FanMode::Id); - switch (attribute_id) { case FanControl::Attributes::FanMode::Id: log_d("FanControl Fan Mode changed to %s (%x)", val->val.u8 < 7 ? fanModeString[val->val.u8] : "Unknown", val->val.u8); From f9b2dec2bd4c2ef9a4c8b74ce38114f9ba571396 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Thu, 5 Dec 2024 23:55:24 -0300 Subject: [PATCH 07/21] fix(matter): printf formating with '%' -> '%%' --- libraries/Matter/examples/MatterFan/MatterFan.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Matter/examples/MatterFan/MatterFan.ino b/libraries/Matter/examples/MatterFan/MatterFan.ino index e561a7e33ef..c2ff5c2f842 100644 --- a/libraries/Matter/examples/MatterFan/MatterFan.ino +++ b/libraries/Matter/examples/MatterFan/MatterFan.ino @@ -87,7 +87,7 @@ void setup() { Fan.onChangeMode([](MatterFan::FanMode_t fanMode) { // when the Fan is turned on using Mode Selection, while it is OFF, shall start it by setting the speed to 50% if (Fan.getSpeedPercent() == 0 && fanMode != MatterFan::FAN_MODE_OFF) { - Serial.printf("Fan set to %s mode -- speed percentage will go to 50%\r\n", Fan.getFanModeString(fanMode)); + Serial.printf("Fan set to %s mode -- speed percentage will go to 50%%\r\n", Fan.getFanModeString(fanMode)); // ATTR_SET do not update the attribute, just set it to avoid inifinite loop return Fan.setSpeedPercent(50, Fan.ATTR_SET); } From 9cec91352a312f2ca45e69b2ba259885a35425c5 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 00:31:23 -0300 Subject: [PATCH 08/21] fix(matter): code log level review - few chnages --- libraries/Matter/src/MatterEndpoints/MatterFan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.cpp b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp index 4e94e2c9a4c..231a8f4aec4 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.cpp +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.cpp @@ -47,7 +47,7 @@ bool MatterFan::attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uin return false; } - log_i("===> Fan Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); + log_d("Fan Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u", endpoint_id, cluster_id, attribute_id, val->val.u32); if (endpoint_id == getEndPointId() && cluster_id == FanControl::Id) { switch (attribute_id) { From 1618003724ead98c4168a3bde857622c5ac5d7c2 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:44:31 -0300 Subject: [PATCH 09/21] fix(matter): commentaries and old work --- libraries/Matter/examples/MatterFan/MatterFan.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Matter/examples/MatterFan/MatterFan.ino b/libraries/Matter/examples/MatterFan/MatterFan.ino index c2ff5c2f842..3b6d046a06d 100644 --- a/libraries/Matter/examples/MatterFan/MatterFan.ino +++ b/libraries/Matter/examples/MatterFan/MatterFan.ino @@ -149,7 +149,8 @@ void loop() { uint32_t time_diff = millis() - button_time_stamp; if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) { button_state = false; // released - // builtin button is released - send a click event to the Matter Controller + // builtin button is released - toggle Fan on/off + Fan.toggle(); Serial.printf("User button released. Setting the Fan %s.\r\n", Fan > 0 ? "ON" : "OFF"); From d19caac6f77f82d068a1edfbc19315090b9e35e7 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:45:08 -0300 Subject: [PATCH 10/21] fix(matter): reverting back modification that are of other ep --- libraries/Matter/src/MatterEndpoints/MatterColorLight.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h index ea762f3bdc9..b05ed09c7d8 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h @@ -66,8 +66,8 @@ class MatterColorLight : public MatterEndPoint { protected: bool started = false; - bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) - espHsvColor_t colorHSV = { 0 }; // default initial color HSV is black, but it can be changed by begin(bool, espHsvColor_t) + bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) + espHsvColor_t colorHSV = {0}; // default initial color HSV is black, but it can be changed by begin(bool, espHsvColor_t)``` EndPointOnOffCB _onChangeOnOffCB = NULL; EndPointRGBColorCB _onChangeColorCB = NULL; EndPointCB _onChangeCB = NULL; From 24c14dba791f91c11aa57a8667235c614f81b17a Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:45:27 -0300 Subject: [PATCH 11/21] fix(matter): commentaries and old work --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index 1b62c0e5849..b435d9ecf11 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -22,7 +22,8 @@ using namespace chip::app::Clusters::FanControl; -// Matter Generic Switch Endpoint that works as a single click smart button +// Matter Fan endpoint with on/off, Mode and Speed control + class MatterFan : public MatterEndPoint { public: // Fan feature constants From ae8f459edaa3dafba85d03818d84ad85e0bed50f Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:45:46 -0300 Subject: [PATCH 12/21] fix(matter): fix commentaries and old work --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index b435d9ecf11..2cb7e271fc3 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -31,7 +31,8 @@ class MatterFan : public MatterEndPoint { static const uint8_t MIN_SPEED = 1; // minimum Low speed static const uint8_t OFF_SPEED = 0; // speed set by Matter when FAN_MODE_OFF - // Default Fan Modes: ON, SMART, LOW and OFF + // Default Fan Modes: ON, SMART, HIGH and OFF + // Other mode will depend on what is the configured Fan Mode Sequence enum FanMode_t { FAN_MODE_OFF = (uint8_t) FanModeEnum::kOff, From 84c9bf8f2d369cb4368d52e915d151904852e2b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:45:59 -0300 Subject: [PATCH 13/21] fix(matter): commentaries and old work --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index 2cb7e271fc3..ddc386891a4 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -66,7 +66,8 @@ class MatterFan : public MatterEndPoint { return fanModeString[mode]; } - // Fan Control of current on off state + // Fan Control of current on/off state + bool setOnOff(bool newState, bool performUpdate = true); // sets Fan on/off state bool getOnOff(); // returns current Fan state bool toggle(bool performUpdate = true); // toggle Fun on/off state From 3f2acfb79a8890d37c6f91b2e9f56506b4359275 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:46:10 -0300 Subject: [PATCH 14/21] fix(matter): commentaries and old work --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index ddc386891a4..88e0d53d9fc 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -72,7 +72,8 @@ class MatterFan : public MatterEndPoint { bool getOnOff(); // returns current Fan state bool toggle(bool performUpdate = true); // toggle Fun on/off state - // Fan Control of current and last speed percent + // Fan Control of current speed percent + bool setSpeedPercent(uint8_t newPercent, bool performUpdate = true); // returns true if successful uint8_t getSpeedPercent() { // returns current Fan Speed Percent return currentPercent; From ab92c62c67161896b0f6ca0bc3ff8721be4e8466 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:46:23 -0300 Subject: [PATCH 15/21] fix(matter): commentaries and old work --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index 88e0d53d9fc..cd50dd45773 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -79,7 +79,8 @@ class MatterFan : public MatterEndPoint { return currentPercent; } - // Fan Control of current and last Fan Mode, which may change the current percent speed + // Fan Control of current Fan Mode + // Turning Fan using setOnOff() or toggle() will change current speed, but not the last setting bool setMode(FanMode_t newMode, bool performUpdate = true); // returns true if successful FanMode_t getMode() { // returns current Fan Mode From 66193fc1947b16a802391c6b3033e90ebf27fffc Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:46:34 -0300 Subject: [PATCH 16/21] fix(matter): commentaries and old work --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index cd50dd45773..a4ad568b0ae 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -81,7 +81,6 @@ class MatterFan : public MatterEndPoint { // Fan Control of current Fan Mode - // Turning Fan using setOnOff() or toggle() will change current speed, but not the last setting bool setMode(FanMode_t newMode, bool performUpdate = true); // returns true if successful FanMode_t getMode() { // returns current Fan Mode return currentFanMode; From e8d315fa1016f2a20ba7216a0f2d0212592d0835 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:46:43 -0300 Subject: [PATCH 17/21] fix(matter): commentaries and old work --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index a4ad568b0ae..bad6ddfe016 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -86,7 +86,8 @@ class MatterFan : public MatterEndPoint { return currentFanMode; } // used to update the state of the Fan using the current Matter Fan internal state - // It is necessary to set a user callback function using onChange() to handle the physical light state + // It is necessary to set a user callback function using onChange() to handle the physical Fan motor state + void updateAccessory() { if (_onChangeCB != NULL) { _onChangeCB(currentFanMode, currentPercent); From 601728a2f9ad59e879501b9e7429c2a8bf9832cb Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:46:54 -0300 Subject: [PATCH 18/21] Update libraries/Matter/src/MatterEndpoints/MatterFan.h --- libraries/Matter/src/MatterEndpoints/MatterFan.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterFan.h b/libraries/Matter/src/MatterEndpoints/MatterFan.h index bad6ddfe016..10aced69980 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterFan.h +++ b/libraries/Matter/src/MatterEndpoints/MatterFan.h @@ -128,8 +128,6 @@ class MatterFan : public MatterEndPoint { bool started = false; uint8_t validFanModes = 0; // bitmap for valid Fan Modes - index of fanModeSequence[] - // tuning fan off will set the speed to 0, but it won't change the internal mode or speed percent - // therefore, turining it back on will resume the last mode and speed percent uint8_t currentPercent = 0; // current speed percent FanMode_t currentFanMode = FAN_MODE_OFF; // current Fan Mode EndPointModeCB _onChangeModeCB = NULL; From 041607136840fd1b482d83e379c0ec9a12e190a3 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 10:48:22 -0300 Subject: [PATCH 19/21] Update libraries/Matter/src/MatterEndpoints/MatterColorLight.h fix(matter): reveting non related endpoint code change --- libraries/Matter/src/MatterEndpoints/MatterColorLight.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h index b05ed09c7d8..a91da2a9b18 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h @@ -72,4 +72,4 @@ class MatterColorLight : public MatterEndPoint { EndPointRGBColorCB _onChangeColorCB = NULL; EndPointCB _onChangeCB = NULL; }; -#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ \ No newline at end of file +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ From 931a6622b22685c2205e1ce6487dcbabe49d5f21 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 17:35:53 -0300 Subject: [PATCH 20/21] fix(matter): reverted mattercolorlight.h format changes --- libraries/Matter/src/MatterEndpoints/MatterColorLight.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h index a91da2a9b18..12ea4ea329d 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h @@ -24,7 +24,7 @@ class MatterColorLight : public MatterEndPoint { MatterColorLight(); ~MatterColorLight(); // default initial state is off, color is red 12% intensity HSV(0, 254, 31) - virtual bool begin(bool initialState = false, espHsvColor_t colorHSV = { 0, 254, 31}); + virtual bool begin(bool initialState = false, espHsvColor_t colorHSV = {0, 254, 31}); // this will just stop processing Light Matter events void end(); @@ -67,9 +67,9 @@ class MatterColorLight : public MatterEndPoint { protected: bool started = false; bool onOffState = false; // default initial state is off, but it can be changed by begin(bool) - espHsvColor_t colorHSV = {0}; // default initial color HSV is black, but it can be changed by begin(bool, espHsvColor_t)``` + espHsvColor_t colorHSV = {0}; // default initial color HSV is black, but it can be changed by begin(bool, espHsvColor_t) EndPointOnOffCB _onChangeOnOffCB = NULL; EndPointRGBColorCB _onChangeColorCB = NULL; EndPointCB _onChangeCB = NULL; }; -#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ \ No newline at end of file From 7b3fe09595a3896eca516498a3f890e637ad0290 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Fri, 6 Dec 2024 17:39:04 -0300 Subject: [PATCH 21/21] fix(matter): reverted mattercolorlight.h format changes --- libraries/Matter/src/MatterEndpoints/MatterColorLight.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h index 12ea4ea329d..568fecc0d29 100644 --- a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h +++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h @@ -72,4 +72,4 @@ class MatterColorLight : public MatterEndPoint { EndPointRGBColorCB _onChangeColorCB = NULL; EndPointCB _onChangeCB = NULL; }; -#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */ \ No newline at end of file +#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */