mirror of
https://github.com/emqx/neuron.git
synced 2026-10-17 04:40:42 +08:00
Merge pull request #1992 from hxy7yx/main-1
check if the written value conforms to the standard
This commit is contained in:
@@ -136,6 +136,7 @@ typedef enum {
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_WRITE_TAGS = 3017,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_READ_SYNC = 3018,
|
||||
NEU_ERR_PLUGIN_TYPE_NOT_SUPPORT = 3019,
|
||||
NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE = 3020,
|
||||
|
||||
NEU_ERR_MQTT_FAILURE = 4000,
|
||||
NEU_ERR_MQTT_NO_CERTFILESET = 4001,
|
||||
|
||||
+222
-3
@@ -17,11 +17,14 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define EPSILON 1e-9
|
||||
|
||||
#include "event/event.h"
|
||||
#include "utils/log.h"
|
||||
#include "utils/utextend.h"
|
||||
@@ -667,6 +670,158 @@ static void cal_decimal(neu_type_e tag_type, neu_type_e value_type,
|
||||
}
|
||||
}
|
||||
|
||||
int almost_equal(double a, double b, double epsilon)
|
||||
{
|
||||
return fabs(a - b) < epsilon;
|
||||
}
|
||||
|
||||
int check_value_decimal(neu_type_e write_type, double result, int64_t value_min,
|
||||
int64_t value_max)
|
||||
{
|
||||
if (write_type != NEU_TYPE_INT64 && write_type != NEU_TYPE_DOUBLE) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else if (result < value_min || result > value_max) {
|
||||
return NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE;
|
||||
} else if (almost_equal(ceil(result), result, EPSILON)) {
|
||||
return NEU_ERR_SUCCESS;
|
||||
} else {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
int check_value(neu_type_e write_type, int64_t value, int64_t value_min,
|
||||
int64_t value_max)
|
||||
{
|
||||
if (write_type != NEU_TYPE_INT64) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else if (value >= value_min && value <= value_max) {
|
||||
return NEU_ERR_SUCCESS;
|
||||
} else {
|
||||
return NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
int is_value_in_range(neu_type_e tag_type, int64_t value, double value_d,
|
||||
neu_type_e write_type, double decimal)
|
||||
{
|
||||
if (decimal != 0) {
|
||||
double result;
|
||||
|
||||
if (write_type == NEU_TYPE_INT64) {
|
||||
result = value / decimal;
|
||||
} else {
|
||||
result = value_d / decimal;
|
||||
}
|
||||
|
||||
switch (tag_type) {
|
||||
case NEU_TYPE_INT8:
|
||||
return check_value_decimal(write_type, result, INT8_MIN, INT8_MAX);
|
||||
case NEU_TYPE_UINT8:
|
||||
return check_value_decimal(write_type, result, 0, UINT8_MAX);
|
||||
case NEU_TYPE_INT16:
|
||||
return check_value_decimal(write_type, result, INT16_MIN,
|
||||
INT16_MAX);
|
||||
case NEU_TYPE_UINT16:
|
||||
return check_value_decimal(write_type, result, 0, UINT16_MAX);
|
||||
case NEU_TYPE_INT32:
|
||||
return check_value_decimal(write_type, result, INT32_MIN,
|
||||
INT32_MAX);
|
||||
case NEU_TYPE_UINT32:
|
||||
return check_value_decimal(write_type, result, 0, UINT32_MAX);
|
||||
case NEU_TYPE_INT64:
|
||||
case NEU_TYPE_UINT64:
|
||||
if (write_type != NEU_TYPE_INT64 && write_type != NEU_TYPE_DOUBLE) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else if (almost_equal(ceil(result), result, EPSILON)) {
|
||||
return NEU_ERR_SUCCESS;
|
||||
} else {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
}
|
||||
case NEU_TYPE_FLOAT:
|
||||
if (write_type != NEU_TYPE_DOUBLE) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else if (result < (int64_t) -FLT_MAX ||
|
||||
result > (int64_t) FLT_MAX) {
|
||||
return NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE;
|
||||
} else {
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
case NEU_TYPE_DOUBLE:
|
||||
if (write_type != NEU_TYPE_DOUBLE) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else {
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
return check_value(write_type, result, INT16_MIN, INT16_MAX);
|
||||
case NEU_TYPE_STRING:
|
||||
case NEU_TYPE_BOOL:
|
||||
case NEU_TYPE_BIT:
|
||||
return NEU_ERR_PARAM_IS_WRONG;
|
||||
default:
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
switch (tag_type) {
|
||||
case NEU_TYPE_BOOL:
|
||||
if (write_type == NEU_TYPE_BOOL) {
|
||||
return NEU_ERR_SUCCESS;
|
||||
} else {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
}
|
||||
case NEU_TYPE_BIT:
|
||||
if (write_type != NEU_TYPE_INT64) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else if (value != 1 && value != 0) {
|
||||
return NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE;
|
||||
} else {
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
case NEU_TYPE_INT8:
|
||||
return check_value(write_type, value, INT8_MIN, INT8_MAX);
|
||||
case NEU_TYPE_UINT8:
|
||||
return check_value(write_type, value, 0, UINT8_MAX);
|
||||
case NEU_TYPE_INT16:
|
||||
return check_value(write_type, value, INT16_MIN, INT16_MAX);
|
||||
case NEU_TYPE_UINT16:
|
||||
return check_value(write_type, value, 0, UINT16_MAX);
|
||||
case NEU_TYPE_INT32:
|
||||
return check_value(write_type, value, INT32_MIN, INT32_MAX);
|
||||
case NEU_TYPE_UINT32:
|
||||
return check_value(write_type, value, 0, UINT32_MAX);
|
||||
case NEU_TYPE_INT64:
|
||||
case NEU_TYPE_UINT64:
|
||||
if (write_type == NEU_TYPE_INT64) {
|
||||
return NEU_ERR_SUCCESS;
|
||||
} else {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
}
|
||||
case NEU_TYPE_FLOAT:
|
||||
if (write_type != NEU_TYPE_DOUBLE) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else if (value < (int64_t) -FLT_MAX ||
|
||||
value > (int64_t) FLT_MAX) {
|
||||
return NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE;
|
||||
} else {
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
case NEU_TYPE_DOUBLE:
|
||||
if (write_type != NEU_TYPE_DOUBLE) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else {
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
case NEU_TYPE_STRING:
|
||||
if (write_type != NEU_TYPE_STRING) {
|
||||
return NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH;
|
||||
} else {
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
default:
|
||||
return NEU_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void neu_adapter_driver_write_tags(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req)
|
||||
{
|
||||
@@ -695,10 +850,24 @@ void neu_adapter_driver_write_tags(neu_adapter_driver_t *driver,
|
||||
UT_array *tags = NULL;
|
||||
UT_icd icd = { sizeof(neu_plugin_tag_value_t), NULL, NULL, NULL };
|
||||
utarray_new(tags, &icd);
|
||||
int value_err = NEU_ERR_SUCCESS;
|
||||
int value_check;
|
||||
|
||||
for (int i = 0; i < cmd->n_tag; i++) {
|
||||
neu_datatag_t *tag = neu_group_find_tag(g->group, cmd->tags[i].tag);
|
||||
|
||||
if (tag != NULL) {
|
||||
value_check =
|
||||
is_value_in_range(tag->type, cmd->tags[i].value.value.i64,
|
||||
cmd->tags[i].value.value.d64,
|
||||
cmd->tags[i].value.type, tag->decimal);
|
||||
} else {
|
||||
value_check = NEU_ERR_TAG_NOT_EXIST;
|
||||
}
|
||||
|
||||
if (tag != NULL && neu_tag_attribute_test(tag, NEU_ATTRIBUTE_WRITE) &&
|
||||
neu_tag_attribute_test(tag, NEU_ATTRIBUTE_STATIC) == false) {
|
||||
neu_tag_attribute_test(tag, NEU_ATTRIBUTE_STATIC) == false &&
|
||||
value_check == NEU_ERR_SUCCESS) {
|
||||
if (tag->type == NEU_TYPE_FLOAT || tag->type == NEU_TYPE_DOUBLE) {
|
||||
if (cmd->tags[i].value.type == NEU_TYPE_INT64) {
|
||||
cmd->tags[i].value.value.d64 =
|
||||
@@ -716,12 +885,25 @@ void neu_adapter_driver_write_tags(neu_adapter_driver_t *driver,
|
||||
.value = cmd->tags[i].value.value,
|
||||
};
|
||||
utarray_push_back(tags, &tv);
|
||||
} else {
|
||||
value_err = value_check;
|
||||
}
|
||||
if (tag != NULL) {
|
||||
neu_tag_free(tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (value_err != NEU_ERR_SUCCESS) {
|
||||
driver->adapter.cb_funs.driver.write_response(&driver->adapter, req,
|
||||
value_err);
|
||||
utarray_foreach(tags, neu_plugin_tag_value_t *, tv)
|
||||
{
|
||||
neu_tag_free(tv->tag);
|
||||
}
|
||||
utarray_free(tags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (utarray_len(tags) != (unsigned int) cmd->n_tag) {
|
||||
driver->adapter.cb_funs.driver.write_response(&driver->adapter, req,
|
||||
NEU_ERR_TAG_NOT_EXIST);
|
||||
@@ -776,6 +958,8 @@ void neu_adapter_driver_write_gtags(neu_adapter_driver_t *driver,
|
||||
UT_array *tags = NULL;
|
||||
UT_icd icd = { sizeof(neu_plugin_tag_value_t), NULL, NULL, NULL };
|
||||
utarray_new(tags, &icd);
|
||||
int value_err = NEU_ERR_SUCCESS;
|
||||
int value_check;
|
||||
|
||||
for (int i = 0; i < cmd->n_group; i++) {
|
||||
group_t *g = find_group(driver, cmd->groups[i].group);
|
||||
@@ -783,10 +967,20 @@ void neu_adapter_driver_write_gtags(neu_adapter_driver_t *driver,
|
||||
for (int k = 0; k < cmd->groups[i].n_tag; k++) {
|
||||
neu_datatag_t *tag =
|
||||
neu_group_find_tag(g->group, cmd->groups[i].tags[k].tag);
|
||||
|
||||
if (tag != NULL) {
|
||||
value_check = is_value_in_range(
|
||||
tag->type, cmd->groups[i].tags[k].value.value.i64,
|
||||
cmd->groups[i].tags[k].value.value.d64,
|
||||
cmd->groups[i].tags[k].value.type, tag->decimal);
|
||||
} else {
|
||||
value_check = NEU_ERR_TAG_NOT_EXIST;
|
||||
}
|
||||
|
||||
if (tag != NULL &&
|
||||
neu_tag_attribute_test(tag, NEU_ATTRIBUTE_WRITE) &&
|
||||
neu_tag_attribute_test(tag, NEU_ATTRIBUTE_STATIC) == false) {
|
||||
|
||||
neu_tag_attribute_test(tag, NEU_ATTRIBUTE_STATIC) == false &&
|
||||
value_check == NEU_ERR_SUCCESS) {
|
||||
if (tag->type == NEU_TYPE_FLOAT ||
|
||||
tag->type == NEU_TYPE_DOUBLE) {
|
||||
if (cmd->groups[i].tags[k].value.type == NEU_TYPE_INT64) {
|
||||
@@ -807,6 +1001,8 @@ void neu_adapter_driver_write_gtags(neu_adapter_driver_t *driver,
|
||||
.value = cmd->groups[i].tags[k].value.value,
|
||||
};
|
||||
utarray_push_back(tags, &tv);
|
||||
} else {
|
||||
value_err = value_check;
|
||||
}
|
||||
if (tag != NULL) {
|
||||
neu_tag_free(tag);
|
||||
@@ -814,6 +1010,17 @@ void neu_adapter_driver_write_gtags(neu_adapter_driver_t *driver,
|
||||
}
|
||||
}
|
||||
|
||||
if (value_err != NEU_ERR_SUCCESS) {
|
||||
driver->adapter.cb_funs.driver.write_response(&driver->adapter, req,
|
||||
value_err);
|
||||
utarray_foreach(tags, neu_plugin_tag_value_t *, tv)
|
||||
{
|
||||
neu_tag_free(tv->tag);
|
||||
}
|
||||
utarray_free(tags);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t n_tag = 0;
|
||||
for (int i = 0; i < cmd->n_group; i++) {
|
||||
n_tag += cmd->groups[i].n_tag;
|
||||
@@ -867,6 +1074,18 @@ void neu_adapter_driver_write_tag(neu_adapter_driver_t *driver,
|
||||
neu_tag_free(tag);
|
||||
return;
|
||||
}
|
||||
|
||||
int value_check = is_value_in_range(tag->type, cmd->value.value.i64,
|
||||
cmd->value.value.d64,
|
||||
cmd->value.type, tag->decimal);
|
||||
|
||||
if (value_check != NEU_ERR_SUCCESS) {
|
||||
driver->adapter.cb_funs.driver.write_response(&driver->adapter, req,
|
||||
value_check);
|
||||
neu_tag_free(tag);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tag->type == NEU_TYPE_FLOAT || tag->type == NEU_TYPE_DOUBLE) {
|
||||
if (cmd->value.type == NEU_TYPE_INT64) {
|
||||
cmd->value.value.d64 = (double) cmd->value.value.i64;
|
||||
|
||||
+2
-1
@@ -254,7 +254,6 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content)
|
||||
case NEU_ERR_LICENSE_MAX_NODES:
|
||||
case NEU_ERR_LICENSE_TOKEN_NOT_MATCH:
|
||||
case NEU_ERR_GROUP_ALREADY_SUBSCRIBED:
|
||||
case NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH:
|
||||
case NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE:
|
||||
case NEU_ERR_PLUGIN_NOT_RUNNING:
|
||||
case NEU_ERR_PLUGIN_TAG_NOT_READY:
|
||||
@@ -320,6 +319,8 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content)
|
||||
case NEU_ERR_TAG_PRECISION_INVALID:
|
||||
case NEU_ERR_TAG_NAME_TOO_LONG:
|
||||
case NEU_ERR_TAG_ADDRESS_TOO_LONG:
|
||||
case NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH:
|
||||
case NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE:
|
||||
case NEU_ERR_TAG_BIAS_INVALID:
|
||||
case NEU_ERR_GROUP_MAX_GROUPS:
|
||||
case NEU_ERR_LICENSE_MAX_TAGS:
|
||||
|
||||
@@ -455,7 +455,7 @@ class TestAzure:
|
||||
},
|
||||
{
|
||||
"tag": "tag1",
|
||||
"value": True,
|
||||
"value": 1,
|
||||
},
|
||||
{
|
||||
"tag": "tag2",
|
||||
|
||||
@@ -377,7 +377,7 @@ class TesteKuiper:
|
||||
}
|
||||
req_tags = {
|
||||
TAGS[0]["name"]: 1234,
|
||||
TAGS[1]["name"]: True,
|
||||
TAGS[1]["name"]: 1,
|
||||
TAGS[2]["name"]: 3.14,
|
||||
TAGS[3]["name"]: "hello",
|
||||
TAGS[4]["name"]: [1, 2, 3, 4],
|
||||
@@ -407,7 +407,7 @@ class TesteKuiper:
|
||||
|
||||
req_tags = {
|
||||
TAGS[0]["name"]: 5678,
|
||||
TAGS[1]["name"]: False,
|
||||
TAGS[1]["name"]: 0,
|
||||
TAGS[2]["name"]: 6.28,
|
||||
TAGS[3]["name"]: "mulitple",
|
||||
TAGS[4]["name"]: [9, 8, 7, 6],
|
||||
|
||||
@@ -657,7 +657,7 @@ class TestMQTT:
|
||||
},
|
||||
{
|
||||
"tag": "tag1",
|
||||
"value": True,
|
||||
"value": 1,
|
||||
},
|
||||
{
|
||||
"tag": "tag2",
|
||||
|
||||
@@ -199,6 +199,8 @@ hold_string_s = [{"name": "hold_string_s", "address": "1!400870.2",
|
||||
|
||||
hold_int16_decimal = [{"name": "hold_int16_decimal", "address": "1!40103",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16, "decimal": 0.1}]
|
||||
hold_int16_decimal_w = [{"name": "hold_int16_decimal_w", "address": "1!40103",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16, "decimal": 0.1}]
|
||||
hold_int16_decimal_neg = [{"name": "int16_decimal_neg", "address": "1!40140",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16, "decimal": -1}]
|
||||
hold_uint16_decimal = [{"name": "hold_uint16_decimal", "address": "1!400105",
|
||||
@@ -524,6 +526,102 @@ class TestModbus:
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_TAG_ADDRESS_FORMAT_INVALID == response.json()[
|
||||
'error']
|
||||
|
||||
@description(given="created modbus node and tags", when="write tags with invalid value", then="write failed")
|
||||
def test_write_tags_invalid_value(self, param):
|
||||
response = api.write_tag(node=param[0], group='group', tag=hold_int16[0]['name'], value=32768)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=hold_uint16[0]['name'], value=-1)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=hold_int32[0]['name'], value=2147483648)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=hold_uint32[0]['name'], value=-1)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=hold_string[0]['name'], value=1)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH == response.json()['error']
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=coil_bit_1[0]['name'], value=2)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=coil_bit_1[0]['name'], value=True)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH == response.json()['error']
|
||||
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_int16_decimal_w)
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=hold_int16_decimal_w[0]['name'], value=1.11)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH == response.json()['error']
|
||||
|
||||
response = api.write_tag(node=param[0], group='group', tag=hold_float[0]['name'], value=1)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH == response.json()['error']
|
||||
|
||||
response = api.write_tags(node=param[0], group='group', tag_values=[
|
||||
{"tag": hold_int16[0]['name'], "value": 32768},
|
||||
{"tag": hold_uint16[0]['name'], "value": 2},
|
||||
{"tag": hold_int32[0]['name'], "value": 3},
|
||||
{"tag": hold_uint32[0]['name'], "value": 4}])
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tags(node=param[0], group='group', tag_values=[
|
||||
{"tag": hold_int16[0]['name'], "value": 1},
|
||||
{"tag": hold_uint16[0]['name'], "value": -1},
|
||||
{"tag": hold_int32[0]['name'], "value": 3},
|
||||
{"tag": hold_uint32[0]['name'], "value": 4}])
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tags(node=param[0], group='group', tag_values=[
|
||||
{"tag": hold_int16[0]['name'], "value": 1},
|
||||
{"tag": hold_uint16[0]['name'], "value": 2},
|
||||
{"tag": hold_int32[0]['name'], "value": 2147483648},
|
||||
{"tag": hold_uint32[0]['name'], "value": 4}])
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
response = api.write_tags(node=param[0], group='group', tag_values=[
|
||||
{"tag": hold_int16[0]['name'], "value": 1},
|
||||
{"tag": hold_uint16[0]['name'], "value": 2},
|
||||
{"tag": hold_int32[0]['name'], "value": 3},
|
||||
{"tag": hold_uint32[0]['name'], "value": -1}])
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
modbus_write_gtags = {"node": param[0], "groups": [{"group": "group", "tags" : [{"tag": "hold_int16", "value": 32768},
|
||||
{"tag": "hold_uint16", "value": 2}, {"tag": "hold_int32", "value": 3}, {"tag": "hold_uint32", "value": 4}]}]}
|
||||
response = api.write_gtags(json=modbus_write_gtags)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
modbus_write_gtags = {"node": param[0], "groups": [{"group": "group", "tags" : [{"tag": "hold_int16", "value": 1},
|
||||
{"tag": "hold_uint16", "value": -1}, {"tag": "hold_int32", "value": 3}, {"tag": "hold_uint32", "value": 4}]}]}
|
||||
response = api.write_gtags(json=modbus_write_gtags)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
modbus_write_gtags = {"node": param[0], "groups": [{"group": "group", "tags" : [{"tag": "hold_int16", "value": 1},
|
||||
{"tag": "hold_uint16", "value": 2}, {"tag": "hold_int32", "value": 2147483648}, {"tag": "hold_uint32", "value": 4}]}]}
|
||||
response = api.write_gtags(json=modbus_write_gtags)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
modbus_write_gtags = {"node": param[0], "groups": [{"group": "group", "tags" : [{"tag": "hold_int16", "value": 1},
|
||||
{"tag": "hold_uint16", "value": 2}, {"tag": "hold_int32", "value": 3}, {"tag": "hold_uint32", "value": -1}]}]}
|
||||
response = api.write_gtags(json=modbus_write_gtags)
|
||||
assert 400 == response.status_code
|
||||
assert error.NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE == response.json()['error']
|
||||
|
||||
@description(given="created modbus node and tags", when="write/read tags", then="write/read success")
|
||||
def test_write_read_tags(self, param):
|
||||
@@ -888,7 +986,7 @@ class TestModbus:
|
||||
node=param[0], group='group', tag=hold_string_utf8[0]['name'])
|
||||
|
||||
@description(given="created modbus node/tag", when="read/write decimal/bias tag", then="read success")
|
||||
def test_read_decimal_bias_tag(self, param):
|
||||
def test_read_decimal_bias_tag_i(self, param):
|
||||
tags = [
|
||||
hold_int16[0],
|
||||
hold_int16_L[0],
|
||||
@@ -912,6 +1010,62 @@ class TestModbus:
|
||||
hold_uint64[0],
|
||||
hold_uint64_L[0],
|
||||
hold_uint64_B[0],
|
||||
]
|
||||
|
||||
tags_bias = [
|
||||
{
|
||||
**tag,
|
||||
"bias": random.randint(1, 1000),
|
||||
"attribute": tag["attribute"] & ~config.NEU_TAG_ATTRIBUTE_WRITE,
|
||||
}
|
||||
for tag in tags
|
||||
]
|
||||
|
||||
tags_decimal_bias = [
|
||||
{
|
||||
**tag,
|
||||
"decimal": 0.1,
|
||||
}
|
||||
for tag in tags_bias
|
||||
]
|
||||
|
||||
tag_values = [
|
||||
{
|
||||
"tag": tag['name'],
|
||||
"value": random.randint(1, 10)
|
||||
}
|
||||
for tag in tags
|
||||
]
|
||||
|
||||
try:
|
||||
# 1. prepare tags
|
||||
grp = "group-bias"
|
||||
api.add_group_check(node=param[0], group=grp, interval=100)
|
||||
api.add_tags_check(node=param[0], group=grp, tags=tags)
|
||||
api.write_tags_check(node=param[0], group=grp, tag_values=tag_values)
|
||||
# 2. read value + bias
|
||||
api.update_tags_check(node=param[0], group=grp, tags=tags_bias)
|
||||
time.sleep(0.3)
|
||||
resp_values = api.read_tags(node=param[0], group=grp).json()['tags']
|
||||
assert len(tag_values) == len(resp_values)
|
||||
for tag, value, resp in zip(tags_bias, tag_values, resp_values):
|
||||
expected = value['value'] + tag['bias']
|
||||
assert compare_float(expected, resp['value'])
|
||||
# 3. read value * decimal + bias
|
||||
api.update_tags_check(
|
||||
node=param[0], group=grp, tags=tags_decimal_bias)
|
||||
time.sleep(0.3)
|
||||
resp_values = api.read_tags(node=param[0], group=grp).json()['tags']
|
||||
assert len(tag_values) == len(resp_values)
|
||||
for tag, value, resp in zip(tags_decimal_bias, tag_values, resp_values):
|
||||
expected = value['value'] * tag['decimal'] + tag['bias']
|
||||
assert compare_float(expected, resp['value'])
|
||||
finally:
|
||||
api.del_group(node=param[0], group=grp)
|
||||
|
||||
@description(given="created modbus node/tag", when="read/write decimal/bias tag", then="read success")
|
||||
def test_read_decimal_bias_tag_f(self, param):
|
||||
tags = [
|
||||
hold_float[0],
|
||||
hold_float_LL[0],
|
||||
hold_float_LB[0],
|
||||
@@ -942,7 +1096,7 @@ class TestModbus:
|
||||
tag_values = [
|
||||
{
|
||||
"tag": tag['name'],
|
||||
"value": random.randint(1, 10)
|
||||
"value": random.uniform(1.0, 10.0)
|
||||
}
|
||||
for tag in tags
|
||||
]
|
||||
|
||||
@@ -106,5 +106,6 @@ NEU_ERR_PLUGIN_NOT_SUPPORT_TEMPLATE = 3016
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_WRITE_TAGS = 3017
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_READ_SYNC = 3018
|
||||
NEU_ERR_PLUGIN_TYPE_NOT_SUPPORT = 3019
|
||||
NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE = 3020
|
||||
|
||||
NEU_ERR_MQTT_SUBSCRIBE_FAILURE = 4010
|
||||
Reference in New Issue
Block a user