Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stuck with matter customization (CON-1563) #1291

Open
ravencarcass opened this issue Feb 25, 2025 · 10 comments
Open

Stuck with matter customization (CON-1563) #1291

ravencarcass opened this issue Feb 25, 2025 · 10 comments

Comments

@ravencarcass
Copy link

Hello,
I'm stuck with a project for school where I need to make my own Matter device.

This device need to be able to control 2 steppermotors and 10 different display modes.
This all need to be controlled with a google home app. The teachers decided to use Matter. Because they had a few students that tried Matter before but it never worked. I would love to be proven wrong.

But this is where the shoe pinches. Namely, I thought to start from a matter example and build on that. I need the following interfaces: I2C, SPI, PWM, Matter and GPIO.

So I have everything finished separately, but I don't know where to start. Personally, I tought to start at the user guide for matter SDK, which is what I have done. The problem, though, is that I hardly understand anything they say.

The only thing I think I understood is the data model. I created one for my project.

Image

Can somebody help me with implementing this? Does have somebody experiences with matter SDK and customize them for specific purposes?

@github-actions github-actions bot changed the title Stuck with matter customization Stuck with matter customization (CON-1563) Feb 25, 2025
@Jerry-ESP
Copy link
Contributor

I think you can setup the esp-matter sdk first and build the light example, after that, you can add other device types base on the light example. Please refer to this document: https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html

@ravencarcass
Copy link
Author

ravencarcass commented Feb 26, 2025

I've build the light example earlier and it worked. The only things indeed is that I then need to add those things. But I don't know how. I've also tried to change the example like in the manuel. I found it also not verry clear if I wanne make a personal data model.

@Jerry-ESP
Copy link
Contributor

If you want to use standard esp-matter data model, you can use the interface in this file:https://github.com/espressif/esp-matter/blob/main/components/esp_matter/esp_matter_endpoint.cpp, if you want to add custom data model, you can follow this guide: https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#custom-cluster . If you don't know how to add driver, you can refer to this file https://github.com/espressif/esp-matter/blob/main/examples/light/main/app_driver.cpp . The motor driver can refer to this file: https://github.com/espressif/esp-matter/tree/main/examples/all_device_types_app/main/driver/fan

@ravencarcass
Copy link
Author

Ok, I've this filled in from the matter SDK manual.

` drift = endpoint::create(node(), ENDPOINT_FLAG_NONE); // Endpoint 1 (drift)
tilt = endpoint::create(node(), ENDPOINT_FLAG_NONE); // Endpoint 2 (tilt)
displayContent = endpoint::create(node(), ENDPOINT_FLAG_NONE); // Endpoint 3 (displayContent)

uint32_t custom_cluster_id = 0x131bfc00;
drift = cluster::create(drift, custom_cluster_id, CLUSTER_FLAG_SERVER);
tilt = cluster::create(tilt, custom_cluster_id, CLUSTER_FLAG_SERVER);
displayContent = cluster::create(displayContent, custom_cluster_id, CLUSTER_FLAG_SERVER);

uint32_t position_drift_attribute_id = 0x0001;
uint16_t default_drift_position = 135;
driftLevel = attribute::create(drift, position_drift_attribute_id, ATTRIBUTE_FLAG_NONE, esp_matter_uint16(default_drift_position));

static esp_err_t move_drift_level_callback(const CreateCommandPath &command_path, TLVReader &tlv_data, void *opaque_ptr) {
ESP_LOGI(TAG, "MoveDriftLevel command received");
// add your code here for functionality
return ESP_OK;
}

uint32_t position_tilt_attribute_id = 0x0002;
uint16_t default_tilt_position = 135;
tiltLevel = attribute::create(tilt, position_tilt_attribute_id, ATTRIBUTE_FLAG_NONE, esp_matter_uint16(default_tilt_position));

static esp_err_t move_tilt_level_callback(const CreateCommandPath &command_path, TLVReader &tlv_data, void *opaque_ptr) {
ESP_LOGI(TAG, "MoveTiltLevel command received");
// add your code here for functionality
return ESP_OK;
}

uint32_t display_content_attribute_id = 0x0003;
uint16_t default_display_content = 0;
Content = attribute::create(diplayContent, display_content_attribute_id, ATTRIBUTE_FLAG_NONE, esp_matter_uint16(default_display_content));

static esp_err_t display_content_callback(const CreateCommandPath &command_path, TLVReader &tlv_data, void *opaque_ptr) {
ESP_LOGI(TAG, "displayContent command received");
// add your code here for functionality
return ESP_OK;
}`

