MatterColorLight

About

The MatterColorLight class provides an RGB color light with HSV control and no color temperature. Matter 1.5 has no Color Light (0x0102) device type, so this endpoint is advertised as an Extended Color Light (0x010D) with Hue/Saturation and XY only. Color Temperature is not in the data model. Use MatterEnhancedColorLight when the endpoint must also include color temperature.

Changing the Color Control feature set (for example, removing color temperature after an upgrade) requires recommissioning the device so the controller reloads the data model.

Features: * On/off control * RGB color control with HSV color model (brightness is HSV value; there is no separate brightness or color-temperature API) * State persistence support * Callback support for state and color changes * Integration with Home Assistant, Apple HomeKit, Amazon Alexa, and Google Home * Matter standard compliance

Use Cases: * RGB smart lights * Color-changing lights * Mood lighting * Entertainment lighting control * Smart home color automation

API Reference

Constructor

MatterColorLight

Creates a new Matter color light endpoint.

MatterColorLight();

Initialization

begin

Initializes the Matter color light endpoint with optional initial state and color.

bool begin(bool initialState = false, espHsvColor_t colorHSV = {0, 254, 31});
  • initialState - Initial on/off state (default: false = off)

  • colorHSV - Initial HSV color (default: red 12% intensity HSV(0, 254, 31))

This function will return true if successful, false otherwise.

end

Stops processing Matter light events.

void end();

On/Off Control

setOnOff

Sets the on/off state of the light.

bool setOnOff(bool newState);

getOnOff

Gets the current on/off state.

bool getOnOff();

toggle

Toggles the on/off state.

bool toggle();

Color Control

setColorRGB

Sets the color using RGB values.

bool setColorRGB(espRgbColor_t rgbColor);
  • rgbColor - RGB color structure with red, green, and blue values (0-255 each)

getColorRGB

Gets the current color as RGB values.

espRgbColor_t getColorRGB();

setColorHSV

Sets the color using HSV values.

bool setColorHSV(espHsvColor_t hsvColor);
  • hsvColor - HSV color structure: hue (0-254, where 254 is 360°), saturation (0-254), and value/brightness (0-254). Do not pass degrees in the 0-360 range.

getColorHSV

Gets the current color as HSV values.

espHsvColor_t getColorHSV();

Event Handling

onChange

Sets a callback for when any parameter changes.

void onChange(EndPointCB onChangeCB);

The callback signature is:

bool onChangeCallback(bool newState, espHsvColor_t newColor);

onChangeOnOff

Sets a callback for on/off state changes.

void onChangeOnOff(EndPointOnOffCB onChangeCB);

onChangeColorHSV

Sets a callback for color changes.

void onChangeColorHSV(EndPointRGBColorCB onChangeCB);

updateAccessory

Updates the physical light state using current Matter internal state.

void updateAccessory();

Operators

bool operator

Returns current on/off state.

operator bool();

Assignment operator

Turns light on or off.

void operator=(bool state);

Example

Color Light

// Copyright 2025 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 <Arduino.h>
#include <Matter.h>
#if !CONFIG_ENABLE_CHIPOBLE
// if the device can be commissioned using BLE, WiFi is not used - save flash space
#include <WiFi.h>
#endif
#include <Preferences.h>

// List of Matter Endpoints for this Node
// Color Light Endpoint
MatterColorLight ColorLight;

// CONFIG_ENABLE_CHIPOBLE is enabled when BLE is used to commission the Matter Network
#if !CONFIG_ENABLE_CHIPOBLE
// 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
#endif

// 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 = BOOT_PIN;  // Set your pin here. Using BOOT Button.

// 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 = 5000;  // keep the button pressed for 5s, or longer, to decommission

// 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 {
#ifndef RGB_BUILTIN
    // after analogWrite(), it is necessary to set the GPIO to digital mode first
    pinMode(ledPin, OUTPUT);
#endif
    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);

// CONFIG_ENABLE_CHIPOBLE is enabled when BLE is used to commission the Matter Network
#if !CONFIG_ENABLE_CHIPOBLE
  // We start by connecting to a WiFi network
  Serial.print("Connecting to ");
  Serial.println(ssid);
  // 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);
#endif

  // 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 (%u,%u,%u)\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 the network. Ready for use.");
    Serial.printf(
      "Initial state: %s | RGB Color: (%u,%u,%u) \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();
  }
}

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: (%u,%u,%u) \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 the network. 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 (digitalRead(buttonPin) == HIGH && button_state && time_diff > debouceTime) {
    // Toggle button is released - toggle the light
    Serial.println("User button released. Toggling Light!");
    ColorLight.toggle();   // Matter Controller also can see the change
    button_state = false;  // released
  }

  // Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node
  if (button_state && time_diff > decommissioningTimeout) {
    Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
    ColorLight = false;  // turn the light off
    Matter.decommission();
    button_time_stamp = millis();  // avoid running decommissining again, reboot takes a second or so
  }
}