feat(read):support pagination and filter(error) when reading tags

This commit is contained in:
hxy7yx
2024-06-03 16:03:26 +08:00
parent a5f912b658
commit 411cdc4f02
14 changed files with 1331 additions and 17 deletions
+42
View File
@@ -62,6 +62,30 @@ typedef struct {
int neu_json_encode_read_resp(void *json_object, void *param);
int neu_json_encode_read_resp1(void *json_object, void *param);
int neu_json_encode_read_paginate_resp(void *json_object, void *param);
typedef struct {
int64_t error;
char * name;
enum neu_json_type t;
union neu_json_value value;
uint8_t precision;
int n_meta;
neu_json_tag_meta_t *metas;
neu_datatag_t datatag;
} neu_json_read_paginate_resp_tag_t;
typedef struct {
unsigned int current_page;
unsigned int page_size;
unsigned int total;
} neu_json_read_meta_resp_t;
typedef struct {
neu_json_read_meta_resp_t meta;
int n_tag;
neu_json_read_paginate_resp_tag_t *tags;
} neu_json_read_paginate_resp_t;
typedef struct {
char * group;
@@ -134,10 +158,28 @@ typedef struct {
int neu_json_decode_read_req(char *buf, neu_json_read_req_t **result);
void neu_json_decode_read_req_free(neu_json_read_req_t *req);
typedef struct {
char *group;
char *node;
char *name;
char *desc;
bool sync;
int current_page;
int page_size;
bool is_error;
} neu_json_read_paginate_req_t;
int neu_json_decode_read_paginate_req(char * buf,
neu_json_read_paginate_req_t **result);
void neu_json_decode_read_paginate_req_free(neu_json_read_paginate_req_t *req);
int neu_json_encode_read_periodic_resp(void *json_object, void *param);
void neu_json_metas_to_json(neu_tag_meta_t *metas, int n_meta,
neu_json_read_resp_tag_t *json_tag);
void neu_json_metas_to_json_paginate(
neu_tag_meta_t *metas, int n_meta,
neu_json_read_paginate_resp_tag_t *json_tag);
#ifdef __cplusplus
}
+191 -5
View File
@@ -46,6 +46,8 @@ typedef enum neu_reqresp_type {
NEU_REQ_READ_GROUP,
NEU_RESP_READ_GROUP,
NEU_REQ_READ_GROUP_PAGINATE,
NEU_RESP_READ_GROUP_PAGINATE,
NEU_REQ_WRITE_TAG,
NEU_REQ_WRITE_TAGS,
NEU_REQ_WRITE_GTAGS,
@@ -123,11 +125,13 @@ typedef enum neu_reqresp_type {
static const char *neu_reqresp_type_string_t[] = {
[NEU_RESP_ERROR] = "NEU_RESP_ERROR",
[NEU_REQ_READ_GROUP] = "NEU_REQ_READ_GROUP",
[NEU_RESP_READ_GROUP] = "NEU_RESP_READ_GROUP",
[NEU_REQ_WRITE_TAG] = "NEU_REQ_WRITE_TAG",
[NEU_REQ_WRITE_TAGS] = "NEU_REQ_WRITE_TAGS",
[NEU_REQ_WRITE_GTAGS] = "NEU_REQ_WRITE_GTAGS",
[NEU_REQ_READ_GROUP] = "NEU_REQ_READ_GROUP",
[NEU_RESP_READ_GROUP] = "NEU_RESP_READ_GROUP",
[NEU_REQ_READ_GROUP_PAGINATE] = "NEU_REQ_READ_GROUP_PAGINATE",
[NEU_RESP_READ_GROUP_PAGINATE] = "NEU_RESP_READ_GROUP_PAGINATE",
[NEU_REQ_WRITE_TAG] = "NEU_REQ_WRITE_TAG",
[NEU_REQ_WRITE_TAGS] = "NEU_REQ_WRITE_TAGS",
[NEU_REQ_WRITE_GTAGS] = "NEU_REQ_WRITE_GTAGS",
[NEU_REQ_SUBSCRIBE_GROUP] = "NEU_REQ_SUBSCRIBE_GROUP",
[NEU_REQ_UNSUBSCRIBE_GROUP] = "NEU_REQ_UNSUBSCRIBE_GROUP",
@@ -619,6 +623,26 @@ static inline void neu_req_read_group_fini(neu_req_read_group_t *req)
free(req->desc);
}
typedef struct neu_req_read_group_paginate {
char *driver;
char *group;
char *name;
char *desc;
bool sync;
int current_page;
int page_size;
bool is_error;
} neu_req_read_group_paginate_t;
static inline void
neu_req_read_group_paginate_fini(neu_req_read_group_paginate_t *req)
{
free(req->driver);
free(req->group);
free(req->name);
free(req->desc);
}
typedef struct neu_req_write_tag {
char * driver;
char * group;
@@ -701,6 +725,30 @@ typedef struct {
UT_array *tags; // neu_resp_tag_value_meta_t
} neu_resp_read_group_t;
typedef struct neu_resp_tag_value_meta_paginate {
char tag[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
neu_tag_meta_t metas[NEU_TAG_META_SIZE];
neu_datatag_t datatag;
} neu_resp_tag_value_meta_paginate_t;
static inline UT_icd *neu_resp_tag_value_meta_paginate_icd()
{
static UT_icd icd = { sizeof(neu_resp_tag_value_meta_paginate_t), NULL,
NULL, NULL };
return &icd;
}
typedef struct {
char *driver;
char *group;
int current_page;
int page_size;
bool is_error;
UT_array *tags; // neu_resp_tag_value_meta_paginate_t
} neu_resp_read_group_paginate_t;
static inline void neu_resp_read_free(neu_resp_read_group_t *resp)
{
utarray_foreach(resp->tags, neu_resp_tag_value_meta_t *, tag_value)
@@ -714,6 +762,20 @@ static inline void neu_resp_read_free(neu_resp_read_group_t *resp)
utarray_free(resp->tags);
}
static inline void
neu_resp_read_paginate_free(neu_resp_read_group_paginate_t *resp)
{
utarray_foreach(resp->tags, neu_resp_tag_value_meta_t *, tag_value)
{
if (tag_value->value.type == NEU_TYPE_PTR) {
free(tag_value->value.value.ptr.ptr);
}
}
free(resp->driver);
free(resp->group);
utarray_free(resp->tags);
}
typedef struct {
uint16_t index;
pthread_mutex_t mtx;
@@ -897,6 +959,130 @@ static inline void neu_tag_value_to_json(neu_resp_tag_value_meta_t *tag_value,
}
}
static inline void
neu_tag_value_to_json_paginate(neu_resp_tag_value_meta_paginate_t *tag_value,
neu_json_read_paginate_resp_tag_t * tag_json)
{
tag_json->name = tag_value->tag;
tag_json->error = 0;
tag_json->datatag.name = strdup(tag_value->datatag.name);
tag_json->datatag.address = strdup(tag_value->datatag.address);
tag_json->datatag.attribute = tag_value->datatag.attribute;
tag_json->datatag.type = tag_value->datatag.type;
tag_json->datatag.precision = tag_value->datatag.precision;
tag_json->datatag.decimal = tag_value->datatag.decimal;
tag_json->datatag.bias = tag_value->datatag.bias;
tag_json->datatag.description = strdup(tag_value->datatag.description);
tag_json->datatag.option = tag_value->datatag.option;
memcpy(tag_json->datatag.meta, tag_value->datatag.meta,
NEU_TAG_META_LENGTH);
for (int k = 0; k < NEU_TAG_META_SIZE; k++) {
if (strlen(tag_value->metas[k].name) > 0) {
tag_json->n_meta++;
} else {
break;
}
}
if (tag_json->n_meta > 0) {
tag_json->metas = (neu_json_tag_meta_t *) calloc(
tag_json->n_meta, sizeof(neu_json_tag_meta_t));
}
neu_json_metas_to_json_paginate(tag_value->metas, NEU_TAG_META_SIZE,
tag_json);
switch (tag_value->value.type) {
case NEU_TYPE_ERROR:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.i32;
tag_json->error = tag_value->value.value.i32;
break;
case NEU_TYPE_UINT8:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.u8;
break;
case NEU_TYPE_INT8:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.i8;
break;
case NEU_TYPE_INT16:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.i16;
break;
case NEU_TYPE_INT32:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.i32;
break;
case NEU_TYPE_INT64:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.i64;
break;
case NEU_TYPE_WORD:
case NEU_TYPE_UINT16:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.u16;
break;
case NEU_TYPE_DWORD:
case NEU_TYPE_UINT32:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.u32;
break;
case NEU_TYPE_LWORD:
case NEU_TYPE_UINT64:
tag_json->t = NEU_JSON_INT;
tag_json->value.val_int = tag_value->value.value.u64;
break;
case NEU_TYPE_FLOAT:
if (isnan(tag_value->value.value.f32)) {
tag_json->t = NEU_JSON_FLOAT;
tag_json->value.val_float = tag_value->value.value.f32;
tag_json->error = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
} else {
tag_json->t = NEU_JSON_FLOAT;
tag_json->value.val_float = tag_value->value.value.f32;
tag_json->precision = tag_value->value.precision;
}
break;
case NEU_TYPE_DOUBLE:
if (isnan(tag_value->value.value.d64)) {
tag_json->t = NEU_JSON_DOUBLE;
tag_json->value.val_double = tag_value->value.value.d64;
tag_json->error = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
} else {
tag_json->t = NEU_JSON_DOUBLE;
tag_json->value.val_double = tag_value->value.value.d64;
tag_json->precision = tag_value->value.precision;
}
break;
case NEU_TYPE_BOOL:
tag_json->t = NEU_JSON_BOOL;
tag_json->value.val_bool = tag_value->value.value.boolean;
break;
case NEU_TYPE_BIT:
tag_json->t = NEU_JSON_BIT;
tag_json->value.val_bit = tag_value->value.value.u8;
break;
case NEU_TYPE_STRING:
case NEU_TYPE_TIME:
case NEU_TYPE_DATA_AND_TIME:
tag_json->t = NEU_JSON_STR;
tag_json->value.val_str = tag_value->value.value.str;
break;
case NEU_TYPE_PTR:
tag_json->t = NEU_JSON_STR;
tag_json->value.val_str = (char *) tag_value->value.value.ptr.ptr;
break;
case NEU_TYPE_BYTES:
tag_json->t = NEU_JSON_BYTES;
tag_json->value.val_bytes.length = tag_value->value.value.bytes.length;
tag_json->value.val_bytes.bytes = tag_value->value.value.bytes.bytes;
break;
default:
break;
}
}
typedef struct {
char node[NEU_NODE_NAME_LEN];
} neu_reqresp_node_deleted_t;
+9
View File
@@ -73,6 +73,9 @@ static struct neu_http_handler cors_handler[] = {
{
.url = "/api/v2/read",
},
{
.url = "/api/v2/read/paginate",
},
{
.url = "/api/v2/write",
},
@@ -263,6 +266,12 @@ static struct neu_http_handler rest_handlers[] = {
.url = "/api/v2/read",
.value.handler = handle_read,
},
{
.method = NEU_HTTP_METHOD_POST,
.type = NEU_HTTP_HANDLER_FUNCTION,
.url = "/api/v2/read/paginate",
.value.handler = handle_read_paginate,
},
{
.method = NEU_HTTP_METHOD_POST,
.type = NEU_HTTP_HANDLER_FUNCTION,
+4
View File
@@ -224,6 +224,10 @@ static int dashb_plugin_request(neu_plugin_t * plugin,
case NEU_RESP_READ_GROUP:
handle_read_resp(header->ctx, (neu_resp_read_group_t *) data);
break;
case NEU_RESP_READ_GROUP_PAGINATE:
handle_read_paginate_resp(header->ctx,
(neu_resp_read_group_paginate_t *) data);
break;
case NEU_RESP_SCAN_TAGS:
handle_scan_tags_resp(header->ctx, (neu_resp_scan_tags_t *) data);
break;
+166
View File
@@ -80,6 +80,61 @@ void handle_read(nng_aio *aio)
})
}
void handle_read_paginate(nng_aio *aio)
{
neu_plugin_t *plugin = neu_rest_get_plugin();
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
aio, neu_json_read_paginate_req_t, neu_json_decode_read_paginate_req, {
int ret = 0;
neu_reqresp_head_t header = { 0 };
neu_req_read_group_paginate_t cmd = { 0 };
int err_type;
header.ctx = aio;
header.type = NEU_REQ_READ_GROUP_PAGINATE;
if (strlen(req->node) >= NEU_NODE_NAME_LEN) {
err_type = NEU_ERR_NODE_NAME_TOO_LONG;
goto error;
}
if (strlen(req->node) >= NEU_GROUP_NAME_LEN) {
err_type = NEU_ERR_GROUP_NAME_TOO_LONG;
goto error;
}
if (strlen(req->node) >= NEU_TAG_NAME_LEN) {
err_type = NEU_ERR_TAG_NAME_TOO_LONG;
goto error;
}
cmd.driver = req->node;
cmd.group = req->group;
cmd.name = req->name;
cmd.desc = req->desc;
cmd.sync = req->sync;
cmd.current_page = req->current_page;
cmd.page_size = req->page_size;
cmd.is_error = req->is_error;
req->node = NULL;
req->group = NULL;
ret = neu_plugin_op(plugin, header, &cmd);
if (ret != 0) {
neu_req_read_group_paginate_fini(&cmd);
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_write(nng_aio *aio)
{
neu_plugin_t *plugin = neu_rest_get_plugin();
@@ -384,3 +439,114 @@ void handle_read_resp(nng_aio *aio, neu_resp_read_group_t *resp)
free(api_res.tags);
free(result);
}
void handle_read_paginate_resp(nng_aio * aio,
neu_resp_read_group_paginate_t *resp)
{
neu_json_read_paginate_resp_t api_res = { 0 };
char * result = NULL;
if (resp->is_error) {
UT_array *filtered_tags;
utarray_new(filtered_tags, neu_resp_tag_value_meta_paginate_icd());
utarray_foreach(resp->tags, neu_resp_tag_value_meta_paginate_t *,
tag_value)
{
if (tag_value->value.type == NEU_TYPE_ERROR) {
neu_resp_tag_value_meta_paginate_t new_tag_value;
memcpy(&new_tag_value, tag_value,
sizeof(neu_resp_tag_value_meta_paginate_t));
new_tag_value.datatag.name = strdup(tag_value->datatag.name);
new_tag_value.datatag.address =
strdup(tag_value->datatag.address);
new_tag_value.datatag.description =
strdup(tag_value->datatag.description);
utarray_push_back(filtered_tags, &new_tag_value);
}
}
for (unsigned int i = 0; i < utarray_len(resp->tags); ++i) {
neu_resp_tag_value_meta_paginate_t *orig_tag_value;
orig_tag_value =
(neu_resp_tag_value_meta_paginate_t *) utarray_eltptr(
resp->tags, i);
if (orig_tag_value) {
free(orig_tag_value->datatag.name);
free(orig_tag_value->datatag.address);
free(orig_tag_value->datatag.description);
}
}
utarray_free(resp->tags);
resp->tags = filtered_tags;
}
unsigned int total_tags = utarray_len(resp->tags);
api_res.meta.current_page = resp->current_page;
api_res.meta.page_size = resp->page_size;
api_res.meta.total = total_tags;
if (resp->current_page > 0 && resp->page_size > 0) {
unsigned int start_index = (resp->current_page - 1) * resp->page_size;
unsigned int end_index = start_index + resp->page_size;
if (start_index >= total_tags) {
api_res.n_tag = 0;
api_res.tags = calloc(1, sizeof(neu_json_read_paginate_resp_tag_t));
} else {
if (end_index > total_tags) {
end_index = total_tags;
}
api_res.n_tag = end_index - start_index;
api_res.tags = calloc(api_res.n_tag,
sizeof(neu_json_read_paginate_resp_tag_t));
for (unsigned int i = start_index; i < end_index; i++) {
neu_resp_tag_value_meta_paginate_t *tag_value =
(neu_resp_tag_value_meta_paginate_t *) utarray_eltptr(
resp->tags, i);
neu_tag_value_to_json_paginate(tag_value,
&api_res.tags[i - start_index]);
}
}
} else {
api_res.n_tag = total_tags;
api_res.tags =
calloc(api_res.n_tag, sizeof(neu_json_read_paginate_resp_tag_t));
int index = 0;
utarray_foreach(resp->tags, neu_resp_tag_value_meta_paginate_t *,
tag_value)
{
neu_tag_value_to_json_paginate(tag_value, &api_res.tags[index++]);
}
}
neu_json_encode_by_fn(&api_res, neu_json_encode_read_paginate_resp,
&result);
for (unsigned int i = 0; i < utarray_len(resp->tags); ++i) {
neu_resp_tag_value_meta_paginate_t *final_tag_value;
final_tag_value = (neu_resp_tag_value_meta_paginate_t *) utarray_eltptr(
resp->tags, i);
if (final_tag_value) {
free(final_tag_value->datatag.name);
free(final_tag_value->datatag.address);
free(final_tag_value->datatag.description);
}
}
for (int i = 0; i < api_res.n_tag; i++) {
if (api_res.tags[i].n_meta > 0) {
free(api_res.tags[i].metas);
}
}
neu_http_ok(aio, result);
free(api_res.tags);
free(result);
}
+3
View File
@@ -27,9 +27,12 @@
void handle_rw_init();
void handle_rw_uninit();
void handle_read(nng_aio *aio);
void handle_read_paginate(nng_aio *aio);
void handle_write(nng_aio *aio);
void handle_write_tags(nng_aio *aio);
void handle_write_gtags(nng_aio *aio);
void handle_read_resp(nng_aio *aio, neu_resp_read_group_t *resp);
void handle_read_paginate_resp(nng_aio * aio,
neu_resp_read_group_paginate_t *resp);
#endif
+30
View File
@@ -444,6 +444,12 @@ static int adapter_command(neu_adapter_t *adapter, neu_reqresp_head_t header,
strcpy(pheader->receiver, cmd->driver);
break;
}
case NEU_REQ_READ_GROUP_PAGINATE: {
neu_req_read_group_paginate_t *cmd =
(neu_req_read_group_paginate_t *) data;
strcpy(pheader->receiver, cmd->driver);
break;
}
case NEU_REQ_WRITE_TAG: {
neu_req_write_tag_t *cmd = (neu_req_write_tag_t *) data;
strcpy(pheader->receiver, cmd->driver);
@@ -732,6 +738,30 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}
case NEU_RESP_READ_GROUP_PAGINATE:
adapter->module->intf_funs->request(
adapter->plugin, (neu_reqresp_head_t *) header, &header[1]);
neu_resp_read_paginate_free(
(neu_resp_read_group_paginate_t *) &header[1]);
neu_msg_free(msg);
break;
case NEU_REQ_READ_GROUP_PAGINATE: {
neu_resp_error_t error = { 0 };
if (adapter->module->type == NEU_NA_TYPE_DRIVER) {
neu_adapter_driver_read_group_paginate(
(neu_adapter_driver_t *) adapter, header);
} else {
neu_req_read_group_paginate_fini(
(neu_req_read_group_paginate_t *) &header[1]);
error.error = NEU_ERR_GROUP_NOT_ALLOW;
header->type = NEU_RESP_ERROR;
neu_msg_exchange(header);
reply(adapter, header, &error);
}
break;
}
case NEU_REQ_WRITE_TAG: {
neu_resp_error_t error = { 0 };
+286 -12
View File
@@ -92,6 +92,10 @@ static void read_group(int64_t timestamp, int64_t timeout,
neu_tag_cache_type_e cache_type,
neu_driver_cache_t *cache, const char *group,
UT_array *tags, UT_array *tag_values);
static void read_group_paginate(int64_t timestamp, int64_t timeout,
neu_tag_cache_type_e cache_type,
neu_driver_cache_t *cache, const char *group,
UT_array *tags, UT_array *tag_values);
static void read_report_group(int64_t timestamp, int64_t timeout,
neu_tag_cache_type_e cache_type,
neu_driver_cache_t *cache, const char *group,
@@ -111,19 +115,19 @@ static inline void start_group_timer(neu_adapter_driver_t *driver,
group_t * grp);
static inline void stop_group_timer(neu_adapter_driver_t *driver, group_t *grp);
static void format_tag_value(neu_resp_tag_value_meta_t *value)
static void format_tag_value(neu_dvalue_t *value)
{
double scale = pow(10, 5);
int negative = 1;
if (value->value.value.d64 < 0) {
value->value.value.d64 *= -1;
if (value->value.d64 < 0) {
value->value.d64 *= -1;
negative = -1;
}
int64_t integer_part = (int64_t) value->value.value.d64;
double decimal_part = value->value.value.d64 - integer_part;
int64_t integer_part = (int64_t) value->value.d64;
double decimal_part = value->value.d64 - integer_part;
decimal_part *= scale;
decimal_part = round(decimal_part);
char str[6] = { 0 };
@@ -139,14 +143,13 @@ static void format_tag_value(neu_resp_tag_value_meta_t *value)
}
}
if (flag != 0 && i != 0) {
decimal_part = round(decimal_part / pow(10, 5 - i));
value->value.value.d64 =
(double) integer_part + decimal_part / pow(10, i);
decimal_part = round(decimal_part / pow(10, 5 - i));
value->value.d64 = (double) integer_part + decimal_part / pow(10, i);
} else {
value->value.value.d64 = (double) integer_part + decimal_part / scale;
value->value.d64 = (double) integer_part + decimal_part / scale;
}
value->value.value.d64 *= negative;
value->value.d64 *= negative;
}
static void write_response(neu_adapter_t *adapter, void *r, neu_error error)
@@ -554,6 +557,106 @@ void neu_adapter_driver_read_group(neu_adapter_driver_t *driver,
driver->adapter.cb_funs.response(&driver->adapter, req, &resp);
}
void neu_adapter_driver_read_group_paginate(neu_adapter_driver_t *driver,
neu_reqresp_head_t * req)
{
neu_req_read_group_paginate_t *cmd =
(neu_req_read_group_paginate_t *) &req[1];
group_t *g = find_group(driver, cmd->group);
if (g == NULL) {
neu_resp_error_t error = { .error = NEU_ERR_GROUP_NOT_EXIST };
req->type = NEU_RESP_ERROR;
neu_req_read_group_paginate_fini(cmd);
driver->adapter.cb_funs.response(&driver->adapter, req, &error);
return;
}
neu_resp_read_group_paginate_t resp = { 0 };
neu_group_t * group = g->group;
UT_array *tags = neu_group_query_read_tag(group, cmd->name, cmd->desc);
utarray_new(resp.tags, neu_resp_tag_value_meta_paginate_icd());
if (driver->adapter.state != NEU_NODE_RUNNING_STATE_RUNNING) {
utarray_foreach(tags, neu_datatag_t *, tag)
{
neu_resp_tag_value_meta_paginate_t tag_value = { 0 };
strcpy(tag_value.tag, tag->name);
tag_value.value.type = NEU_TYPE_ERROR;
tag_value.value.value.i32 = NEU_ERR_PLUGIN_NOT_RUNNING;
tag_value.datatag.name = strdup(tag->name);
tag_value.datatag.address = strdup(tag->address);
tag_value.datatag.attribute = tag->attribute;
tag_value.datatag.type = tag->type;
tag_value.datatag.precision = tag->precision;
tag_value.datatag.decimal = tag->decimal;
tag_value.datatag.bias = tag->bias;
tag_value.datatag.description = strdup(tag->description);
tag_value.datatag.option = tag->option;
memcpy(tag_value.datatag.meta, tag->meta, NEU_TAG_META_LENGTH);
utarray_push_back(resp.tags, &tag_value);
}
} else if (cmd->sync) {
if (NULL == driver->adapter.module->intf_funs->driver.group_sync) {
// plugin does not support sync read
utarray_foreach(tags, neu_datatag_t *, tag)
{
neu_resp_tag_value_meta_paginate_t tag_value = { 0 };
strcpy(tag_value.tag, tag->name);
tag_value.value.type = NEU_TYPE_ERROR;
tag_value.value.value.i32 =
NEU_ERR_PLUGIN_NOT_SUPPORT_READ_SYNC;
tag_value.datatag.name = strdup(tag->name);
tag_value.datatag.address = strdup(tag->address);
tag_value.datatag.attribute = tag->attribute;
tag_value.datatag.type = tag->type;
tag_value.datatag.precision = tag->precision;
tag_value.datatag.decimal = tag->decimal;
tag_value.datatag.bias = tag->bias;
tag_value.datatag.description = strdup(tag->description);
tag_value.datatag.option = tag->option;
memcpy(tag_value.datatag.meta, tag->meta, NEU_TAG_META_LENGTH);
utarray_push_back(resp.tags, &tag_value);
}
} else {
// sync read to update cache
driver->adapter.module->intf_funs->driver.group_sync(
driver->adapter.plugin, &g->grp);
// fetch updated data from cache
read_group_paginate(
global_timestamp,
neu_group_get_interval(group) *
NEU_DRIVER_TAG_CACHE_EXPIRE_TIME,
neu_adapter_get_tag_cache_type(&driver->adapter), driver->cache,
cmd->group, tags, resp.tags);
}
} else {
read_group_paginate(global_timestamp,
neu_group_get_interval(group) *
NEU_DRIVER_TAG_CACHE_EXPIRE_TIME,
neu_adapter_get_tag_cache_type(&driver->adapter),
driver->cache, cmd->group, tags, resp.tags);
}
resp.driver = cmd->driver;
resp.group = cmd->group;
resp.current_page = cmd->current_page;
resp.page_size = cmd->page_size;
resp.is_error = cmd->is_error;
cmd->driver = NULL; // ownership moved
cmd->group = NULL; // ownership moved
utarray_free(tags);
neu_req_read_group_paginate_fini(cmd);
req->type = NEU_RESP_READ_GROUP_PAGINATE;
driver->adapter.cb_funs.response(&driver->adapter, req, &resp);
}
static void fix_value(neu_datatag_t *tag, neu_type_e value_type,
neu_dvalue_t *value)
{
@@ -2129,7 +2232,7 @@ static void read_report_group(int64_t timestamp, int64_t timeout,
}
}
if (tag->precision == 0 && tag->type == NEU_TYPE_DOUBLE) {
format_tag_value(&tag_value);
format_tag_value(&tag_value.value);
}
}
@@ -2290,7 +2393,178 @@ static void read_group(int64_t timestamp, int64_t timeout,
}
if (tag->precision == 0 && tag->type == NEU_TYPE_DOUBLE) {
format_tag_value(&tag_value);
format_tag_value(&tag_value.value);
}
}
utarray_push_back(tag_values, &tag_value);
}
}
static void read_group_paginate(int64_t timestamp, int64_t timeout,
neu_tag_cache_type_e cache_type,
neu_driver_cache_t *cache, const char *group,
UT_array *tags, UT_array *tag_values)
{
utarray_foreach(tags, neu_datatag_t *, tag)
{
neu_resp_tag_value_meta_paginate_t tag_value = { 0 };
neu_driver_cache_value_t value = { 0 };
strcpy(tag_value.tag, tag->name);
tag_value.datatag.name = strdup(tag->name);
tag_value.datatag.address = strdup(tag->address);
tag_value.datatag.attribute = tag->attribute;
tag_value.datatag.type = tag->type;
tag_value.datatag.precision = tag->precision;
tag_value.datatag.decimal = tag->decimal;
tag_value.datatag.bias = tag->bias;
tag_value.datatag.description = strdup(tag->description);
tag_value.datatag.option = tag->option;
memcpy(tag_value.datatag.meta, tag->meta, NEU_TAG_META_LENGTH);
if (neu_driver_cache_meta_get(cache, group, tag->name, &value,
tag_value.metas,
NEU_TAG_META_SIZE) != 0) {
tag_value.value.type = NEU_TYPE_ERROR;
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_NOT_READY;
utarray_push_back(tag_values, &tag_value);
continue;
}
if (value.value.type == NEU_TYPE_ERROR) {
tag_value.value = value.value;
utarray_push_back(tag_values, &tag_value);
continue;
}
switch (tag->type) {
case NEU_TYPE_UINT16:
case NEU_TYPE_INT16:
switch (tag->option.value16.endian) {
case NEU_DATATAG_ENDIAN_B16:
value.value.value.u16 = htons(value.value.value.u16);
break;
case NEU_DATATAG_ENDIAN_L16:
default:
break;
}
break;
case NEU_TYPE_FLOAT:
case NEU_TYPE_UINT32:
case NEU_TYPE_INT32:
switch (tag->option.value32.endian) {
case NEU_DATATAG_ENDIAN_LB32: {
uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes;
uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2);
neu_htons_p(v1);
neu_htons_p(v2);
break;
}
case NEU_DATATAG_ENDIAN_BB32:
value.value.value.u32 = htonl(value.value.value.u32);
break;
case NEU_DATATAG_ENDIAN_BL32:
value.value.value.u32 = htonl(value.value.value.u32);
uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes;
uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2);
neu_htons_p(v1);
neu_htons_p(v2);
break;
case NEU_DATATAG_ENDIAN_LL32:
default:
break;
}
break;
case NEU_TYPE_DOUBLE:
case NEU_TYPE_INT64:
case NEU_TYPE_UINT64:
switch (tag->option.value64.endian) {
case NEU_DATATAG_ENDIAN_B64:
value.value.value.u64 = neu_htonll(value.value.value.u64);
break;
case NEU_DATATAG_ENDIAN_L64:
default:
break;
}
break;
default:
break;
}
if (cache_type != NEU_TAG_CACHE_TYPE_NEVER &&
!neu_tag_attribute_test(tag, NEU_ATTRIBUTE_STATIC) &&
(timestamp - value.timestamp) > timeout) {
if (value.value.type == NEU_TYPE_PTR) {
free(value.value.value.ptr.ptr);
}
tag_value.value.type = NEU_TYPE_ERROR;
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
} else {
if (value.value.type == NEU_TYPE_PTR) {
tag_value.value.type = NEU_TYPE_PTR;
tag_value.value.value.ptr.length = value.value.value.ptr.length;
tag_value.value.value.ptr.type = value.value.value.ptr.type;
tag_value.value.value.ptr.ptr = value.value.value.ptr.ptr;
} else {
tag_value.value = value.value;
}
if (tag->decimal != 0 || tag->bias != 0) {
tag_value.value.type = NEU_TYPE_DOUBLE;
double decimal = tag->decimal != 0 ? tag->decimal : 1;
double bias = tag->bias;
switch (tag->type) {
case NEU_TYPE_INT8:
tag_value.value.value.d64 =
(double) tag_value.value.value.i8 * decimal + bias;
break;
case NEU_TYPE_UINT8:
tag_value.value.value.d64 =
(double) tag_value.value.value.u8 * decimal + bias;
break;
case NEU_TYPE_INT16:
tag_value.value.value.d64 =
(double) tag_value.value.value.i16 * decimal + bias;
break;
case NEU_TYPE_UINT16:
tag_value.value.value.d64 =
(double) tag_value.value.value.u16 * decimal + bias;
break;
case NEU_TYPE_INT32:
tag_value.value.value.d64 =
(double) tag_value.value.value.i32 * decimal + bias;
break;
case NEU_TYPE_UINT32:
tag_value.value.value.d64 =
(double) tag_value.value.value.u32 * decimal + bias;
break;
case NEU_TYPE_INT64:
tag_value.value.value.d64 =
(double) tag_value.value.value.i64 * decimal + bias;
break;
case NEU_TYPE_UINT64:
tag_value.value.value.d64 =
(double) tag_value.value.value.u64 * decimal + bias;
break;
case NEU_TYPE_FLOAT:
tag_value.value.value.d64 =
(double) tag_value.value.value.f32 * decimal + bias;
break;
case NEU_TYPE_DOUBLE:
tag_value.value.value.d64 =
(double) tag_value.value.value.d64 * decimal + bias;
break;
default:
tag_value.value.type = tag->type;
break;
}
}
if (tag->precision == 0 && tag->type == NEU_TYPE_DOUBLE) {
format_tag_value(&tag_value.value);
}
}
utarray_push_back(tag_values, &tag_value);
+2
View File
@@ -33,6 +33,8 @@ void neu_adapter_driver_stop_group_timer(neu_adapter_driver_t *driver);
void neu_adapter_driver_read_group(neu_adapter_driver_t *driver,
neu_reqresp_head_t * req);
void neu_adapter_driver_read_group_paginate(neu_adapter_driver_t *driver,
neu_reqresp_head_t * req);
void neu_adapter_driver_write_tag(neu_adapter_driver_t *driver,
neu_reqresp_head_t * req);
+2
View File
@@ -34,6 +34,8 @@ extern "C" {
XX(NEU_RESP_ERROR, neu_resp_error_t) \
XX(NEU_REQ_READ_GROUP, neu_req_read_group_t) \
XX(NEU_RESP_READ_GROUP, neu_resp_read_group_t) \
XX(NEU_REQ_READ_GROUP_PAGINATE, neu_req_read_group_paginate_t) \
XX(NEU_RESP_READ_GROUP_PAGINATE, neu_resp_read_group_paginate_t) \
XX(NEU_REQ_WRITE_TAG, neu_req_write_tag_t) \
XX(NEU_REQ_WRITE_TAGS, neu_req_write_tags_t) \
XX(NEU_REQ_WRITE_GTAGS, neu_req_write_gtags_t) \
+5
View File
@@ -1007,6 +1007,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
case NEU_REQ_GET_GROUP:
case NEU_REQ_GET_NODE_SETTING:
case NEU_REQ_READ_GROUP:
case NEU_REQ_READ_GROUP_PAGINATE:
case NEU_REQ_WRITE_TAG:
case NEU_REQ_WRITE_TAGS:
case NEU_REQ_WRITE_GTAGS:
@@ -1017,6 +1018,9 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
NULL) {
if (NEU_REQ_READ_GROUP == header->type) {
neu_req_read_group_fini((neu_req_read_group_t *) &header[1]);
} else if (NEU_REQ_READ_GROUP_PAGINATE == header->type) {
neu_req_read_group_paginate_fini(
(neu_req_read_group_paginate_t *) &header[1]);
} else if (NEU_REQ_WRITE_TAG == header->type) {
neu_req_write_tag_fini((neu_req_write_tag_t *) &header[1]);
} else if (NEU_REQ_WRITE_TAGS == header->type) {
@@ -1245,6 +1249,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
case NEU_RESP_GET_NODE_SETTING:
case NEU_RESP_ERROR:
case NEU_RESP_READ_GROUP:
case NEU_RESP_READ_GROUP_PAGINATE:
case NEU_RESP_PRGFILE_PROCESS:
case NEU_RESP_SCAN_TAGS:
forward_msg(manager, header, header->receiver);
+293
View File
@@ -90,6 +90,107 @@ int neu_json_encode_read_resp(void *json_object, void *param)
return ret;
}
int neu_json_encode_read_paginate_resp(void *json_object, void *param)
{
int ret = 0;
neu_json_read_paginate_resp_t *resp =
(neu_json_read_paginate_resp_t *) param;
void * tag_array = neu_json_array();
neu_json_read_paginate_resp_tag_t *p_tag = resp->tags;
for (int i = 0; i < resp->n_tag; i++) {
neu_json_elem_t tag_elems[10 + NEU_TAG_META_SIZE] = { 0 };
int if_precision = 0;
tag_elems[0].name = "name";
tag_elems[0].t = NEU_JSON_STR;
tag_elems[0].v.val_str = p_tag->name;
tag_elems[1].name = "type";
tag_elems[1].t = NEU_JSON_INT;
tag_elems[1].v.val_int = p_tag->datatag.type;
tag_elems[2].name = "address";
tag_elems[2].t = NEU_JSON_STR;
tag_elems[2].v.val_str = p_tag->datatag.address;
tag_elems[3].name = "attribute";
tag_elems[3].t = NEU_JSON_INT;
tag_elems[3].v.val_int = p_tag->datatag.attribute;
tag_elems[4].name = "description";
tag_elems[4].t = NEU_JSON_STR;
tag_elems[4].v.val_str = p_tag->datatag.description;
tag_elems[5].name = "precision";
tag_elems[5].t = NEU_JSON_INT;
tag_elems[5].v.val_int = p_tag->datatag.precision;
tag_elems[6].name = "decimal";
tag_elems[6].t = NEU_JSON_DOUBLE;
tag_elems[6].v.val_double = p_tag->datatag.decimal;
tag_elems[7].name = "bias";
tag_elems[7].t = NEU_JSON_DOUBLE;
tag_elems[7].v.val_double = p_tag->datatag.bias;
if (p_tag->error != 0) {
tag_elems[8].name = "error";
tag_elems[8].t = NEU_JSON_INT;
tag_elems[8].v.val_int = p_tag->error;
} else {
tag_elems[8].name = "value";
tag_elems[8].t = p_tag->t;
tag_elems[8].v = p_tag->value;
tag_elems[8].precision = p_tag->precision;
if (p_tag->t == NEU_JSON_FLOAT || p_tag->t == NEU_JSON_DOUBLE) {
if_precision = 1;
tag_elems[9].name = "precision";
tag_elems[9].t = NEU_JSON_INT;
tag_elems[9].v.val_int =
p_tag->precision > 0 ? p_tag->precision : 1;
}
}
for (int k = 0; k < p_tag->n_meta; k++) {
tag_elems[if_precision + 9 + k].name = p_tag->metas[k].name;
tag_elems[if_precision + 9 + k].t = p_tag->metas[k].t;
tag_elems[if_precision + 9 + k].v = p_tag->metas[k].value;
}
tag_array = neu_json_encode_array(tag_array, tag_elems,
9 + if_precision + p_tag->n_meta);
free(p_tag->datatag.name);
free(p_tag->datatag.address);
free(p_tag->datatag.description);
p_tag++;
}
void * meta_object = neu_json_encode_new();
neu_json_elem_t meta_elems[] = {
{ .name = "currentPage",
.t = NEU_JSON_INT,
.v.val_int = resp->meta.current_page },
{ .name = "pageSize",
.t = NEU_JSON_INT,
.v.val_int = resp->meta.page_size },
{ .name = "total", .t = NEU_JSON_INT, .v.val_int = resp->meta.total }
};
neu_json_encode_field(meta_object, meta_elems, 3);
neu_json_elem_t resp_elems[] = {
{ .name = "meta", .t = NEU_JSON_OBJECT, .v.val_object = meta_object },
{ .name = "items", .t = NEU_JSON_OBJECT, .v.val_object = tag_array },
};
ret = neu_json_encode_field(json_object, resp_elems, 2);
return ret;
}
int neu_json_encode_read_resp1(void *json_object, void *param)
{
int ret = 0;
@@ -519,6 +620,123 @@ void neu_json_decode_read_req_free(neu_json_read_req_t *req)
free(req);
}
int neu_json_decode_read_paginate_req(char * buf,
neu_json_read_paginate_req_t **result)
{
int ret = 0;
void *json_obj = NULL;
json_obj = neu_json_decode_new(buf);
if (NULL == json_obj) {
return -1;
}
neu_json_read_paginate_req_t *req =
calloc(1, sizeof(neu_json_read_paginate_req_t));
if (req == NULL) {
neu_json_decode_free(json_obj);
return -1;
}
neu_json_elem_t req_elems[] = {
{
.name = "node",
.t = NEU_JSON_STR,
},
{
.name = "group",
.t = NEU_JSON_STR,
},
{
.name = "sync",
.t = NEU_JSON_BOOL,
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
},
{
.name = "query",
.t = NEU_JSON_OBJECT,
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
},
};
neu_json_elem_t query_elems[] = {
{
.name = "name",
.t = NEU_JSON_STR,
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
},
{
.name = "description",
.t = NEU_JSON_STR,
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
},
{
.name = "currentPage",
.t = NEU_JSON_INT,
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
},
{
.name = "pageSize",
.t = NEU_JSON_INT,
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
},
{
.name = "isError",
.t = NEU_JSON_BOOL,
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
},
};
ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
req_elems);
if (ret != 0) {
goto error;
}
req->node = req_elems[0].v.val_str;
req->group = req_elems[1].v.val_str;
req->sync = req_elems[2].v.val_bool;
if (req_elems[3].v.val_object) {
ret = neu_json_decode_by_json(req_elems[3].v.val_object,
NEU_JSON_ELEM_SIZE(query_elems),
query_elems);
if (ret != 0) {
goto error;
}
req->name = query_elems[0].v.val_str;
req->desc = query_elems[1].v.val_str;
req->current_page = query_elems[2].v.val_int;
req->page_size = query_elems[3].v.val_int;
req->is_error = query_elems[4].v.val_bool;
}
*result = req;
neu_json_decode_free(json_obj);
return ret;
error:
free(query_elems[0].v.val_str);
free(query_elems[1].v.val_str);
free(req_elems[0].v.val_str);
free(req_elems[1].v.val_str);
free(req);
if (json_obj != NULL) {
neu_json_decode_free(json_obj);
}
return ret;
}
void neu_json_decode_read_paginate_req_free(neu_json_read_paginate_req_t *req)
{
free(req->group);
free(req->node);
free(req);
}
int neu_json_encode_read_periodic_resp(void *json_object, void *param)
{
int ret = 0;
@@ -619,6 +837,81 @@ void neu_json_metas_to_json(neu_tag_meta_t *metas, int n_meta,
}
}
void neu_json_metas_to_json_paginate(
neu_tag_meta_t *metas, int n_meta,
neu_json_read_paginate_resp_tag_t *json_tag)
{
for (int k = 0; k < n_meta; k++) {
if (strlen(metas[k].name) > 0) {
json_tag->metas[k].name = metas[k].name;
switch (metas[k].value.type) {
case NEU_TYPE_UINT8:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.u8;
break;
case NEU_TYPE_INT8:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.i8;
break;
case NEU_TYPE_INT16:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.i16;
break;
case NEU_TYPE_INT32:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.i32;
break;
case NEU_TYPE_INT64:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.i64;
break;
case NEU_TYPE_WORD:
case NEU_TYPE_UINT16:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.u16;
break;
case NEU_TYPE_DWORD:
case NEU_TYPE_UINT32:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.u32;
break;
case NEU_TYPE_LWORD:
case NEU_TYPE_UINT64:
json_tag->metas[k].t = NEU_JSON_INT;
json_tag->metas[k].value.val_int = metas[k].value.value.u64;
break;
case NEU_TYPE_FLOAT:
json_tag->metas[k].t = NEU_JSON_FLOAT;
json_tag->metas[k].value.val_float = metas[k].value.value.f32;
break;
case NEU_TYPE_DOUBLE:
json_tag->metas[k].t = NEU_JSON_DOUBLE;
json_tag->metas[k].value.val_double = metas[k].value.value.d64;
break;
case NEU_TYPE_BOOL:
json_tag->metas[k].t = NEU_JSON_BOOL;
json_tag->metas[k].value.val_bool =
metas[k].value.value.boolean;
break;
case NEU_TYPE_BIT:
json_tag->metas[k].t = NEU_JSON_BIT;
json_tag->metas[k].value.val_bit = metas[k].value.value.u8;
break;
case NEU_TYPE_STRING:
case NEU_TYPE_TIME:
case NEU_TYPE_DATA_AND_TIME:
json_tag->metas[k].t = NEU_JSON_STR;
json_tag->metas[k].value.val_str = metas[k].value.value.str;
break;
default:
break;
}
} else {
break;
}
}
}
int neu_json_decode_write_gtags_req(char * buf,
neu_json_write_gtags_req_t **result)
{
+293
View File
@@ -0,0 +1,293 @@
import neuron.api as api
import neuron.error as error
import neuron.config as config
from neuron.common import *
tcp_port = random_port()
@pytest.fixture(params=[('modbus-tcp', config.PLUGIN_MODBUS_TCP)], scope='class')
def param(request):
return request.param
@pytest.fixture(autouse=True, scope='class')
def simulator_setup_teardown(param):
p = process.start_simulator(
['./modbus_simulator', 'tcp', f'{tcp_port}', 'ip_v4'])
response = api.add_node(node=param[0], plugin=param[1])
assert 200 == response.status_code
response = api.add_group(node=param[0], group='group')
assert 200 == response.status_code
response = api.modbus_tcp_node_setting(
node=param[0], interval=1, port=tcp_port)
yield
process.stop_simulator(p)
hold_bit = [{"name": "hold_bit", "address": "1!400001.15",
"attribute": config.NEU_TAG_ATTRIBUTE_READ_SUBSCRIBE, "type": config.NEU_TYPE_BIT, "description": "123"}]
hold_int16 = [{"name": "hold_int16", "address": "1!400001",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_INT16, "description": "123"}]
hold_uint16 = [{"name": "hold_uint16", "address": "1!400002",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_UINT16, "description": "456"}]
hold_int32 = [{"name": "hold_int32", "address": "1!400003",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_INT32, "description": "456"}]
hold_uint32 = [{"name": "hold_uint32", "address": "1!400015",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_UINT32}]
hold_float = [{"name": "hold_float", "address": "1!400017",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_FLOAT}]
hold_string = [{"name": "hold_string", "address": "1!400020.10",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_STRING}]
hold_bytes = [{"name": "hold_bytes", "address": "1!400040.10",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_BYTES}]
class TestReadPaginate:
@description(given="created modbus node", when="add multiple tags", then="add success")
def test_add_tags(self, param):
api.add_tags_check(node=param[0], group='group', tags=hold_bit)
api.add_tags_check(node=param[0], group='group', tags=hold_int16)
api.add_tags_check(node=param[0], group='group', tags=hold_uint16)
api.add_tags_check(node=param[0], group='group', tags=hold_int32)
api.add_tags_check(node=param[0], group='group', tags=hold_uint32)
api.add_tags_check(node=param[0], group='group', tags=hold_float)
api.add_tags_check(node=param[0], group='group', tags=hold_string)
api.add_tags_check(node=param[0], group='group', tags=hold_bytes)
@description(given="created modbus node and tags", when="write/read tags without filter", then="write/read success")
def test_write_read_tags(self, param):
api.write_tag_check(
node=param[0], group='group', tag=hold_int16[0]['name'], value=-123)
api.write_tag_check(
node=param[0], group='group', tag=hold_uint16[0]['name'], value=123)
api.write_tag_check(
node=param[0], group='group', tag=hold_int32[0]['name'], value=-1234)
api.write_tag_check(
node=param[0], group='group', tag=hold_uint32[0]['name'], value=1234)
api.write_tag_check(
node=param[0], group='group', tag=hold_float[0]['name'], value=13.4121)
api.write_tag_check(
node=param[0], group='group', tag=hold_string[0]['name'], value='hello')
api.write_tag_check(
node=param[0], group='group', tag=hold_bytes[0]['name'], value=[0x1, 0x2, 0x3, 0x4])
time.sleep(0.3)
response = api.read_tags_paginate(node=param[0], group='group')
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 8 == len(response.json()["items"])
assert "hold_bit" == response.json()["items"][0]["name"]
assert 1 == response.json()["items"][0]["value"]
assert "hold_int16" == response.json()["items"][1]["name"]
assert -123 == response.json()["items"][1]["value"]
assert "hold_uint16" == response.json()["items"][2]["name"]
assert 123 == response.json()["items"][2]["value"]
assert "hold_int32" == response.json()["items"][3]["name"]
assert -1234 == response.json()["items"][3]["value"]
assert "hold_uint32" == response.json()["items"][4]["name"]
assert 1234 == response.json()["items"][4]["value"]
assert "hold_float" == response.json()["items"][5]["name"]
assert compare_float(13.4121, response.json()["items"][5]["value"])
assert "hold_string" == response.json()["items"][6]["name"]
assert 'hello' == response.json()["items"][6]["value"]
assert "hold_bytes" == response.json()["items"][7]["name"]
assert [0x1, 0x2, 0x3, 0x4, 0, 0, 0, 0, 0, 0] == response.json()["items"][7]["value"]
@description(given="created modbus node and tags", when="read tags with filter(name)", then="read success")
def test_read_tags_filter_name(self, param):
response = api.read_tags_paginate(node=param[0], group='group', query= {"name": "int16"})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 2 == response.json()["meta"]["total"]
assert 2 == len(response.json()["items"])
assert "hold_int16" == response.json()["items"][0]["name"]
assert -123 == response.json()["items"][0]["value"]
assert "hold_uint16" == response.json()["items"][1]["name"]
assert 123 == response.json()["items"][1]["value"]
@description(given="created modbus node and tags", when="read tags with filter(desc)", then="read success")
def test_read_tags_filter_desc(self, param):
response = api.read_tags_paginate(node=param[0], group='group', query= {"description": "12"})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 2 == response.json()["meta"]["total"]
assert 2 == len(response.json()["items"])
assert "hold_bit" == response.json()["items"][0]["name"]
assert 1 == response.json()["items"][0]["value"]
assert "hold_int16" == response.json()["items"][1]["name"]
assert -123 == response.json()["items"][1]["value"]
@description(given="created modbus node and tags", when="read tags with paginate", then="read success")
def test_read_tags_paginate(self, param):
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 1, "pageSize": 5})
assert 1 == response.json()["meta"]["currentPage"]
assert 5 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 5 == len(response.json()["items"])
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 2, "pageSize": 5})
assert 2 == response.json()["meta"]["currentPage"]
assert 5 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 3 == len(response.json()["items"])
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 3, "pageSize": 5})
assert 3 == response.json()["meta"]["currentPage"]
assert 5 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 0 == len(response.json()["items"])
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 6, "pageSize": 5})
assert 6 == response.json()["meta"]["currentPage"]
assert 5 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 0 == len(response.json()["items"])
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 0, "pageSize": 5})
assert 0 == response.json()["meta"]["currentPage"]
assert 5 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 8 == len(response.json()["items"])
@description(given="created modbus node and tags", when="read tags with filter(isError)", then="read success")
def test_read_tags_filter_isError(self, param):
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 0 == response.json()["meta"]["total"]
assert 0 == len(response.json()["items"])
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 8 == len(response.json()["items"])
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
time.sleep(0.3)
@description(given="created modbus node and tags", when="read tags with filter(name&desc)", then="read success")
def test_read_tags_filter_name_desc(self, param):
response = api.read_tags_paginate(node=param[0], group='group', query= {"name": "16", "description": "123"})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 1 == response.json()["meta"]["total"]
assert 1 == len(response.json()["items"])
assert "hold_int16" == response.json()["items"][0]["name"]
assert -123 == response.json()["items"][0]["value"]
@description(given="created modbus node and tags", when="read tags with filter(isError&name)", then="read success")
def test_read_tags_filter_isError_name(self, param):
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True, "name": "16"})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 2 == response.json()["meta"]["total"]
assert 2 == len(response.json()["items"])
assert "hold_int16" == response.json()["items"][0]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
assert "hold_uint16" == response.json()["items"][1]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
time.sleep(0.3)
@description(given="created modbus node and tags", when="read tags with filter(isError&desc)", then="read success")
def test_read_tags_filter_isError_desc(self, param):
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True, "description": "12"})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 2 == response.json()["meta"]["total"]
assert 2 == len(response.json()["items"])
assert "hold_bit" == response.json()["items"][0]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
assert "hold_int16" == response.json()["items"][1]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
time.sleep(0.3)
@description(given="created modbus node and tags", when="read tags with filter(isError&name&desc)", then="read success")
def test_read_tags_filter_isError_name_desc(self, param):
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True, "name":"16", "description": "12"})
assert 0 == response.json()["meta"]["currentPage"]
assert 0 == response.json()["meta"]["pageSize"]
assert 1 == response.json()["meta"]["total"]
assert 1 == len(response.json()["items"])
assert "hold_int16" == response.json()["items"][0]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
time.sleep(0.3)
@description(given="created modbus node and tags", when="read tags with paginate & filter(isError)", then="read success")
def test_read_tags_paginate_filter_isError(self, param):
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 1, "pageSize": 5, "isError": True})
assert 1 == response.json()["meta"]["currentPage"]
assert 5 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 5 == len(response.json()["items"])
assert "hold_bit" == response.json()["items"][0]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
assert "hold_int16" == response.json()["items"][1]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
assert "hold_uint16" == response.json()["items"][2]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][2]["error"]
assert "hold_int32" == response.json()["items"][3]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][3]["error"]
assert "hold_uint32" == response.json()["items"][4]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][4]["error"]
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 2, "pageSize": 5, "isError": True})
assert 2 == response.json()["meta"]["currentPage"]
assert 5 == response.json()["meta"]["pageSize"]
assert 8 == response.json()["meta"]["total"]
assert 3 == len(response.json()["items"])
assert "hold_float" == response.json()["items"][0]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
assert "hold_string" == response.json()["items"][1]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
assert "hold_bytes" == response.json()["items"][2]["name"]
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][2]["error"]
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
time.sleep(0.3)
+5
View File
@@ -157,6 +157,11 @@ def read_tags(node, group, sync=False, query=None):
body["query"] = query
return requests.post(url=config.BASE_URL + "/api/v2/read", headers={"Authorization": config.default_jwt}, json=body)
def read_tags_paginate(node, group, sync=False, query=None):
body = {"node": node, "group": group, "sync": sync}
if query:
body["query"] = query
return requests.post(url=config.BASE_URL + "/api/v2/read/paginate", headers={"Authorization": config.default_jwt}, json=body)
def read_tag(node, group, tag, sync=False):
response = read_tags(node, group, sync, query={"name": tag})