@Jerry-ESP
Copy link
Contributor

Please note: For the custom endpoint, cluster, attribute, you can't handle them through Goole Home App. The Google ecosystem can only control standard matter device which defined in the matter spec.

@ravencarcass
Copy link
Author

ravencarcass commented Feb 26, 2025

I mayby need to start back from the begin with the example and work from their up to my application. I read part 2.5 now 10 times even more. It is for real verry frustrating that I'm not able to fix it. I begin to read and everything I read is relative easy but it's just the problem to apply the theory in the code. This is what I get if I follow the color_temperture_lightbulb.

app_main.cpp

/*

This example code is in the Public Domain (or CC0 licensed, at your option.)



Unless required by applicable law or agreed to in writing, this

software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR

CONDITIONS OF ANY KIND, either express or implied.

*/



#include <esp_err.h>

#include <esp_log.h>

#include <nvs_flash.h>



#include <esp_matter.h>

#include <esp_matter_console.h>

#include <esp_matter_ota.h>



#include <common_macros.h>

#include <app_priv.h>

#include <app_reset.h>

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD

#include <platform/ESP32/OpenthreadLauncher.h>

#endif



#include <app/server/CommissioningWindowManager.h>

#include <app/server/Server.h>



#ifdef CONFIG_ENABLE_SET_CERT_DECLARATION_API

#include <esp_matter_providers.h>

#include <lib/support/Span.h>

#ifdef CONFIG_SEC_CERT_DAC_PROVIDER

#include <platform/ESP32/ESP32SecureCertDACProvider.h>

#elif defined(CONFIG_FACTORY_PARTITION_DAC_PROVIDER)

#include <platform/ESP32/ESP32FactoryDataProvider.h>

#endif

using namespace chip::DeviceLayer;

#endif



static const char *TAG = "app_main";

uint16_t light_endpoint_id = 0;



using namespace esp_matter;

using namespace esp_matter::attribute;

using namespace esp_matter::endpoint;

using namespace chip::app::Clusters;



constexpr auto k_timeout_seconds = 300;



#ifdef CONFIG_ENABLE_SET_CERT_DECLARATION_API

extern const uint8_t cd_start[] asm("_binary_certification_declaration_der_start");

extern const uint8_t cd_end[] asm("_binary_certification_declaration_der_end");



const chip::ByteSpan cdSpan(cd_start, static_cast<size_t>(cd_end - cd_start));

#endif // CONFIG_ENABLE_SET_CERT_DECLARATION_API



#if CONFIG_ENABLE_ENCRYPTED_OTA

extern const char decryption_key_start[] asm("_binary_esp_image_encryption_key_pem_start");

extern const char decryption_key_end[] asm("_binary_esp_image_encryption_key_pem_end");



static const char *s_decryption_key = decryption_key_start;

static const uint16_t s_decryption_key_len = decryption_key_end - decryption_key_start;

#endif // CONFIG_ENABLE_ENCRYPTED_OTA



static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)

{

switch (event->Type) {

case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged:

ESP_LOGI(TAG, "Interface IP Address changed");

break;



case chip::DeviceLayer::DeviceEventType::kCommissioningComplete:

ESP_LOGI(TAG, "Commissioning complete");

break;



case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired:

ESP_LOGI(TAG, "Commissioning failed, fail safe timer expired");

break;



case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted:

ESP_LOGI(TAG, "Commissioning session started");

break;



case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped:

ESP_LOGI(TAG, "Commissioning session stopped");

break;



case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened:

ESP_LOGI(TAG, "Commissioning window opened");

break;



case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed:

ESP_LOGI(TAG, "Commissioning window closed");

break;



case chip::DeviceLayer::DeviceEventType::kFabricRemoved:

{

ESP_LOGI(TAG, "Fabric removed successfully");

if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0)

{

chip::CommissioningWindowManager & commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager();

constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds);

if (!commissionMgr.IsCommissioningWindowOpen())

{

/* After removing last fabric, this example does not remove the Wi-Fi credentials

* and still has IP connectivity so, only advertising on DNS-SD.

*/

CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(kTimeoutSeconds,

chip::CommissioningWindowAdvertisement::kDnssdOnly);

if (err != CHIP_NO_ERROR)

{

ESP_LOGE(TAG, "Failed to open commissioning window, err:%" CHIP_ERROR_FORMAT, err.Format());

}

}

}

break;

}



case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved:

ESP_LOGI(TAG, "Fabric will be removed");

