diff --git a/CHANGES.md b/CHANGES.md index 0d953d8f9..fe320b21e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,7 +26,7 @@ There is now just one attribute update callback which calls the other callbacks The application receives this callback twice, once before updating the value in the data model (pre_attribute) and once after updating the value (post_attribute). ``` -esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val, void *priv_data); +esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val, void *priv_data); ``` The app_driver component has been moved to the application itself and it now uses the endpoint_id, @@ -34,7 +34,7 @@ cluster_id, attribute_id for setting/getting the values. The application calls t for drivers first when it gets the pre_attribute callback. If this returns success, i.e. ESP_OK, only then the data model value is updated and the application receives the post_attribute callback. ``` -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); ``` The rainmaker example creates its data model dynamically based on the ESP Matter data model. New @@ -45,7 +45,7 @@ callback. /* Create a device and add the relevant parameters to it */ app_rainmaker_device_create(); -esp_err_t app_rainmaker_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t app_rainmaker_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); ``` Non-mandatory endpoints, clusters, attributes or commands can also be easily added by using the diff --git a/components/esp_matter/CMakeLists.txt b/components/esp_matter/CMakeLists.txt index 3ddeeccbb..f10468f6b 100644 --- a/components/esp_matter/CMakeLists.txt +++ b/components/esp_matter/CMakeLists.txt @@ -67,7 +67,7 @@ set(INCLUDE_DIRS_LIST "." "${MATTER_SDK_PATH}/src" "${ZAP_GENERATED_PATH}/../") -set(REQUIRES_LIST chip bt) +set(REQUIRES_LIST chip bt esp_matter_console) if ("${IDF_TARGET}" STREQUAL "esp32h2") list(APPEND REQUIRES_LIST openthread esp_matter_openthread) diff --git a/components/esp_matter/esp_matter_attribute.cpp b/components/esp_matter/esp_matter_attribute.cpp index ad4508c4d..063bef743 100644 --- a/components/esp_matter/esp_matter_attribute.cpp +++ b/components/esp_matter/esp_matter_attribute.cpp @@ -13,7 +13,9 @@ // limitations under the License. #include +#include #include +#include #include #include @@ -25,11 +27,168 @@ using chip::ClusterId; using chip::EndpointId; using chip::Protocols::InteractionModel::Status; -static const char *TAG = "esp_matter"; +static const char *TAG = "esp_matter_attribute"; static esp_matter_attribute_callback_t attribute_callback = NULL; static void *attribute_callback_priv_data = NULL; +static esp_matter_val_type_t get_val_type_from_attribute_type(int attribute_type); + +static esp_err_t esp_matter_attribute_console_handler(int argc, char **argv) +{ + if (argc == 5 && strncmp(argv[0], "set", sizeof("set")) == 0) { + int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); + int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); + int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); + + /* Get type from matter_attribute */ + EmberAfAttributeMetadata *matter_attribute = NULL; + EmberAfAttributeSearchRecord record = { + .endpoint = (EndpointId)endpoint_id, + .clusterId = (ClusterId)cluster_id, + .clusterMask = ESP_MATTER_CLUSTER_FLAG_SERVER, + .attributeId = (AttributeId)attribute_id, + }; + emAfReadOrWriteAttribute(&record, &matter_attribute, NULL, 0, false); + if (!matter_attribute) { + ESP_LOGE(TAG, "Matter attribute not found"); + return ESP_ERR_INVALID_ARG; + } + + /* Use the type to create the val and then update te attribute */ + esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + bool value = atoi(argv[4]); + val = esp_matter_bool(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT8) { + int8_t value = atoi(argv[4]); + val = esp_matter_int8(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { + uint8_t value = atoi(argv[4]); + val = esp_matter_uint8(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT16) { + int16_t value = atoi(argv[4]); + val = esp_matter_int16(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { + uint16_t value = atoi(argv[4]); + val = esp_matter_uint16(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { + uint32_t value = atoi(argv[4]); + val = esp_matter_uint32(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { + uint64_t value = atoi(argv[4]); + val = esp_matter_uint64(value); + } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { + char *value = argv[4]; + val = esp_matter_char_str(value, strlen(value)); + } else { + ESP_LOGE(TAG, "Type not handled: %d", type); + return ESP_ERR_INVALID_ARG; + } + esp_matter_attribute_update(endpoint_id, cluster_id, attribute_id, &val); + } else if (argc == 4 && strncmp(argv[0], "get", sizeof("get")) == 0) { + int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); + int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); + int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); + + /* Directly print if esp matter data model is used */ + esp_matter_node_t *node = esp_matter_node_get(); + if (node) { + esp_matter_endpoint_t *endpoint = esp_matter_endpoint_get(node, endpoint_id); + esp_matter_cluster_t *cluster = esp_matter_cluster_get(endpoint, cluster_id); + esp_matter_attribute_t *attribute = esp_matter_attribute_get(cluster, attribute_id); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + esp_matter_attribute_get_val(attribute, &val); + esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, &val); + return ESP_OK; + } + + /* Get type from matter_attribute if esp matter data model is not used */ + EmberAfAttributeMetadata *matter_attribute = NULL; + EmberAfAttributeSearchRecord record = { + .endpoint = (EndpointId)endpoint_id, + .clusterId = (ClusterId)cluster_id, + .clusterMask = ESP_MATTER_CLUSTER_FLAG_SERVER, + .attributeId = (AttributeId)attribute_id, + }; + emAfReadOrWriteAttribute(&record, &matter_attribute, NULL, 0, false); + if (!matter_attribute) { + ESP_LOGE(TAG, "Matter attribute not found"); + return ESP_ERR_INVALID_ARG; + } + + /* Use the type to read the raw value and then print if esp matter data model is not used */ + esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + bool value = false; + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_bool(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT8) { + int8_t value = 0; + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_int8(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { + uint8_t value = 0; + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint8(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT16) { + int16_t value = 0; + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_int16(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { + uint16_t value = 0; + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint16(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { + uint32_t value = 0; + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint32(value); + } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { + uint64_t value = 0; + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + val = esp_matter_uint64(value); + } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { + /* Get raw value */ + char value[256] = {0}; /* It can go upto 256 since only 1 byte (first) is used for size */ + esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + /* Get val from raw value */ + val = esp_matter_char_str(NULL, 0); + int data_size_len = val.val.a.t - val.val.a.s; + int data_count = 0; + memcpy(&data_count, &value[0], data_size_len); + val = esp_matter_char_str((char *)(value + data_size_len), data_count); + } else { + ESP_LOGE(TAG, "Type not handled: %d", type); + return ESP_ERR_INVALID_ARG; + } + esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, &val); + } else { + ESP_LOGE(TAG, "Incorrect arguments"); + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + +static void esp_matter_attribute_register_commands() +{ + static bool init_done = false; + if (init_done) { + return; + } + esp_matter_console_command_t command = { + .name = "attribute", + .description = "This can be used to simulate on-device control. " + "Usage: matter esp attribute [value]. " + "Example1: matter esp attribute set 0x0001 0x0006 0x0000 1. " + "Example2: matter esp attribute get 0x0001 0x0006 0x0000.", + .handler = esp_matter_attribute_console_handler, + }; + esp_matter_console_add_command(&command); + init_done = true; +} + esp_matter_attr_val_t esp_matter_invalid(void *val) { esp_matter_attr_val_t attr_val = { @@ -74,39 +233,6 @@ esp_matter_attr_val_t esp_matter_float(float val) return attr_val; } -esp_matter_attr_val_t esp_matter_str(const char *val) -{ - esp_matter_attr_val_t attr_val = { - .type = ESP_MATTER_VAL_TYPE_STRING, - .val = { - .s = (char *)val, - }, - }; - return attr_val; -} - -esp_matter_attr_val_t esp_matter_json_obj(const char *val) -{ - esp_matter_attr_val_t attr_val = { - .type = ESP_MATTER_VAL_TYPE_JSON_OBJECT, - .val = { - .s = (char *)val, - }, - }; - return attr_val; -} - -esp_matter_attr_val_t esp_matter_json_array(const char *val) -{ - esp_matter_attr_val_t attr_val = { - .type = ESP_MATTER_VAL_TYPE_JSON_ARRAY, - .val = { - .s = (char *)val, - }, - }; - return attr_val; -} - esp_matter_attr_val_t esp_matter_int8(int8_t val) { esp_matter_attr_val_t attr_val = { @@ -217,51 +343,127 @@ esp_matter_attr_val_t esp_matter_bitmap32(uint32_t val) return attr_val; } -esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t total_size) +esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t data_size) { + uint16_t data_size_len = 1; /* Number of bytes used to store the length */ esp_matter_attr_val_t attr_val = { .type = ESP_MATTER_VAL_TYPE_CHAR_STRING, .val = { .a = { .b = (uint8_t *)val, - .s = total_size, - .n = 0, + .s = data_size, + .n = data_size, + .t = (uint16_t)(data_size + data_size_len), }, }, }; return attr_val; } -esp_matter_attr_val_t esp_matter_octet_str(uint8_t *val, uint16_t total_size, uint16_t count) +esp_matter_attr_val_t esp_matter_octet_str(uint8_t *val, uint16_t data_size) { + uint16_t data_size_len = 1; /* Number of bytes used to store the length */ esp_matter_attr_val_t attr_val = { .type = ESP_MATTER_VAL_TYPE_OCTET_STRING, .val = { .a = { .b = val, - .s = total_size, - .n = count, + .s = data_size, + .n = data_size, + .t = (uint16_t)(data_size + data_size_len), }, }, }; return attr_val; } -esp_matter_attr_val_t esp_matter_array(uint8_t *val, uint16_t total_size, uint16_t count) +esp_matter_attr_val_t esp_matter_array(uint8_t *val, uint16_t data_size, uint16_t count) { + uint16_t data_size_len = 2; /* Number of bytes used to store the length */ esp_matter_attr_val_t attr_val = { .type = ESP_MATTER_VAL_TYPE_ARRAY, .val = { .a = { .b = val, - .s = total_size, + .s = data_size, .n = count, + .t = (uint16_t)(data_size + data_size_len), }, }, }; return attr_val; } +static esp_matter_val_type_t get_val_type_from_attribute_type(int attribute_type) +{ + switch(attribute_type) { + case ZCL_BOOLEAN_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_BOOLEAN; + break; + + case ZCL_SINGLE_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_FLOAT; + break; + + case ZCL_ARRAY_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_ARRAY; + break; + + case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_CHAR_STRING; + break; + + case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_OCTET_STRING; + break; + + case ZCL_INT8S_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_INT8; + break; + + case ZCL_INT8U_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_UINT8; + break; + + case ZCL_INT16S_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_INT16; + break; + + case ZCL_INT16U_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_UINT16; + break; + + case ZCL_INT32U_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_UINT32; + break; + + case ZCL_INT64U_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_UINT64; + break; + + case ZCL_ENUM8_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_ENUM8; + break; + + case ZCL_BITMAP8_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_BITMAP8; + break; + + case ZCL_BITMAP16_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_BITMAP16; + break; + + case ZCL_BITMAP32_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_BITMAP32; + break; + + default: + return ESP_MATTER_VAL_TYPE_INVALID; + break; + } + return ESP_MATTER_VAL_TYPE_INVALID; +} + esp_err_t esp_matter_attribute_get_type_and_val_default(esp_matter_attr_val_t *val, EmberAfAttributeType *attribute_type, uint16_t *attribute_size, EmberAfDefaultOrMinMaxAttributeValue *default_value) @@ -285,16 +487,6 @@ esp_err_t esp_matter_attribute_get_type_and_val_default(esp_matter_attr_val_t *v *default_value = (uint8_t *)&val->val.f; break; - case ESP_MATTER_VAL_TYPE_STRING: - *attribute_type = ZCL_CHAR_STRING_ATTRIBUTE_TYPE; - if (val->val.s) { - *attribute_size = strlen(val->val.s); - } else { - *attribute_size = 0; - } - *default_value = (uint8_t *)val->val.s; - break; - case ESP_MATTER_VAL_TYPE_ARRAY: *attribute_type = ZCL_ARRAY_ATTRIBUTE_TYPE; *attribute_size = val->val.a.s; @@ -385,48 +577,72 @@ esp_err_t esp_matter_attribute_get_type_and_val_default(esp_matter_attr_val_t *v return ESP_OK; } -static esp_err_t esp_matter_attribute_get_type_and_val(esp_matter_attr_val_t *val, EmberAfAttributeType *attribute_type, - uint16_t *attribute_size, uint8_t **value) +static esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeType *attribute_type, + uint16_t *attribute_size, uint8_t *value) { switch (val->type) { case ESP_MATTER_VAL_TYPE_BOOLEAN: - *attribute_type = ZCL_BOOLEAN_ATTRIBUTE_TYPE; - *attribute_size = sizeof(bool); - *value = (uint8_t *)&val->val.b; + if (attribute_type) { + *attribute_type = ZCL_BOOLEAN_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(bool); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.b, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_INTEGER: - *attribute_type = ZCL_INT16U_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint16_t); - *value = (uint8_t *)&val->val.i; + if (attribute_type) { + *attribute_type = ZCL_INT16U_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint16_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.i, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_FLOAT: - *attribute_type = ZCL_SINGLE_ATTRIBUTE_TYPE; - *attribute_size = sizeof(float); - *value = (uint8_t *)&val->val.f; - break; - - case ESP_MATTER_VAL_TYPE_STRING: - *attribute_type = ZCL_CHAR_STRING_ATTRIBUTE_TYPE; - if (val->val.s) { - *attribute_size = strlen(val->val.s); - } else { - *attribute_size = 0; + if (attribute_type) { + *attribute_type = ZCL_SINGLE_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(float); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.f, *attribute_size); } - *value = (uint8_t *)val->val.s; break; case ESP_MATTER_VAL_TYPE_ARRAY: - *attribute_type = ZCL_ARRAY_ATTRIBUTE_TYPE; - *attribute_size = val->val.a.s; - *value = (uint8_t *)val->val.a.b; + if (attribute_type) { + *attribute_type = ZCL_ARRAY_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = val->val.a.t; + } + if (value) { + int data_size_len = val->val.a.t - val->val.a.s; + memcpy(value, (uint8_t *)&val->val.a.s, data_size_len); + memcpy((value + data_size_len), (uint8_t *)val->val.a.b, (*attribute_size - data_size_len)); + } break; case ESP_MATTER_VAL_TYPE_CHAR_STRING: - *attribute_type = ZCL_CHAR_STRING_ATTRIBUTE_TYPE; - *attribute_size = val->val.a.s; - *value = (uint8_t *)val->val.a.b; + if (attribute_type) { + *attribute_type = ZCL_CHAR_STRING_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = val->val.a.t; + } + if (value) { + int data_size_len = val->val.a.t - val->val.a.s; + memcpy(value, (uint8_t *)&val->val.a.s, data_size_len); + memcpy((value + data_size_len), (uint8_t *)val->val.a.b, (*attribute_size - data_size_len)); + } break; case ESP_MATTER_VAL_TYPE_BYTE_STRING: @@ -434,69 +650,137 @@ static esp_err_t esp_matter_attribute_get_type_and_val(esp_matter_attr_val_t *va break; case ESP_MATTER_VAL_TYPE_OCTET_STRING: - *attribute_type = ZCL_OCTET_STRING_ATTRIBUTE_TYPE; - *attribute_size = val->val.a.s; - *value = (uint8_t *)val->val.a.b; + if (attribute_type) { + *attribute_type = ZCL_OCTET_STRING_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = val->val.a.t; + } + if (value) { + int data_size_len = val->val.a.t - val->val.a.s; + memcpy(value, (uint8_t *)&val->val.a.s, data_size_len); + memcpy((value + data_size_len), (uint8_t *)val->val.a.b, (*attribute_size - data_size_len)); + } break; case ESP_MATTER_VAL_TYPE_INT8: - *attribute_type = ZCL_INT8S_ATTRIBUTE_TYPE; - *attribute_size = sizeof(int8_t); - *value = (uint8_t *)&val->val.i8; + if (attribute_type) { + *attribute_type = ZCL_INT8S_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(int8_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.i8, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_UINT8: - *attribute_type = ZCL_INT8U_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint8_t); - *value = (uint8_t *)&val->val.u8; + if (attribute_type) { + *attribute_type = ZCL_INT8U_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint8_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u8, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_INT16: - *attribute_type = ZCL_INT16S_ATTRIBUTE_TYPE; - *attribute_size = sizeof(int16_t); - *value = (uint8_t *)&val->val.i16; + if (attribute_type) { + *attribute_type = ZCL_INT16S_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(int16_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.i16, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_UINT16: - *attribute_type = ZCL_INT16U_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint16_t); - *value = (uint8_t *)&val->val.u16; + if (attribute_type) { + *attribute_type = ZCL_INT16U_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint16_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u16, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_UINT32: - *attribute_type = ZCL_INT32U_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint32_t); - *value = (uint8_t *)&val->val.u32; + if (attribute_type) { + *attribute_type = ZCL_INT32U_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint32_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u32, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_UINT64: - *attribute_type = ZCL_INT64U_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint64_t); - *value = (uint8_t *)&val->val.u64; + if (attribute_type) { + *attribute_type = ZCL_INT64U_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint64_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u64, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_ENUM8: - *attribute_type = ZCL_ENUM8_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint8_t); - *value = (uint8_t *)&val->val.u8; + if (attribute_type) { + *attribute_type = ZCL_ENUM8_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint8_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u8, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_BITMAP8: - *attribute_type = ZCL_BITMAP8_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint8_t); - *value = (uint8_t *)&val->val.u8; + if (attribute_type) { + *attribute_type = ZCL_BITMAP8_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint8_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u8, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_BITMAP16: - *attribute_type = ZCL_BITMAP16_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint16_t); - *value = (uint8_t *)&val->val.u16; + if (attribute_type) { + *attribute_type = ZCL_BITMAP16_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint16_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u16, *attribute_size); + } break; case ESP_MATTER_VAL_TYPE_BITMAP32: - *attribute_type = ZCL_BITMAP32_ATTRIBUTE_TYPE; - *attribute_size = sizeof(uint32_t); - *value = (uint8_t *)&val->val.u32; + if (attribute_type) { + *attribute_type = ZCL_BITMAP32_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(uint32_t); + } + if (value) { + memcpy(value, (uint8_t *)&val->val.u32, *attribute_size); + } break; default: @@ -507,101 +791,160 @@ static esp_err_t esp_matter_attribute_get_type_and_val(esp_matter_attr_val_t *va return ESP_OK; } -static esp_matter_attr_val_t esp_matter_attribute_get_attr_val(EmberAfAttributeType attribute_type, - uint16_t attribute_size, uint8_t *value) +static esp_err_t get_attr_val_from_data(esp_matter_attr_val_t *val, EmberAfAttributeType attribute_type, + uint16_t attribute_size, uint8_t *value) { switch (attribute_type) { case ZCL_BOOLEAN_ATTRIBUTE_TYPE: - return esp_matter_bool((bool)*value); - break; - - case ZCL_ARRAY_ATTRIBUTE_TYPE: - return esp_matter_array(value, attribute_size, (uint16_t)value[0]); - break; - - case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: - return esp_matter_char_str((char *)&value[1], value[0]); - break; - - case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: - return esp_matter_octet_str(value, attribute_size, (uint16_t)value[0]); - break; - - case ZCL_INT8S_ATTRIBUTE_TYPE: - return esp_matter_int8((int8_t)*value); - break; - - case ZCL_INT8U_ATTRIBUTE_TYPE: - return esp_matter_uint8((uint8_t)*value); - break; - - case ZCL_INT16S_ATTRIBUTE_TYPE: - return esp_matter_int16((int16_t)*value); - break; - - case ZCL_INT16U_ATTRIBUTE_TYPE: - return esp_matter_uint16((uint16_t)*value); - break; - - case ZCL_INT32U_ATTRIBUTE_TYPE: - return esp_matter_uint32((uint32_t)*value); - break; - - case ZCL_INT64U_ATTRIBUTE_TYPE: - return esp_matter_uint64((uint64_t)*value); - break; - - case ZCL_ENUM8_ATTRIBUTE_TYPE: - return esp_matter_enum8((uint8_t)*value); - break; - - case ZCL_BITMAP8_ATTRIBUTE_TYPE: - return esp_matter_bitmap8((uint8_t)*value); - break; - - case ZCL_BITMAP16_ATTRIBUTE_TYPE: - return esp_matter_bitmap16((uint16_t)*value); - break; - - default: - return esp_matter_invalid(NULL); + { + bool attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(bool)); + *val = esp_matter_bool(attribute_value); break; } + + case ZCL_ARRAY_ATTRIBUTE_TYPE: + { + *val = esp_matter_array(NULL, 0, 0); + int data_size_len = val->val.a.t - val->val.a.s; + int data_count = 0; + memcpy(&data_count, &value[0], data_size_len); + *val = esp_matter_array((value + data_size_len), attribute_size, data_count); + break; + } + + case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: + { + *val = esp_matter_char_str(NULL, 0); + int data_size_len = val->val.a.t - val->val.a.s; + int data_count = 0; + memcpy(&data_count, &value[0], data_size_len); + *val = esp_matter_char_str((char *)(value + data_size_len), data_count); + break; + } + + case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: + { + *val = esp_matter_octet_str(NULL, 0); + int data_size_len = val->val.a.t - val->val.a.s; + int data_count = 0; + memcpy(&data_count, &value[0], data_size_len); + *val = esp_matter_octet_str((value + data_size_len), data_count); + break; + } + + case ZCL_INT8S_ATTRIBUTE_TYPE: + { + int8_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(int8_t)); + *val = esp_matter_int8(attribute_value); + break; + } + + case ZCL_INT8U_ATTRIBUTE_TYPE: + { + uint8_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(uint8_t)); + *val = esp_matter_uint8(attribute_value); + break; + } + + case ZCL_INT16S_ATTRIBUTE_TYPE: + { + int16_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(int16_t)); + *val = esp_matter_int16(attribute_value); + break; + } + + case ZCL_INT16U_ATTRIBUTE_TYPE: + { + uint16_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(uint16_t)); + *val = esp_matter_uint16(attribute_value); + break; + } + + case ZCL_INT32U_ATTRIBUTE_TYPE: + { + uint32_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(uint32_t)); + *val = esp_matter_uint32(attribute_value); + break; + } + + case ZCL_INT64U_ATTRIBUTE_TYPE: + { + uint64_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(uint64_t)); + *val = esp_matter_uint64(attribute_value); + break; + } + + case ZCL_ENUM8_ATTRIBUTE_TYPE: + { + uint8_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(uint8_t)); + *val = esp_matter_enum8(attribute_value); + break; + } + + case ZCL_BITMAP8_ATTRIBUTE_TYPE: + { + uint8_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(uint8_t)); + *val = esp_matter_bitmap8(attribute_value); + break; + } + + case ZCL_BITMAP16_ATTRIBUTE_TYPE: + { + uint16_t attribute_value = 0; + memcpy((uint8_t *)&attribute_value, value, sizeof(uint16_t)); + *val = esp_matter_bitmap16(attribute_value); + break; + } + + default: + *val = esp_matter_invalid(NULL); + break; + } + + return ESP_OK; } -void esp_matter_attribute_val_print(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +void esp_matter_attribute_val_print(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { - if (val.type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + if (val->type == ESP_MATTER_VAL_TYPE_BOOLEAN) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, - cluster_id, attribute_id, val.val.b); - } else if (val.type == ESP_MATTER_VAL_TYPE_INTEGER) { + cluster_id, attribute_id, val->val.b); + } else if (val->type == ESP_MATTER_VAL_TYPE_INTEGER) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, - cluster_id, attribute_id, val.val.i); - } else if (val.type == ESP_MATTER_VAL_TYPE_FLOAT) { + cluster_id, attribute_id, val->val.i); + } else if (val->type == ESP_MATTER_VAL_TYPE_FLOAT) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %f **********", endpoint_id, - cluster_id, attribute_id, val.val.f); - } else if (val.type == ESP_MATTER_VAL_TYPE_STRING || val.type == ESP_MATTER_VAL_TYPE_JSON_OBJECT || - val.type == ESP_MATTER_VAL_TYPE_JSON_ARRAY) { - ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %s **********", endpoint_id, - cluster_id, attribute_id, val.val.s); - } else if (val.type == ESP_MATTER_VAL_TYPE_UINT8 || val.type == ESP_MATTER_VAL_TYPE_BITMAP8) { + cluster_id, attribute_id, val->val.f); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT8 || val->type == ESP_MATTER_VAL_TYPE_BITMAP8) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, - cluster_id, attribute_id, val.val.u8); - } else if (val.type == ESP_MATTER_VAL_TYPE_INT16) { + cluster_id, attribute_id, val->val.u8); + } else if (val->type == ESP_MATTER_VAL_TYPE_INT16) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, - cluster_id, attribute_id, val.val.i16); - } else if (val.type == ESP_MATTER_VAL_TYPE_UINT16) { + cluster_id, attribute_id, val->val.i16); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT16) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, - cluster_id, attribute_id, val.val.u16); - } else if (val.type == ESP_MATTER_VAL_TYPE_UINT32) { + cluster_id, attribute_id, val->val.u16); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT32) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, - cluster_id, attribute_id, val.val.u32); - } else if (val.type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { + cluster_id, attribute_id, val->val.u32); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT64) { + ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %lld **********", endpoint_id, + cluster_id, attribute_id, val->val.u64); + } else if (val->type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %.*s **********", endpoint_id, - cluster_id, attribute_id, val.val.a.s, val.val.a.b); + cluster_id, attribute_id, val->val.a.s, val->val.a.b); } else { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is **********", - endpoint_id, cluster_id, attribute_id, val.type); + endpoint_id, cluster_id, attribute_id, val->type); } } @@ -609,6 +952,9 @@ esp_err_t esp_matter_attribute_callback_set(esp_matter_attribute_callback_t call { attribute_callback = callback; attribute_callback_priv_data = priv_data; + + /* Other initialisations */ + esp_matter_attribute_register_commands(); return ESP_OK; } @@ -617,18 +963,26 @@ esp_err_t esp_matter_attribute_get_val_raw(int endpoint_id, int cluster_id, int { EmberAfStatus status = emberAfReadServerAttribute(endpoint_id, cluster_id, attribute_id, value, attribute_size); if (status != EMBER_ZCL_STATUS_SUCCESS) { - ESP_LOGE(TAG, "Error getting raw value from matter"); + ESP_LOGE(TAG, "Error getting raw value from matter: 0x%x", status); return ESP_FAIL; } return ESP_OK; } -esp_err_t esp_matter_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +esp_err_t esp_matter_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { + /* Get size */ EmberAfAttributeType attribute_type = 0; uint16_t attribute_size = 0; - uint8_t *value = NULL; - esp_matter_attribute_get_type_and_val(&val, &attribute_type, &attribute_size, &value); + get_data_from_attr_val(val, &attribute_type, &attribute_size, NULL); + + /* Get value */ + uint8_t *value = (uint8_t *)calloc(1, attribute_size); + if (!value) { + ESP_LOGE(TAG, "Could not allocate value buffer"); + return ESP_ERR_NO_MEM; + } + get_data_from_attr_val(val, &attribute_type, &attribute_size, value); /* Update matter */ EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; @@ -636,9 +990,11 @@ esp_err_t esp_matter_attribute_update(int endpoint_id, int cluster_id, int attri status = emberAfWriteServerAttribute(endpoint_id, cluster_id, attribute_id, value, attribute_type); if (status != EMBER_ZCL_STATUS_SUCCESS) { ESP_LOGE(TAG, "Error updating attribute to matter"); + free(value); return ESP_FAIL; } } + free(value); return ESP_OK; } @@ -648,15 +1004,16 @@ Status MatterPreAttributeChangeCallback(const chip::app::ConcreteAttributePath & int endpoint_id = path.mEndpointId; int cluster_id = path.mClusterId; int attribute_id = path.mAttributeId; - esp_matter_attr_val_t val = esp_matter_attribute_get_attr_val(type, size, value); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + get_attr_val_from_data(&val, type, size, value); /* Print */ - esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, val); + esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, &val); /* Callback to application */ if (attribute_callback) { esp_err_t err = attribute_callback(ESP_MATTER_CALLBACK_TYPE_PRE_ATTRIBUTE, endpoint_id, cluster_id, - attribute_id, val, attribute_callback_priv_data); + attribute_id, &val, attribute_callback_priv_data); if (err != ESP_OK) { return Status::Failure; } @@ -670,11 +1027,12 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &p int endpoint_id = path.mEndpointId; int cluster_id = path.mClusterId; int attribute_id = path.mAttributeId; - esp_matter_attr_val_t val = esp_matter_attribute_get_attr_val(type, size, value); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + get_attr_val_from_data(&val, type, size, value); /* Callback to application */ if (attribute_callback) { - attribute_callback(ESP_MATTER_CALLBACK_TYPE_POST_ATTRIBUTE, endpoint_id, cluster_id, attribute_id, val, + attribute_callback(ESP_MATTER_CALLBACK_TYPE_POST_ATTRIBUTE, endpoint_id, cluster_id, attribute_id, &val, attribute_callback_priv_data); } } @@ -692,20 +1050,23 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint_id, Clust esp_matter_endpoint_t *endpoint = esp_matter_endpoint_get(node, endpoint_id); esp_matter_cluster_t *cluster = esp_matter_cluster_get(endpoint, cluster_id); esp_matter_attribute_t *attribute = esp_matter_attribute_get(cluster, attribute_id); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + esp_matter_attribute_get_val(attribute, &val); - /* Convert */ - EmberAfAttributeType attribute_type = 0; + /* Print */ + esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, &val); + + /* Get size */ uint16_t attribute_size = 0; - uint8_t *value = NULL; - esp_matter_attribute_get_type_and_val(&val, &attribute_type, &attribute_size, &value); - + get_data_from_attr_val(&val, NULL, &attribute_size, NULL); if (attribute_size > max_read_length) { + ESP_LOGE(TAG, "Insufficient space for reading attribute: required: %d, max: %d", attribute_size, + max_read_length); return EMBER_ZCL_STATUS_INSUFFICIENT_SPACE; } /* Assign value */ - *buffer = *value; + get_data_from_attr_val(&val, NULL, &attribute_size, buffer); return EMBER_ZCL_STATUS_SUCCESS; } @@ -721,19 +1082,14 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint_id, Clus esp_matter_endpoint_t *endpoint = esp_matter_endpoint_get(node, endpoint_id); esp_matter_cluster_t *cluster = esp_matter_cluster_get(endpoint, cluster_id); esp_matter_attribute_t *attribute = esp_matter_attribute_get(cluster, attribute_id); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - /* Convert */ - EmberAfAttributeType attribute_type = 0; - uint16_t attribute_size = 0; - uint8_t *value = NULL; - esp_matter_attribute_get_type_and_val(&val, &attribute_type, &attribute_size, &value); + /* Get val */ + /* This creates a new variable val, and stores the new attribute value in the new variable. + The value in esp-matter data model is updated only when esp_matter_attribute_set_val() is called */ + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + get_attr_val_from_data(&val, matter_attribute->attributeType, matter_attribute->size, buffer); - /* Convert back */ - value = buffer; - val = esp_matter_attribute_get_attr_val(attribute_type, attribute_size, value); - - /* Update value */ - esp_matter_attribute_set_val(attribute, val); + /* Update val */ + esp_matter_attribute_set_val(attribute, &val); return EMBER_ZCL_STATUS_SUCCESS; } diff --git a/components/esp_matter/esp_matter_attribute.h b/components/esp_matter/esp_matter_attribute.h index 96af68da0..eaf513c57 100644 --- a/components/esp_matter/esp_matter_attribute.h +++ b/components/esp_matter/esp_matter_attribute.h @@ -30,8 +30,6 @@ typedef enum { ESP_MATTER_VAL_TYPE_INTEGER, /** Floating point number */ ESP_MATTER_VAL_TYPE_FLOAT, - /** NULL terminated string */ - ESP_MATTER_VAL_TYPE_STRING, /** Array Eg. [1,2,3] */ ESP_MATTER_VAL_TYPE_ARRAY, /** Byte String Eg. "123" */ @@ -60,10 +58,6 @@ typedef enum { ESP_MATTER_VAL_TYPE_BITMAP16, /** 32 bit bitmap */ ESP_MATTER_VAL_TYPE_BITMAP32, - /** NULL terminated JSON Object string Eg. "{\"name\":\"value\"}" */ - ESP_MATTER_VAL_TYPE_JSON_OBJECT, - /** NULL terminated JSON Array string Eg. "[1,2,3]" */ - ESP_MATTER_VAL_TYPE_JSON_ARRAY, } esp_matter_val_type_t; /* ESP Matter Value */ @@ -74,8 +68,6 @@ typedef union { int i; /** Float */ float f; - /** NULL terminated string. It should stay allocated throughout the lifetime of the device. */ - char *s; /** 8 bit signed integer */ int8_t i8; /** 8 bit unsigned integer */ @@ -92,10 +84,12 @@ typedef union { struct { /** Buffer */ uint8_t *b; - /** Total size */ + /** Data size */ uint16_t s; - /** Total count */ + /** Data count */ uint16_t n; + /** Total size */ + uint16_t t; } a; /** Pointer */ void *p; @@ -122,15 +116,6 @@ esp_matter_attr_val_t esp_matter_int(int val); /** Float */ esp_matter_attr_val_t esp_matter_float(float val); -/** String */ -esp_matter_attr_val_t esp_matter_str(const char *val); - -/** JSON object string */ -esp_matter_attr_val_t esp_matter_json_obj(const char *val); - -/** JSON array string */ -esp_matter_attr_val_t esp_matter_json_array(const char *val); - /** 8 bit integer */ esp_matter_attr_val_t esp_matter_int8(int8_t val); @@ -162,22 +147,22 @@ esp_matter_attr_val_t esp_matter_bitmap16(uint16_t val); esp_matter_attr_val_t esp_matter_bitmap32(uint32_t val); /** Character string */ -esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t total_size); +esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t data_size); /** Octet string */ -esp_matter_attr_val_t esp_matter_octet_str(uint8_t *val, uint16_t total_size, uint16_t count); +esp_matter_attr_val_t esp_matter_octet_str(uint8_t *val, uint16_t data_size); /** Array */ -esp_matter_attr_val_t esp_matter_array(uint8_t *val, uint16_t total_size, uint16_t count); +esp_matter_attr_val_t esp_matter_array(uint8_t *val, uint16_t data_size, uint16_t count); /** Attribute update * * This API updates the attribute value */ -esp_err_t esp_matter_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t esp_matter_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); /** Attribute value print * * This API prints the attribute value according to the type */ -void esp_matter_attribute_val_print(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +void esp_matter_attribute_val_print(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); diff --git a/components/esp_matter/esp_matter_cluster.cpp b/components/esp_matter/esp_matter_cluster.cpp index bfd1cbdc3..1c6cd20a7 100644 --- a/components/esp_matter/esp_matter_cluster.cpp +++ b/components/esp_matter/esp_matter_cluster.cpp @@ -358,7 +358,7 @@ esp_matter_cluster_t *esp_matter_cluster_create_ota_requestor(esp_matter_endpoin esp_matter_uint16(config->cluster_revision)); esp_matter_attribute_create(cluster, ZCL_DEFAULT_OTA_PROVIDERS_ATTRIBUTE_ID, ESP_MATTER_ATTRIBUTE_FLAG_NONE, esp_matter_octet_str(config->default_ota_providers, - sizeof(config->default_ota_providers), 0)); + sizeof(config->default_ota_providers))); esp_matter_attribute_create(cluster, ZCL_UPDATE_POSSIBLE_ATTRIBUTE_ID, ESP_MATTER_ATTRIBUTE_FLAG_NONE, esp_matter_bool(config->update_possible)); esp_matter_attribute_create(cluster, ZCL_UPDATE_STATE_ATTRIBUTE_ID, ESP_MATTER_ATTRIBUTE_FLAG_NONE, @@ -448,7 +448,7 @@ esp_matter_cluster_t *esp_matter_cluster_create_network_commissioning(esp_matter esp_matter_attribute_create(cluster, ZCL_LAST_NETWORKING_STATUS_ATTRIBUTE_ID, ESP_MATTER_ATTRIBUTE_FLAG_NONE, esp_matter_enum8(config->last_networking_status)); esp_matter_attribute_create(cluster, ZCL_LAST_NETWORK_ID_ATTRIBUTE_ID, ESP_MATTER_ATTRIBUTE_FLAG_NONE, - esp_matter_octet_str(config->last_network_id, sizeof(config->last_network_id), 0)); + esp_matter_octet_str(config->last_network_id, sizeof(config->last_network_id))); esp_matter_attribute_create(cluster, ZCL_LAST_CONNECT_ERROR_VALUE_ATTRIBUTE_ID, ESP_MATTER_ATTRIBUTE_FLAG_NONE, esp_matter_uint32(config->last_connect_error_value)); diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index d5321a33c..ad9cbaa6c 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -578,24 +578,46 @@ esp_err_t esp_matter_cluster_add_function_list(esp_matter_cluster_t *cluster, return ESP_OK; } -esp_matter_attr_val_t esp_matter_attribute_get_val(esp_matter_attribute_t *attribute) +esp_err_t esp_matter_attribute_get_val(esp_matter_attribute_t *attribute, esp_matter_attr_val_t *val) { if (!attribute) { ESP_LOGE(TAG, "Attribute cannot be NULL"); - return esp_matter_invalid(NULL); + return ESP_ERR_INVALID_ARG; } _esp_matter_attribute_t *current_attribute = (_esp_matter_attribute_t *)attribute; - return current_attribute->val; + memcpy((void *)val, (void *)¤t_attribute->val, sizeof(esp_matter_attr_val_t)); + return ESP_OK; } -esp_err_t esp_matter_attribute_set_val(esp_matter_attribute_t *attribute, esp_matter_attr_val_t val) +esp_err_t esp_matter_attribute_set_val(esp_matter_attribute_t *attribute, esp_matter_attr_val_t *val) { if (!attribute) { ESP_LOGE(TAG, "Attribute cannot be NULL"); return ESP_FAIL; } _esp_matter_attribute_t *current_attribute = (_esp_matter_attribute_t *)attribute; - current_attribute->val = val; + if (val->type == ESP_MATTER_VAL_TYPE_CHAR_STRING || val->type == ESP_MATTER_VAL_TYPE_OCTET_STRING + || val->type == ESP_MATTER_VAL_TYPE_ARRAY) { + /* Free old buf */ + if (current_attribute->val.val.a.b) { + free(current_attribute->val.val.a.b); + } + if (val->val.a.s > 0) { + /* Alloc new buf */ + uint8_t *new_buf = (uint8_t *)calloc(1, val->val.a.s); + if (!new_buf) { + ESP_LOGE(TAG, "Could not allocate new buffer"); + return ESP_ERR_NO_MEM; + } + /* Copy to new buf and assign */ + memcpy(new_buf, val->val.a.b, val->val.a.s); + val->val.a.b = new_buf; + } else { + ESP_LOGI(TAG, "Set val called with string with size 0"); + val->val.a.b = NULL; + } + } + memcpy((void *)¤t_attribute->val, (void *)val, sizeof(esp_matter_attr_val_t)); return ESP_OK; } @@ -645,6 +667,14 @@ static esp_err_t esp_matter_attribute_delete(esp_matter_attribute_t *attribute) _esp_matter_attribute_t *current_attribute = (_esp_matter_attribute_t *)attribute; /* Delete val here, if required */ + if (current_attribute->val.type == ESP_MATTER_VAL_TYPE_CHAR_STRING + || current_attribute->val.type == ESP_MATTER_VAL_TYPE_OCTET_STRING + || current_attribute->val.type == ESP_MATTER_VAL_TYPE_ARRAY) { + /* Free buf */ + if (current_attribute->val.val.a.b) { + free(current_attribute->val.val.a.b); + } + } /* Free */ free(current_attribute); @@ -672,7 +702,7 @@ esp_matter_attribute_t *esp_matter_attribute_create(esp_matter_cluster_t *cluste attribute->attribute_id = attribute_id; attribute->flags = flags; attribute->flags |= ESP_MATTER_ATTRIBUTE_FLAG_EXTERNAL_STORAGE; - attribute->val = val; + esp_matter_attribute_set_val((esp_matter_attribute_t *)attribute, &val); /* Add */ _esp_matter_attribute_t *previous_attribute = NULL; diff --git a/components/esp_matter/esp_matter_core.h b/components/esp_matter/esp_matter_core.h index fdbd0cfb2..0b8c8f81b 100644 --- a/components/esp_matter/esp_matter_core.h +++ b/components/esp_matter/esp_matter_core.h @@ -42,7 +42,7 @@ typedef enum esp_matter_callback_type { * @return error in case of failure. */ typedef esp_err_t (*esp_matter_attribute_callback_t)(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, - int attribute_id, esp_matter_attr_val_t val, void *priv_data); + int attribute_id, esp_matter_attr_val_t *val, void *priv_data); typedef void (*esp_matter_event_callback_t)(const ChipDeviceEvent *event, intptr_t arg); @@ -109,8 +109,8 @@ esp_matter_attribute_t *esp_matter_attribute_get_next(esp_matter_attribute_t *at int esp_matter_attribute_get_id(esp_matter_attribute_t *attribute); /** Attribute val APIs */ -esp_err_t esp_matter_attribute_set_val(esp_matter_attribute_t *attribute, esp_matter_attr_val_t val); -esp_matter_attr_val_t esp_matter_attribute_get_val(esp_matter_attribute_t *attribute); +esp_err_t esp_matter_attribute_set_val(esp_matter_attribute_t *attribute, esp_matter_attr_val_t *val); +esp_err_t esp_matter_attribute_get_val(esp_matter_attribute_t *attribute, esp_matter_attr_val_t *val); esp_err_t esp_matter_attribute_get_val_raw(int endpoint_id, int cluster_id, int attribute_id, uint8_t *value, uint16_t attribute_size); diff --git a/examples/bridge_zigbee/main/app_main.cpp b/examples/bridge_zigbee/main/app_main.cpp index e78e584f0..206686287 100644 --- a/examples/bridge_zigbee/main/app_main.cpp +++ b/examples/bridge_zigbee/main/app_main.cpp @@ -34,7 +34,7 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) } static esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, - int attribute_id, esp_matter_attr_val_t val, void *priv_data) + int attribute_id, esp_matter_attr_val_t *val, void *priv_data) { esp_err_t err = ESP_OK; diff --git a/examples/bridge_zigbee/main/zigbee_bridge.cpp b/examples/bridge_zigbee/main/zigbee_bridge.cpp index f15e8ce1a..bfc1fa428 100644 --- a/examples/bridge_zigbee/main/zigbee_bridge.cpp +++ b/examples/bridge_zigbee/main/zigbee_bridge.cpp @@ -117,13 +117,13 @@ void zigbee_bridge_send_off(zb_uint8_t buf, zb_uint16_t zigbee_shortaddr) ZB_ZCL_CMD_ON_OFF_OFF_ID, NULL); } -esp_err_t zigbee_bridge_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +esp_err_t zigbee_bridge_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { app_bridge_zigbee_device_t *zigbee_device = app_bridge_get_zigbee_device_by_matter_endpointid(endpoint_id); if (zigbee_device && zigbee_device->dev && zigbee_device->dev->endpoint) { if (cluster_id == ZCL_ON_OFF_CLUSTER_ID) { if (attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) { - zb_buf_get_out_delayed_ext((val.val.b ? zigbee_bridge_send_on : zigbee_bridge_send_off), + zb_buf_get_out_delayed_ext((val->val.b ? zigbee_bridge_send_on : zigbee_bridge_send_off), zigbee_device->zigbee_shortaddr, 0); } } diff --git a/examples/bridge_zigbee/main/zigbee_bridge.h b/examples/bridge_zigbee/main/zigbee_bridge.h index 0e4b211fb..e363118ba 100644 --- a/examples/bridge_zigbee/main/zigbee_bridge.h +++ b/examples/bridge_zigbee/main/zigbee_bridge.h @@ -23,7 +23,7 @@ void zigbee_bridge_match_bridged_onoff_light(zb_bufid_t bufid); void zigbee_bridge_match_bridged_onoff_light_timeout(zb_bufid_t bufid); -esp_err_t zigbee_bridge_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t zigbee_bridge_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); #ifdef __cplusplus } diff --git a/examples/light/main/app_driver.cpp b/examples/light/main/app_driver.cpp index 51c9e45e3..58185cc3b 100644 --- a/examples/light/main/app_driver.cpp +++ b/examples/light/main/app_driver.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -30,78 +29,31 @@ extern int light_endpoint_id; #define MATTER_SATURATION 255 #define MATTER_TEMPERATURE 255 -static esp_err_t app_driver_console_handler(int argc, char **argv) -{ - if (argc == 5 && strncmp(argv[0], "set", sizeof("set")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - int value = atoi(argv[4]); - - esp_matter_attr_val_t val = esp_matter_uint8(value); - - /* Change val if bool */ - if (cluster_id == ZCL_ON_OFF_CLUSTER_ID && attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) { - val.type = ESP_MATTER_VAL_TYPE_BOOLEAN; - val.val.b = (bool)value; - } - esp_matter_attribute_update(endpoint_id, cluster_id, attribute_id, val); - } else if (argc == 4 && strncmp(argv[0], "get", sizeof("get")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - - esp_matter_node_t *node = esp_matter_node_get(); - esp_matter_endpoint_t *endpoint = esp_matter_endpoint_get(node, endpoint_id); - esp_matter_cluster_t *cluster = esp_matter_cluster_get(endpoint, cluster_id); - esp_matter_attribute_t *attribute = esp_matter_attribute_get(cluster, attribute_id); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, val); - } else { - ESP_LOGE(TAG, "Incorrect arguments"); - return ESP_ERR_INVALID_ARG; - } - return ESP_OK; -} - -static void app_driver_register_commands() -{ - esp_matter_console_command_t command = { - .name = "driver", - .description = "This can be used to simulate on-device control. " - "Usage: matter esp driver [value]. " - "Example1: matter esp driver set 0x1001 0x0006 0x0000 1. " - "Example2: matter esp driver get 0x1001 0x0006 0x0000.", - .handler = app_driver_console_handler, - }; - esp_matter_console_add_command(&command); -} - /* Do any conversions/remapping for the actual value here */ -static esp_err_t app_driver_light_set_power(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_power(esp_matter_attr_val_t *val) { - return light_driver_set_power(val.val.b); + return light_driver_set_power(val->val.b); } -static esp_err_t app_driver_light_set_brightness(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_brightness(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); return light_driver_set_brightness(value); } -static esp_err_t app_driver_light_set_hue(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_hue(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_HUE, STANDARD_HUE); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE); return light_driver_set_hue(value); } -static esp_err_t app_driver_light_set_saturation(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_saturation(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_SATURATION, STANDARD_SATURATION); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION); return light_driver_set_saturation(value); } -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { esp_err_t err = ESP_OK; if (endpoint_id == light_endpoint_id) { @@ -138,8 +90,9 @@ static esp_err_t app_driver_attribute_set_defaults() esp_matter_attribute_t *attribute = esp_matter_attribute_get_first(cluster); while (attribute) { int attribute_id = esp_matter_attribute_get_id(attribute); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, val); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + err |= esp_matter_attribute_get_val(attribute, &val); + err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, &val); attribute = esp_matter_attribute_get_next(attribute); } cluster = esp_matter_cluster_get_next(cluster); @@ -153,6 +106,5 @@ esp_err_t app_driver_init() { device_init(); app_driver_attribute_set_defaults(); - app_driver_register_commands(); return ESP_OK; } diff --git a/examples/light/main/app_driver.h b/examples/light/main/app_driver.h index e8656e837..99aa09a93 100644 --- a/examples/light/main/app_driver.h +++ b/examples/light/main/app_driver.h @@ -24,7 +24,7 @@ extern "C" { */ esp_err_t app_driver_init(void); -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); #ifdef __cplusplus } diff --git a/examples/light/main/app_main.cpp b/examples/light/main/app_main.cpp index 17fe79b0d..9824a98c1 100644 --- a/examples/light/main/app_main.cpp +++ b/examples/light/main/app_main.cpp @@ -40,7 +40,7 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) } static esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, - int attribute_id, esp_matter_attr_val_t val, void *priv_data) + int attribute_id, esp_matter_attr_val_t *val, void *priv_data) { esp_err_t err = ESP_OK; diff --git a/examples/rainmaker_light/main/app_driver.cpp b/examples/rainmaker_light/main/app_driver.cpp index 51c9e45e3..58185cc3b 100644 --- a/examples/rainmaker_light/main/app_driver.cpp +++ b/examples/rainmaker_light/main/app_driver.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -30,78 +29,31 @@ extern int light_endpoint_id; #define MATTER_SATURATION 255 #define MATTER_TEMPERATURE 255 -static esp_err_t app_driver_console_handler(int argc, char **argv) -{ - if (argc == 5 && strncmp(argv[0], "set", sizeof("set")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - int value = atoi(argv[4]); - - esp_matter_attr_val_t val = esp_matter_uint8(value); - - /* Change val if bool */ - if (cluster_id == ZCL_ON_OFF_CLUSTER_ID && attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) { - val.type = ESP_MATTER_VAL_TYPE_BOOLEAN; - val.val.b = (bool)value; - } - esp_matter_attribute_update(endpoint_id, cluster_id, attribute_id, val); - } else if (argc == 4 && strncmp(argv[0], "get", sizeof("get")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - - esp_matter_node_t *node = esp_matter_node_get(); - esp_matter_endpoint_t *endpoint = esp_matter_endpoint_get(node, endpoint_id); - esp_matter_cluster_t *cluster = esp_matter_cluster_get(endpoint, cluster_id); - esp_matter_attribute_t *attribute = esp_matter_attribute_get(cluster, attribute_id); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, val); - } else { - ESP_LOGE(TAG, "Incorrect arguments"); - return ESP_ERR_INVALID_ARG; - } - return ESP_OK; -} - -static void app_driver_register_commands() -{ - esp_matter_console_command_t command = { - .name = "driver", - .description = "This can be used to simulate on-device control. " - "Usage: matter esp driver [value]. " - "Example1: matter esp driver set 0x1001 0x0006 0x0000 1. " - "Example2: matter esp driver get 0x1001 0x0006 0x0000.", - .handler = app_driver_console_handler, - }; - esp_matter_console_add_command(&command); -} - /* Do any conversions/remapping for the actual value here */ -static esp_err_t app_driver_light_set_power(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_power(esp_matter_attr_val_t *val) { - return light_driver_set_power(val.val.b); + return light_driver_set_power(val->val.b); } -static esp_err_t app_driver_light_set_brightness(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_brightness(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); return light_driver_set_brightness(value); } -static esp_err_t app_driver_light_set_hue(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_hue(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_HUE, STANDARD_HUE); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE); return light_driver_set_hue(value); } -static esp_err_t app_driver_light_set_saturation(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_saturation(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_SATURATION, STANDARD_SATURATION); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION); return light_driver_set_saturation(value); } -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { esp_err_t err = ESP_OK; if (endpoint_id == light_endpoint_id) { @@ -138,8 +90,9 @@ static esp_err_t app_driver_attribute_set_defaults() esp_matter_attribute_t *attribute = esp_matter_attribute_get_first(cluster); while (attribute) { int attribute_id = esp_matter_attribute_get_id(attribute); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, val); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + err |= esp_matter_attribute_get_val(attribute, &val); + err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, &val); attribute = esp_matter_attribute_get_next(attribute); } cluster = esp_matter_cluster_get_next(cluster); @@ -153,6 +106,5 @@ esp_err_t app_driver_init() { device_init(); app_driver_attribute_set_defaults(); - app_driver_register_commands(); return ESP_OK; } diff --git a/examples/rainmaker_light/main/app_driver.h b/examples/rainmaker_light/main/app_driver.h index e8656e837..99aa09a93 100644 --- a/examples/rainmaker_light/main/app_driver.h +++ b/examples/rainmaker_light/main/app_driver.h @@ -24,7 +24,7 @@ extern "C" { */ esp_err_t app_driver_init(void); -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); #ifdef __cplusplus } diff --git a/examples/rainmaker_light/main/app_main.cpp b/examples/rainmaker_light/main/app_main.cpp index d0f711ae9..f4764da24 100644 --- a/examples/rainmaker_light/main/app_main.cpp +++ b/examples/rainmaker_light/main/app_main.cpp @@ -40,7 +40,7 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) } static esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, - int attribute_id, esp_matter_attr_val_t val, void *priv_data) + int attribute_id, esp_matter_attr_val_t *val, void *priv_data) { esp_err_t err = ESP_OK; diff --git a/examples/rainmaker_light/main/app_rainmaker.cpp b/examples/rainmaker_light/main/app_rainmaker.cpp index a91a22450..7b893930b 100644 --- a/examples/rainmaker_light/main/app_rainmaker.cpp +++ b/examples/rainmaker_light/main/app_rainmaker.cpp @@ -195,28 +195,22 @@ static int app_rainmaker_get_attribute_id_from_name(const char *param_name) return 0; } -static esp_rmaker_param_val_t app_rainmaker_get_rmaker_val(esp_matter_attr_val_t val) +static esp_rmaker_param_val_t app_rainmaker_get_rmaker_val(esp_matter_attr_val_t *val) { - if (val.type == ESP_MATTER_VAL_TYPE_BOOLEAN) { - return esp_rmaker_bool(val.val.b); - } else if (val.type == ESP_MATTER_VAL_TYPE_INTEGER) { - return esp_rmaker_int(val.val.i); - } else if (val.type == ESP_MATTER_VAL_TYPE_FLOAT) { - return esp_rmaker_float(val.val.f); - } else if (val.type == ESP_MATTER_VAL_TYPE_STRING) { - return esp_rmaker_str(val.val.s); - } else if (val.type == ESP_MATTER_VAL_TYPE_JSON_OBJECT) { - return esp_rmaker_obj(val.val.s); - } else if (val.type == ESP_MATTER_VAL_TYPE_JSON_ARRAY) { - return esp_rmaker_array(val.val.s); - } else if (val.type == ESP_MATTER_VAL_TYPE_UINT8) { - return esp_rmaker_int(val.val.u8); - } else if (val.type == ESP_MATTER_VAL_TYPE_INT16) { - return esp_rmaker_int(val.val.i16); - } else if (val.type == ESP_MATTER_VAL_TYPE_UINT16) { - return esp_rmaker_int(val.val.u16); + if (val->type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + return esp_rmaker_bool(val->val.b); + } else if (val->type == ESP_MATTER_VAL_TYPE_INTEGER) { + return esp_rmaker_int(val->val.i); + } else if (val->type == ESP_MATTER_VAL_TYPE_FLOAT) { + return esp_rmaker_float(val->val.f); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT8) { + return esp_rmaker_int(val->val.u8); + } else if (val->type == ESP_MATTER_VAL_TYPE_INT16) { + return esp_rmaker_int(val->val.i16); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT16) { + return esp_rmaker_int(val->val.u16); } else { - ESP_LOGE(TAG, "Invalid val type: %d", val.type); + ESP_LOGE(TAG, "Invalid val type: %d", val->type); } return esp_rmaker_int(0); } @@ -229,19 +223,13 @@ static esp_matter_attr_val_t app_rainmaker_get_matter_val(esp_rmaker_param_val_t return esp_matter_int(val.val.i); } else if (val.type == RMAKER_VAL_TYPE_FLOAT) { return esp_matter_float(val.val.f); - } else if (val.type == RMAKER_VAL_TYPE_STRING) { - return esp_matter_str(val.val.s); - } else if (val.type == RMAKER_VAL_TYPE_OBJECT) { - return esp_matter_json_obj(val.val.s); - } else if (val.type == RMAKER_VAL_TYPE_ARRAY) { - return esp_matter_json_array(val.val.s); } else { ESP_LOGE(TAG, "Invalid val type: %d", val.type); } return esp_matter_int(0); } -esp_err_t app_rainmaker_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +esp_err_t app_rainmaker_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { const char *device_name = app_rainmaker_get_device_name_from_id(endpoint_id); const char *param_name = app_rainmaker_get_param_name_from_id(cluster_id, attribute_id); @@ -278,7 +266,7 @@ static esp_err_t write_cb(const esp_rmaker_device_t *device, const esp_rmaker_pa int attribute_id = app_rainmaker_get_attribute_id_from_name(param_name); esp_matter_attr_val_t matter_val = app_rainmaker_get_matter_val(val); - return esp_matter_attribute_update(endpoint_id, cluster_id, attribute_id, matter_val); + return esp_matter_attribute_update(endpoint_id, cluster_id, attribute_id, &matter_val); } static void app_rainmaker_device_create() @@ -321,8 +309,9 @@ static void app_rainmaker_device_create() bool add_bounds = app_rainmaker_get_param_bounds_from_id(cluster_id, attribute_id, &min, &max, &step); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - esp_rmaker_param_val_t rmaker_val = app_rainmaker_get_rmaker_val(val); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + esp_matter_attribute_get_val(attribute, &val); + esp_rmaker_param_val_t rmaker_val = app_rainmaker_get_rmaker_val(&val); esp_rmaker_param_t *param = esp_rmaker_param_create(param_name, param_type, rmaker_val, PROP_FLAG_READ | PROP_FLAG_WRITE); diff --git a/examples/rainmaker_light/main/app_rainmaker.h b/examples/rainmaker_light/main/app_rainmaker.h index cf9644196..05d41e67c 100644 --- a/examples/rainmaker_light/main/app_rainmaker.h +++ b/examples/rainmaker_light/main/app_rainmaker.h @@ -25,7 +25,7 @@ extern "C" { */ esp_err_t app_rainmaker_init(void); -esp_err_t app_rainmaker_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t app_rainmaker_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); #ifdef __cplusplus } diff --git a/examples/switch/main/app_driver.cpp b/examples/switch/main/app_driver.cpp index d9c34ebac..e23a635a5 100644 --- a/examples/switch/main/app_driver.cpp +++ b/examples/switch/main/app_driver.cpp @@ -30,39 +30,10 @@ static esp_err_t app_driver_console_handler(int argc, char **argv) if (argc == 1 && strncmp(argv[0], "help", sizeof("help")) == 0) { printf("Driver commands:\n" "\thelp: Print help\n" - "\tset: ." - "Example: matter esp driver set 0x0001 0x0006 0x0000 1.\n" - "\tget: . " - "Example: matter esp driver get 0x0001 0x0006 0x0000.\n" "\tsend_bind: . " "Example: matter esp driver send_bind 0x0001 0x0006 0x0002.\n" "\tsend: . " "Example: matter esp driver send 0x0001 0xBC5C01 0x0001 0x0006 0x0002.\n"); - } else if (argc == 5 && strncmp(argv[0], "set", sizeof("set")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - int value = atoi(argv[4]); - - esp_matter_attr_val_t val = esp_matter_uint8(value); - - /* Change val if bool */ - if (cluster_id == ZCL_ON_OFF_CLUSTER_ID && attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) { - val.type = ESP_MATTER_VAL_TYPE_BOOLEAN; - val.val.b = (bool)value; - } - esp_matter_attribute_update(endpoint_id, cluster_id, attribute_id, val); - } else if (argc == 4 && strncmp(argv[0], "get", sizeof("get")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - - esp_matter_node_t *node = esp_matter_node_get(); - esp_matter_endpoint_t *endpoint = esp_matter_endpoint_get(node, endpoint_id); - esp_matter_cluster_t *cluster = esp_matter_cluster_get(endpoint, cluster_id); - esp_matter_attribute_t *attribute = esp_matter_attribute_get(cluster, attribute_id); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, val); } else if (argc == 4 && strncmp(argv[0], "send_bind", sizeof("send_bind")) == 0) { int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); @@ -93,7 +64,7 @@ static void app_driver_register_commands() esp_matter_console_command_t command = { .name = "driver", .description = "This can be used to simulate on-device control. Usage: matter esp driver . " - "Driver commands: help, set, get, send, send_bind", + "Driver commands: help, send, send_bind", .handler = app_driver_console_handler, }; esp_matter_console_add_command(&command); @@ -101,7 +72,8 @@ static void app_driver_register_commands() void app_driver_client_command_callback(esp_matter_peer_device_t *peer_device, int remote_endpoint_id, void *priv_data) { - /** TODO: Find a better way to get the cluster_id and command_id */ + /** TODO: Find a better way to get the cluster_id and command_id. + Once done, move the console commands to esp_matter_client. */ if (g_cluster_id == ZCL_ON_OFF_CLUSTER_ID) { if (g_command_id == ZCL_OFF_COMMAND_ID) { esp_matter_on_off_send_command_off(peer_device, remote_endpoint_id); @@ -113,7 +85,7 @@ void app_driver_client_command_callback(esp_matter_peer_device_t *peer_device, i } } -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { /* Nothing to do here */ return ESP_OK; @@ -133,8 +105,9 @@ static esp_err_t app_driver_attribute_set_defaults() esp_matter_attribute_t *attribute = esp_matter_attribute_get_first(cluster); while (attribute) { int attribute_id = esp_matter_attribute_get_id(attribute); - esp_matter_attr_val_t val = esp_matter_attribute_get_val(attribute); - err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, val); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + err |= esp_matter_attribute_get_val(attribute, &val); + err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, &val); attribute = esp_matter_attribute_get_next(attribute); } cluster = esp_matter_cluster_get_next(cluster); diff --git a/examples/switch/main/app_driver.h b/examples/switch/main/app_driver.h index e8656e837..99aa09a93 100644 --- a/examples/switch/main/app_driver.h +++ b/examples/switch/main/app_driver.h @@ -24,7 +24,7 @@ extern "C" { */ esp_err_t app_driver_init(void); -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); #ifdef __cplusplus } diff --git a/examples/switch/main/app_main.cpp b/examples/switch/main/app_main.cpp index b4cd77ee5..109078a62 100644 --- a/examples/switch/main/app_main.cpp +++ b/examples/switch/main/app_main.cpp @@ -36,7 +36,7 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) } static esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, - int attribute_id, esp_matter_attr_val_t val, void *priv_data) + int attribute_id, esp_matter_attr_val_t *val, void *priv_data) { esp_err_t err = ESP_OK; diff --git a/examples/zap_light/main/app_driver.cpp b/examples/zap_light/main/app_driver.cpp index a1a6ce72c..4cd2c31c0 100644 --- a/examples/zap_light/main/app_driver.cpp +++ b/examples/zap_light/main/app_driver.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -30,107 +29,31 @@ extern int light_endpoint_id; #define MATTER_SATURATION 255 #define MATTER_TEMPERATURE 255 -static uint32_t app_driver_light_get_attribute(int endpoint_id, int cluster_id, int attribute_id) -{ - uint32_t value = 0; - if (endpoint_id == light_endpoint_id) { - if (cluster_id == ZCL_ON_OFF_CLUSTER_ID) { - if (attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) { - value = (uint32_t)light_driver_get_power(); - } - } else if (cluster_id == ZCL_LEVEL_CONTROL_CLUSTER_ID) { - if (attribute_id == ZCL_CURRENT_LEVEL_ATTRIBUTE_ID) { - value = (uint32_t)light_driver_get_brightness(); - value = REMAP_TO_RANGE(value, STANDARD_BRIGHTNESS, MATTER_BRIGHTNESS); - } - } else if (cluster_id == ZCL_COLOR_CONTROL_CLUSTER_ID) { - if (attribute_id == ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID) { - value = (uint32_t)light_driver_get_hue(); - value = REMAP_TO_RANGE(value, STANDARD_HUE, MATTER_HUE); - } else if (attribute_id == ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID) { - value = (uint32_t)light_driver_get_saturation(); - value = REMAP_TO_RANGE(value, STANDARD_SATURATION, MATTER_SATURATION); - } - } - } - return value; -} - -static esp_err_t app_driver_console_handler(int argc, char **argv) -{ - if (argc == 5 && strncmp(argv[0], "set", sizeof("set")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - int value = atoi(argv[4]); - - esp_matter_attr_val_t val = esp_matter_uint8(value); - - /* Change val if bool */ - if (cluster_id == ZCL_ON_OFF_CLUSTER_ID && attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) { - val.type = ESP_MATTER_VAL_TYPE_BOOLEAN; - val.val.b = (bool)value; - } - esp_matter_attribute_update(endpoint_id, cluster_id, attribute_id, val); - } else if (argc == 4 && strncmp(argv[0], "get", sizeof("get")) == 0) { - int endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - int cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - int attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - int value = app_driver_light_get_attribute(endpoint_id, cluster_id, attribute_id); - - esp_matter_attr_val_t val = esp_matter_uint8(value); - - /* Change val if bool */ - if (cluster_id == ZCL_ON_OFF_CLUSTER_ID && attribute_id == ZCL_ON_OFF_ATTRIBUTE_ID) { - val.type = ESP_MATTER_VAL_TYPE_BOOLEAN; - val.val.b = (bool)value; - } - esp_matter_attribute_val_print(endpoint_id, cluster_id, attribute_id, val); - } else { - ESP_LOGE(TAG, "Incorrect arguments"); - return ESP_ERR_INVALID_ARG; - } - return ESP_OK; -} - -static void app_driver_register_commands() -{ - esp_matter_console_command_t command = { - .name = "driver", - .description = "This can be used to simulate on-device control. " - "Usage: matter esp driver [value]. " - "Example1: matter esp driver set 0x1001 0x0006 0x0000 1. " - "Example2: matter esp driver get 0x1001 0x0006 0x0000.", - .handler = app_driver_console_handler, - }; - esp_matter_console_add_command(&command); -} - /* Do any conversions/remapping for the actual value here */ -static esp_err_t app_driver_light_set_power(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_power(esp_matter_attr_val_t *val) { - return light_driver_set_power(val.val.b); + return light_driver_set_power(val->val.b); } -static esp_err_t app_driver_light_set_brightness(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_brightness(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS); return light_driver_set_brightness(value); } -static esp_err_t app_driver_light_set_hue(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_hue(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_HUE, STANDARD_HUE); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE); return light_driver_set_hue(value); } -static esp_err_t app_driver_light_set_saturation(esp_matter_attr_val_t val) +static esp_err_t app_driver_light_set_saturation(esp_matter_attr_val_t *val) { - int value = REMAP_TO_RANGE(val.val.u8, MATTER_SATURATION, STANDARD_SATURATION); + int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION); return light_driver_set_saturation(value); } -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val) +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val) { esp_err_t err = ESP_OK; if (endpoint_id == light_endpoint_id) { @@ -170,28 +93,28 @@ esp_err_t app_driver_attribute_set_defaults() attribute_id = ZCL_ON_OFF_ATTRIBUTE_ID; esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, &value, sizeof(uint8_t)); val = esp_matter_bool(value); - err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, val); + err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, &val); endpoint_id = light_endpoint_id; cluster_id = ZCL_LEVEL_CONTROL_CLUSTER_ID; attribute_id = ZCL_CURRENT_LEVEL_ATTRIBUTE_ID; esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, &value, sizeof(uint8_t)); val = esp_matter_uint8(value); - err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, val); + err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, &val); endpoint_id = light_endpoint_id; cluster_id = ZCL_COLOR_CONTROL_CLUSTER_ID; attribute_id = ZCL_COLOR_CONTROL_CURRENT_HUE_ATTRIBUTE_ID; esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, &value, sizeof(uint8_t)); val = esp_matter_uint8(value); - err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, val); + err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, &val); endpoint_id = light_endpoint_id; cluster_id = ZCL_COLOR_CONTROL_CLUSTER_ID; attribute_id = ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID; esp_matter_attribute_get_val_raw(endpoint_id, cluster_id, attribute_id, &value, sizeof(uint8_t)); val = esp_matter_uint8(value); - err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, val); + err |= app_driver_attribute_update(endpoint_id, cluster_id, attribute_id, &val); return err; } @@ -199,6 +122,5 @@ esp_err_t app_driver_attribute_set_defaults() esp_err_t app_driver_init() { device_init(); - app_driver_register_commands(); return ESP_OK; } diff --git a/examples/zap_light/main/app_driver.h b/examples/zap_light/main/app_driver.h index 05b5a0290..bd0376d5c 100644 --- a/examples/zap_light/main/app_driver.h +++ b/examples/zap_light/main/app_driver.h @@ -24,7 +24,7 @@ extern "C" { */ esp_err_t app_driver_init(void); -esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t val); +esp_err_t app_driver_attribute_update(int endpoint_id, int cluster_id, int attribute_id, esp_matter_attr_val_t *val); esp_err_t app_driver_attribute_set_defaults(); diff --git a/examples/zap_light/main/app_main.cpp b/examples/zap_light/main/app_main.cpp index b243ea32e..b1b2ce9f4 100644 --- a/examples/zap_light/main/app_main.cpp +++ b/examples/zap_light/main/app_main.cpp @@ -31,7 +31,7 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) } static esp_err_t app_attribute_update_cb(esp_matter_callback_type_t type, int endpoint_id, int cluster_id, - int attribute_id, esp_matter_attr_val_t val, void *priv_data) + int attribute_id, esp_matter_attr_val_t *val, void *priv_data) { esp_err_t err = ESP_OK;