feat(Matter): Creates New Matter Fan Controller Endpoint (#10691)
* feat(matter): creates new matter fan controller endpoint
This commit is contained in:
parent
76d1f9e643
commit
7a82b8be83
8 changed files with 709 additions and 1 deletions
|
|
@ -174,6 +174,7 @@ set(ARDUINO_LIBRARY_Matter_SRCS
|
||||||
libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp
|
libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.cpp
|
||||||
libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
|
libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
|
||||||
libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp
|
libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.cpp
|
||||||
|
libraries/Matter/src/MatterEndpoints/MatterFan.cpp
|
||||||
libraries/Matter/src/Matter.cpp)
|
libraries/Matter/src/Matter.cpp)
|
||||||
|
|
||||||
set(ARDUINO_LIBRARY_PPP_SRCS
|
set(ARDUINO_LIBRARY_PPP_SRCS
|
||||||
|
|
|
||||||
202
libraries/Matter/examples/MatterFan/MatterFan.ino
Normal file
202
libraries/Matter/examples/MatterFan/MatterFan.ino
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
// 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 <Matter.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// set your board PWM Pin here - used for controlling the Fan speed (DC motor example)
|
||||||
|
// for this example, it will use the builtin board RGB LED to simulate the Fan DC motor using its brightness
|
||||||
|
#ifdef RGB_BUILTIN
|
||||||
|
const uint8_t dcMotorPin = RGB_BUILTIN;
|
||||||
|
#else
|
||||||
|
const uint8_t dcMotorPin = 2; // Set your pin here if your board has not defined LED_BUILTIN
|
||||||
|
#warning "Do not forget to set the RGB LED pin"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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 fanDCMotorDrive(bool fanState, uint8_t speedPercent) {
|
||||||
|
// drive the Fan DC motor
|
||||||
|
if (fanState == false) {
|
||||||
|
// turn off the Fan
|
||||||
|
digitalWrite(dcMotorPin, LOW);
|
||||||
|
} else {
|
||||||
|
// set the Fan speed
|
||||||
|
uint8_t fanDCMotorPWM = map(speedPercent, 0, 100, 0, 255);
|
||||||
|
#ifdef RGB_BUILTIN
|
||||||
|
rgbLedWrite(dcMotorPin, fanDCMotorPWM, fanDCMotorPWM, fanDCMotorPWM);
|
||||||
|
#else
|
||||||
|
analogWrite(dcMotorPin, fanDCMotorPWM);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
// Initialize the PWM output pin for a Fan DC motor
|
||||||
|
pinMode(dcMotorPin, OUTPUT);
|
||||||
|
|
||||||
|
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 whenever 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 == MatterFan::OFF_SPEED && Fan.getMode() != MatterFan::FAN_MODE_OFF) {
|
||||||
|
// ATTR_SET do not update the attribute, just SET it to avoid infinite 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 > MatterFan::OFF_SPEED && Fan.getMode() == MatterFan::FAN_MODE_OFF) {
|
||||||
|
// ATTR_SET do not update the attribute, just SET it to avoid infinite 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() == MatterFan::OFF_SPEED && fanMode != MatterFan::FAN_MODE_OFF) {
|
||||||
|
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 infinite 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);
|
||||||
|
// drive the Fan DC motor
|
||||||
|
fanDCMotorDrive(fanMode != MatterFan::FAN_MODE_OFF, 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
|
||||||
|
// button is released - toggle Fan On/Off
|
||||||
|
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) / 103 => mapped into 10 steps (0..9)
|
||||||
|
int anaVal = analogRead(analogPin) / 103;
|
||||||
|
if (lastRead != anaVal) {
|
||||||
|
// speed percent moves in steps of 10. Range is 10..100
|
||||||
|
if (Fan.setSpeedPercent((anaVal + 1) * 10)) {
|
||||||
|
lastRead = anaVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
libraries/Matter/examples/MatterFan/ci.json
Normal file
7
libraries/Matter/examples/MatterFan/ci.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"fqbn_append": "PartitionScheme=huge_app",
|
||||||
|
"requires": [
|
||||||
|
"CONFIG_SOC_WIFI_SUPPORTED=y",
|
||||||
|
"CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,9 @@ MatterColorTemperatureLight KEYWORD1
|
||||||
MatterColorLight KEYWORD1
|
MatterColorLight KEYWORD1
|
||||||
MatterEnhancedColorLight KEYWORD1
|
MatterEnhancedColorLight KEYWORD1
|
||||||
MatterEndPoint KEYWORD1
|
MatterEndPoint KEYWORD1
|
||||||
|
MatterFan KEYWORD1
|
||||||
|
FanMode_t KEYWORD1
|
||||||
|
FanModeSequence_t KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Methods and Functions (KEYWORD2)
|
# Methods and Functions (KEYWORD2)
|
||||||
|
|
@ -32,6 +35,7 @@ decommission KEYWORD2
|
||||||
attributeChangeCB KEYWORD2
|
attributeChangeCB KEYWORD2
|
||||||
setOnOff KEYWORD2
|
setOnOff KEYWORD2
|
||||||
getOnOff KEYWORD2
|
getOnOff KEYWORD2
|
||||||
|
toggle KEYWORD2
|
||||||
setBrightness KEYWORD2
|
setBrightness KEYWORD2
|
||||||
getBrightness KEYWORD2
|
getBrightness KEYWORD2
|
||||||
setColorTemperature KEYWORD2
|
setColorTemperature KEYWORD2
|
||||||
|
|
@ -40,7 +44,6 @@ setColorRGB KEYWORD2
|
||||||
getColorRGB KEYWORD2
|
getColorRGB KEYWORD2
|
||||||
setColorHSV KEYWORD2
|
setColorHSV KEYWORD2
|
||||||
getColorHSV KEYWORD2
|
getColorHSV KEYWORD2
|
||||||
toggle KEYWORD2
|
|
||||||
updateAccessory KEYWORD2
|
updateAccessory KEYWORD2
|
||||||
onChange KEYWORD2
|
onChange KEYWORD2
|
||||||
onChangeOnOff KEYWORD2
|
onChangeOnOff KEYWORD2
|
||||||
|
|
@ -48,6 +51,17 @@ onChangeBrightness KEYWORD2
|
||||||
onChangeColorTemperature KEYWORD2
|
onChangeColorTemperature KEYWORD2
|
||||||
onChangeColorHSV KEYWORD2
|
onChangeColorHSV KEYWORD2
|
||||||
click KEYWORD2
|
click 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)
|
# Constants (LITERAL1)
|
||||||
|
|
@ -56,3 +70,21 @@ click KEYWORD2
|
||||||
MAX_BRIGHTNESS LITERAL1
|
MAX_BRIGHTNESS LITERAL1
|
||||||
MAX_COLOR_TEMPERATURE LITERAL1
|
MAX_COLOR_TEMPERATURE LITERAL1
|
||||||
MIN_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
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <MatterEndpoints/MatterColorTemperatureLight.h>
|
#include <MatterEndpoints/MatterColorTemperatureLight.h>
|
||||||
#include <MatterEndpoints/MatterColorLight.h>
|
#include <MatterEndpoints/MatterColorLight.h>
|
||||||
#include <MatterEndpoints/MatterEnhancedColorLight.h>
|
#include <MatterEndpoints/MatterEnhancedColorLight.h>
|
||||||
|
#include <MatterEndpoints/MatterFan.h>
|
||||||
|
|
||||||
using namespace esp_matter;
|
using namespace esp_matter;
|
||||||
|
|
||||||
|
|
@ -56,6 +57,7 @@ public:
|
||||||
friend class MatterColorTemperatureLight;
|
friend class MatterColorTemperatureLight;
|
||||||
friend class MatterColorLight;
|
friend class MatterColorLight;
|
||||||
friend class MatterEnhancedColorLight;
|
friend class MatterEnhancedColorLight;
|
||||||
|
friend class MatterFan;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _init();
|
static void _init();
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,86 @@
|
||||||
#include <Matter.h>
|
#include <Matter.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
using namespace esp_matter;
|
||||||
|
|
||||||
// Matter Endpoint Base Class. Controls the endpoint ID and allows the child class to overwrite attribute change call
|
// Matter Endpoint Base Class. Controls the endpoint ID and allows the child class to overwrite attribute change call
|
||||||
class MatterEndPoint {
|
class MatterEndPoint {
|
||||||
public:
|
public:
|
||||||
|
enum attrOperation_t {
|
||||||
|
ATTR_SET = false,
|
||||||
|
ATTR_UPDATE = true
|
||||||
|
};
|
||||||
|
|
||||||
uint16_t getEndPointId() {
|
uint16_t getEndPointId() {
|
||||||
return endpoint_id;
|
return endpoint_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEndPointId(uint16_t ep) {
|
void setEndPointId(uint16_t ep) {
|
||||||
endpoint_id = 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 Success for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
log_e("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 Success for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
log_e("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 Success for cluster %d, attribute %d with value %d", cluster_id, attribute_id, attrVal->val.u32);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
log_e("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.
|
// 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;
|
virtual bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) = 0;
|
||||||
|
|
||||||
|
|
|
||||||
230
libraries/Matter/src/MatterEndpoints/MatterFan.cpp
Normal file
230
libraries/Matter/src/MatterEndpoints/MatterFan.cpp
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
// 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 <sdkconfig.h>
|
||||||
|
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
|
||||||
|
|
||||||
|
#include <Matter.h>
|
||||||
|
#include <MatterEndpoints/MatterFan.h>
|
||||||
|
|
||||||
|
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_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) {
|
||||||
|
case FanControl::Attributes::FanMode::Id:
|
||||||
|
log_v("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_v("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 Fan 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_v("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 calling 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_v("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_v(
|
||||||
|
"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 */
|
||||||
163
libraries/Matter/src/MatterEndpoints/MatterFan.h
Normal file
163
libraries/Matter/src/MatterEndpoints/MatterFan.h
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
// 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 <sdkconfig.h>
|
||||||
|
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
|
||||||
|
|
||||||
|
#include <Matter.h>
|
||||||
|
#include <MatterEndPoint.h>
|
||||||
|
#include <app-common/zap-generated/cluster-objects.h>
|
||||||
|
|
||||||
|
using namespace chip::app::Clusters::FanControl;
|
||||||
|
|
||||||
|
// Matter Fan endpoint with On/Off, Mode and Speed control
|
||||||
|
|
||||||
|
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, 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,
|
||||||
|
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 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 Fan Mode
|
||||||
|
|
||||||
|
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 Fan motor 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<bool(FanMode_t)>;
|
||||||
|
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<bool(uint8_t)>;
|
||||||
|
void onChangeSpeedPercent(EndPointSpeedCB onChangeCB) {
|
||||||
|
_onChangeSpeedCB = onChangeCB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// User Callback for whenever any parameter is changed by the Matter Controller
|
||||||
|
using EndPointCB = std::function<bool(FanMode_t, uint8_t)>;
|
||||||
|
void onChange(EndPointCB onChangeCB) {
|
||||||
|
_onChangeCB = onChangeCB;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool started = false;
|
||||||
|
uint8_t validFanModes = 0; // bitmap for valid Fan Modes - index of fanModeSequence[]
|
||||||
|
|
||||||
|
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 */
|
||||||
Loading…
Reference in a new issue