diff --git a/CMakeLists.txt b/CMakeLists.txt
index 67c4bd2e0ab..5ad9d8272ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,6 +25,7 @@ endif()
 set(CORE_SRCS
   cores/esp32/base64.cpp
   cores/esp32/cbuf.cpp
+  cores/esp32/ColorFormat.c
   cores/esp32/esp32-hal-adc.c
   cores/esp32/esp32-hal-bt.c
   cores/esp32/esp32-hal-cpu.c
diff --git a/cores/esp32/ColorFormat.c b/cores/esp32/ColorFormat.c
new file mode 100644
index 00000000000..a01123545b3
--- /dev/null
+++ b/cores/esp32/ColorFormat.c
@@ -0,0 +1,279 @@
+/*
+ *
+ *    Copyright (c) 2021 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    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 "ColorFormat.h"
+
+#include <math.h>
+
+// define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards
+#define clamp(a, min, max) ((a) < (min) ? (min) : ((a) > (max) ? (max) : (a)))
+
+const espHsvColor_t HSV_BLACK = {0, 0, 0};
+const espHsvColor_t HSV_WHITE = {0, 0, 254};
+const espHsvColor_t HSV_RED = {0, 254, 254};
+const espHsvColor_t HSV_YELLOW = {42, 254, 254};
+const espHsvColor_t HSV_GREEN = {84, 254, 254};
+const espHsvColor_t HSV_CYAN = {127, 254, 254};
+const espHsvColor_t HSV_BLUE = {169, 254, 254};
+const espHsvColor_t HSV_MAGENTA = {211, 254, 254};
+
+const espRgbColor_t RGB_BLACK = {0, 0, 0};
+const espRgbColor_t RGB_WHITE = {255, 255, 255};
+const espRgbColor_t RGB_RED = {255, 0, 0};
+const espRgbColor_t RGB_YELLOW = {255, 255, 0};
+const espRgbColor_t RGB_GREEN = {0, 255, 0};
+const espRgbColor_t RGB_CYAN = {0, 255, 255};
+const espRgbColor_t RGB_BLUE = {0, 0, 255};
+const espRgbColor_t RGB_MAGENTA = {255, 0, 255};
+
+// main color temperature values
+const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE = {142};
+const espCtColor_t DAYLIGHT_WHITE_COLOR_TEMPERATURE = {181};
+const espCtColor_t WHITE_COLOR_TEMPERATURE = {250};
+const espCtColor_t SOFT_WHITE_COLOR_TEMPERATURE = {370};
+const espCtColor_t WARM_WHITE_COLOR_TEMPERATURE = {454};
+
+espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v) {
+  espHsvColor_t hsv = {h, s, v};
+  return espHsvColorToRgbColor(hsv);
+}
+
+espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv) {
+  espRgbColor_t rgb;
+
+  uint8_t region, p, q, t;
+  uint32_t h, s, v, remainder;
+
+  if (hsv.s == 0) {
+    rgb.r = rgb.g = rgb.b = hsv.v;
+  } else {
+    h = hsv.h;
+    s = hsv.s;
+    v = hsv.v;
+
+    region = h / 43;
+    remainder = (h - (region * 43)) * 6;
+    p = (v * (255 - s)) >> 8;
+    q = (v * (255 - ((s * remainder) >> 8))) >> 8;
+    t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
+    switch (region) {
+      case 0:  rgb.r = v, rgb.g = t, rgb.b = p; break;
+      case 1:  rgb.r = q, rgb.g = v, rgb.b = p; break;
+      case 2:  rgb.r = p, rgb.g = v, rgb.b = t; break;
+      case 3:  rgb.r = p, rgb.g = q, rgb.b = v; break;
+      case 4:  rgb.r = t, rgb.g = p, rgb.b = v; break;
+      case 5:
+      default: rgb.r = v, rgb.g = p, rgb.b = q; break;
+    }
+  }
+  return rgb;
+}
+
+espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b) {
+  espRgbColor_t rgb = {r, g, b};
+  return espRgbColorToHsvColor(rgb);
+}
+
+espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb) {
+  espHsvColor_t hsv;
+  uint8_t rgbMin, rgbMax;
+
+  rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
+  rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
+
+  hsv.v = rgbMax;
+  if (hsv.v == 0) {
+    hsv.h = 0;
+    hsv.s = 0;
+    return hsv;
+  }
+
+  hsv.s = 255 * (rgbMax - rgbMin) / hsv.v;
+  if (hsv.s == 0) {
+    hsv.h = 0;
+    return hsv;
+  }
+  if (rgbMax == rgb.r) {
+    hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
+  } else if (rgbMax == rgb.g) {
+    hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
+  } else {
+    hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);
+  }
+  return hsv;
+}
+
+espRgbColor_t espXYColorToRgbColor(uint8_t Level, espXyColor_t xy) {
+  return espXYToRgbColor(Level, xy.x, xy.y);
+}
+
+espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y) {
+  // convert xyY color space to RGB
+
+  // https://www.easyrgb.com/en/math.php
+  // https://en.wikipedia.org/wiki/SRGB
+  // refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
+
+  // The current_X/current_Y attribute contains the current value of the normalized chromaticity value of x/y.
+  // The value of x/y shall be related to the current_X/current_Y attribute by the relationship
+  // x = current_X/65536
+  // y = current_Y/65536
+  // z = 1-x-y
+
+  espRgbColor_t rgb;
+
+  float x, y, z;
+  float X, Y, Z;
+  float r, g, b;
+
+  x = ((float)current_X) / 65535.0f;
+  y = ((float)current_Y) / 65535.0f;
+
+  z = 1.0f - x - y;
+
+  // Calculate XYZ values
+
+  // Y - given brightness in 0 - 1 range
+  Y = ((float)Level) / 254.0f;
+  X = (Y / y) * x;
+  Z = (Y / y) * z;
+
+  // X, Y and Z input refer to a D65/2° standard illuminant.
+  // sR, sG and sB (standard RGB) output range = 0 ÷ 255
+  // convert XYZ to RGB - CIE XYZ to sRGB
+  X = X / 100.0f;
+  Y = Y / 100.0f;
+  Z = Z / 100.0f;
+
+  r = (X * 3.2406f) - (Y * 1.5372f) - (Z * 0.4986f);
+  g = -(X * 0.9689f) + (Y * 1.8758f) + (Z * 0.0415f);
+  b = (X * 0.0557f) - (Y * 0.2040f) + (Z * 1.0570f);
+
+  // apply gamma 2.2 correction
+  r = (r <= 0.0031308f ? 12.92f * r : (1.055f) * pow(r, (1.0f / 2.4f)) - 0.055f);
+  g = (g <= 0.0031308f ? 12.92f * g : (1.055f) * pow(g, (1.0f / 2.4f)) - 0.055f);
+  b = (b <= 0.0031308f ? 12.92f * b : (1.055f) * pow(b, (1.0f / 2.4f)) - 0.055f);
+
+  // Round off
+  r = clamp(r, 0, 1);
+  g = clamp(g, 0, 1);
+  b = clamp(b, 0, 1);
+
+  // these rgb values are in  the range of 0 to 1, convert to limit of HW specific LED
+  rgb.r = (uint8_t)(r * 255);
+  rgb.g = (uint8_t)(g * 255);
+  rgb.b = (uint8_t)(b * 255);
+
+  return rgb;
+}
+
+espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b) {
+  espRgbColor_t rgb = {r, g, b};
+  return espRgbColorToXYColor(rgb);
+}
+
+espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb) {
+  // convert RGB to xy color space
+
+  // https://www.easyrgb.com/en/math.php
+  // https://en.wikipedia.org/wiki/SRGB
+  // refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
+
+  espXyColor_t xy;
+
+  float r, g, b;
+  float X, Y, Z;
+  float x, y;
+
+  r = ((float)rgb.r) / 255.0f;
+  g = ((float)rgb.g) / 255.0f;
+  b = ((float)rgb.b) / 255.0f;
+
+  // convert RGB to XYZ - sRGB to CIE XYZ
+  r = (r <= 0.04045f ? r / 12.92f : pow((r + 0.055f) / 1.055f, 2.4f));
+  g = (g <= 0.04045f ? g / 12.92f : pow((g + 0.055f) / 1.055f, 2.4f));
+  b = (b <= 0.04045f ? b / 12.92f : pow((b + 0.055f) / 1.055f, 2.4f));
+
+  // https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
+  X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
+  Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
+  Z = r * 0.0000000f + g * 0.053077f + b * 1.035763f;
+
+  // sR, sG and sB (standard RGB) input range = 0 ÷ 255
+  // X, Y and Z output refer to a D65/2° standard illuminant.
+  X = r * 0.4124564f + g * 0.3575761f + b * 0.1804375f;
+  Y = r * 0.2126729f + g * 0.7151522f + b * 0.0721750f;
+  Z = r * 0.0193339f + g * 0.1191920f + b * 0.9503041f;
+
+  // Calculate xy values
+  x = X / (X + Y + Z);
+  y = Y / (X + Y + Z);
+
+  // convert to 0-65535 range
+  xy.x = (uint16_t)(x * 65535);
+  xy.y = (uint16_t)(y * 65535);
+  return xy;
+}
+
+espRgbColor_t espCTToRgbColor(uint16_t ct) {
+  espCtColor_t ctColor = {ct};
+  return espCTColorToRgbColor(ctColor);
+}
+
+espRgbColor_t espCTColorToRgbColor(espCtColor_t ct) {
+  espRgbColor_t rgb = {0, 0, 0};
+  float r, g, b;
+
+  if (ct.ctMireds == 0) {
+    return rgb;
+  }
+  // Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
+
+  // Convert Mireds to centiKelvins. k = 1,000,000/mired
+  float ctCentiKelvin = 10000 / ct.ctMireds;
+
+  // Red
+  if (ctCentiKelvin <= 66) {
+    r = 255;
+  } else {
+    r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f);
+  }
+
+  // Green
+  if (ctCentiKelvin <= 66) {
+    g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f;
+  } else {
+    g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f);
+  }
+
+  // Blue
+  if (ctCentiKelvin >= 66) {
+    b = 255;
+  } else {
+    if (ctCentiKelvin <= 19) {
+      b = 0;
+    } else {
+      b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307;
+    }
+  }
+  rgb.r = (uint8_t)clamp(r, 0, 255);
+  rgb.g = (uint8_t)clamp(g, 0, 255);
+  rgb.b = (uint8_t)clamp(b, 0, 255);
+
+  return rgb;
+}
diff --git a/cores/esp32/ColorFormat.h b/cores/esp32/ColorFormat.h
new file mode 100644
index 00000000000..0bb87145d16
--- /dev/null
+++ b/cores/esp32/ColorFormat.h
@@ -0,0 +1,70 @@
+/*
+ *
+ *    Copyright (c) 2021 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    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 <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct RgbColor_t {
+  uint8_t r;
+  uint8_t g;
+  uint8_t b;
+};
+
+struct HsvColor_t {
+  uint16_t h;
+  uint8_t s;
+  uint8_t v;
+};
+
+struct XyColor_t {
+  uint16_t x;
+  uint16_t y;
+};
+
+struct CtColor_t {
+  uint16_t ctMireds;
+};
+
+typedef struct RgbColor_t espRgbColor_t;
+typedef struct HsvColor_t espHsvColor_t;
+typedef struct XyColor_t espXyColor_t;
+typedef struct CtColor_t espCtColor_t;
+
+espRgbColor_t espXYToRgbColor(uint8_t Level, uint16_t current_X, uint16_t current_Y);
+espRgbColor_t espXYColorToRgb(uint8_t Level, espXyColor_t xy);
+espXyColor_t espRgbColorToXYColor(espRgbColor_t rgb);
+espXyColor_t espRgbToXYColor(uint8_t r, uint8_t g, uint8_t b);
+espRgbColor_t espHsvColorToRgbColor(espHsvColor_t hsv);
+espRgbColor_t espHsvToRgbColor(uint16_t h, uint8_t s, uint8_t v);
+espRgbColor_t espCTColorToRgbColor(espCtColor_t ct);
+espRgbColor_t espCTToRgbColor(uint16_t ct);
+espHsvColor_t espRgbColorToHsvColor(espRgbColor_t rgb);
+espHsvColor_t espRgbToHsvColor(uint8_t r, uint8_t g, uint8_t b);
+
+extern const espHsvColor_t HSV_BLACK, HSV_WHITE, HSV_RED, HSV_YELLOW, HSV_GREEN, HSV_CYAN, HSV_BLUE, HSV_MAGENTA;
+extern const espCtColor_t COOL_WHITE_COLOR_TEMPERATURE, DAYLIGHT_WHITE_COLOR_TEMPERATURE, WHITE_COLOR_TEMPERATURE, SOFT_WHITE_COLOR_TEMPERATURE,
+  WARM_WHITE_COLOR_TEMPERATURE;
+extern const espRgbColor_t RGB_BLACK, RGB_WHITE, RGB_RED, RGB_YELLOW, RGB_GREEN, RGB_CYAN, RGB_BLUE, RGB_MAGENTA;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libraries/ESP32/keywords.txt b/libraries/ESP32/keywords.txt
index 7e36360c840..866e76babd8 100644
--- a/libraries/ESP32/keywords.txt
+++ b/libraries/ESP32/keywords.txt
@@ -6,14 +6,50 @@
 # Datatypes (KEYWORD1)
 #######################################
 
-Serial4  KEYWORD1
+Serial4	KEYWORD1
+espCtColor_t	KEYWORD1
+espXyColor_t	KEYWORD1
+espHsvColor_t	KEYWORD1
+espRgbColor_t	KEYWORD1
 
 #######################################
 # Methods and Functions (KEYWORD2)
 #######################################
 
+espXYToRgbColor	KEYWORD2
+espXYColorToRgb	KEYWORD2
+espRgbColorToXYColor	KEYWORD2
+espRgbToXYColor	KEYWORD2
+espHsvColorToRgbColor	KEYWORD2
+espHsvToRgbColor	KEYWORD2
+espCTColorToRgbColor	KEYWORD2
+espCTToRgbColor	KEYWORD2
+espRgbColorToHsvColor	KEYWORD2
+espRgbToHsvColor	KEYWORD2
+
 #######################################
 # Constants (LITERAL1)
 #######################################
 
 RGB_BUILTIN	LITERAL1
+HSV_BLACK	LITERAL1
+HSV_WHITE	LITERAL1
+HSV_RED	LITERAL1
+HSV_YELLOW	LITERAL1
+HSV_GREEN	LITERAL1
+HSV_CYAN	LITERAL1
+HSV_BLUE	LITERAL1
+HSV_MAGENTA	LITERAL1
+COOL_WHITE_COLOR_TEMPERATURE	LITERAL1
+DAYLIGHT_WHITE_COLOR_TEMPERATURE	LITERAL1
+WHITE_COLOR_TEMPERATURE	LITERAL1
+SOFT_WHITE_COLOR_TEMPERATURE	LITERAL1
+WARM_WHITE_COLOR_TEMPERATURE	LITERAL1
+RGB_BLACK	LITERAL1
+RGB_WHITE	LITERAL1
+RGB_RED	LITERAL1
+RGB_YELLOW	LITERAL1
+RGB_GREEN	LITERAL1
+RGB_CYAN	LITERAL1
+RGB_BLUE	LITERAL1
+RGB_MAGENTA	LITERAL1
diff --git a/libraries/Matter/examples/Matter_CW_WW_Light/Matter_CW_WW_Light.ino b/libraries/Matter/examples/Matter_CW_WW_Light/Matter_CW_WW_Light.ino
index 39392d90225..0ff30f53ec0 100644
--- a/libraries/Matter/examples/Matter_CW_WW_Light/Matter_CW_WW_Light.ino
+++ b/libraries/Matter/examples/Matter_CW_WW_Light/Matter_CW_WW_Light.ino
@@ -47,8 +47,7 @@ bool setLightState(bool state, uint8_t brightness, uint16_t temperature_Mireds)
 
   if (state) {
 #ifdef RGB_BUILTIN
-    CtColor_t ct = {temperature_Mireds};
-    RgbColor_t rgb_ct = CTToRgb(ct);
+    espRgbColor_t rgb_ct = espCTToRgbColor(temperature_Mireds);
     // simple intensity correction
     float brightnessPercent = (float)brightness / MatterColorTemperatureLight::MAX_BRIGHTNESS;
     rgb_ct.r = brightnessPercent * rgb_ct.r;
@@ -106,7 +105,7 @@ void setup() {
   // default brightness ~= 6% (15/255)
   uint8_t lastBrightness = matterPref.getUChar(brightnessPrefKey, 15);
   // default temperature ~= 454 Mireds (Warm White)
-  uint16_t lastTemperature = matterPref.getUShort(temperaturePrefKey, MatterColorTemperatureLight::WARM_WHITE_COLOR_TEMPERATURE);
+  uint16_t lastTemperature = matterPref.getUShort(temperaturePrefKey, WARM_WHITE_COLOR_TEMPERATURE.ctMireds);
   CW_WW_Light.begin(lastOnOffState, lastBrightness, lastTemperature);
   // set the callback function to handle the Light state change
   CW_WW_Light.onChange(setLightState);
diff --git a/libraries/Matter/examples/Matter_ColorLight/Matter_ColorLight.ino b/libraries/Matter/examples/Matter_ColorLight/Matter_ColorLight.ino
new file mode 100644
index 00000000000..2b9c4e4033a
--- /dev/null
+++ b/libraries/Matter/examples/Matter_ColorLight/Matter_ColorLight.ino
@@ -0,0 +1,183 @@
+// 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>
+#include <Preferences.h>
+
+// List of Matter Endpoints for this Node
+// Color Light Endpoint
+MatterColorLight ColorLight;
+
+// it will keep last OnOff & HSV Color state stored, using Preferences
+Preferences matterPref;
+const char *onOffPrefKey = "OnOff";
+const char *hsvColorPrefKey = "HSV";
+
+// set your board RGB LED pin here
+#ifdef RGB_BUILTIN
+const uint8_t ledPin = RGB_BUILTIN;
+#else
+const uint8_t ledPin = 2;  // Set your pin here if your board has not defined LED_BUILTIN
+#warning "Do not forget to set the RGB LED pin"
+#endif
+
+// set your board USER BUTTON pin here
+const uint8_t buttonPin = 0;  // Set your pin here. Using BOOT Button. C6/C3 use GPIO9.
+
+// 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
+
+// Set the RGB LED Light based on the current state of the Color Light
+bool setLightState(bool state, espHsvColor_t colorHSV) {
+
+  if (state) {
+#ifdef RGB_BUILTIN
+    espRgbColor_t rgbColor = espHsvColorToRgbColor(colorHSV);
+    // set the RGB LED
+    rgbLedWrite(ledPin, rgbColor.r, rgbColor.g, rgbColor.b);
+#else
+    // No Color RGB LED, just use the HSV value (brightness) to control the LED
+    analogWrite(ledPin, colorHSV.v);
+#endif
+  } else {
+    digitalWrite(ledPin, LOW);
+  }
+  // store last HSV Color and OnOff state for when the Light is restarted / power goes off
+  matterPref.putBool(onOffPrefKey, state);
+  matterPref.putUInt(hsvColorPrefKey, colorHSV.h << 16 | colorHSV.s << 8 | colorHSV.v);
+  // This callback must return the success state to Matter core
+  return true;
+}
+
+void setup() {
+  // Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch
+  pinMode(buttonPin, INPUT_PULLUP);
+  // Initialize the LED (light) GPIO and Matter End Point
+  pinMode(ledPin, 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);
+
+  // Initialize Matter EndPoint
+  matterPref.begin("MatterPrefs", false);
+  // default OnOff state is ON if not stored before
+  bool lastOnOffState = matterPref.getBool(onOffPrefKey, true);
+  // default HSV color is blue HSV(169, 254, 254)
+  uint32_t prefHsvColor = matterPref.getUInt(hsvColorPrefKey, 169 << 16 | 254 << 8 | 254);
+  espHsvColor_t lastHsvColor = {uint8_t(prefHsvColor >> 16), uint8_t(prefHsvColor >> 8), uint8_t(prefHsvColor)};
+  ColorLight.begin(lastOnOffState, lastHsvColor);
+  // set the callback function to handle the Light state change
+  ColorLight.onChange(setLightState);
+
+  // lambda functions are used to set the attribute change callbacks
+  ColorLight.onChangeOnOff([](bool state) {
+    Serial.printf("Light OnOff changed to %s\r\n", state ? "ON" : "OFF");
+    return true;
+  });
+  ColorLight.onChangeColorHSV([](HsvColor_t hsvColor) {
+    Serial.printf("Light HSV Color changed to (%d,%d,%d)\r\n", hsvColor.h, hsvColor.s, hsvColor.v);
+    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.");
+    Serial.printf(
+      "Initial state: %s | RGB Color: (%d,%d,%d) \r\n", ColorLight ? "ON" : "OFF", ColorLight.getColorRGB().r, ColorLight.getColorRGB().g,
+      ColorLight.getColorRGB().b
+    );
+    // configure the Light based on initial on-off state and its color
+    ColorLight.updateAccessory();
+  }
+}
+// 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 light
+
+void loop() {
+  // Check Matter Light 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 Light 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.printf(
+      "Initial state: %s | RGB Color: (%d,%d,%d) \r\n", ColorLight ? "ON" : "OFF", ColorLight.getColorRGB().r, ColorLight.getColorRGB().g,
+      ColorLight.getColorRGB().b
+    );
+    // configure the Light based on initial on-off state and its color
+    ColorLight.updateAccessory();
+    Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
+  }
+
+  // A button is also used to control the light
+  // 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 Light toggle switch 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
+    // Toggle button is released - toggle the light
+    Serial.println("User button released. Toggling Light!");
+    ColorLight.toggle();  // Matter Controller also can see the change
+
+    // Factory reset is triggered if the button is pressed longer than 10 seconds
+    if (time_diff > decommissioningTimeout) {
+      Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
+      ColorLight = false;  // turn the light off
+      Matter.decommission();
+    }
+  }
+}
diff --git a/libraries/Matter/examples/Matter_ColorLight/ci.json b/libraries/Matter/examples/Matter_ColorLight/ci.json
new file mode 100644
index 00000000000..d5f63487506
--- /dev/null
+++ b/libraries/Matter/examples/Matter_ColorLight/ci.json
@@ -0,0 +1,7 @@
+{
+    "fqbn_append": "PartitionScheme=huge_app",
+    "requires": [
+      "CONFIG_SOC_WIFI_SUPPORTED=y",
+      "CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y"
+    ]
+  }
diff --git a/libraries/Matter/keywords.txt b/libraries/Matter/keywords.txt
index bcc99253e72..39a74e76583 100644
--- a/libraries/Matter/keywords.txt
+++ b/libraries/Matter/keywords.txt
@@ -1,5 +1,5 @@
 #######################################
-# Syntax Coloring Map For OpenThread
+# Syntax Coloring Map For Matter
 #######################################
 
 #######################################
@@ -10,12 +10,9 @@ Matter	KEYWORD1
 ArduinoMatter	KEYWORD1
 MatterOnOffLight	KEYWORD1
 MatterDimmableLight	KEYWORD1
-MatterColorTemperatureLight KEYWORD1
+MatterColorTemperatureLight	KEYWORD1
+MatterColorLight	KEYWORD1
 MatterEndPoint	KEYWORD1
-CtColor_t	KEYWORD1
-XyColor_t	KEYWORD1
-HsvColor_t	KEYWORD1
-RgbColor_t	KEYWORD1
 
 #######################################
 # Methods and Functions (KEYWORD2)
@@ -37,26 +34,23 @@ setBrightness	KEYWORD2
 getBrightness	KEYWORD2
 setColorTemperature	KEYWORD2
 getColorTemperature	KEYWORD2
+setColorRGB	KEYWORD2
+getColorRGB	KEYWORD2
+setColorHSV	KEYWORD2
+getColorHSV	KEYWORD2
 toggle	KEYWORD2
 updateAccessory	KEYWORD2
 onChange	KEYWORD2
 onChangeOnOff	KEYWORD2
 onChangeBrightness	KEYWORD2
-onChangeColorTemperature KEYWORD2
-XYToRgb KEYWORD2
-HsvToRgb KEYWORD2
-CTToRgb KEYWORD2
-RgbToHsv KEYWORD2
+onChangeColorTemperature	KEYWORD2
+onChangeColorHSV	KEYWORD2
+
 
 #######################################
 # Constants (LITERAL1)
 #######################################
 
-MAX_BRIGHTNESS  LITERAL1
-MAX_COLOR_TEMPERATURE  LITERAL1
-MIN_COLOR_TEMPERATURE  LITERAL1
-COOL_WHITE_COLOR_TEMPERATURE  LITERAL1
-DAYLIGHT_WHITE_COLOR_TEMPERATURE  LITERAL1
-WHITE_COLOR_TEMPERATURE  LITERAL1
-SOFT_WHITE_COLOR_TEMPERATURE  LITERAL1
-WARM_WHITE_COLOR_TEMPERATURE  LITERAL1
+MAX_BRIGHTNESS	LITERAL1
+MAX_COLOR_TEMPERATURE	LITERAL1
+MIN_COLOR_TEMPERATURE	LITERAL1
diff --git a/libraries/Matter/src/Matter.cpp b/libraries/Matter/src/Matter.cpp
index 857438cce03..89ef87b4db3 100644
--- a/libraries/Matter/src/Matter.cpp
+++ b/libraries/Matter/src/Matter.cpp
@@ -17,7 +17,6 @@
 
 #include <Matter.h>
 #include <app/server/Server.h>
-#include "MatterEndPoint.h"
 
 using namespace esp_matter;
 using namespace esp_matter::attribute;
diff --git a/libraries/Matter/src/Matter.h b/libraries/Matter/src/Matter.h
index e9d8b715388..4d269474187 100644
--- a/libraries/Matter/src/Matter.h
+++ b/libraries/Matter/src/Matter.h
@@ -18,10 +18,11 @@
 
 #include <Arduino.h>
 #include <esp_matter.h>
-#include <MatterUtil/ColorFormat.h>
+#include <ColorFormat.h>
 #include <MatterEndpoints/MatterOnOffLight.h>
 #include <MatterEndpoints/MatterDimmableLight.h>
 #include <MatterEndpoints/MatterColorTemperatureLight.h>
+#include <MatterEndpoints/MatterColorLight.h>
 
 using namespace esp_matter;
 
@@ -50,6 +51,7 @@ class ArduinoMatter {
   friend class MatterOnOffLight;
   friend class MatterDimmableLight;
   friend class MatterColorTemperatureLight;
+  friend class MatterColorLight;
 
 protected:
   static void _init();
diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp b/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
new file mode 100644
index 00000000000..b67cf6a23b1
--- /dev/null
+++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.cpp
@@ -0,0 +1,307 @@
+// 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 <app/server/Server.h>
+#include <MatterEndpoints/MatterColorLight.h>
+
+using namespace esp_matter;
+using namespace esp_matter::endpoint;
+using namespace chip::app::Clusters;
+
+// endpoint for color light device
+namespace esp_matter {
+using namespace cluster;
+namespace endpoint {
+namespace rgb_color_light {
+typedef struct config {
+  cluster::descriptor::config_t descriptor;
+  cluster::identify::config_t identify;
+  cluster::groups::config_t groups;
+  cluster::scenes_management::config_t scenes_management;
+  cluster::on_off::config_t on_off;
+  cluster::level_control::config_t level_control;
+  cluster::color_control::config_t color_control;
+} config_t;
+
+uint32_t get_device_type_id() {
+  return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_ID;
+}
+
+uint8_t get_device_type_version() {
+  return ESP_MATTER_EXTENDED_COLOR_LIGHT_DEVICE_TYPE_VERSION;
+}
+
+esp_err_t add(endpoint_t *endpoint, config_t *config) {
+  if (!endpoint) {
+    log_e("Endpoint cannot be NULL");
+    return ESP_ERR_INVALID_ARG;
+  }
+  esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version());
+  if (err != ESP_OK) {
+    log_e("Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err);
+    return err;
+  }
+
+  descriptor::create(endpoint, &(config->descriptor), CLUSTER_FLAG_SERVER);
+  cluster_t *identify_cluster = identify::create(endpoint, &(config->identify), CLUSTER_FLAG_SERVER);
+  identify::command::create_trigger_effect(identify_cluster);
+  groups::create(endpoint, &(config->groups), CLUSTER_FLAG_SERVER);
+  cluster_t *scenes_cluster = scenes_management::create(endpoint, &(config->scenes_management), CLUSTER_FLAG_SERVER);
+  scenes_management::command::create_copy_scene(scenes_cluster);
+  scenes_management::command::create_copy_scene_response(scenes_cluster);
+
+  on_off::create(endpoint, &(config->on_off), CLUSTER_FLAG_SERVER, on_off::feature::lighting::get_id());
+  level_control::create(
+    endpoint, &(config->level_control), CLUSTER_FLAG_SERVER, level_control::feature::on_off::get_id() | level_control::feature::lighting::get_id()
+  );
+  color_control::create(endpoint, &(config->color_control), CLUSTER_FLAG_SERVER, color_control::feature::hue_saturation::get_id());
+  return ESP_OK;
+}
+
+endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) {
+  endpoint_t *endpoint = endpoint::create(node, flags, priv_data);
+  add(endpoint, config);
+  return endpoint;
+}
+}  // namespace rgb_color_light
+}  // namespace endpoint
+}  // namespace esp_matter
+
+bool MatterColorLight::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 RGB Color Light device has not begun.");
+    return false;
+  }
+
+  log_d(
+    "RGB Color Attr update callback: endpoint: %u, cluster: %u, attribute: %u, val: %u, type: %u", endpoint_id, cluster_id, attribute_id, val->val.u32,
+    val->type
+  );
+
+  if (endpoint_id == getEndPointId()) {
+    switch (cluster_id) {
+      case OnOff::Id:
+        if (attribute_id == OnOff::Attributes::OnOff::Id) {
+          log_d("RGB Color Light On/Off State changed to %d", val->val.b);
+          if (_onChangeOnOffCB != NULL) {
+            ret &= _onChangeOnOffCB(val->val.b);
+          }
+          if (_onChangeCB != NULL) {
+            ret &= _onChangeCB(val->val.b, colorHSV);
+          }
+          if (ret == true) {
+            onOffState = val->val.b;
+          }
+        }
+        break;
+      case LevelControl::Id:
+        if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
+          log_d("RGB Color Light Brightness changed to %d", val->val.u8);
+          if (_onChangeColorCB != NULL) {
+            ret &= _onChangeColorCB({colorHSV.h, colorHSV.s, val->val.u8});
+          }
+          if (_onChangeCB != NULL) {
+            ret &= _onChangeCB(onOffState, {colorHSV.h, colorHSV.s, val->val.u8});
+          }
+          if (ret == true) {
+            colorHSV.v = val->val.u8;
+          }
+        }
+        break;
+      case ColorControl::Id:
+      {
+        if (attribute_id != ColorControl::Attributes::CurrentHue::Id && attribute_id != ColorControl::Attributes::CurrentSaturation::Id) {
+          log_i("Color Control Attribute ID [%x] not processed.", attribute_id);
+          break;
+        }
+        espHsvColor_t hsvColor = {colorHSV.h, colorHSV.s, colorHSV.v};
+        if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
+          log_d("RGB Light Hue changed to %d", val->val.u8);
+          hsvColor.h = val->val.u8;
+        } else {  // attribute_id == ColorControl::Attributes::CurrentSaturation::Id)
+          log_d("RGB Light Saturation changed to %d", val->val.u8);
+          hsvColor.s = val->val.u8;
+        }
+        if (_onChangeColorCB != NULL) {
+          ret &= _onChangeColorCB(hsvColor);
+        }
+        if (_onChangeCB != NULL) {
+          ret &= _onChangeCB(onOffState, hsvColor);
+        }
+        if (ret == true) {
+          colorHSV = {hsvColor.h, hsvColor.s, hsvColor.v};
+        }
+        break;
+      }
+    }
+  }
+  return ret;
+}
+
+MatterColorLight::MatterColorLight() {}
+
+MatterColorLight::~MatterColorLight() {
+  end();
+}
+
+bool MatterColorLight::begin(bool initialState, espHsvColor_t _colorHSV) {
+  ArduinoMatter::_init();
+  rgb_color_light::config_t light_config;
+
+  light_config.on_off.on_off = initialState;
+  light_config.on_off.lighting.start_up_on_off = nullptr;
+  onOffState = initialState;
+
+  light_config.level_control.current_level = _colorHSV.v;
+  light_config.level_control.lighting.start_up_current_level = nullptr;
+
+  light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation;
+  light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation;
+  light_config.color_control.hue_saturation.current_hue = _colorHSV.h;
+  light_config.color_control.hue_saturation.current_saturation = _colorHSV.s;
+  colorHSV = {_colorHSV.h, _colorHSV.s, _colorHSV.v};
+
+  // endpoint handles can be used to add/modify clusters.
+  endpoint_t *endpoint = rgb_color_light::create(node::get(), &light_config, ENDPOINT_FLAG_NONE, (void *)this);
+  if (endpoint == nullptr) {
+    log_e("Failed to create RGB Color light endpoint");
+    return false;
+  }
+
+  setEndPointId(endpoint::get_id(endpoint));
+  log_i("RGB Color Light created with endpoint_id %d", getEndPointId());
+
+  /* Mark deferred persistence for some attributes that might be changed rapidly */
+  cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id);
+  attribute_t *current_level_attribute = attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id);
+  attribute::set_deferred_persistence(current_level_attribute);
+
+  started = true;
+  return true;
+}
+
+void MatterColorLight::end() {
+  started = false;
+}
+
+bool MatterColorLight::setOnOff(bool newState) {
+  if (!started) {
+    log_e("Matter RGB Color Light device has not begun.");
+    return false;
+  }
+
+  // avoid processing the a "no-change"
+  if (onOffState == newState) {
+    return true;
+  }
+
+  onOffState = newState;
+
+  endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
+  cluster_t *cluster = cluster::get(endpoint, OnOff::Id);
+  attribute_t *attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id);
+
+  esp_matter_attr_val_t val = esp_matter_invalid(NULL);
+  attribute::get_val(attribute, &val);
+
+  if (val.val.b != onOffState) {
+    val.val.b = onOffState;
+    attribute::update(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id, &val);
+  }
+  return true;
+}
+
+void MatterColorLight::updateAccessory() {
+  if (_onChangeCB != NULL) {
+    _onChangeCB(onOffState, colorHSV);
+  }
+}
+
+bool MatterColorLight::getOnOff() {
+  return onOffState;
+}
+
+bool MatterColorLight::toggle() {
+  return setOnOff(!onOffState);
+}
+
+bool MatterColorLight::setColorRGB(espRgbColor_t _rgbColor) {
+  return setColorHSV(espRgbColorToHsvColor(_rgbColor));
+}
+
+espRgbColor_t MatterColorLight::getColorRGB() {
+  return espHsvColorToRgbColor(colorHSV);
+}
+
+bool MatterColorLight::setColorHSV(espHsvColor_t _hsvColor) {
+
+  if (!started) {
+    log_w("Matter RGB Color Light device has not begun.");
+    return false;
+  }
+
+  // avoid processing the a "no-change"
+  if (colorHSV.h == _hsvColor.h && colorHSV.s == _hsvColor.s && colorHSV.v == _hsvColor.v) {
+    return true;
+  }
+
+  colorHSV = {_hsvColor.h, _hsvColor.s, _hsvColor.v};
+
+  endpoint_t *endpoint = endpoint::get(node::get(), endpoint_id);
+  cluster_t *cluster = cluster::get(endpoint, ColorControl::Id);
+  // update hue
+  attribute_t *attribute = attribute::get(cluster, ColorControl::Attributes::CurrentHue::Id);
+  esp_matter_attr_val_t val = esp_matter_invalid(NULL);
+  attribute::get_val(attribute, &val);
+  if (val.val.u8 != colorHSV.h) {
+    val.val.u8 = colorHSV.h;
+    attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id, &val);
+  }
+  // update saturation
+  attribute = attribute::get(cluster, ColorControl::Attributes::CurrentSaturation::Id);
+  val = esp_matter_invalid(NULL);
+  attribute::get_val(attribute, &val);
+  if (val.val.u8 != colorHSV.s) {
+    val.val.u8 = colorHSV.s;
+    attribute::update(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id, &val);
+  }
+  // update value (brightness)
+  cluster = cluster::get(endpoint, LevelControl::Id);
+  attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id);
+  val = esp_matter_invalid(NULL);
+  attribute::get_val(attribute, &val);
+  if (val.val.u8 != colorHSV.v) {
+    val.val.u8 = colorHSV.v;
+    attribute::update(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id, &val);
+  }
+  return true;
+}
+
+espHsvColor_t MatterColorLight::getColorHSV() {
+  return colorHSV;
+}
+
+MatterColorLight::operator bool() {
+  return getOnOff();
+}
+
+void MatterColorLight::operator=(bool newState) {
+  setOnOff(newState);
+}
+#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */
diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h
new file mode 100644
index 00000000000..13ff0decbc2
--- /dev/null
+++ b/libraries/Matter/src/MatterEndpoints/MatterColorLight.h
@@ -0,0 +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 <sdkconfig.h>
+#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
+
+#include <Matter.h>
+#include <MatterEndPoint.h>
+
+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<bool(bool)>;
+  void onChangeOnOff(EndPointOnOffCB onChangeCB) {
+    _onChangeOnOffCB = onChangeCB;
+  }
+  // User Callback for whenever the HSV Color value is changed by the Matter Controller
+  using EndPointRGBColorCB = std::function<bool(espHsvColor_t)>;
+  void onChangeColorHSV(EndPointRGBColorCB onChangeCB) {
+    _onChangeColorCB = onChangeCB;
+  }
+
+  // User Callback for whenever any parameter is changed by the Matter Controller
+  using EndPointCB = std::function<bool(bool, espHsvColor_t)>;
+  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 */
diff --git a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h
index a37f362f475..723849e354a 100644
--- a/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h
+++ b/libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h
@@ -24,12 +24,6 @@ class MatterColorTemperatureLight : public MatterEndPoint {
   static const uint8_t MAX_BRIGHTNESS = 255;
   static const uint16_t MAX_COLOR_TEMPERATURE = 500;
   static const uint16_t MIN_COLOR_TEMPERATURE = 100;
-  // main color temperature values
-  static const uint16_t COOL_WHITE_COLOR_TEMPERATURE = 142;
-  static const uint16_t DAYLIGHT_WHITE_COLOR_TEMPERATURE = 181;
-  static const uint16_t WHITE_COLOR_TEMPERATURE = 250;
-  static const uint16_t SOFT_WHITE_COLOR_TEMPERATURE = 370;
-  static const uint16_t WARM_WHITE_COLOR_TEMPERATURE = 454;
 
   MatterColorTemperatureLight();
   ~MatterColorTemperatureLight();
diff --git a/libraries/Matter/src/MatterUtil/ColorFormat.cpp b/libraries/Matter/src/MatterUtil/ColorFormat.cpp
deleted file mode 100644
index 41d845dcdb9..00000000000
--- a/libraries/Matter/src/MatterUtil/ColorFormat.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- *
- *    Copyright (c) 2021 Project CHIP Authors
- *    All rights reserved.
- *
- *    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 "ColorFormat.h"
-
-#include <math.h>
-
-// define a clamp macro to substitute the std::clamp macro which is available from C++17 onwards
-#define clamp(a, min, max) ((a) < (min) ? (min) : ((a) > (max) ? (max) : (a)))
-
-RgbColor_t HsvToRgb(HsvColor_t hsv) {
-  RgbColor_t rgb;
-
-  uint16_t i = hsv.h / 60;
-  uint16_t rgb_max = hsv.v;
-  uint16_t rgb_min = (uint16_t)(rgb_max * (100 - hsv.s)) / 100;
-  uint16_t diff = hsv.h % 60;
-  uint16_t rgb_adj = (uint16_t)((rgb_max - rgb_min) * diff) / 60;
-
-  switch (i) {
-    case 0:
-      rgb.r = (uint8_t)rgb_max;
-      rgb.g = (uint8_t)(rgb_min + rgb_adj);
-      rgb.b = (uint8_t)rgb_min;
-      break;
-    case 1:
-      rgb.r = (uint8_t)(rgb_max - rgb_adj);
-      rgb.g = (uint8_t)rgb_max;
-      rgb.b = (uint8_t)rgb_min;
-      break;
-    case 2:
-      rgb.r = (uint8_t)rgb_min;
-      rgb.g = (uint8_t)rgb_max;
-      rgb.b = (uint8_t)(rgb_min + rgb_adj);
-      break;
-    case 3:
-      rgb.r = (uint8_t)rgb_min;
-      rgb.g = (uint8_t)(rgb_max - rgb_adj);
-      rgb.b = (uint8_t)rgb_max;
-      break;
-    case 4:
-      rgb.r = (uint8_t)(rgb_min + rgb_adj);
-      rgb.g = (uint8_t)rgb_min;
-      rgb.b = (uint8_t)rgb_max;
-      break;
-    default:
-      rgb.r = (uint8_t)rgb_max;
-      rgb.g = (uint8_t)rgb_min;
-      rgb.b = (uint8_t)(rgb_max - rgb_adj);
-      break;
-  }
-
-  return rgb;
-}
-
-HsvColor_t RgbToHsv(RgbColor_t rgb) {
-  HsvColor_t hsv;
-
-  uint16_t rgb_max = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
-  uint16_t rgb_min = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
-  uint16_t diff = rgb_max - rgb_min;
-
-  if (diff == 0) {
-    hsv.h = 0;
-  } else if (rgb_max == rgb.r) {
-    hsv.h = (uint8_t)(60 * ((rgb.g - rgb.b) * 100) / diff);
-  } else if (rgb_max == rgb.g) {
-    hsv.h = (uint8_t)(60 * (((rgb.b - rgb.r) * 100) / diff + 2 * 100));
-  } else {
-    hsv.h = (uint8_t)(60 * (((rgb.r - rgb.g) * 100) / diff + 4 * 100));
-  }
-
-  if (rgb_max == 0) {
-    hsv.s = 0;
-  } else {
-    hsv.s = (uint8_t)((diff * 100) / rgb_max);
-  }
-
-  hsv.v = (uint8_t)rgb_max;
-  if (hsv.h < 0) {
-    hsv.h += 360;
-  }
-
-  return hsv;
-}
-
-RgbColor_t XYToRgb(uint8_t Level, uint16_t current_X, uint16_t current_Y) {
-  // convert xyY color space to RGB
-
-  // https://www.easyrgb.com/en/math.php
-  // https://en.wikipedia.org/wiki/SRGB
-  // refer https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space
-
-  // The current_X/current_Y attribute contains the current value of the normalized chromaticity value of x/y.
-  // The value of x/y shall be related to the current_X/current_Y attribute by the relationship
-  // x = current_X/65536
-  // y = current_Y/65536
-  // z = 1-x-y
-
-  RgbColor_t rgb;
-
-  float x, y, z;
-  float X, Y, Z;
-  float r, g, b;
-
-  x = ((float)current_X) / 65535.0f;
-  y = ((float)current_Y) / 65535.0f;
-
-  z = 1.0f - x - y;
-
-  // Calculate XYZ values
-
-  // Y - given brightness in 0 - 1 range
-  Y = ((float)Level) / 254.0f;
-  X = (Y / y) * x;
-  Z = (Y / y) * z;
-
-  // X, Y and Z input refer to a D65/2° standard illuminant.
-  // sR, sG and sB (standard RGB) output range = 0 ÷ 255
-  // convert XYZ to RGB - CIE XYZ to sRGB
-  X = X / 100.0f;
-  Y = Y / 100.0f;
-  Z = Z / 100.0f;
-
-  r = (X * 3.2406f) - (Y * 1.5372f) - (Z * 0.4986f);
-  g = -(X * 0.9689f) + (Y * 1.8758f) + (Z * 0.0415f);
-  b = (X * 0.0557f) - (Y * 0.2040f) + (Z * 1.0570f);
-
-  // apply gamma 2.2 correction
-  r = (r <= 0.0031308f ? 12.92f * r : (1.055f) * pow(r, (1.0f / 2.4f)) - 0.055f);
-  g = (g <= 0.0031308f ? 12.92f * g : (1.055f) * pow(g, (1.0f / 2.4f)) - 0.055f);
-  b = (b <= 0.0031308f ? 12.92f * b : (1.055f) * pow(b, (1.0f / 2.4f)) - 0.055f);
-
-  // Round off
-  r = clamp(r, 0, 1);
-  g = clamp(g, 0, 1);
-  b = clamp(b, 0, 1);
-
-  // these rgb values are in  the range of 0 to 1, convert to limit of HW specific LED
-  rgb.r = (uint8_t)(r * 255);
-  rgb.g = (uint8_t)(g * 255);
-  rgb.b = (uint8_t)(b * 255);
-
-  return rgb;
-}
-
-RgbColor_t CTToRgb(CtColor_t ct) {
-  RgbColor_t rgb = {0, 0, 0};
-  float r, g, b;
-
-  if (ct.ctMireds == 0) {
-    return rgb;
-  }
-  // Algorithm credits to Tanner Helland: https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
-
-  // Convert Mireds to centiKelvins. k = 1,000,000/mired
-  float ctCentiKelvin = 10000 / ct.ctMireds;
-
-  // Red
-  if (ctCentiKelvin <= 66) {
-    r = 255;
-  } else {
-    r = 329.698727446f * pow(ctCentiKelvin - 60, -0.1332047592f);
-  }
-
-  // Green
-  if (ctCentiKelvin <= 66) {
-    g = 99.4708025861f * log(ctCentiKelvin) - 161.1195681661f;
-  } else {
-    g = 288.1221695283f * pow(ctCentiKelvin - 60, -0.0755148492f);
-  }
-
-  // Blue
-  if (ctCentiKelvin >= 66) {
-    b = 255;
-  } else {
-    if (ctCentiKelvin <= 19) {
-      b = 0;
-    } else {
-      b = 138.5177312231 * log(ctCentiKelvin - 10) - 305.0447927307;
-    }
-  }
-  rgb.r = (uint8_t)clamp(r, 0, 255);
-  rgb.g = (uint8_t)clamp(g, 0, 255);
-  rgb.b = (uint8_t)clamp(b, 0, 255);
-
-  return rgb;
-}
diff --git a/libraries/Matter/src/MatterUtil/ColorFormat.h b/libraries/Matter/src/MatterUtil/ColorFormat.h
deleted file mode 100644
index 254a51c7144..00000000000
--- a/libraries/Matter/src/MatterUtil/ColorFormat.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- *    Copyright (c) 2021 Project CHIP Authors
- *    All rights reserved.
- *
- *    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 <stdint.h>
-
-struct RgbColor_t {
-  uint8_t r;
-  uint8_t g;
-  uint8_t b;
-};
-
-struct HsvColor_t {
-  int16_t h;
-  uint8_t s;
-  uint8_t v;
-};
-
-struct XyColor_t {
-  uint16_t x;
-  uint16_t y;
-};
-
-struct CtColor_t {
-  uint16_t ctMireds;
-};
-
-RgbColor_t XYToRgb(uint8_t Level, uint16_t current_X, uint16_t current_Y);
-RgbColor_t HsvToRgb(HsvColor_t hsv);
-RgbColor_t CTToRgb(CtColor_t ct);
-HsvColor_t RgbToHsv(RgbColor_t rgb);
diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt
index 1a8b7ae85ba..40e5dcec004 100644
--- a/libraries/Zigbee/keywords.txt
+++ b/libraries/Zigbee/keywords.txt
@@ -40,6 +40,8 @@ getRadioConfig	KEYWORD2
 setHostConfig	KEYWORD2
 getHostConfig	KEYWORD2
 setPrimaryChannelMask	KEYWORD2
+setScanDuration	KEYWORD2
+getScanDuration	KEYWORD2
 setRebootOpenNetwork	KEYWORD2
 openNetwork	KEYWORD2
 scanNetworks	KEYWORD2
diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp
index 38ef9b169d5..442dc4b7ee0 100644
--- a/libraries/Zigbee/src/ZigbeeCore.cpp
+++ b/libraries/Zigbee/src/ZigbeeCore.cpp
@@ -6,7 +6,7 @@
 #include "ZigbeeHandlers.cpp"
 #include "Arduino.h"
 
-#define ZB_INIT_TIMEOUT 10000  // 10 seconds
+#define ZB_INIT_TIMEOUT 30000  // 30 seconds
 
 extern "C" void zb_set_ed_node_descriptor(bool power_src, bool rx_on_when_idle, bool alloc_addr);
 static bool edBatteryPowered = false;
@@ -20,6 +20,7 @@ ZigbeeCore::ZigbeeCore() {
   _scan_status = ZB_SCAN_FAILED;
   _started = false;
   _connected = false;
+  _scan_duration = 4;  // maximum scan duration
   if (!lock) {
     lock = xSemaphoreCreateBinary();
     if (lock == NULL) {
@@ -90,6 +91,8 @@ void ZigbeeCore::addEndpoint(ZigbeeEP *ep) {
 }
 
 static void esp_zb_task(void *pvParameters) {
+  esp_zb_bdb_set_scan_duration(Zigbee.getScanDuration());
+
   /* initialize Zigbee stack */
   ESP_ERROR_CHECK(esp_zb_start(false));
 
@@ -178,6 +181,14 @@ void ZigbeeCore::setPrimaryChannelMask(uint32_t mask) {
   _primary_channel_mask = mask;
 }
 
+void ZigbeeCore::setScanDuration(uint8_t duration) {
+  if (duration < 1 || duration > 4) {
+    log_e("Invalid scan duration, must be between 1 and 4");
+    return;
+  }
+  _scan_duration = duration;
+}
+
 void ZigbeeCore::setRebootOpenNetwork(uint8_t time) {
   _open_network = time;
 }
@@ -235,8 +246,8 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
         }
       } else {
         /* commissioning failed */
-        log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status));
-        xSemaphoreGive(Zigbee.lock);
+        log_w("Commissioning failed, trying again...", esp_err_to_name(err_status));
+        esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_INITIALIZATION, 500);
       }
       break;
     case ESP_ZB_BDB_SIGNAL_FORMATION:  // Coordinator
diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h
index e068d74430e..75fecd59198 100644
--- a/libraries/Zigbee/src/ZigbeeCore.h
+++ b/libraries/Zigbee/src/ZigbeeCore.h
@@ -66,6 +66,7 @@ class ZigbeeCore {
   esp_zb_host_config_t _host_config;
   uint32_t _primary_channel_mask;
   int16_t _scan_status;
+  uint8_t _scan_duration;
 
   esp_zb_ep_list_t *_zb_ep_list;
   zigbee_role_t _role;
@@ -109,7 +110,12 @@ class ZigbeeCore {
   void setHostConfig(esp_zb_host_config_t config);
   esp_zb_host_config_t getHostConfig();
 
-  void setPrimaryChannelMask(uint32_t mask);
+  void setPrimaryChannelMask(uint32_t mask);  // By default all channels are scanned (11-26) -> mask 0x07FFF800
+  void setScanDuration(uint8_t duration);     // Can be set from 1 - 4. 1 is fastest, 4 is slowest
+  uint8_t getScanDuration() {
+    return _scan_duration;
+  }
+
   void setRebootOpenNetwork(uint8_t time);
   void openNetwork(uint8_t time);