break;



case chip::DeviceLayer::DeviceEventType::kFabricUpdated:

ESP_LOGI(TAG, "Fabric is updated");

break;



case chip::DeviceLayer::DeviceEventType::kFabricCommitted:

ESP_LOGI(TAG, "Fabric is committed");

break;



case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized:

ESP_LOGI(TAG, "BLE deinitialized and memory reclaimed");

break;



default:

break;

}

}



// This callback is invoked when clients interact with the Identify Cluster.

// In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light).

static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id,

uint8_t effect_variant, void *priv_data)

{

ESP_LOGI(TAG, "Identification callback: type: %u, effect: %u, variant: %u", type, effect_id, effect_variant);

return ESP_OK;

}



// This callback is called for every attribute update. The callback implementation shall

// handle the desired attributes and return an appropriate error code. If the attribute

// is not of your interest, please do not return an error code and strictly return ESP_OK.

static esp_err_t app_attribute_update_cb(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)

{

esp_err_t err = ESP_OK;



if (type == PRE_UPDATE) {

/* Driver update */

app_driver_handle_t driver_handle = (app_driver_handle_t)priv_data;

err = app_driver_attribute_update(driver_handle, endpoint_id, cluster_id, attribute_id, val);

}



return err;

}



esp_err_t app_driver_attribute_update(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val){

esp_err_t err = ESP_OK;

if(endpoint_id == light_endpoint_id) {

if(cluster_id == OnOff::Id) {

if(attribute_id == OnOff::Attributes::OnOff::Id) {

err = app_driver_light_set_power(val);

}

} else if(cluster_id == LevelControl::Id) {

if(attribute_id == LevelControl::Attributes::CurrentLevel::Id) {

err = app_driver_light_set_brightness(val);

}

}else if(cluster_id == ColorControl::Id) {

if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {

err = app_driver_light_set_hue(val);

}else if(attribute_id == ColorControl::Attributes::CurrentSaturation::Id){

err = app_driver_light_set_saturation(val);

} else if (attribute_id == ColorControl::Attributes::ColorTemperature::Id){

err = app_driver_light_set_temperature(val);

}

}

}

return err;

}



extern "C" void app_main()

{

esp_err_t err = ESP_OK;



/* Initialize the ESP NVS layer */

nvs_flash_init();



/* Initialize driver */

app_driver_handle_t light_handle = app_driver_light_init();

app_driver_handle_t button_handle = app_driver_button_init();

app_reset_button_register(button_handle);



/* Create a Matter node and add the mandatory Root Node device type on endpoint 0 */

node::config_t node_config;



// node handle can be used to add/modify other endpoints.

node_t *node = node::create(&node_config, app_attribute_update_cb, app_identification_cb);

ABORT_APP_ON_FAILURE(node != nullptr, ESP_LOGE(TAG, "Failed to create Matter node"));



/*extended_color_light::config_t light_config;

light_config.on_off.on_off = DEFAULT_POWER;

light_config.on_off.lighting.start_up_on_off = nullptr;

light_config.level_control.current_level = DEFAULT_BRIGHTNESS;

light_config.level_control.on_level = DEFAULT_BRIGHTNESS;

light_config.level_control.lighting.start_up_current_level = DEFAULT_BRIGHTNESS;

light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;

light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;

light_config.color_control.color_temperature.startup_color_temperature_mireds = nullptr;

*/

color_temperature_light::config_t light_config;

light_config.on_off.on_off = DEFAULT_POWER;

light_config.level_control.current_level = DEFAULT_BRIGHTNESS;

endpoint_t *endpoint = color_temperature_light::create(node, &light_config, ENDPOINT_FLAG_NONE);



// endpoint handles can be used to add/modify clusters.

endpoint_t *endpoint = extended_color_light::create(node, &light_config, ENDPOINT_FLAG_NONE, light_handle);

ABORT_APP_ON_FAILURE(endpoint != nullptr, ESP_LOGE(TAG, "Failed to create extended color light endpoint"));



light_endpoint_id = endpoint::get_id(endpoint);

ESP_LOGI(TAG, "Light created with endpoint_id %d", light_endpoint_id);



/* Mark deferred persistence for some attributes that might be changed rapidly */

attribute_t *current_level_attribute = attribute::get(light_endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id);

attribute::set_deferred_persistence(current_level_attribute);



attribute_t *current_x_attribute = attribute::get(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentX::Id);

attribute::set_deferred_persistence(current_x_attribute);

attribute_t *current_y_attribute = attribute::get(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentY::Id);

attribute::set_deferred_persistence(current_y_attribute);

attribute_t *color_temp_attribute = attribute::get(light_endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id);

attribute::set_deferred_persistence(color_temp_attribute);



#if CHIP_DEVICE_CONFIG_ENABLE_THREAD && CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION

// Enable secondary network interface

secondary_network_interface::config_t secondary_network_interface_config;

endpoint = endpoint::secondary_network_interface::create(node, &secondary_network_interface_config, ENDPOINT_FLAG_NONE, nullptr);

ABORT_APP_ON_FAILURE(endpoint != nullptr, ESP_LOGE(TAG, "Failed to create secondary network interface endpoint"));

#endif





#if CHIP_DEVICE_CONFIG_ENABLE_THREAD

/* Set OpenThread platform config */

esp_openthread_platform_config_t config = {

.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),

.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),

