Merge branch 'feature/long_char_str' into 'main'

esp-matter: Add support for long char string and long octet string

See merge request app-frameworks/esp-matter!441
This commit is contained in:
Shu Chen
2023-08-09 19:24:04 +08:00
4 changed files with 114 additions and 2 deletions
@@ -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<int8_t>;
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 <invalid type: %d> **********", action,
endpoint_id, cluster_id, attribute_id, val->type);
@@ -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<uint32_t> 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);
@@ -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;
@@ -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) {