From 58a01a770c6d1ca1b05bb2e650ff6a2209dedf43 Mon Sep 17 00:00:00 2001 From: fengzero Date: Wed, 15 Jun 2022 03:17:44 +0000 Subject: [PATCH] api(tag): add description field in add/update/get --- ft/tag_test.robot | 20 +++ include/neuron/json/json.h | 6 + include/neuron/json/neu_json_tag.h | 3 + include/neuron/tag.h | 13 +- plugins/restful/datatag_handle.c | 19 ++- src/adapter/driver/driver.c | 1 + src/base/group.c | 44 ++++--- src/base/tag.c | 10 +- src/core/manager.c | 2 + src/parser/neu_json_tag.c | 153 ++++++++++++++--------- src/persist/json/persist_json_datatags.c | 19 ++- src/persist/json/persist_json_datatags.h | 2 + src/persist/persist.c | 18 +-- src/utils/json.c | 3 + 14 files changed, 204 insertions(+), 109 deletions(-) diff --git a/ft/tag_test.robot b/ft/tag_test.robot index 1abd7b11..5a493358 100644 --- a/ft/tag_test.robot +++ b/ft/tag_test.robot @@ -11,6 +11,7 @@ ${tag2} {"name": "tag2", "address": "1!00001", "attribute": ${TAG_AT ${tag3} {"name": "tag3", "address": "1!00001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT16}} ${tag4} {"name": "tag4", "address": "1!00031", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}} ${tag1update} {"name": "tag1", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}} +${tag_desc} {"name": "tag_desc", "description": "description info", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}} *** Test Cases *** Add tags to non-existent node, it should return failure @@ -116,3 +117,22 @@ Delete tags, it should return success Check Response Status ${res} 200 ${len} = Get Length ${res}[tags] Should Be Equal As Integers ${len} 0 + +Add a tag with description, it should return success + ${res}= Add Tags modbus-node group ${tag_desc} + + Check Response Status ${res} 200 + Check Error Code ${res} ${NEU_ERR_SUCCESS} + Should Be Equal As Integers ${res}[index] 1 + + ${res}= Get Tags modbus-node group + + Check Response Status ${res} 200 + ${len} = Get Length ${res}[tags] + Should Be Equal As Integers ${len} 1 + + Should Be Equal As Strings ${res}[tags][0][name] tag_desc + Should Be Equal As Strings ${res}[tags][0][address] 1!400001 + Should Be Equal As Strings ${res}[tags][0][description] description info + Should Be Equal As Strings ${res}[tags][0][attribute] ${TAG_ATTRIBUTE_READ} + Should Be Equal As Strings ${res}[tags][0][type] ${TAG_TYPE_INT16} diff --git a/include/neuron/json/json.h b/include/neuron/json/json.h index 079ca0bc..ffd18fe1 100644 --- a/include/neuron/json/json.h +++ b/include/neuron/json/json.h @@ -50,7 +50,13 @@ typedef union neu_json_value { void * val_object; } neu_json_value_u; +typedef enum neu_json_attribute { + NEU_JSON_ATTRIBUTE_REQUIRED, + NEU_JSON_ATTRIBUTE_OPTIONAL, +} neu_json_attribute_t; + typedef struct neu_json_elem { + neu_json_attribute_t attribute; char * name; enum neu_json_type t; union neu_json_value v; diff --git a/include/neuron/json/neu_json_tag.h b/include/neuron/json/neu_json_tag.h index aa939ea1..9a2ea6b2 100644 --- a/include/neuron/json/neu_json_tag.h +++ b/include/neuron/json/neu_json_tag.h @@ -34,6 +34,7 @@ extern "C" { typedef struct { char * address; char * name; + char * description; int64_t type; int64_t attribute; } neu_json_add_tags_req_tag_t; @@ -70,6 +71,7 @@ void neu_json_decode_del_tags_req_free(neu_json_del_tags_req_t *req); typedef struct { char * address; char * name; + char * description; int64_t type; int64_t attribute; } neu_json_get_tags_resp_tag_t; @@ -84,6 +86,7 @@ int neu_json_encode_get_tags_resp(void *json_object, void *param); typedef struct { char * name; char * address; + char * description; int64_t type; int64_t attribute; } neu_json_update_tags_req_tag_t; diff --git a/include/neuron/tag.h b/include/neuron/tag.h index 06dc15c3..007cf7ab 100644 --- a/include/neuron/tag.h +++ b/include/neuron/tag.h @@ -27,9 +27,6 @@ config_ **/ #define NEU_TAG_ADDRESS_SIZE 128 -typedef uint32_t neu_datatag_id_t; -typedef char * neu_addr_str_t; -typedef char * neu_tag_name; typedef enum { NEU_DTYPE_VOID, ///< like Haskell, a no value type NEU_DTYPE_UNIT, ///< like Haskell, a () type, same as void in C @@ -120,11 +117,11 @@ typedef enum { } neu_attribute_e; typedef struct { - neu_datatag_id_t id; - neu_attribute_e attribute; - neu_dtype_e type; - neu_addr_str_t addr_str; - neu_tag_name name; + char * name; + char * addr_str; + char * description; + neu_attribute_e attribute; + neu_dtype_e type; } neu_datatag_t; UT_icd *neu_tag_get_icd(); diff --git a/plugins/restful/datatag_handle.c b/plugins/restful/datatag_handle.c index 45caf04c..f9f8c2cd 100644 --- a/plugins/restful/datatag_handle.c +++ b/plugins/restful/datatag_handle.c @@ -52,6 +52,11 @@ void handle_add_tags(nng_aio *aio) cmd.tags[i].type = req->tags[i].type; cmd.tags[i].addr_str = strdup(req->tags[i].address); cmd.tags[i].name = strdup(req->tags[i].name); + if (req->tags[i].description != NULL) { + cmd.tags[i].description = strdup(req->tags[i].description); + } else { + cmd.tags[i].description = strdup(""); + } } ret = neu_plugin_op(plugin, header, &cmd); @@ -129,6 +134,11 @@ void handle_update_tags(nng_aio *aio) cmd.tags[i].type = req->tags[i].type; cmd.tags[i].addr_str = strdup(req->tags[i].address); cmd.tags[i].name = strdup(req->tags[i].name); + if (req->tags[i].description != NULL) { + cmd.tags[i].description = strdup(req->tags[i].description); + } else { + cmd.tags[i].description = strdup(""); + } } ret = neu_plugin_op(plugin, header, &cmd); @@ -196,10 +206,11 @@ void handle_get_tags_resp(nng_aio *aio, neu_resp_get_tag_t *tags) { int index = utarray_eltidx(tags->tags, tag); - tags_res.tags[index].name = tag->name; - tags_res.tags[index].address = tag->addr_str; - tags_res.tags[index].type = tag->type; - tags_res.tags[index].attribute = tag->attribute; + tags_res.tags[index].name = tag->name; + tags_res.tags[index].address = tag->addr_str; + tags_res.tags[index].description = tag->description; + tags_res.tags[index].type = tag->type; + tags_res.tags[index].attribute = tag->attribute; } neu_json_encode_by_fn(&tags_res, neu_json_encode_get_tags_resp, &result); diff --git a/src/adapter/driver/driver.c b/src/adapter/driver/driver.c index b02fda21..82d083cd 100644 --- a/src/adapter/driver/driver.c +++ b/src/adapter/driver/driver.c @@ -269,6 +269,7 @@ void neu_adapter_driver_write_tag(neu_adapter_driver_t *driver, cmd->value.value); free(tag->addr_str); free(tag->name); + free(tag->description); free(tag); } } diff --git a/src/base/group.c b/src/base/group.c index 4f76a2a0..a66ab98f 100644 --- a/src/base/group.c +++ b/src/base/group.c @@ -73,6 +73,7 @@ void neu_group_destroy(neu_group_t *group) free(el->name); free(el->tag->name); free(el->tag->addr_str); + free(el->tag->description); free(el->tag); free(el); } @@ -132,13 +133,14 @@ int neu_group_add_tag(neu_group_t *group, neu_datatag_t *tag) return NEU_ERR_TAG_NAME_CONFLICT; } - el = calloc(1, sizeof(tag_elem_t)); - el->name = strdup(tag->name); - el->tag = calloc(1, sizeof(neu_datatag_t)); - el->tag->name = strdup(tag->name); - el->tag->addr_str = strdup(tag->addr_str); - el->tag->type = tag->type; - el->tag->attribute = tag->attribute; + el = calloc(1, sizeof(tag_elem_t)); + el->name = strdup(tag->name); + el->tag = calloc(1, sizeof(neu_datatag_t)); + el->tag->name = strdup(tag->name); + el->tag->addr_str = strdup(tag->addr_str); + el->tag->description = strdup(tag->description); + el->tag->type = tag->type; + el->tag->attribute = tag->attribute; HASH_ADD_STR(group->tags, name, el); update_timestamp(group); @@ -161,16 +163,18 @@ int neu_group_update_tag(neu_group_t *group, neu_datatag_t *tag) free(el->name); free(el->tag->name); free(el->tag->addr_str); + free(el->tag->description); free(el->tag); free(el); - el = calloc(1, sizeof(tag_elem_t)); - el->name = strdup(tag->name); - el->tag = calloc(1, sizeof(neu_datatag_t)); - el->tag->name = strdup(tag->name); - el->tag->addr_str = strdup(tag->addr_str); - el->tag->type = tag->type; - el->tag->attribute = tag->attribute; + el = calloc(1, sizeof(tag_elem_t)); + el->name = strdup(tag->name); + el->tag = calloc(1, sizeof(neu_datatag_t)); + el->tag->name = strdup(tag->name); + el->tag->addr_str = strdup(tag->addr_str); + el->tag->description = strdup(tag->description); + el->tag->type = tag->type; + el->tag->attribute = tag->attribute; HASH_ADD_STR(group->tags, name, el); update_timestamp(group); @@ -195,6 +199,7 @@ int neu_group_del_tag(neu_group_t *group, const char *tag_name) free(el->name); free(el->tag->name); free(el->tag->addr_str); + free(el->tag->description); free(el->tag); free(el); @@ -248,11 +253,12 @@ neu_datatag_t *neu_group_find_tag(neu_group_t *group, const char *tag) nng_mtx_lock(group->mtx); HASH_FIND_STR(group->tags, tag, find); if (find != NULL) { - result = calloc(1, sizeof(neu_datatag_t)); - result->type = find->tag->type; - result->attribute = find->tag->attribute; - result->name = strdup(find->tag->name); - result->addr_str = strdup(find->tag->addr_str); + result = calloc(1, sizeof(neu_datatag_t)); + result->type = find->tag->type; + result->attribute = find->tag->attribute; + result->name = strdup(find->tag->name); + result->addr_str = strdup(find->tag->addr_str); + result->description = strdup(find->tag->description); } nng_mtx_unlock(group->mtx); diff --git a/src/base/tag.c b/src/base/tag.c index 43d7c0e5..d4f06794 100644 --- a/src/base/tag.c +++ b/src/base/tag.c @@ -29,10 +29,11 @@ static void tag_array_copy(void *_dst, const void *_src) neu_datatag_t *dst = (neu_datatag_t *) _dst; neu_datatag_t *src = (neu_datatag_t *) _src; - dst->type = src->type; - dst->attribute = src->attribute; - dst->addr_str = strdup(src->addr_str); - dst->name = strdup(src->name); + dst->type = src->type; + dst->attribute = src->attribute; + dst->addr_str = strdup(src->addr_str); + dst->name = strdup(src->name); + dst->description = strdup(src->description); } static void tag_array_free(void *_elt) @@ -41,6 +42,7 @@ static void tag_array_free(void *_elt) free(elt->name); free(elt->addr_str); + free(elt->description); } static UT_icd tag_icd = { sizeof(neu_datatag_t), NULL, tag_array_copy, diff --git a/src/core/manager.c b/src/core/manager.c index 01e7d030..0076bacf 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -291,6 +291,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) for (int i = 0; i < cmd->n_tag; i++) { free(cmd->tags[i].addr_str); free(cmd->tags[i].name); + free(cmd->tags[i].description); } free(cmd->tags); @@ -334,6 +335,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) for (int i = 0; i < cmd->n_tag; i++) { free(cmd->tags[i].addr_str); free(cmd->tags[i].name); + free(cmd->tags[i].description); } free(cmd->tags); diff --git a/src/parser/neu_json_tag.c b/src/parser/neu_json_tag.c index f0e30710..82cfaa76 100644 --- a/src/parser/neu_json_tag.c +++ b/src/parser/neu_json_tag.c @@ -65,32 +65,40 @@ int neu_json_decode_add_tags_req(char *buf, neu_json_add_tags_req_t **result) req->tags = calloc(req->n_tag, sizeof(neu_json_add_tags_req_tag_t)); neu_json_add_tags_req_tag_t *p_tag = req->tags; for (int i = 0; i < req->n_tag; i++) { - neu_json_elem_t tag_elems[] = { { - .name = "type", - .t = NEU_JSON_INT, - }, - { - .name = "name", - .t = NEU_JSON_STR, - }, - { - .name = "attribute", - .t = NEU_JSON_INT, - }, - { - .name = "address", - .t = NEU_JSON_STR, - } }; - ret = neu_json_decode_array_by_json( + neu_json_elem_t tag_elems[] = { + { + .name = "type", + .t = NEU_JSON_INT, + }, + { + .name = "name", + .t = NEU_JSON_STR, + }, + { + .name = "attribute", + .t = NEU_JSON_INT, + }, + { + .name = "address", + .t = NEU_JSON_STR, + }, + { + .name = "description", + .t = NEU_JSON_STR, + .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL, + }, + }; + ret = neu_json_decode_array_by_json( json_obj, "tags", i, NEU_JSON_ELEM_SIZE(tag_elems), tag_elems); if (ret != 0) { goto decode_fail; } - p_tag->type = tag_elems[0].v.val_int; - p_tag->name = tag_elems[1].v.val_str; - p_tag->attribute = tag_elems[2].v.val_int; - p_tag->address = tag_elems[3].v.val_str; + p_tag->type = tag_elems[0].v.val_int; + p_tag->name = tag_elems[1].v.val_str; + p_tag->attribute = tag_elems[2].v.val_int; + p_tag->address = tag_elems[3].v.val_str; + p_tag->description = tag_elems[4].v.val_str; p_tag++; } @@ -118,6 +126,9 @@ void neu_json_decode_add_tags_req_free(neu_json_add_tags_req_t *req) neu_json_add_tags_req_tag_t *p_tag = req->tags; for (int i = 0; i < req->n_tag; i++) { + if (p_tag->description != NULL) { + free(p_tag->description); + } free(p_tag->name); free(p_tag->address); p_tag++; @@ -243,26 +254,33 @@ int neu_json_encode_get_tags_resp(void *json_object, void *param) void * tag_array = neu_json_array(); neu_json_get_tags_resp_tag_t *p_tag = resp->tags; for (int i = 0; i < resp->n_tag; i++) { - neu_json_elem_t tag_elems[] = { { - .name = "type", - .t = NEU_JSON_INT, - .v.val_int = p_tag->type, - }, - { - .name = "name", - .t = NEU_JSON_STR, - .v.val_str = p_tag->name, - }, - { - .name = "attribute", - .t = NEU_JSON_INT, - .v.val_int = p_tag->attribute, - }, - { - .name = "address", - .t = NEU_JSON_STR, - .v.val_str = p_tag->address, - } }; + neu_json_elem_t tag_elems[] = { + { + .name = "type", + .t = NEU_JSON_INT, + .v.val_int = p_tag->type, + }, + { + .name = "name", + .t = NEU_JSON_STR, + .v.val_str = p_tag->name, + }, + { + .name = "attribute", + .t = NEU_JSON_INT, + .v.val_int = p_tag->attribute, + }, + { + .name = "address", + .t = NEU_JSON_STR, + .v.val_str = p_tag->address, + }, + { + .name = "description", + .t = NEU_JSON_STR, + .v.val_str = p_tag->description, + }, + }; tag_array = neu_json_encode_array(tag_array, tag_elems, NEU_JSON_ELEM_SIZE(tag_elems)); p_tag++; @@ -317,32 +335,40 @@ int neu_json_decode_update_tags_req(char * buf, req->tags = calloc(req->n_tag, sizeof(neu_json_update_tags_req_tag_t)); neu_json_update_tags_req_tag_t *p_tag = req->tags; for (int i = 0; i < req->n_tag; i++) { - neu_json_elem_t tag_elems[] = { { - .name = "type", - .t = NEU_JSON_INT, - }, - { - .name = "name", - .t = NEU_JSON_STR, - }, - { - .name = "attribute", - .t = NEU_JSON_INT, - }, - { - .name = "address", - .t = NEU_JSON_STR, - } }; - ret = neu_json_decode_array_by_json( + neu_json_elem_t tag_elems[] = { + { + .name = "type", + .t = NEU_JSON_INT, + }, + { + .name = "name", + .t = NEU_JSON_STR, + }, + { + .name = "attribute", + .t = NEU_JSON_INT, + }, + { + .name = "address", + .t = NEU_JSON_STR, + }, + { + .name = "description", + .t = NEU_JSON_STR, + .attribute = NEU_JSON_ATTRIBUTE_OPTIONAL, + }, + }; + ret = neu_json_decode_array_by_json( json_obj, "tags", i, NEU_JSON_ELEM_SIZE(tag_elems), tag_elems); if (ret != 0) { goto decode_fail; } - p_tag->type = tag_elems[0].v.val_int; - p_tag->name = tag_elems[1].v.val_str; - p_tag->attribute = tag_elems[2].v.val_int; - p_tag->address = tag_elems[3].v.val_str; + p_tag->type = tag_elems[0].v.val_int; + p_tag->name = tag_elems[1].v.val_str; + p_tag->attribute = tag_elems[2].v.val_int; + p_tag->address = tag_elems[3].v.val_str; + p_tag->description = tag_elems[4].v.val_str; p_tag++; } @@ -370,6 +396,9 @@ void neu_json_decode_update_tags_req_free(neu_json_update_tags_req_t *req) neu_json_update_tags_req_tag_t *p_tag = req->tags; for (int i = 0; i < req->n_tag; i++) { + if (p_tag->description != NULL) { + free(p_tag->description); + } free(p_tag->name); free(p_tag->address); p_tag++; diff --git a/src/persist/json/persist_json_datatags.c b/src/persist/json/persist_json_datatags.c index 5b8b68f8..f1a25fcf 100644 --- a/src/persist/json/persist_json_datatags.c +++ b/src/persist/json/persist_json_datatags.c @@ -65,6 +65,10 @@ int neu_json_decode_datatag_req(char *buf, neu_json_datatag_req_t **result) .name = "address", .t = NEU_JSON_STR, }, + { + .name = "description", + .t = NEU_JSON_STR, + }, }; ret = neu_json_decode_array_by_json( json_obj, "tags", i, NEU_JSON_ELEM_SIZE(tag_elems), tag_elems); @@ -72,10 +76,11 @@ int neu_json_decode_datatag_req(char *buf, neu_json_datatag_req_t **result) goto decode_fail; } - p_tag->type = tag_elems[0].v.val_int; - p_tag->name = tag_elems[1].v.val_str; - p_tag->attribute = tag_elems[2].v.val_int; - p_tag->address = tag_elems[3].v.val_str; + p_tag->type = tag_elems[0].v.val_int; + p_tag->name = tag_elems[1].v.val_str; + p_tag->attribute = tag_elems[2].v.val_int; + p_tag->address = tag_elems[3].v.val_str; + p_tag->description = tag_elems[4].v.val_str; p_tag++; } @@ -105,6 +110,7 @@ void neu_json_decode_datatag_req_free(neu_json_datatag_req_t *req) for (int i = 0; i < req->n_tag; i++) { free(p_tag->name); free(p_tag->address); + free(p_tag->description); p_tag++; } @@ -142,6 +148,11 @@ int neu_json_encode_datatag_resp(void *json_object, void *param) .t = NEU_JSON_STR, .v.val_str = p_tag->address, }, + { + .name = "description", + .t = NEU_JSON_STR, + .v.val_str = p_tag->description, + }, }; tag_array = neu_json_encode_array(tag_array, tag_elems, NEU_JSON_ELEM_SIZE(tag_elems)); diff --git a/src/persist/json/persist_json_datatags.h b/src/persist/json/persist_json_datatags.h index cb9f5abf..59f17ce7 100644 --- a/src/persist/json/persist_json_datatags.h +++ b/src/persist/json/persist_json_datatags.h @@ -34,6 +34,7 @@ extern "C" { typedef struct { char * address; char * name; + char * description; int64_t type; int64_t attribute; } neu_json_datatag_req_tag_t; @@ -49,6 +50,7 @@ void neu_json_decode_datatag_req_free(neu_json_datatag_req_t *req); typedef struct { char * address; char * name; + char * description; int64_t type; int64_t attribute; } neu_json_datatag_resp_tag_t; diff --git a/src/persist/persist.c b/src/persist/persist.c index 0d1dc37d..84793a3f 100644 --- a/src/persist/persist.c +++ b/src/persist/persist.c @@ -880,10 +880,11 @@ int neu_persister_store_datatags(neu_persister_t *persister, int index = 0; utarray_foreach(datatag_infos, neu_datatag_t *, tag) { - datatags_resp.tags[index].name = tag->name; - datatags_resp.tags[index].address = tag->addr_str; - datatags_resp.tags[index].attribute = tag->attribute; - datatags_resp.tags[index].type = tag->type; + datatags_resp.tags[index].name = tag->name; + datatags_resp.tags[index].description = tag->description; + datatags_resp.tags[index].address = tag->addr_str; + datatags_resp.tags[index].attribute = tag->attribute; + datatags_resp.tags[index].type = tag->type; index += 1; } @@ -936,10 +937,11 @@ int neu_persister_load_datatags(neu_persister_t *persister, utarray_new(*tags, neu_tag_get_icd()); for (int i = 0; i < datatag_req->n_tag; i++) { neu_datatag_t tag = { - .name = datatag_req->tags[i].name, - .addr_str = datatag_req->tags[i].address, - .type = datatag_req->tags[i].type, - .attribute = datatag_req->tags[i].attribute, + .name = datatag_req->tags[i].name, + .addr_str = datatag_req->tags[i].address, + .type = datatag_req->tags[i].type, + .attribute = datatag_req->tags[i].attribute, + .description = datatag_req->tags[i].description, }; utarray_push_back(*tags, &tag); diff --git a/src/utils/json.c b/src/utils/json.c index bfa9bb4c..54412720 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -99,6 +99,9 @@ static int decode_object(json_t *root, neu_json_elem_t *ele) } if (ob == NULL) { + if (ele->attribute == NEU_JSON_ATTRIBUTE_OPTIONAL) { + return 0; + } zlog_error(neuron, "json decode: %s failed", ele->name); return -1; }