.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),

};

set_openthread_platform_config(&config);

#endif



#ifdef CONFIG_ENABLE_SET_CERT_DECLARATION_API

auto * dac_provider = get_dac_provider();

#ifdef CONFIG_SEC_CERT_DAC_PROVIDER

static_cast<ESP32SecureCertDACProvider *>(dac_provider)->SetCertificationDeclaration(cdSpan);

#elif defined(CONFIG_FACTORY_PARTITION_DAC_PROVIDER)

static_cast<ESP32FactoryDataProvider *>(dac_provider)->SetCertificationDeclaration(cdSpan);

#endif

#endif // CONFIG_ENABLE_SET_CERT_DECLARATION_API



/* Matter start */

err = esp_matter::start(app_event_cb);

ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to start Matter, err:%d", err));



/* Starting driver with default values */

app_driver_light_set_defaults(light_endpoint_id);



#if CONFIG_ENABLE_ENCRYPTED_OTA

err = esp_matter_ota_requestor_encrypted_init(s_decryption_key, s_decryption_key_len);

ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to initialized the encrypted OTA, err: %d", err));

#endif // CONFIG_ENABLE_ENCRYPTED_OTA



#if CONFIG_ENABLE_CHIP_SHELL

esp_matter::console::diagnostics_register_commands();

esp_matter::console::wifi_register_commands();

esp_matter::console::factoryreset_register_commands();

#if CONFIG_OPENTHREAD_CLI

esp_matter::console::otcli_register_commands();

#endif

esp_matter::console::init();

#endif

}

app_driver.cpp

/*

This example code is in the Public Domain (or CC0 licensed, at your option.)



Unless required by applicable law or agreed to in writing, this

software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR

CONDITIONS OF ANY KIND, either express or implied.

*/



#include <esp_log.h>

#include <stdlib.h>

#include <string.h>



#include <esp_matter.h>

#include "bsp/esp-bsp.h"



#include <app_priv.h>



using namespace chip::app::Clusters;

using namespace esp_matter;



static const char *TAG = "app_driver";

extern uint16_t light_endpoint_id;



/* Do any conversions/remapping for the actual value here */

static esp_err_t app_driver_light_set_power(led_indicator_handle_t handle, esp_matter_attr_val_t *val)

{

#if CONFIG_BSP_LEDS_NUM > 0

esp_err_t err = ESP_OK;

if (val->val.b) {

err = led_indicator_start(handle, BSP_LED_ON);

} else {

err = led_indicator_start(handle, BSP_LED_OFF);

}

return err;

#else

ESP_LOGI(TAG, "LED set power: %d", val->val.b);

return ESP_OK;

#endif

}



static esp_err_t app_driver_light_set_brightness(led_indicator_handle_t handle, esp_matter_attr_val_t *val)

{

int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS);

#if CONFIG_BSP_LEDS_NUM > 0

return led_indicator_set_brightness(handle, value);

#else

ESP_LOGI(TAG, "LED set brightness: %d", value);

return ESP_OK;

#endif

}



static esp_err_t app_driver_light_set_hue(led_indicator_handle_t handle, esp_matter_attr_val_t *val)

{

int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE);

#if CONFIG_BSP_LEDS_NUM > 0

led_indicator_ihsv_t hsv;

hsv.value = led_indicator_get_hsv(handle);

hsv.h = value;

return led_indicator_set_hsv(handle, hsv.value);

#else

ESP_LOGI(TAG, "LED set hue: %d", value);

return ESP_OK;

#endif

}



static esp_err_t app_driver_light_set_saturation(led_indicator_handle_t handle, esp_matter_attr_val_t *val)

