Hello, everyone. I am currently trying to develop using esp32-arduino-matter. I am using an ESP32-C3 with WS2812 LEDs, and I have already implemented the extended_color_light. However, after adding it to Apple Home, the light turns into a Color Temperature Light. I am also encountering a slow LED response during Pre Update. I would appreciate it if anyone could help me identify what the issue might be. Thank you!
#include <Adafruit_NeoPixel.h>
#include "Matter.h"
#include <esp_matter.h>
#include <app/server/OnboardingCodesUtil.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include "func.h"
using namespace chip;
using namespace chip::app::Clusters;
using namespace esp_matter;
using namespace esp_matter::endpoint;
#define REMAP_TO_RANGE(value, from, to) ((value * to) / from) // Mapping value to a different range
#define REMAP_TO_RANGE_INVERSE(value, factor) (factor / (value ? value : 1)) // Inverse mapping of value
static int hue = 0; // Hue (0-360 degrees)
static int saturation = 0; // Saturation (0-255)
static int brightness = 0; // Brightness (assuming default value)
const int LED_PIN = 1; // Pin where the LED is connected
// Cluster and attribute IDs used by Matter light device
const uint32_t CLUSTER_ID = OnOff::Id, CID_LevelCtl = LevelControl::Id, CID_ColorCtl = ColorControl::Id;
const uint32_t ATTRIBUTE_ID = OnOff::Attributes::OnOff::Id, AID_LevelCtl = LevelControl::Attributes::CurrentLevel::Id,
AID_ColorCtlHue = ColorControl::Attributes::CurrentHue::Id, AID_ColorCtlSat = ColorControl::Attributes::CurrentSaturation::Id, AID_ColorCtlCol = ColorControl::Attributes::ColorTemperatureMireds::Id;
// Endpoint and attribute ref that will be assigned to Matter device
uint16_t light_endpoint_id = 0; // This is the endpoint ID for the light device
#define NUMPIXELS 1 // Number of pixels (LEDs) used
Adafruit_NeoPixel pixels(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800); // Initialize the LED strip
// Callback function for device events
static void on_device_event(const ChipDeviceEvent *event, intptr_t arg) {}
// Callback for device identification, for example, during the commissioning process
static esp_err_t on_identification(identification::callback_type_t type, uint16_t endpoint_id,
uint8_t effect_id, uint8_t effect_variant, void *priv_data) {
return ESP_OK; // Return success when the device is identified
}
// Listener for attribute update requests. This function is triggered when an attribute is updated in Matter.
static esp_err_t on_attribute_update(attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data) {
// Handle On/Off attribute update (for turning the light on/off)
if (type == attribute::PRE_UPDATE && endpoint_id == light_endpoint_id && cluster_id == CLUSTER_ID && attribute_id == ATTRIBUTE_ID) {
bool new_state = val->val.b; // Get the new On/Off state
if (new_state) {
// Turn on the light and set it to white
pixels.setBrightness(brightness);
pixels.show();
} else {
// Turn off the light
pixels.setBrightness(0);
pixels.show();
}
}
// Handle LevelControl attribute update (for adjusting brightness)
if (type == attribute::PRE_UPDATE && endpoint_id == light_endpoint_id && cluster_id == CID_LevelCtl && attribute_id == AID_LevelCtl) {
brightness = REMAP_TO_RANGE(val->val.u8, 254, 255); // Map the brightness value
pixels.setBrightness(brightness); // Set the new brightness
}
// Handle ColorControl attribute update (for changing color)
if (type == attribute::PRE_UPDATE && endpoint_id == light_endpoint_id && cluster_id == CID_ColorCtl) {
if (attribute_id == AID_ColorCtlHue) {
hue = REMAP_TO_RANGE(val->val.u8, 254, 360); // Map the hue value to 360 degrees
ESP_LOGI("ColorControl", "Hue updated: %d", hue);
} else if (attribute_id == AID_ColorCtlSat) {
saturation = REMAP_TO_RANGE(val->val.u8, 254, 255); // Map the saturation value
ESP_LOGI("ColorControl", "Saturation updated: %d", saturation);
}
// Update light display when Hue or Saturation is updated
if (attribute_id == AID_ColorCtlHue || attribute_id == AID_ColorCtlSat) {
uint8_t r, g, b;
hsv_to_rgb(hue, saturation, brightness, r, g, b); // Convert HSV to RGB
pixels.setPixelColor(0, pixels.Color(r, g, b)); // Set the LED color
pixels.show();
ESP_LOGI("ColorControl", "Updated RGB from HSV(%d, %d, %d) -> RGB(%d, %d, %d)", hue, saturation, brightness, r, g, b);
} else if (attribute_id == AID_ColorCtlCol) {
// Handle color temperature change
uint32_t kelvin = mireds_to_kelvin(val->val.u16); // Convert Mireds to Kelvin
uint8_t r, g, b;
kelvin_to_rgb(kelvin, r, g, b); // Convert Kelvin to RGB
pixels.setPixelColor(0, pixels.Color(r, g, b)); // Set the LED color
pixels.show();
ESP_LOGI("ColorControl", "Color Temperature: %d Mireds (%d K) -> RGB(%d, %d, %d)",
val->val.u16, kelvin, r, g, b);
}
}
return ESP_OK; // Return success after processing attribute update
}
void setup() {
Serial.begin(115200); // Initialize the serial communication
pixels.begin(); // Initialize the LED strip
esp_log_level_set("*", ESP_LOG_DEBUG); // Enable debug logging
// Setup Matter node
node::config_t node_config;
node_t *node = node::create(&node_config, on_attribute_update, on_identification); // Create Matter node
// Set up initial light configuration (off by default)
extended_color_light::config_t light_config;
light_config.on_off.on_off = false; // Light is initially off
light_config.on_off.lighting.start_up_on_off = nullptr;
light_config.level_control.current_level = 64; // Set default brightness level
light_config.level_control.on_level = 64;
light_config.level_control.lighting.start_up_current_level = 64;
light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::EMBER_ZCL_COLOR_MODE_COLOR_TEMPERATURE;
light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::EMBER_ZCL_COLOR_MODE_COLOR_TEMPERATURE;
endpoint_t *endpoint = extended_color_light::create(node, &light_config, ENDPOINT_FLAG_NONE, NULL); // Create light endpoint
// Save the generated endpoint ID
light_endpoint_id = endpoint::get_id(endpoint);
// Set custom Device Attestation Credentials (DAC) provider
esp_matter::set_custom_dac_provider(chip::Credentials::Examples::GetExampleDACProvider());
// Start the Matter device
esp_matter::start(on_device_event);
// Print the onboarding codes needed for Matter device setup
PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
}
void loop() {
// The loop is intentionally left empty, as the device is event-driven
}
func.h
// Function to convert HSV to RGB
void hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v, uint8_t &r, uint8_t &g, uint8_t &b) {
float hh = h / 60.0;
int i = floor(hh);
float ff = hh - i;
float p = v * (1.0 - s / 255.0);
float q = v * (1.0 - (s / 255.0) * ff);
float t = v * (1.0 - (s / 255.0) * (1.0 - ff));
// Switch case to calculate RGB values based on HSV
switch (i) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5:
default: r = v; g = p; b = q; break;
}
}
// Function to convert Mireds to Kelvin
uint32_t mireds_to_kelvin(uint16_t mireds) {
return 1000000 / mireds; // Return the Kelvin temperature from Mireds
}
// Function to convert Kelvin to RGB
void kelvin_to_rgb(uint32_t kelvin, uint8_t &r, uint8_t &g, uint8_t &b) {
float temperature = kelvin / 100.0; // Convert Kelvin to temperature in Celsius
// Calculate the Red (R) value
if (temperature <= 66) {
r = 255;
} else {
r = temperature - 60;
r = 329.698727446 * pow(r, -0.1332047592); // Apply formula for red color
r = (r < 0) ? 0 : (r > 255) ? 255 : r; // Clamp value between 0 and 255
}
// Calculate the Green (G) value
if (temperature <= 66) {
g = temperature;
g = 99.4708025861 * log(g) - 161.1195681661; // Apply formula for green color
g = (g < 0) ? 0 : (g > 255) ? 255 : g; // Clamp value between 0 and 255
} else {
g = temperature - 60;
g = 288.1221695283 * pow(g, -0.0755148492); // Apply formula for green color
g = (g < 0) ? 0 : (g > 255) ? 255 : g; // Clamp value between 0 and 255
}
// Calculate the Blue (B) value
if (temperature >= 66) {
b = 255;
} else {
if (temperature <= 19) {
b = 0;
} else {
b = temperature - 10;
b = 138.5177312231 * log(b) - 305.0447927307; // Apply formula for blue color
b = (b < 0) ? 0 : (b > 255) ? 255 : b; // Clamp value between 0 and 255
}
}
}
