From 2aacde317cf05337b088c3fe8f3a7bedcdab603c Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 26 Jul 2023 19:51:54 +0800 Subject: [PATCH] esp-matter: Add support for long char string and long octet string --- .../esp_matter/esp_matter_attribute_utils.cpp | 94 +++++++++++++++++++ .../esp_matter/esp_matter_attribute_utils.h | 11 ++- components/esp_matter/esp_matter_core.cpp | 7 ++ .../esp_matter/private/esp_matter_nvs.cpp | 4 + 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/components/esp_matter/esp_matter_attribute_utils.cpp b/components/esp_matter/esp_matter_attribute_utils.cpp index 56fdcd12c..dcbdfc383 100644 --- a/components/esp_matter/esp_matter_attribute_utils.cpp +++ b/components/esp_matter/esp_matter_attribute_utils.cpp @@ -432,6 +432,23 @@ esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t data_size) return attr_val; } +esp_matter_attr_val_t esp_matter_long_char_str(char *val, uint16_t data_size) +{ + 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_LONG_CHAR_STRING, + .val = { + .a = { + .b = (uint8_t *)val, + .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 data_size) { uint16_t data_size_len = 1; /* Number of bytes used to store the length */ @@ -449,6 +466,23 @@ esp_matter_attr_val_t esp_matter_octet_str(uint8_t *val, uint16_t data_size) return attr_val; } +esp_matter_attr_val_t esp_matter_long_octet_str(uint8_t *val, uint16_t data_size) +{ + 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_LONG_OCTET_STRING, + .val = { + .a = { + .b = val, + .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 data_size, uint16_t count) { uint16_t data_size_len = 2; /* Number of bytes used to store the length */ @@ -598,6 +632,9 @@ static esp_err_t console_set_handler(int argc, char **argv) } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { char *value = argv[3]; val = esp_matter_char_str(value, strlen(value)); + } else if (type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING) { + char *value = argv[3]; + val = esp_matter_long_char_str(value, strlen(value)); } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { if (matter_attribute->IsNullable()) { if (strncmp(argv[3], "null", sizeof("null")) == 0) { @@ -990,10 +1027,18 @@ static esp_matter_val_type_t get_val_type_from_attribute_type(int attribute_type return ESP_MATTER_VAL_TYPE_CHAR_STRING; break; + case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING; + break; + case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: return ESP_MATTER_VAL_TYPE_OCTET_STRING; break; + case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: + return ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING; + break; + case ZCL_INT8S_ATTRIBUTE_TYPE: return ESP_MATTER_VAL_TYPE_INT8; break; @@ -1179,6 +1224,20 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp } break; + case ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING: + if (attribute_type) { + *attribute_type = ZCL_LONG_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_OCTET_STRING: if (attribute_type) { *attribute_type = ZCL_OCTET_STRING_ATTRIBUTE_TYPE; @@ -1193,6 +1252,20 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp } break; + case ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING: + if (attribute_type) { + *attribute_type = ZCL_LONG_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: case ESP_MATTER_VAL_TYPE_NULLABLE_INT8: if (attribute_type) { @@ -1466,6 +1539,15 @@ static esp_err_t get_attr_val_from_data(esp_matter_attr_val_t *val, EmberAfAttri break; } + case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: { + *val = esp_matter_long_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_long_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; @@ -1475,6 +1557,15 @@ static esp_err_t get_attr_val_from_data(esp_matter_attr_val_t *val, EmberAfAttri break; } + case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: { + *val = esp_matter_long_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_long_octet_str((value + data_size_len), data_count); + break; + } + case ZCL_INT8S_ATTRIBUTE_TYPE: { using Traits = chip::app::NumericAttributeTraits; Traits::StorageType attribute_value; @@ -1727,6 +1818,9 @@ void val_print(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, } else if (val->type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { ESP_LOGI(TAG, "********** %c : Endpoint 0x%04" PRIX16 "'s Cluster 0x%08" PRIX32 "'s Attribute 0x%08" PRIX32 " is %.*s **********", action, endpoint_id, cluster_id, attribute_id, val->val.a.s, val->val.a.b); + } else if (val->type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING) { + ESP_LOGI(TAG, "********** %c : Endpoint 0x%04" PRIX16 "'s Cluster 0x%08" PRIX32 "'s Attribute 0x%08" PRIX32 " is %.*s **********", action, + endpoint_id, cluster_id, attribute_id, val->val.a.s, val->val.a.b); } else { ESP_LOGI(TAG, "********** %c : Endpoint 0x%04" PRIX16 "'s Cluster 0x%08" PRIX32 "'s Attribute 0x%08" PRIX32 " is **********", action, endpoint_id, cluster_id, attribute_id, val->type); diff --git a/components/esp_matter/esp_matter_attribute_utils.h b/components/esp_matter/esp_matter_attribute_utils.h index e6563a7ef..d591df6aa 100644 --- a/components/esp_matter/esp_matter_attribute_utils.h +++ b/components/esp_matter/esp_matter_attribute_utils.h @@ -50,9 +50,9 @@ typedef enum { ESP_MATTER_VAL_TYPE_FLOAT = 3, /** Array Eg. [1,2,3] */ ESP_MATTER_VAL_TYPE_ARRAY = 4, - /** Char String Eg. "123" */ + /** Char String Eg. "123", Max length 0xFE */ ESP_MATTER_VAL_TYPE_CHAR_STRING = 5, - /** Octet String Eg. [0x01, 0x20] */ + /** Octet String Eg. [0x01, 0x20], Max length 0xFE */ ESP_MATTER_VAL_TYPE_OCTET_STRING = 6, /** 8 bit signed integer */ ESP_MATTER_VAL_TYPE_INT8 = 7, @@ -80,6 +80,11 @@ typedef enum { ESP_MATTER_VAL_TYPE_BITMAP32 = 18, /** 16 bit enum */ ESP_MATTER_VAL_TYPE_ENUM16 = 19, + /** Long Char String, Max length 0xFFFE **/ + ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING = 20, + /** Long Octet String, Max length 0xFFFE **/ + ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING = 21, + /** nullable types **/ ESP_MATTER_VAL_TYPE_NULLABLE_INTEGER = ESP_MATTER_VAL_TYPE_INTEGER + ESP_MATTER_VAL_NULLABLE_BASE, ESP_MATTER_VAL_TYPE_NULLABLE_FLOAT = ESP_MATTER_VAL_TYPE_FLOAT + ESP_MATTER_VAL_NULLABLE_BASE, @@ -298,9 +303,11 @@ esp_matter_attr_val_t esp_matter_nullable_bitmap32(nullable val); /** Character string */ esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t data_size); +esp_matter_attr_val_t esp_matter_long_char_str(char *val, uint16_t data_size); /** Octet string */ esp_matter_attr_val_t esp_matter_octet_str(uint8_t *val, uint16_t data_size); +esp_matter_attr_val_t esp_matter_long_octet_str(uint8_t *val, uint16_t data_size); /** Array */ esp_matter_attr_val_t esp_matter_array(uint8_t *val, uint16_t data_size, uint16_t count); diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 7a49dfdec..f73da2711 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -1097,7 +1097,9 @@ attribute_t *create(cluster_t *cluster, uint32_t attribute_id, uint8_t flags, es // After reboot, string and array are treated as Invalid. So need to store val.type and size of attribute value. attribute->val.type = val.type; if (val.type == ESP_MATTER_VAL_TYPE_CHAR_STRING || + val.type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING || val.type == ESP_MATTER_VAL_TYPE_OCTET_STRING || + val.type == ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING || val.type == ESP_MATTER_VAL_TYPE_ARRAY) { attribute->val.val.a.s = val.val.a.s; attribute->val.val.a.n = val.val.a.n; @@ -1148,7 +1150,9 @@ static esp_err_t destroy(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_LONG_CHAR_STRING || current_attribute->val.type == ESP_MATTER_VAL_TYPE_OCTET_STRING || + current_attribute->val.type == ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING || current_attribute->val.type == ESP_MATTER_VAL_TYPE_ARRAY) { /* Free buf */ if (current_attribute->val.val.a.b) { @@ -1221,6 +1225,7 @@ esp_err_t set_val(attribute_t *attribute, esp_matter_attr_val_t *val) } _attribute_t *current_attribute = (_attribute_t *)attribute; if (val->type == ESP_MATTER_VAL_TYPE_CHAR_STRING || val->type == ESP_MATTER_VAL_TYPE_OCTET_STRING || + val->type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING || val->type == ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING || val->type == ESP_MATTER_VAL_TYPE_ARRAY) { /* Free old buf */ if (current_attribute->val.val.a.b) { @@ -1275,7 +1280,9 @@ esp_err_t add_bounds(attribute_t *attribute, esp_matter_attr_val_t min, esp_matt /* Check if bounds can be set */ if (current_attribute->val.type == ESP_MATTER_VAL_TYPE_CHAR_STRING || + current_attribute->val.type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING || current_attribute->val.type == ESP_MATTER_VAL_TYPE_OCTET_STRING || + current_attribute->val.type == ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING || current_attribute->val.type == ESP_MATTER_VAL_TYPE_ARRAY) { ESP_LOGE(TAG, "Bounds cannot be set for string/array type attributes"); return ESP_ERR_INVALID_ARG; diff --git a/components/esp_matter/private/esp_matter_nvs.cpp b/components/esp_matter/private/esp_matter_nvs.cpp index b4e0c69f1..78f35a256 100644 --- a/components/esp_matter/private/esp_matter_nvs.cpp +++ b/components/esp_matter/private/esp_matter_nvs.cpp @@ -42,7 +42,9 @@ esp_err_t get_val_from_nvs(uint16_t endpoint_id, uint32_t cluster_id, uint32_t a ESP_LOGD(TAG, "read attribute from nvs: endpoint_id-0x%" PRIx16 ", cluster_id-0x%" PRIx32 ", attribute_id-0x%" PRIx32 "", endpoint_id, cluster_id, attribute_id); if (val.type == ESP_MATTER_VAL_TYPE_CHAR_STRING || + val.type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING || val.type == ESP_MATTER_VAL_TYPE_OCTET_STRING || + val.type == ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING || val.type == ESP_MATTER_VAL_TYPE_ARRAY) { size_t len = 0; if ((err = nvs_get_blob(handle, attribute_key, NULL, &len)) == ESP_OK) { @@ -185,7 +187,9 @@ esp_err_t store_val_in_nvs(uint16_t endpoint_id, uint32_t cluster_id, uint32_t a ESP_LOGD(TAG, "Store attribute in nvs: endpoint_id-0x%" PRIx16 ", cluster_id-0x%" PRIx32 ", attribute_id-0x%" PRIx32 "", endpoint_id, cluster_id, attribute_id); if (val.type == ESP_MATTER_VAL_TYPE_CHAR_STRING || + val.type == ESP_MATTER_VAL_TYPE_LONG_CHAR_STRING || val.type == ESP_MATTER_VAL_TYPE_OCTET_STRING || + val.type == ESP_MATTER_VAL_TYPE_LONG_OCTET_STRING || val.type == ESP_MATTER_VAL_TYPE_ARRAY) { /* Store only if value is not NULL */ if (val.val.a.b) {