{

int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION);

#if CONFIG_BSP_LEDS_NUM > 0

led_indicator_ihsv_t hsv;

hsv.value = led_indicator_get_hsv(handle);

hsv.s = value;

return led_indicator_set_hsv(handle, hsv.value);

#else

ESP_LOGI(TAG, "LED set saturation: %d", value);

return ESP_OK;

#endif

}



static esp_err_t app_driver_light_set_temperature(led_indicator_handle_t handle, esp_matter_attr_val_t *val)

{

uint32_t value = REMAP_TO_RANGE_INVERSE(val->val.u16, STANDARD_TEMPERATURE_FACTOR);

#if CONFIG_BSP_LEDS_NUM > 0

return led_indicator_set_color_temperature(handle, value);

#else

ESP_LOGI(TAG, "LED set temperature: %ld", value);

return ESP_OK;

#endif

}



static void app_driver_button_toggle_cb(void *arg, void *data)

{

ESP_LOGI(TAG, "Toggle button pressed");

uint16_t endpoint_id = light_endpoint_id;

uint32_t cluster_id = OnOff::Id;

uint32_t attribute_id = OnOff::Attributes::OnOff::Id;



attribute_t *attribute = attribute::get(endpoint_id, cluster_id, attribute_id);



esp_matter_attr_val_t val = esp_matter_invalid(NULL);

attribute::get_val(attribute, &val);

val.val.b = !val.val.b;

attribute::update(endpoint_id, cluster_id, attribute_id, &val);

}



esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,

uint32_t attribute_id, esp_matter_attr_val_t *val)

{

esp_err_t err = ESP_OK;

if (endpoint_id == light_endpoint_id) {

led_indicator_handle_t handle = (led_indicator_handle_t)driver_handle;

if (cluster_id == OnOff::Id) {

if (attribute_id == OnOff::Attributes::OnOff::Id) {

err = app_driver_light_set_power(handle, val);

}

} else if (cluster_id == LevelControl::Id) {

if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {

err = app_driver_light_set_brightness(handle, val);

}

} else if (cluster_id == ColorControl::Id) {

if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {

err = app_driver_light_set_hue(handle, val);

} else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) {

err = app_driver_light_set_saturation(handle, val);

} else if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) {

err = app_driver_light_set_temperature(handle, val);

}

}

}

return err;

}



esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id)

{

esp_err_t err = ESP_OK;

void *priv_data = endpoint::get_priv_data(endpoint_id);

led_indicator_handle_t handle = (led_indicator_handle_t)priv_data;

esp_matter_attr_val_t val = esp_matter_invalid(NULL);



/* Setting brightness */

attribute_t *attribute = attribute::get(endpoint_id, LevelControl::Id, LevelControl::Attributes::CurrentLevel::Id);

attribute::get_val(attribute, &val);

err |= app_driver_light_set_brightness(handle, &val);



/* Setting color */

attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorMode::Id);

attribute::get_val(attribute, &val);

if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation) {

/* Setting hue */

attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentHue::Id);

attribute::get_val(attribute, &val);

err |= app_driver_light_set_hue(handle, &val);

/* Setting saturation */

attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::CurrentSaturation::Id);

attribute::get_val(attribute, &val);

err |= app_driver_light_set_saturation(handle, &val);

} else if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kColorTemperature) {

/* Setting temperature */

attribute = attribute::get(endpoint_id, ColorControl::Id, ColorControl::Attributes::ColorTemperatureMireds::Id);

attribute::get_val(attribute, &val);

err |= app_driver_light_set_temperature(handle, &val);

} else {

ESP_LOGE(TAG, "Color mode not supported");

}



/* Setting power */

attribute = attribute::get(endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id);

attribute::get_val(attribute, &val);

err |= app_driver_light_set_power(handle, &val);



return err;

}



app_driver_handle_t app_driver_light_init()

{

#if CONFIG_BSP_LEDS_NUM > 0

/* Initialize led */

led_indicator_handle_t leds[CONFIG_BSP_LEDS_NUM];

ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, CONFIG_BSP_LEDS_NUM));

led_indicator_set_hsv(leds[0], SET_HSV(DEFAULT_HUE, DEFAULT_SATURATION, DEFAULT_BRIGHTNESS));


return (app_driver_handle_t)leds[0];

#else

return NULL;

#endif

}



app_driver_handle_t app_driver_button_init()

