mirror of
https://github.com/emqx/neuron.git
synced 2026-10-17 04:40:42 +08:00
tag: option unit
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
#define NEU_TAG_META_LENGTH 20
|
||||
#define NEU_TAG_META_SIZE 32
|
||||
#define NEU_TAG_FORMAT_LENGTH 16
|
||||
#define NEU_TAG_UNIT_LENGTH 16
|
||||
|
||||
#define NEU_LOG_LEVEL_DEBUG "debug"
|
||||
#define NEU_LOG_LEVEL_INFO "info"
|
||||
|
||||
@@ -1470,6 +1470,11 @@ neu_tag_value_to_json_paginate(neu_resp_tag_value_meta_paginate_t *tag_value,
|
||||
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;
|
||||
if (tag_value->datatag.unit) {
|
||||
tag_json->datatag.unit = strdup(tag_value->datatag.unit);
|
||||
} else {
|
||||
tag_json->datatag.unit = strdup("");
|
||||
}
|
||||
memcpy(tag_json->datatag.meta, tag_value->datatag.meta,
|
||||
NEU_TAG_META_LENGTH);
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ typedef struct {
|
||||
double decimal;
|
||||
double bias;
|
||||
char * description;
|
||||
char * unit;
|
||||
neu_datatag_addr_option_u option;
|
||||
uint8_t meta[NEU_TAG_META_LENGTH];
|
||||
uint8_t format[NEU_TAG_FORMAT_LENGTH];
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
alter TABLE tags add column unit TEXT NULL check(length(unit) <= 128);
|
||||
|
||||
COMMIT;
|
||||
@@ -95,6 +95,11 @@ void handle_add_tags(nng_aio *aio)
|
||||
} else {
|
||||
cmd.tags[i].description = strdup("");
|
||||
}
|
||||
if (req->tags[i].unit == NULL) {
|
||||
cmd.tags[i].unit = strdup("");
|
||||
} else {
|
||||
cmd.tags[i].unit = strdup(req->tags[i].unit);
|
||||
}
|
||||
}
|
||||
|
||||
int ret = neu_plugin_op(plugin, header, &cmd);
|
||||
@@ -216,6 +221,12 @@ void handle_add_gtags(nng_aio *aio)
|
||||
} else {
|
||||
cmd.groups[i].tags[j].description = strdup("");
|
||||
}
|
||||
if (req->groups[i].tags[j].unit == NULL) {
|
||||
cmd.groups[i].tags[j].unit = strdup("");
|
||||
} else {
|
||||
cmd.groups[i].tags[j].unit =
|
||||
strdup(req->groups[i].tags[j].unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +393,11 @@ void handle_update_tags(nng_aio *aio)
|
||||
} else {
|
||||
cmd.tags[i].description = strdup("");
|
||||
}
|
||||
if (req->tags[i].unit == NULL) {
|
||||
cmd.tags[i].unit = strdup("");
|
||||
} else {
|
||||
cmd.tags[i].unit = strdup(req->tags[i].unit);
|
||||
}
|
||||
}
|
||||
|
||||
ret = neu_plugin_op(plugin, header, &cmd);
|
||||
@@ -529,6 +545,7 @@ void handle_get_tags_resp(nng_aio *aio, neu_resp_get_tag_t *tags)
|
||||
tags_res.tags[index].decimal = tag->decimal;
|
||||
tags_res.tags[index].bias = tag->bias;
|
||||
tags_res.tags[index].t = NEU_JSON_UNDEFINE;
|
||||
tags_res.tags[index].unit = tag->unit;
|
||||
}
|
||||
|
||||
neu_json_encode_by_fn(&tags_res, neu_json_encode_get_tags_resp, &result);
|
||||
|
||||
@@ -894,6 +894,12 @@ void handle_read_paginate_resp(nng_aio * aio,
|
||||
strdup(tag_value->datatag.address);
|
||||
new_tag_value.datatag.description =
|
||||
strdup(tag_value->datatag.description);
|
||||
if (tag_value->datatag.unit) {
|
||||
new_tag_value.datatag.unit =
|
||||
strdup(tag_value->datatag.unit);
|
||||
} else {
|
||||
new_tag_value.datatag.unit = strdup("");
|
||||
}
|
||||
|
||||
utarray_push_back(filtered_tags, &new_tag_value);
|
||||
}
|
||||
@@ -908,6 +914,7 @@ void handle_read_paginate_resp(nng_aio * aio,
|
||||
free(orig_tag_value->datatag.name);
|
||||
free(orig_tag_value->datatag.address);
|
||||
free(orig_tag_value->datatag.description);
|
||||
free(orig_tag_value->datatag.unit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,6 +1004,7 @@ void handle_read_paginate_resp(nng_aio * aio,
|
||||
free(final_tag_value->datatag.name);
|
||||
free(final_tag_value->datatag.address);
|
||||
free(final_tag_value->datatag.description);
|
||||
free(final_tag_value->datatag.unit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,11 @@ static void tag_array_copy(void *_dst, const void *_src)
|
||||
dst->address = strdup(src->address);
|
||||
dst->name = strdup(src->name);
|
||||
dst->description = strdup(src->description);
|
||||
if (src->unit == NULL) {
|
||||
dst->unit = strdup("");
|
||||
} else {
|
||||
dst->unit = strdup(src->unit);
|
||||
}
|
||||
|
||||
memcpy(dst->format, src->format, sizeof(src->format));
|
||||
dst->n_format = src->n_format;
|
||||
@@ -53,6 +58,9 @@ static void tag_array_free(void *_elt)
|
||||
free(elt->name);
|
||||
free(elt->address);
|
||||
free(elt->description);
|
||||
if (elt->unit) {
|
||||
free(elt->unit);
|
||||
}
|
||||
}
|
||||
|
||||
void neu_tag_format_str(const neu_datatag_t *tag, char *buf, int len)
|
||||
|
||||
+21
-16
@@ -137,22 +137,26 @@ int neu_json_encode_read_paginate_resp(void *json_object, void *param)
|
||||
tag_elems[7].t = NEU_JSON_DOUBLE;
|
||||
tag_elems[7].v.val_double = p_tag->datatag.bias;
|
||||
|
||||
tag_elems[8].name = "unit";
|
||||
tag_elems[8].t = NEU_JSON_STR;
|
||||
tag_elems[8].v.val_str = p_tag->datatag.unit;
|
||||
|
||||
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;
|
||||
tag_elems[9].name = "error";
|
||||
tag_elems[9].t = NEU_JSON_INT;
|
||||
tag_elems[9].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;
|
||||
tag_elems[8].bias = p_tag->datatag.bias;
|
||||
tag_elems[9].name = "value";
|
||||
tag_elems[9].t = p_tag->t;
|
||||
tag_elems[9].v = p_tag->value;
|
||||
tag_elems[9].precision = p_tag->precision;
|
||||
tag_elems[9].bias = p_tag->datatag.bias;
|
||||
|
||||
if (p_tag->t == NEU_JSON_FLOAT || p_tag->t == NEU_JSON_DOUBLE) {
|
||||
if_precision = 1;
|
||||
tag_elems[9].name = "transferPrecision";
|
||||
tag_elems[9].t = NEU_JSON_INT;
|
||||
tag_elems[9].v.val_int =
|
||||
if_precision = 1;
|
||||
tag_elems[10].name = "transferPrecision";
|
||||
tag_elems[10].t = NEU_JSON_INT;
|
||||
tag_elems[10].v.val_int =
|
||||
p_tag->precision > 0 ? p_tag->precision : 1;
|
||||
}
|
||||
}
|
||||
@@ -166,16 +170,17 @@ int neu_json_encode_read_paginate_resp(void *json_object, void *param)
|
||||
neu_json_encode_field(attributes_object, &meta_elem, 1);
|
||||
}
|
||||
|
||||
tag_elems[if_precision + 9].name = "attributes";
|
||||
tag_elems[if_precision + 9].t = NEU_JSON_OBJECT;
|
||||
tag_elems[if_precision + 9].v.val_object = attributes_object;
|
||||
tag_elems[if_precision + 10].name = "attributes";
|
||||
tag_elems[if_precision + 10].t = NEU_JSON_OBJECT;
|
||||
tag_elems[if_precision + 10].v.val_object = attributes_object;
|
||||
|
||||
tag_array =
|
||||
neu_json_encode_array(tag_array, tag_elems, 10 + if_precision);
|
||||
neu_json_encode_array(tag_array, tag_elems, 11 + if_precision);
|
||||
|
||||
free(p_tag->datatag.name);
|
||||
free(p_tag->datatag.address);
|
||||
free(p_tag->datatag.description);
|
||||
free(p_tag->datatag.unit);
|
||||
|
||||
p_tag++;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,11 @@ int neu_json_encode_tag(void *json_obj, void *param)
|
||||
.t = tag->t,
|
||||
.v = tag->value,
|
||||
},
|
||||
{
|
||||
.name = "unit",
|
||||
.t = NEU_JSON_STR,
|
||||
.v.val_str = tag->unit,
|
||||
},
|
||||
};
|
||||
|
||||
ret = neu_json_encode_field(json_obj, tag_elems,
|
||||
@@ -140,6 +145,11 @@ int neu_json_decode_tag_json(void *json_obj, neu_json_tag_t *tag_p)
|
||||
.t = NEU_JSON_DOUBLE,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
{
|
||||
.name = "unit",
|
||||
.t = NEU_JSON_STR,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
};
|
||||
|
||||
int ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(tag_elems),
|
||||
@@ -157,6 +167,7 @@ int neu_json_decode_tag_json(void *json_obj, neu_json_tag_t *tag_p)
|
||||
.t = tag_elems[7].t,
|
||||
.value = tag_elems[7].v,
|
||||
.bias = tag_elems[8].v.val_double,
|
||||
.unit = tag_elems[9].v.val_str,
|
||||
};
|
||||
|
||||
if (0 != ret) {
|
||||
@@ -180,6 +191,7 @@ void neu_json_decode_tag_fini(neu_json_tag_t *tag)
|
||||
free(tag->name);
|
||||
free(tag->address);
|
||||
free(tag->description);
|
||||
free(tag->unit);
|
||||
if (NEU_JSON_STR == tag->t) {
|
||||
free(tag->value.val_str);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef struct {
|
||||
double bias;
|
||||
neu_json_type_e t;
|
||||
neu_json_value_u value;
|
||||
char * unit;
|
||||
} neu_json_tag_t;
|
||||
|
||||
int neu_json_encode_tag(void *json_obj, void *param);
|
||||
|
||||
+22
-14
@@ -623,11 +623,11 @@ int neu_sqlite_persister_store_tag(neu_persister_t * self,
|
||||
((neu_sqlite_persister_t *) self)->db,
|
||||
"INSERT INTO tags ("
|
||||
" driver_name, group_name, name, address, attribute,"
|
||||
" precision, type, decimal, bias, description, value, format"
|
||||
") VALUES (%Q, %Q, %Q, %Q, %i, %i, %i, %lf, %lf, %Q, %Q, %Q)",
|
||||
" precision, type, decimal, bias, description, value, format, unit"
|
||||
") VALUES (%Q, %Q, %Q, %Q, %i, %i, %i, %lf, %lf, %Q, %Q, %Q, %Q)",
|
||||
driver_name, group_name, tag->name, tag->address, tag->attribute,
|
||||
tag->precision, tag->type, tag->decimal, tag->bias, tag->description,
|
||||
"", format_buf);
|
||||
"", format_buf, tag->unit);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -706,6 +706,12 @@ static int put_tags(sqlite3 *db, const char *query, sqlite3_stmt *stmt,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_text(stmt, 13, tag->unit, -1, NULL)) {
|
||||
nlog_error("bind `%s` with unit=`%s` fail: %s", query, tag->unit,
|
||||
sqlite3_errmsg(db));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SQLITE_DONE != sqlite3_step(stmt)) {
|
||||
nlog_error("sqlite3_step fail: %s", sqlite3_errmsg(db));
|
||||
return -1;
|
||||
@@ -726,8 +732,8 @@ int neu_sqlite_persister_store_tags(neu_persister_t * self,
|
||||
const char * query =
|
||||
"INSERT INTO tags ("
|
||||
" driver_name, group_name, name, address, attribute,"
|
||||
" precision, type, decimal, bias, description, value, format"
|
||||
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)";
|
||||
" precision, type, decimal, bias, description, value, format, unit"
|
||||
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)";
|
||||
|
||||
if (SQLITE_OK != sqlite3_exec(persister->db, "BEGIN", NULL, NULL, NULL)) {
|
||||
nlog_error("begin transaction fail: %s", sqlite3_errmsg(persister->db));
|
||||
@@ -788,6 +794,7 @@ static int collect_tag_info(sqlite3_stmt *stmt, UT_array **tags)
|
||||
.decimal = sqlite3_column_double(stmt, 5),
|
||||
.bias = sqlite3_column_double(stmt, 6),
|
||||
.description = (char *) sqlite3_column_text(stmt, 7),
|
||||
.unit = (char *) sqlite3_column_text(stmt, 10),
|
||||
};
|
||||
|
||||
tag.n_format = neu_format_from_str(format, tag.format);
|
||||
@@ -812,7 +819,7 @@ int neu_sqlite_persister_load_tags(neu_persister_t *self,
|
||||
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
const char * query = "SELECT name, address, attribute, precision, type, "
|
||||
"decimal, bias, description, value, format "
|
||||
"decimal, bias, description, value, format, unit "
|
||||
"FROM tags WHERE driver_name=? AND group_name=? "
|
||||
"ORDER BY rowid ASC";
|
||||
|
||||
@@ -856,14 +863,15 @@ int neu_sqlite_persister_update_tag(neu_persister_t * self,
|
||||
const char * group_name,
|
||||
const neu_datatag_t *tag)
|
||||
{
|
||||
int rv = execute_sql(((neu_sqlite_persister_t *) self)->db,
|
||||
"UPDATE tags SET"
|
||||
" address=%Q, attribute=%i, precision=%i, type=%i,"
|
||||
" decimal=%lf, bias=%lf, description=%Q, value=%Q "
|
||||
"WHERE driver_name=%Q AND group_name=%Q AND name=%Q",
|
||||
tag->address, tag->attribute, tag->precision,
|
||||
tag->type, tag->decimal, tag->bias, tag->description,
|
||||
"", driver_name, group_name, tag->name);
|
||||
int rv =
|
||||
execute_sql(((neu_sqlite_persister_t *) self)->db,
|
||||
"UPDATE tags SET"
|
||||
" address=%Q, attribute=%i, precision=%i, type=%i,"
|
||||
" decimal=%lf, bias=%lf, description=%Q, value=%Q, unit=%Q "
|
||||
"WHERE driver_name=%Q AND group_name=%Q AND name=%Q",
|
||||
tag->address, tag->attribute, tag->precision, tag->type,
|
||||
tag->decimal, tag->bias, tag->description, "", tag->unit,
|
||||
driver_name, group_name, tag->name);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +156,8 @@ driver_1 = {
|
||||
"decimal": 0.0,
|
||||
"bias": 1.0,
|
||||
"address": "1!400001",
|
||||
"description": ""
|
||||
"description": "",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
@@ -166,7 +167,8 @@ driver_1 = {
|
||||
"decimal": 0.0,
|
||||
"bias": 1.0,
|
||||
"address": "1!400002",
|
||||
"description": ""
|
||||
"description": "",
|
||||
"unit": ""
|
||||
}
|
||||
],
|
||||
},
|
||||
@@ -204,7 +206,8 @@ driver_2 = {
|
||||
"decimal": 0.0,
|
||||
"bias": 1.0,
|
||||
"address": "1!400001",
|
||||
"description": ""
|
||||
"description": "",
|
||||
"unit": ""
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
@@ -214,7 +217,8 @@ driver_2 = {
|
||||
"decimal": 0.0,
|
||||
"bias": 1.0,
|
||||
"address": "1!400002",
|
||||
"description": ""
|
||||
"description": "",
|
||||
"unit": ""
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ hold_int16_bit = [{"name": "hold_int16_type", "address": "1!400001",
|
||||
"attribute": NEU_TAG_ATTRIBUTE_RW, "type": NEU_TYPE_BIT}]
|
||||
hold_int16_description = [{"name": "hold_int16_description", "address": "1!400001",
|
||||
"attribute": NEU_TAG_ATTRIBUTE_RW, "type": NEU_TYPE_INT16, "description": "description info"}]
|
||||
hold_int16_unit = [{"name": "hold_int16_unit", "address": "1!400001",
|
||||
"attribute": NEU_TAG_ATTRIBUTE_RW, "type": NEU_TYPE_INT16, "unit": "unit_info"}]
|
||||
hold_int16_decimal = [{"name": "hold_int16_decimal", "address": "1!400001",
|
||||
"attribute": NEU_TAG_ATTRIBUTE_RW, "type": NEU_TYPE_INT16, "decimal": 0.1}]
|
||||
hold_int16_bias = [{"name": "hold_int16_bias", "address": "1!400001",
|
||||
@@ -1013,3 +1015,44 @@ class TestTag:
|
||||
old_name="some_tag", new_name="new_tag")
|
||||
assert 404 == response.status_code
|
||||
assert NEU_ERR_NODE_NOT_EXIST == response.json()['error']
|
||||
|
||||
@description(given="a node and group", when="add a tag with unit", then="add success")
|
||||
def test_add_tag_with_unit(self):
|
||||
response = api.add_tags(node="modbus-tcp", group="group1", tags=hold_int16_unit)
|
||||
assert 200 == response.status_code
|
||||
assert NEU_ERR_SUCCESS == response.json()['error']
|
||||
|
||||
response = api.get_tags(node="modbus-tcp", group="group1")
|
||||
assert 200 == response.status_code
|
||||
assert "hold_int16_unit" == response.json()["tags"][0]["name"]
|
||||
assert "1!400001" == response.json()["tags"][0]["address"]
|
||||
assert NEU_TAG_ATTRIBUTE_RW == response.json()["tags"][0]["attribute"]
|
||||
assert NEU_TYPE_INT16 == response.json()["tags"][0]["type"]
|
||||
assert "unit_info" == response.json()["tags"][0]["unit"]
|
||||
|
||||
response = api.del_tags(node="modbus-tcp", group="group1", tags=["hold_int16_unit"])
|
||||
assert 200 == response.status_code
|
||||
assert NEU_ERR_SUCCESS == response.json()['error']
|
||||
|
||||
@description(given="a node and group", when="add a tag and update with unit", then="update success")
|
||||
def test_update_tag_with_unit(self):
|
||||
api.add_tags_check(node="modbus-tcp", group="group1", tags=hold_int16)
|
||||
|
||||
tag = {
|
||||
**hold_int16[0],
|
||||
"unit": "unit_info",
|
||||
}
|
||||
try:
|
||||
response = api.update_tags(node="modbus-tcp", group="group1", tags=[tag])
|
||||
assert 200 == response.status_code
|
||||
assert NEU_ERR_SUCCESS == response.json()['error']
|
||||
|
||||
response = api.get_tags(node="modbus-tcp", group="group1")
|
||||
assert 200 == response.status_code
|
||||
assert tag["name"] == response.json()["tags"][0]["name"]
|
||||
assert tag["address"] == response.json()["tags"][0]["address"]
|
||||
assert tag["attribute"] == response.json()["tags"][0]["attribute"]
|
||||
assert tag["type"] == response.json()["tags"][0]["type"]
|
||||
assert tag["unit"] == response.json()["tags"][0]["unit"]
|
||||
finally:
|
||||
api.del_tags(node="modbus-tcp", group="group1", tags=[tag["name"]])
|
||||
|
||||
Reference in New Issue
Block a user