diff --git a/include/neuron/errcodes.h b/include/neuron/errcodes.h index 2c351f0e..e0bc34ed 100644 --- a/include/neuron/errcodes.h +++ b/include/neuron/errcodes.h @@ -83,6 +83,7 @@ typedef enum { NEU_ERR_TAG_DESCRIPTION_TOO_LONG = 2208, NEU_ERR_TAG_PRECISION_INVALID = 2209, NEU_ERR_TAG_EXIST = 2210, + NEU_ERR_TAG_DECIMAL_INVALID = 2211, NEU_ERR_TAG_BIAS_INVALID = 2212, NEU_ERR_LIBRARY_NOT_FOUND = 2301, diff --git a/plugins/restful/datatag_handle.c b/plugins/restful/datatag_handle.c index 21ad8e5d..b1fefe2f 100644 --- a/plugins/restful/datatag_handle.c +++ b/plugins/restful/datatag_handle.c @@ -41,43 +41,73 @@ void handle_add_tags(nng_aio *aio) } else if (strlen(req->group) >= NEU_GROUP_NAME_LEN) { CHECK_GROUP_NAME_LENGTH_ERR; } else { - int ret = 0; - neu_reqresp_head_t header = { 0 }; - neu_req_add_tag_t cmd = { 0 }; - header.otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM; - - header.ctx = aio; - header.type = NEU_REQ_ADD_TAG; - strcpy(cmd.driver, req->node); - strcpy(cmd.group, req->group); - cmd.n_tag = req->n_tag; - cmd.tags = calloc(req->n_tag, sizeof(neu_datatag_t)); + neu_reqresp_head_t header = { 0 }; + neu_req_add_tag_t cmd = { 0 }; + header.otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM; + neu_resp_add_tag_t add_resp = { 0 }; for (int i = 0; i < req->n_tag; i++) { - cmd.tags[i].attribute = req->tags[i].attribute; - cmd.tags[i].type = req->tags[i].type; - cmd.tags[i].precision = req->tags[i].precision; - cmd.tags[i].decimal = req->tags[i].decimal; - cmd.tags[i].bias = req->tags[i].bias; - cmd.tags[i].address = 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(""); - } - if (NEU_ATTRIBUTE_STATIC & req->tags[i].attribute) { - neu_tag_set_static_value_json( - &cmd.tags[i], req->tags[i].t, &req->tags[i].value); + if (req->tags[i].type == NEU_TYPE_STRING || + req->tags[i].type == NEU_TYPE_BOOL || + req->tags[i].type == NEU_TYPE_BIT || + req->tags[i].type == NEU_TYPE_TIME || + req->tags[i].type == NEU_TYPE_DATA_AND_TIME) { + if (req->tags[i].precision > 0) { + add_resp.index = i; + add_resp.error = NEU_ERR_TAG_PRECISION_INVALID; + break; + } + if (req->tags[i].decimal > 0) { + add_resp.index = i; + add_resp.error = NEU_ERR_TAG_DECIMAL_INVALID; + break; + } + if (req->tags[i].bias > 0) { + add_resp.index = i; + add_resp.error = NEU_ERR_TAG_BIAS_INVALID; + break; + } } } - ret = neu_plugin_op(plugin, header, &cmd); - if (ret != 0) { - NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, { - neu_http_response(aio, NEU_ERR_IS_BUSY, result_error); - }); + if (add_resp.error > 0) { + handle_add_tags_resp(aio, &add_resp); + } else { + header.ctx = aio; + header.type = NEU_REQ_ADD_TAG; + strcpy(cmd.driver, req->node); + strcpy(cmd.group, req->group); + cmd.n_tag = req->n_tag; + cmd.tags = calloc(req->n_tag, sizeof(neu_datatag_t)); + + for (int i = 0; i < req->n_tag; i++) { + cmd.tags[i].attribute = req->tags[i].attribute; + cmd.tags[i].type = req->tags[i].type; + cmd.tags[i].precision = req->tags[i].precision; + cmd.tags[i].decimal = req->tags[i].decimal; + cmd.tags[i].bias = req->tags[i].bias; + cmd.tags[i].address = 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(""); + } + if (NEU_ATTRIBUTE_STATIC & req->tags[i].attribute) { + neu_tag_set_static_value_json(&cmd.tags[i], + req->tags[i].t, + &req->tags[i].value); + } + } + + int ret = neu_plugin_op(plugin, header, &cmd); + if (ret != 0) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, { + neu_http_response(aio, NEU_ERR_IS_BUSY, + result_error); + }); + } } } }) @@ -108,9 +138,11 @@ void handle_add_gtags(nng_aio *aio) neu_reqresp_head_t header = { 0 }; neu_req_add_gtag_t cmd = { 0 }; int err_type; - header.ctx = aio; - header.type = NEU_REQ_ADD_GTAG; - header.otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM; + int n_tags = 0; + neu_resp_add_tag_t add_resp = { 0 }; + header.ctx = aio; + header.type = NEU_REQ_ADD_GTAG; + header.otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM; if (strlen(req->node) >= NEU_NODE_NAME_LEN) { err_type = NEU_ERR_NODE_NAME_TOO_LONG; @@ -126,58 +158,90 @@ void handle_add_gtags(nng_aio *aio) err_type = NEU_ERR_GROUP_PARAMETER_INVALID; goto error; } - } - - strcpy(cmd.driver, req->node); - cmd.n_group = req->n_group; - cmd.groups = calloc(req->n_group, sizeof(neu_gdatatag_t)); - - for (int i = 0; i < req->n_group; i++) { - strcpy(cmd.groups[i].group, req->groups[i].group); - cmd.groups[i].n_tag = req->groups[i].n_tag; - cmd.groups[i].interval = req->groups[i].interval; - cmd.groups[i].tags = - calloc(cmd.groups[i].n_tag, sizeof(neu_datatag_t)); - for (int j = 0; j < req->groups[i].n_tag; j++) { - cmd.groups[i].tags[j].attribute = - req->groups[i].tags[j].attribute; - cmd.groups[i].tags[j].type = req->groups[i].tags[j].type; - cmd.groups[i].tags[j].precision = - req->groups[i].tags[j].precision; - cmd.groups[i].tags[j].decimal = - req->groups[i].tags[j].decimal; - cmd.groups[i].tags[j].bias = req->groups[i].tags[j].bias; - cmd.groups[i].tags[j].address = - strdup(req->groups[i].tags[j].address); - cmd.groups[i].tags[j].name = - strdup(req->groups[i].tags[j].name); - if (req->groups[i].tags[j].description != NULL) { - cmd.groups[i].tags[j].description = - strdup(req->groups[i].tags[j].description); - } else { - cmd.groups[i].tags[j].description = strdup(""); - } - if (NEU_ATTRIBUTE_STATIC & - req->groups[i].tags[j].attribute) { - neu_tag_set_static_value_json( - &cmd.groups[i].tags[j], req->groups[i].tags[j].t, - &req->groups[i].tags[j].value); + if (req->groups[i].tags[j].type == NEU_TYPE_STRING || + req->groups[i].tags[j].type == NEU_TYPE_BOOL || + req->groups[i].tags[j].type == NEU_TYPE_BIT || + req->groups[i].tags[j].type == NEU_TYPE_TIME || + req->groups[i].tags[j].type == NEU_TYPE_DATA_AND_TIME) { + if (req->groups[i].tags[j].precision > 0) { + add_resp.index = n_tags + j; + add_resp.error = NEU_ERR_TAG_PRECISION_INVALID; + break; + } + if (req->groups[i].tags[j].decimal > 0) { + add_resp.index = n_tags + j; + add_resp.error = NEU_ERR_TAG_DECIMAL_INVALID; + break; + } + if (req->groups[i].tags[j].bias > 0) { + add_resp.index = n_tags + j; + add_resp.error = NEU_ERR_TAG_BIAS_INVALID; + break; + } } } - } - ret = neu_plugin_op(plugin, header, &cmd); - if (ret != 0) { - NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, { - neu_http_response(aio, NEU_ERR_IS_BUSY, result_error); - }); + n_tags += req->groups[i].n_tag; + } + if (add_resp.error > 0) { + handle_add_tags_resp(aio, &add_resp); + } else { + strcpy(cmd.driver, req->node); + cmd.n_group = req->n_group; + cmd.groups = calloc(req->n_group, sizeof(neu_gdatatag_t)); + + for (int i = 0; i < req->n_group; i++) { + strcpy(cmd.groups[i].group, req->groups[i].group); + cmd.groups[i].n_tag = req->groups[i].n_tag; + cmd.groups[i].interval = req->groups[i].interval; + cmd.groups[i].tags = + calloc(cmd.groups[i].n_tag, sizeof(neu_datatag_t)); + + for (int j = 0; j < req->groups[i].n_tag; j++) { + cmd.groups[i].tags[j].attribute = + req->groups[i].tags[j].attribute; + cmd.groups[i].tags[j].type = + req->groups[i].tags[j].type; + cmd.groups[i].tags[j].precision = + req->groups[i].tags[j].precision; + cmd.groups[i].tags[j].decimal = + req->groups[i].tags[j].decimal; + cmd.groups[i].tags[j].bias = + req->groups[i].tags[j].bias; + cmd.groups[i].tags[j].address = + strdup(req->groups[i].tags[j].address); + cmd.groups[i].tags[j].name = + strdup(req->groups[i].tags[j].name); + if (req->groups[i].tags[j].description != NULL) { + cmd.groups[i].tags[j].description = + strdup(req->groups[i].tags[j].description); + } else { + cmd.groups[i].tags[j].description = strdup(""); + } + if (NEU_ATTRIBUTE_STATIC & + req->groups[i].tags[j].attribute) { + neu_tag_set_static_value_json( + &cmd.groups[i].tags[j], + req->groups[i].tags[j].t, + &req->groups[i].tags[j].value); + } + } + } + + ret = neu_plugin_op(plugin, header, &cmd); + if (ret != 0) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, { + neu_http_response(aio, NEU_ERR_IS_BUSY, result_error); + }); + } + goto success; + error: + NEU_JSON_RESPONSE_ERROR(err_type, { + neu_http_response(aio, err_type, result_error); + }); + success:; } - goto success; - error: - NEU_JSON_RESPONSE_ERROR( - err_type, { neu_http_response(aio, err_type, result_error); }); - success:; }) } diff --git a/plugins/restful/rw_handle.c b/plugins/restful/rw_handle.c index e4c02cb1..e24f2fcd 100644 --- a/plugins/restful/rw_handle.c +++ b/plugins/restful/rw_handle.c @@ -329,7 +329,6 @@ void handle_write(nng_aio *aio) case NEU_JSON_STR: cmd.value.type = NEU_TYPE_STRING; strcpy(cmd.value.value.str, req->value.val_str); - break; case NEU_JSON_BYTES: cmd.value.type = NEU_TYPE_BYTES; diff --git a/src/adapter/driver/driver.c b/src/adapter/driver/driver.c index 0a1ee574..b6278737 100644 --- a/src/adapter/driver/driver.c +++ b/src/adapter/driver/driver.c @@ -1002,7 +1002,7 @@ int is_value_in_range(neu_type_e tag_type, int64_t value, double value_d, case NEU_TYPE_STRING: case NEU_TYPE_BOOL: case NEU_TYPE_BIT: - return NEU_ERR_PARAM_IS_WRONG; + return NEU_ERR_TAG_DECIMAL_INVALID; default: return NEU_ERR_SUCCESS; } diff --git a/src/utils/http.c b/src/utils/http.c index 279911b7..46afb5b8 100644 --- a/src/utils/http.c +++ b/src/utils/http.c @@ -319,6 +319,7 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content) case NEU_ERR_TAG_ADDRESS_FORMAT_INVALID: case NEU_ERR_TAG_DESCRIPTION_TOO_LONG: case NEU_ERR_TAG_PRECISION_INVALID: + case NEU_ERR_TAG_DECIMAL_INVALID: case NEU_ERR_TAG_NAME_TOO_LONG: case NEU_ERR_TAG_ADDRESS_TOO_LONG: case NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH: diff --git a/tests/ft/neuron/error.py b/tests/ft/neuron/error.py index 597e47fb..9dac85b5 100644 --- a/tests/ft/neuron/error.py +++ b/tests/ft/neuron/error.py @@ -53,6 +53,7 @@ NEU_ERR_TAG_ADDRESS_TOO_LONG = 2207 NEU_ERR_TAG_DESCRIPTION_TOO_LONG = 2208 NEU_ERR_TAG_PRECISION_INVALID = 2209 NEU_ERR_TAG_EXIST = 2210 +NEU_ERR_TAG_DECIMAL_INVALID = 2211 NEU_ERR_TAG_BIAS_INVALID = 2212 NEU_ERR_LIBRARY_NOT_FOUND = 2301 diff --git a/tests/ft/tag/test_tag.py b/tests/ft/tag/test_tag.py index b61366e4..81d914fe 100644 --- a/tests/ft/tag/test_tag.py +++ b/tests/ft/tag/test_tag.py @@ -916,3 +916,34 @@ class TestTag: api.del_tags( node="modbus-tcp", group="group1", tags=[tag["name"]] ) + + @description(given="node and group", when="add string tag with decimal", then="add fail") + def test_add_string_tag_with_decimal(self): + string_decimal = [{"name": "string_decimal", "address": "1!400001.10", + "attribute": NEU_TAG_ATTRIBUTE_RW, "type": NEU_TYPE_STRING, "decimal": 0.1}] + response = api.add_tags(node="modbus-tcp", group="group1", tags=string_decimal) + assert 400 == response.status_code + assert NEU_ERR_TAG_DECIMAL_INVALID == response.json()['error'] + + @description(given="node and group", when="add string gtags with decimal", then="add fail") + def test_add_string_tag_with_decimal(self): + response = api.add_gtags( + node='modbus-tcp', + groups=[ + {"group": "group_ok","interval": 3000, + "tags": [{ + "name": "tag_string_ok", + "address": "1!400001.10", + "attribute": 3, + "type": NEU_TYPE_STRING}]}, + {"group": "group123","interval": 3000, + "tags": [{ + "name": "tag_string_decimal", + "address": "1!400001.10", + "attribute": 3, + "type": NEU_TYPE_STRING, + "decimal": 0.01}]} + ]) + assert 400 == response.status_code + assert NEU_ERR_TAG_DECIMAL_INVALID == response.json()['error'] + assert 1 == response.json()['index']