{

/* Initialize button */

button_handle_t btns[BSP_BUTTON_NUM];

ESP_ERROR_CHECK(bsp_iot_button_create(btns, NULL, BSP_BUTTON_NUM));

ESP_ERROR_CHECK(iot_button_register_cb(btns[0], BUTTON_PRESS_DOWN, app_driver_button_toggle_cb, NULL));


return (app_driver_handle_t)btns[0];

}



esp_err_t app_driver_init(){

ESP_LOGI(TAG, "Initialising driver");



/*init btm*/

button_config_t button_config = button_driver_get_config();

button_handle_t handle = iot_button_create (&button_config);

iot_button_register_cb(handle, BUTTON_PRESS_DOWN, app_driver_button_toggle_cb);

app_reset_button_register(handle);



/*init led*/

led_driver_config_t led_config = led_driver_get_config();

led_driver_init(&led_config);



app_driver_attribute_set_defaults();

return ESP_OK;

}

@jonsmirl
Copy link
Contributor

Don't make custom clusters, they take too long and you will never finish in time.

Just map the existing light bulb app to control the motors and displays. Make 12 light bulb devices if you need to. That will work fine in GoogleHome. Start from the light bulb example. Make 12 bulbs instead of just one. Give them names so that you know what they do. Then modify the LED driver code to control your stepper or display. You will be able to finish that in a reasonable of time for a class.

@ravencarcass
Copy link
Author

Well,
I also thought that, because otherwise I can't test it with the google home app. I was working on it but unfortunately don't understand a lot about how to convert the programme to my application. This is because I am used to a different programming structure and environment. Could you by any chance inform me a bit more about the programming structure. I don't understand a few things and have been working on it all week but don't see much progress. I also try to understand the information of espressif but still have a few questions.

I have also created smaller partition programs in which I programme all output separately. So it is only the implementation in the example that stops me.

@jonsmirl
Copy link
Contributor

Make 12 endpoints here instead of just one

https://github.com/espressif/esp-matter/blob/main/examples/light/main/app_main.cpp#L183

@ravencarcass
Copy link
Author

ravencarcass commented Feb 28, 2025

I have currently done this which might work if I also use a slider for changing the display content. Which makes the application rate higher. Do I now need to change the attributes and the app_attribute_update_cb? Because those two where not very clear to me.

   dimmable_light::config_t motor_horizontal;
   light_config.level_control.current_level = DEFAULT_BRIGHTNESS;
   light_config.level_control.on_level = DEFAULT_BRIGHTNESS;
   light_config.level_control.lighting.start_up_current_level = DEFAULT_BRIGHTNESS;
   
   dimmable_light::config_t motor_vertical;
   light_config.level_control.current_level = DEFAULT_BRIGHTNESS;
   light_config.level_control.on_level = DEFAULT_BRIGHTNESS;
   light_config.level_control.lighting.start_up_current_level = DEFAULT_BRIGHTNESS;
   
   dimmable_light::config_t  display_content;
   light_config.level_control.current_level = DEFAULT_BRIGHTNESS;
   light_config.level_control.on_level = DEFAULT_BRIGHTNESS;
   light_config.level_control.lighting.start_up_current_level = DEFAULT_BRIGHTNESS;


//endpoints
   endpoint_t *mot_hor = motor_horizontal::create(node, &light_config, ENDPOINT_FLAG_NONE, light_handle);
   ABORT_APP_ON_FAILURE(mot_hor != nullptr, ESP_LOGE(TAG, "Failed to create horizontal motor endpoint"));
   
   mot_hor_endpoint_id = endpoint::get_id(mot_hor);
   ESP_LOGI(TAG, "motor horizontal created with mot_hor_endpoint_id %d", mot_hor_endpoint_id );


   endpoint_t *mot_ver = motor_vertical::create(node, &light_config, ENDPOINT_FLAG_NONE, light_handle);
   ABORT_APP_ON_FAILURE(mot_ver != nullptr, ESP_LOGE(TAG, "Failed to create vertical motor endpoint"));
   
   mot_ver_endpoint_id = endpoint::get_id(mot_ver);
   ESP_LOGI(TAG, "motor vertical created with mot_ver_endpoint_id %d", mot_ver_endpoint_id );


   endpoint_t *disp = display_content::create(node, &light_config, ENDPOINT_FLAG_NONE, light_handle);
   ABORT_APP_ON_FAILURE(disp != nullptr, ESP_LOGE(TAG, "Failed to create display content endpoint"));

   disp_endpoint_id = endpoint::get_id(disp);
   ESP_LOGI(TAG, "disp created with disp_endpoint_id %d", disp_endpoint_id );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants