Merge pull request #1621 from hxy7yx/main-3

feat(restful): Add API for single-request bulk tag addition across multiple groups
This commit is contained in:
fengzeroz
2023-11-05 20:38:24 -06:00
committed by GitHub
18 changed files with 850 additions and 9 deletions
+17
View File
@@ -89,6 +89,8 @@ typedef enum neu_reqresp_type {
NEU_REQ_ADD_TAG,
NEU_RESP_ADD_TAG,
NEU_REQ_ADD_GTAG,
NEU_RESP_ADD_GTAG,
NEU_REQ_DEL_TAG,
NEU_REQ_UPDATE_TAG,
NEU_RESP_UPDATE_TAG,
@@ -197,6 +199,8 @@ static const char *neu_reqresp_type_string_t[] = {
[NEU_REQ_ADD_TAG] = "NEU_REQ_ADD_TAG",
[NEU_RESP_ADD_TAG] = "NEU_RESP_ADD_TAG",
[NEU_REQ_ADD_GTAG] = "NEU_REQ_ADD_GTAG",
[NEU_RESP_ADD_GTAG] = "NEU_RESP_ADD_GTAG",
[NEU_REQ_DEL_TAG] = "NEU_REQ_DEL_TAG",
[NEU_REQ_UPDATE_TAG] = "NEU_REQ_UPDATE_TAG",
[NEU_RESP_UPDATE_TAG] = "NEU_RESP_UPDATE_TAG",
@@ -384,6 +388,19 @@ typedef struct neu_resp_get_group {
UT_array *groups; // array neu_resp_group_info_t
} neu_resp_get_group_t;
typedef struct {
char group[NEU_GROUP_NAME_LEN];
int n_tag;
int interval;
neu_datatag_t *tags;
} neu_gdatatag_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
uint16_t n_group;
neu_gdatatag_t *groups;
} neu_req_add_gtag_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
+1
View File
@@ -27,6 +27,7 @@
#define NEU_TAG_DESCRIPTION_LEN 128
#define NEU_GROUP_NAME_LEN 128
#define NEU_GROUP_INTERVAL_LIMIT 100
#define NEU_DEFAULT_GROUP_INTERVAL 100
#define NEU_NODE_NAME_LEN 128
#define NEU_PLUGIN_NAME_LEN 32
#define NEU_PLUGIN_LIBRARY_LEN 32
+92
View File
@@ -96,6 +96,98 @@ void handle_add_tags_resp(nng_aio *aio, neu_resp_add_tag_t *resp)
free(result);
}
void handle_add_gtags(nng_aio *aio)
{
neu_plugin_t *plugin = neu_rest_get_plugin();
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
aio, neu_json_add_gtags_req_t, neu_json_decode_add_gtags_req, {
int ret = 0;
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;
for (int i = 0; i < req->n_group; i++) {
if (strlen(req->groups[i].group) >= NEU_GROUP_NAME_LEN) {
err_type = NEU_ERR_GROUP_NAME_TOO_LONG;
goto error;
}
if (req->groups[i].interval < NEU_DEFAULT_GROUP_INTERVAL) {
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].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:;
})
}
void handle_add_gtags_resp(nng_aio *aio, neu_resp_add_tag_t *resp)
{
neu_json_add_gtag_res_t res = { 0 };
char * result = NULL;
res.error = resp->error;
res.index = resp->index;
neu_json_encode_by_fn(&res, neu_json_encode_au_gtags_resp, &result);
neu_http_ok(aio, result);
free(result);
}
void handle_del_tags(nng_aio *aio)
{
neu_plugin_t *plugin = neu_rest_get_plugin();
+2
View File
@@ -26,6 +26,8 @@
void handle_add_tags(nng_aio *aio);
void handle_add_tags_resp(nng_aio *aio, neu_resp_add_tag_t *resp);
void handle_add_gtags(nng_aio *aio);
void handle_add_gtags_resp(nng_aio *aio, neu_resp_add_tag_t *resp);
void handle_del_tags(nng_aio *aio);
void handle_update_tags(nng_aio *aio);
void handle_update_tags_resp(nng_aio *aio, neu_resp_update_tag_t *resp);
+9 -1
View File
@@ -56,6 +56,9 @@ static struct neu_http_handler cors_handler[] = {
{
.url = "/api/v2/tags",
},
{
.url = "/api/v2/gtags",
},
{
.url = "/api/v2/group",
},
@@ -183,12 +186,17 @@ static struct neu_http_handler rest_handlers[] = {
.value.handler = handle_add_tags,
},
{
.method = NEU_HTTP_METHOD_POST,
.type = NEU_HTTP_HANDLER_FUNCTION,
.url = "/api/v2/gtags",
.value.handler = handle_add_gtags,
},
{
.method = NEU_HTTP_METHOD_PUT,
.type = NEU_HTTP_HANDLER_FUNCTION,
.url = "/api/v2/tags",
.value.handler = handle_update_tags,
},
{
.method = NEU_HTTP_METHOD_GET,
+3
View File
@@ -198,6 +198,9 @@ static int dashb_plugin_request(neu_plugin_t * plugin,
case NEU_RESP_ADD_TEMPLATE_TAG:
handle_add_tags_resp(header->ctx, (neu_resp_add_tag_t *) data);
break;
case NEU_RESP_ADD_GTAG:
handle_add_gtags_resp(header->ctx, (neu_resp_add_tag_t *) data);
break;
case NEU_RESP_UPDATE_TAG:
case NEU_RESP_UPDATE_TEMPLATE_TAG:
handle_update_tags_resp(header->ctx, (neu_resp_update_tag_t *) data);
+87 -1
View File
@@ -454,6 +454,11 @@ static int adapter_command(neu_adapter_t *adapter, neu_reqresp_head_t header,
strcpy(pheader->receiver, cmd->driver);
break;
}
case NEU_REQ_ADD_GTAG: {
neu_req_add_gtag_t *cmd = (neu_req_add_gtag_t *) data;
strcpy(pheader->receiver, cmd->driver);
break;
}
case NEU_REQ_UPDATE_NODE:
case NEU_REQ_NODE_CTL:
case NEU_REQ_GET_NODE_STATE:
@@ -639,6 +644,7 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
case NEU_REQ_UPDATE_GROUP:
case NEU_RESP_GET_SUBSCRIBE_GROUP:
case NEU_RESP_ADD_TAG:
case NEU_RESP_ADD_GTAG:
case NEU_RESP_ADD_TEMPLATE_TAG:
case NEU_RESP_UPDATE_TAG:
case NEU_RESP_UPDATE_TEMPLATE_TAG:
@@ -998,7 +1004,8 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
for (int i = 0; i < resp.index; i++) {
int ret = neu_adapter_driver_add_tag(
(neu_adapter_driver_t *) adapter, cmd->group, &cmd->tags[i]);
(neu_adapter_driver_t *) adapter, cmd->group, &cmd->tags[i],
NEU_DEFAULT_GROUP_INTERVAL);
if (ret != 0) {
neu_adapter_driver_try_del_tag((neu_adapter_driver_t *) adapter,
resp.index - i);
@@ -1027,6 +1034,81 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
reply(adapter, header, &resp);
break;
}
case NEU_REQ_ADD_GTAG: {
neu_req_add_gtag_t *cmd = (neu_req_add_gtag_t *) &header[1];
neu_resp_add_tag_t resp = { 0 };
if (adapter->module->type == NEU_NA_TYPE_DRIVER) {
for (int i = 0; i < cmd->n_group; i++) {
for (int j = 0; j < cmd->groups[i].n_tag; j++) {
int ret = neu_adapter_driver_validate_tag(
(neu_adapter_driver_t *) adapter, cmd->groups[i].group,
&cmd->groups[i].tags[j]);
if (ret == 0) {
resp.index += 1;
} else {
resp.error = ret;
resp.index = 0;
i = cmd->n_group;
break;
}
}
}
} else {
resp.error = NEU_ERR_GROUP_NOT_ALLOW;
}
if (resp.index > 0) {
for (int i = 0; i < cmd->n_group; i++) {
int ret = neu_adapter_driver_try_add_tag(
(neu_adapter_driver_t *) adapter, cmd->groups[i].group,
cmd->groups[i].tags, cmd->groups[i].n_tag);
if (ret != 0) {
resp.index = 0;
resp.error = ret;
break;
}
}
}
if (resp.index > 0) {
for (int i = 0; i < cmd->n_group; i++) {
for (int j = 0; j < cmd->groups[i].n_tag; j++) {
int ret = neu_adapter_driver_add_tag(
(neu_adapter_driver_t *) adapter, cmd->groups[i].group,
&cmd->groups[i].tags[j], cmd->groups[i].interval);
if (ret != 0) {
neu_adapter_driver_try_del_tag(
(neu_adapter_driver_t *) adapter,
cmd->groups[i].n_tag - j);
resp.index = 0;
i = cmd->n_group;
resp.error = ret;
break;
}
}
}
}
if (resp.index) {
for (int i = 0; i < cmd->n_group; i++) {
adapter_storage_add_tags(cmd->driver, cmd->groups[i].group,
cmd->groups[i].tags,
cmd->groups[i].n_tag);
}
}
for (int i = 0; i < cmd->n_group; i++) {
for (int j = 0; j < cmd->groups[i].n_tag; j++) {
neu_tag_fini(&cmd->groups[i].tags[j]);
}
free(cmd->groups[i].tags);
}
free(cmd->groups);
neu_msg_exchange(header);
header->type = NEU_RESP_ADD_GTAG;
reply(adapter, header, &resp);
break;
}
case NEU_REQ_UPDATE_TAG: {
neu_req_update_tag_t *cmd = (neu_req_update_tag_t *) &header[1];
neu_resp_update_tag_t resp = { 0 };
@@ -1643,9 +1725,13 @@ void neu_msg_gen(neu_reqresp_head_t *header, void *data)
data_size = sizeof(neu_req_add_tag_t);
break;
case NEU_RESP_ADD_TAG:
case NEU_RESP_ADD_GTAG:
case NEU_RESP_ADD_TEMPLATE_TAG:
data_size = sizeof(neu_resp_add_tag_t);
break;
case NEU_REQ_ADD_GTAG:
data_size = sizeof(neu_req_add_gtag_t);
break;
case NEU_RESP_UPDATE_TAG:
case NEU_RESP_UPDATE_TEMPLATE_TAG:
data_size = sizeof(neu_resp_update_tag_t);
+3 -3
View File
@@ -1195,7 +1195,7 @@ int neu_adapter_driver_validate_tag(neu_adapter_driver_t *driver,
}
int neu_adapter_driver_add_tag(neu_adapter_driver_t *driver, const char *group,
neu_datatag_t *tag)
neu_datatag_t *tag, uint16_t interval)
{
int ret = NEU_ERR_SUCCESS;
group_t *find = NULL;
@@ -1206,8 +1206,8 @@ int neu_adapter_driver_add_tag(neu_adapter_driver_t *driver, const char *group,
HASH_FIND_STR(driver->groups, group, find);
if (find == NULL) {
neu_adapter_driver_add_group(driver, group, 100);
adapter_storage_add_group(driver->adapter.name, group, 100);
neu_adapter_driver_add_group(driver, group, interval);
adapter_storage_add_group(driver->adapter.name, group, interval);
}
HASH_FIND_STR(driver->groups, group, find);
assert(find != NULL);
+1 -1
View File
@@ -65,7 +65,7 @@ int neu_adapter_driver_validate_tag(neu_adapter_driver_t *driver,
const char *group, neu_datatag_t *tag);
int neu_adapter_driver_add_tag(neu_adapter_driver_t *driver, const char *group,
neu_datatag_t *tag);
neu_datatag_t *tag, uint16_t interval);
int neu_adapter_driver_del_tag(neu_adapter_driver_t *driver, const char *group,
const char *tag);
int neu_adapter_driver_update_tag(neu_adapter_driver_t *driver,
+1 -1
View File
@@ -156,7 +156,7 @@ int adapter_load_group_and_tag(neu_adapter_driver_t *driver)
utarray_foreach(tags, neu_datatag_t *, tag)
{
neu_adapter_driver_add_tag(driver, p->name, tag);
neu_adapter_driver_add_tag(driver, p->name, tag, -1);
neu_adapter_driver_load_tag(driver, p->name, tag, 1);
}
+23
View File
@@ -1379,6 +1379,28 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}
case NEU_REQ_ADD_GTAG: {
neu_req_add_gtag_t *cmd = (neu_req_add_gtag_t *) &header[1];
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
NULL) {
neu_resp_error_t e = { .error = NEU_ERR_NODE_NOT_EXIST };
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(manager, header, &e);
for (int i = 0; i < cmd->n_group; i++) {
for (int j = 0; j < cmd->groups[i].n_tag; j++) {
neu_tag_fini(&cmd->groups[i].tags[j]);
}
free(cmd->groups[i].tags);
}
free(cmd->groups);
} else {
forward_msg(manager, header, header->receiver);
}
break;
}
case NEU_REQ_NODE_SETTING: {
neu_req_node_setting_t *cmd = (neu_req_node_setting_t *) &header[1];
@@ -1396,6 +1418,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
}
case NEU_RESP_ADD_TAG:
case NEU_RESP_ADD_GTAG:
case NEU_RESP_ADD_TEMPLATE_TAG:
case NEU_RESP_UPDATE_TAG:
case NEU_RESP_UPDATE_TEMPLATE_TAG:
+1 -1
View File
@@ -536,7 +536,7 @@ static int add_template_group(neu_group_t *grp, void *data)
break;
}
ret = neu_adapter_driver_add_tag(driver, name, tag);
ret = neu_adapter_driver_add_tag(driver, name, tag, -1);
if (0 != ret) {
break;
}
+207
View File
@@ -427,6 +427,213 @@ int neu_json_encode_au_tags_resp(void *json_object, void *param)
return ret;
}
int neu_json_decode_gtag_json(void *json_obj, neu_json_gtag_t *gtag_p)
{
if (NULL == gtag_p) {
return -1;
}
neu_json_elem_t gtag_elems[] = { {
.name = "group",
.t = NEU_JSON_STR,
},
{
.name = "interval",
.t = NEU_JSON_INT,
},
{
.name = "tags",
.t = NEU_JSON_OBJECT,
} };
int ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(gtag_elems),
gtag_elems);
if (0 != ret) {
goto decode_fail;
}
neu_json_tag_array_t arr = { 0 };
ret = neu_json_decode_tag_array_json(gtag_elems[2].v.val_object, &arr);
if (ret != 0) {
goto decode_fail;
}
if (arr.len <= 0) {
goto decode_fail;
}
gtag_p->group = gtag_elems[0].v.val_str;
gtag_p->interval = gtag_elems[1].v.val_int;
gtag_p->n_tag = arr.len;
gtag_p->tags = arr.tags;
goto decode_exit;
decode_fail:
free(gtag_p);
free(gtag_elems[0].v.val_str);
return -1;
decode_exit:
if (json_obj != NULL) {
neu_json_decode_free(json_obj);
}
return 0;
}
void neu_json_decode_gtag_fini(neu_json_gtag_t *gtag)
{
free(gtag->group);
for (int i = 0; i < gtag->n_tag; i++) {
neu_json_decode_tag_fini(&(gtag->tags[i]));
}
free(gtag->tags);
}
int neu_json_decode_gtag_array_json(void *json_obj, neu_json_gtag_array_t *arr)
{
int len = 0;
neu_json_gtag_t *gtags = NULL;
if (!json_is_array((json_t *) json_obj)) {
return -1;
}
len = json_array_size(json_obj);
if (0 == len) {
arr->len = 0;
arr->gtags = NULL;
return 0;
}
gtags = calloc(len, sizeof(*gtags));
if (NULL == gtags) {
return -1;
}
int i = 0;
for (i = 0; i < len; i++) {
json_t *tag_obj = json_array_get(json_obj, i);
if (0 != neu_json_decode_gtag_json(tag_obj, &gtags[i])) {
goto decode_fail;
}
}
arr->len = len;
arr->gtags = gtags;
return 0;
decode_fail:
while (--i > 0) {
neu_json_decode_gtag_fini(&gtags[i]);
}
free(gtags);
return -1;
}
void neu_json_decode_gtag_array_fini(neu_json_gtag_array_t *arr)
{
for (int i = 0; i < arr->len; ++i) {
neu_json_decode_gtag_fini(&arr->gtags[i]);
}
free(arr->gtags);
}
int neu_json_decode_add_gtags_req(char *buf, neu_json_add_gtags_req_t **result)
{
int ret = 0;
void * json_obj = NULL;
neu_json_add_gtags_req_t *req = calloc(1, sizeof(neu_json_add_gtags_req_t));
if (req == NULL) {
return -1;
}
json_obj = neu_json_decode_new(buf);
if (NULL == json_obj) {
goto decode_fail;
}
neu_json_elem_t req_elems[] = {
{
.name = "node",
.t = NEU_JSON_STR,
},
{
.name = "groups",
.t = NEU_JSON_OBJECT,
},
};
ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
req_elems);
if (ret != 0) {
goto decode_fail;
}
neu_json_gtag_array_t arr = { 0 };
ret = neu_json_decode_gtag_array_json(req_elems[1].v.val_object, &arr);
if (ret != 0) {
goto decode_fail;
}
if (arr.len <= 0) {
goto decode_fail;
}
req->node = req_elems[0].v.val_str;
req->n_group = arr.len;
req->groups = arr.gtags;
*result = req;
goto decode_exit;
decode_fail:
free(req);
free(req_elems[0].v.val_str);
ret = -1;
decode_exit:
if (json_obj != NULL) {
neu_json_decode_free(json_obj);
}
return ret;
}
void neu_json_decode_add_gtags_req_free(neu_json_add_gtags_req_t *req)
{
if (NULL == req) {
return;
}
neu_json_gtag_array_t arr = {
.len = req->n_group,
.gtags = req->groups,
};
neu_json_decode_gtag_array_fini(&arr);
free(req->node);
free(req);
}
int neu_json_encode_au_gtags_resp(void *json_object, void *param)
{
int ret = 0;
neu_json_add_gtag_res_t *resp = (neu_json_add_gtag_res_t *) param;
neu_json_elem_t resp_elems[] = {
{
.name = "index",
.t = NEU_JSON_INT,
.v.val_int = resp->index,
},
{
.name = "error",
.t = NEU_JSON_INT,
.v.val_int = resp->error,
},
};
ret = neu_json_encode_field(json_object, resp_elems,
NEU_JSON_ELEM_SIZE(resp_elems));
return ret;
}
int neu_json_encode_del_tags_req(void *json_object, void *param)
{
int ret = 0;
+34
View File
@@ -75,6 +75,40 @@ typedef struct {
int neu_json_encode_au_tags_resp(void *json_object, void *param);
typedef struct {
char * group;
int n_tag;
int interval;
neu_json_tag_t *tags;
} neu_json_gtag_t;
int neu_json_decode_gtag_json(void *json_obj, neu_json_gtag_t *gtag_p);
void neu_json_decode_gtag_fini(neu_json_gtag_t *gtag);
typedef struct {
int len;
neu_json_gtag_t *gtags;
} neu_json_gtag_array_t;
int neu_json_decode_gtag_array_json(void *json_obj, neu_json_gtag_array_t *arr);
void neu_json_decode_gtag_array_fini(neu_json_gtag_array_t *arr);
typedef struct {
char * node;
int n_group;
neu_json_gtag_t *groups;
} neu_json_add_gtags_req_t;
int neu_json_decode_add_gtags_req(char *buf, neu_json_add_gtags_req_t **result);
void neu_json_decode_add_gtags_req_free(neu_json_add_gtags_req_t *req);
typedef struct {
uint16_t index;
int error;
} neu_json_add_gtag_res_t, neu_json_update_gtag_res_t;
int neu_json_encode_au_gtags_resp(void *json_object, void *param);
typedef char *neu_json_del_tags_req_name_t;
typedef struct {
+7
View File
@@ -110,11 +110,18 @@ def update_group(node, group, new_name="", interval=0):
else:
assert False
@gen_check
def get_group():
return requests.get(url=config.BASE_URL + '/api/v2/group', headers={"Authorization": config.default_jwt})
@gen_check
def add_tags(node, group, tags):
return requests.post(url=config.BASE_URL + '/api/v2/tags', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "tags": tags})
@gen_check
def add_gtags(node, groups):
return requests.post(url=config.BASE_URL + '/api/v2/gtags', headers={"Authorization": config.default_jwt}, json={"node": node, "groups": groups})
@gen_check
def del_tags(node, group, tags):
+1 -1
View File
@@ -52,4 +52,4 @@ def start_simulator(args, dir='build/simulator'):
def stop_simulator(process):
process.terminate()
process.terminate()
+3
View File
@@ -0,0 +1,3 @@
import sys
sys.path.append("tests/ft")
+358
View File
@@ -0,0 +1,358 @@
import neuron.api as api
from neuron.config import *
from neuron.common import *
from neuron.error import *
class TestLog:
@description(given="multiple non-existing groups and multiple correct tags",
when="adding",
then="successfully added")
def test_adding_correct_gtags_nonexisting_groups(self):
response = api.add_node(node='modbus-tcp-tag-test', plugin=PLUGIN_MODBUS_TCP)
assert 200 == response.status_code
assert 0 == response.json()['error']
response = api.add_gtags(
node='modbus-tcp-tag-test',
groups=[
{
"group": "group_1",
"interval": 3000,
"tags": [
{
"name": "tag1",
"address": "1!400001",
"attribute": 3,
"type": 3,
"decimal": 0.01
},
{
"name": "tag2",
"address": "1!400002",
"attribute": 3,
"type": 9,
"precision": 3
}
]
},
{
"group": "group_2",
"interval": 300,
"tags": [
{
"name": "tag1",
"address": "1!400003",
"attribute": 3,
"type": 9,
"precision": 3
},
{
"name": "tag2",
"address": "1!400004",
"attribute": 3,
"type": 9,
"precision": 3
}
]
}
]
)
assert 200 == response.status_code
assert NEU_ERR_SUCCESS == response.json()['error']
response = api.get_group()
assert 200 == response.status_code
assert 'group_1' == response.json()['groups'][0]['group']
assert 3000 == response.json()['groups'][0]['interval']
assert 2 == response.json()['groups'][0]['tag_count']
assert 'group_2' == response.json()['groups'][1]['group']
assert 300 == response.json()['groups'][1]['interval']
assert 2 == response.json()['groups'][1]['tag_count']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_1')
assert 200 == response.status_code
assert 'tag1' == response.json()['tags'][0]['name']
assert '1!400001' == response.json()['tags'][0]['address']
assert 0.01 == response.json()['tags'][0]['decimal']
assert 3 == response.json()['tags'][0]['type']
assert 3 == response.json()['tags'][0]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_1')
assert 200 == response.status_code
assert 'tag2' == response.json()['tags'][1]['name']
assert '1!400002' == response.json()['tags'][1]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_2')
assert 200 == response.status_code
assert 'tag1' == response.json()['tags'][0]['name']
assert '1!400003' == response.json()['tags'][0]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_2')
assert 200 == response.status_code
assert 'tag2' == response.json()['tags'][1]['name']
assert '1!400004' == response.json()['tags'][1]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
@description(given="multiple groups including partly existing ones and multiple correct tags", when="adding", then="successfully added")
def test_adding_correct_gtags_existing_groups(self):
response = api.add_gtags(
node='modbus-tcp-tag-test',
groups=[
{
"group": "group_1",
"interval": 3000,
"tags": [
{
"name": "tag3",
"address": "1!400005",
"attribute": 3,
"type": 3,
"decimal": 0.01
},
{
"name": "tag4",
"address": "1!400006",
"attribute": 3,
"type": 9,
"precision": 3
}
]
},
{
"group": "group_3",
"interval": 3000,
"tags": [
{
"name": "tag1",
"address": "1!400007",
"attribute": 3,
"type": 9,
"precision": 3
},
{
"name": "tag2",
"address": "1!400008",
"attribute": 3,
"type": 9,
"precision": 3
}
]
}
]
)
assert 200 == response.status_code
assert NEU_ERR_SUCCESS == response.json()['error']
response = api.get_group()
assert 200 == response.status_code
assert 'group_1' == response.json()['groups'][0]['group']
assert 3000 == response.json()['groups'][0]['interval']
assert 4 == response.json()['groups'][0]['tag_count']
assert 'group_2' == response.json()['groups'][1]['group']
assert 300 == response.json()['groups'][1]['interval']
assert 2 == response.json()['groups'][1]['tag_count']
assert 'group_3' == response.json()['groups'][2]['group']
assert 3000 == response.json()['groups'][2]['interval']
assert 2 == response.json()['groups'][2]['tag_count']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_1')
assert 200 == response.status_code
assert 'tag1' == response.json()['tags'][0]['name']
assert '1!400001' == response.json()['tags'][0]['address']
assert 0.01 == response.json()['tags'][0]['decimal']
assert 3 == response.json()['tags'][0]['type']
assert 3 == response.json()['tags'][0]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_1')
assert 200 == response.status_code
assert 'tag2' == response.json()['tags'][1]['name']
assert '1!400002' == response.json()['tags'][1]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_1')
assert 200 == response.status_code
assert 'tag3' == response.json()['tags'][2]['name']
assert '1!400005' == response.json()['tags'][2]['address']
assert 0.01 == response.json()['tags'][2]['decimal']
assert 3 == response.json()['tags'][2]['type']
assert 3 == response.json()['tags'][2]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_1')
assert 200 == response.status_code
assert 'tag4' == response.json()['tags'][3]['name']
assert '1!400006' == response.json()['tags'][3]['address']
assert 3 == response.json()['tags'][3]['precision']
assert 9 == response.json()['tags'][3]['type']
assert 3 == response.json()['tags'][3]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_2')
assert 200 == response.status_code
assert 'tag1' == response.json()['tags'][0]['name']
assert '1!400003' == response.json()['tags'][0]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_2')
assert 200 == response.status_code
assert 'tag2' == response.json()['tags'][1]['name']
assert '1!400004' == response.json()['tags'][1]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_3')
assert 200 == response.status_code
assert 'tag1' == response.json()['tags'][0]['name']
assert '1!400007' == response.json()['tags'][0]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
response = api.get_tags(node='modbus-tcp-tag-test', group='group_3')
assert 200 == response.status_code
assert 'tag2' == response.json()['tags'][1]['name']
assert '1!400008' == response.json()['tags'][1]['address']
assert 3 == response.json()['tags'][1]['precision']
assert 9 == response.json()['tags'][1]['type']
assert 3 == response.json()['tags'][1]['attribute']
@description(given="multiple groups and tags with errors", when="adding", then="error reported, unable to add")
def test_adding_gtags_type_err(self):
response = api.add_gtags(
node='modbus-tcp-tag-test',
groups=[
{
"group": "group_4",
"interval": 3000,
"tags": [
{
"name": "tag1",
"address": "1!000009",
"attribute": 3,
"type": 3,
"decimal": 0.01
},
{
"name": "tag4",
"address": "1!400010",
"attribute": 3,
"type": 9,
"precision": 3
}
]
},
{
"group": "group_5",
"interval": 3000,
"tags": [
{
"name": "tag1",
"address": "1!400011",
"attribute": 3,
"type": 9,
"precision": 3
},
{
"name": "tag2",
"address": "1!400012",
"attribute": 3,
"type": 9,
"precision": 3
}
]
}
]
)
assert 200 == response.status_code
assert NEU_ERR_TAG_TYPE_NOT_SUPPORT == response.json()['error']
response = api.get_group()
assert 200 == response.status_code
assert 'group_1' == response.json()['groups'][0]['group']
assert 3000 == response.json()['groups'][0]['interval']
assert 4 == response.json()['groups'][0]['tag_count']
assert 'group_2' == response.json()['groups'][1]['group']
assert 300 == response.json()['groups'][1]['interval']
assert 2 == response.json()['groups'][1]['tag_count']
assert 'group_3' == response.json()['groups'][2]['group']
assert 3000 == response.json()['groups'][2]['interval']
assert 2 == response.json()['groups'][2]['tag_count']
@description(given="multiple groups and conflicting tag names", when="adding", then="error reported, unable to add")
def test_adding_gtags_name_err(self):
response = api.add_gtags(
node='modbus-tcp-tag-test',
groups=[
{
"group": "group_1",
"interval": 3000,
"tags": [
{
"name": "tag1",
"address": "1!400001",
"attribute": 3,
"type": 3,
"decimal": 0.01
},
{
"name": "tag2",
"address": "1!400002",
"attribute": 3,
"type": 9,
"precision": 3
}
]
},
{
"group": "group_2",
"interval": 3000,
"tags": [
{
"name": "tag1",
"address": "1!400003",
"attribute": 3,
"type": 9,
"precision": 3
},
{
"name": "tag2",
"address": "1!400004",
"attribute": 3,
"type": 9,
"precision": 3
}
]
}
]
)
assert 200 == response.status_code
assert NEU_ERR_TAG_NAME_CONFLICT == response.json()['error']
response = api.get_group()
assert 200 == response.status_code
assert 'group_1' == response.json()['groups'][0]['group']
assert 3000 == response.json()['groups'][0]['interval']
assert 4 == response.json()['groups'][0]['tag_count']
assert 'group_2' == response.json()['groups'][1]['group']
assert 300 == response.json()['groups'][1]['interval']
assert 2 == response.json()['groups'][1]['tag_count']
assert 'group_3' == response.json()['groups'][2]['group']
assert 3000 == response.json()['groups'][2]['interval']
assert 2 == response.json()['groups'][2]['tag_count']