mirror of
https://github.com/emqx/neuron.git
synced 2026-10-24 02:39:13 +08:00
@@ -107,9 +107,6 @@ static struct neu_http_handler cors_handler[] = {
|
||||
{
|
||||
.url = "/api/v2/password",
|
||||
},
|
||||
{
|
||||
.url = "/api/v2/logs",
|
||||
},
|
||||
{
|
||||
.url = "/api/v2/log/level",
|
||||
},
|
||||
@@ -366,12 +363,6 @@ static struct neu_http_handler rest_handlers[] = {
|
||||
.url = "/api/v2/node/state",
|
||||
.value.handler = handle_get_node_state,
|
||||
},
|
||||
{
|
||||
.method = NEU_HTTP_METHOD_GET,
|
||||
.type = NEU_HTTP_HANDLER_FUNCTION,
|
||||
.url = "/api/v2/logs",
|
||||
.value.handler = handle_logs_files,
|
||||
},
|
||||
{
|
||||
.method = NEU_HTTP_METHOD_PUT,
|
||||
.type = NEU_HTTP_HANDLER_FUNCTION,
|
||||
|
||||
@@ -42,70 +42,6 @@
|
||||
#include "log_handle.h"
|
||||
#include "utils/utarray.h"
|
||||
|
||||
void handle_logs_files(nng_aio *aio)
|
||||
{
|
||||
void * data = NULL;
|
||||
size_t len = 0;
|
||||
int rv = 0;
|
||||
|
||||
NEU_VALIDATE_JWT(aio);
|
||||
|
||||
/* check whether the neuron directory exists */
|
||||
rv = access("../neuron", F_OK);
|
||||
if (0 != rv) {
|
||||
nlog_error("The neuron directory does not exists");
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_NOT_EXIST, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
rv = system("rm -rf /tmp/neuron_debug.tar.gz");
|
||||
nlog_warn("remove old neuron_debug.tar.gz, rv: %d", rv);
|
||||
/* tar the neuron directory */
|
||||
rv = system("tar -zcvf /tmp/neuron_debug.tar.gz "
|
||||
"--exclude='persistence/neuron.lic' ../neuron");
|
||||
if (rv == -1) {
|
||||
nlog_error("failed to create neuron_debug.tar.gz, rv: %d", rv);
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_COMMAND_EXECUTION_FAILED, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
if (WIFEXITED(rv)) {
|
||||
if (WEXITSTATUS(rv) < 0) {
|
||||
nlog_error("failed to create neuron_debug.tar.gz, rv: %d",
|
||||
WEXITSTATUS(rv));
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_COMMAND_EXECUTION_FAILED, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
nlog_error("failed to create neuron_debug.tar.gz, rv: %d",
|
||||
WEXITSTATUS(rv));
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_COMMAND_EXECUTION_FAILED, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rv = read_file("/tmp/neuron_debug.tar.gz", &data, &len);
|
||||
if (0 != rv) {
|
||||
NEU_JSON_RESPONSE_ERROR(
|
||||
rv, { neu_http_response(aio, error_code.error, result_error); });
|
||||
return;
|
||||
}
|
||||
|
||||
/* handle http response */
|
||||
rv = neu_http_response_file(aio, data, len,
|
||||
"attachment; filename=neuron_debug.tar.gz");
|
||||
|
||||
free(data);
|
||||
nlog_notice("download neuron_debug.tar.gz, ret: %d", rv);
|
||||
}
|
||||
|
||||
void handle_log_level(nng_aio *aio)
|
||||
{
|
||||
neu_plugin_t *plugin = neu_rest_get_plugin();
|
||||
@@ -156,44 +92,4 @@ void handle_log_level(nng_aio *aio)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
int read_file(const char *file_name, void **datap, size_t *lenp)
|
||||
{
|
||||
int rv = 0;
|
||||
FILE * f;
|
||||
struct stat st;
|
||||
size_t len;
|
||||
void * data;
|
||||
|
||||
if (stat(file_name, &st) != 0) {
|
||||
return NEU_ERR_FILE_NOT_EXIST;
|
||||
}
|
||||
|
||||
if ((f = fopen(file_name, "rb")) == NULL) {
|
||||
nlog_error("open fail: %s", file_name);
|
||||
return NEU_ERR_FILE_OPEN_FAILURE;
|
||||
}
|
||||
|
||||
len = st.st_size;
|
||||
if (len > 0) {
|
||||
if ((data = malloc(len)) == NULL) {
|
||||
rv = NEU_ERR_EINTERNAL;
|
||||
goto done;
|
||||
}
|
||||
if (fread(data, 1, len, f) != len) {
|
||||
nlog_error("file read failued, errno = %d", errno);
|
||||
rv = NEU_ERR_FILE_READ_FAILURE;
|
||||
free(data);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
*datap = data;
|
||||
*lenp = len;
|
||||
done:
|
||||
fclose(f);
|
||||
return (rv);
|
||||
}
|
||||
@@ -23,9 +23,6 @@
|
||||
#include <nng/nng.h>
|
||||
|
||||
// void handle_get_log(nng_aio *aio);
|
||||
void handle_logs_files(nng_aio *aio);
|
||||
void handle_log_level(nng_aio *aio);
|
||||
|
||||
int read_file(const char *file_name, void **datap, size_t *lenp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -896,6 +896,20 @@ class TestModbus:
|
||||
node=param[0], group='group', tag=hold_string_l1[0]['name'])
|
||||
assert 'b' == api.read_tag(
|
||||
node=param[0], group='group', tag=hold_string_l2[0]['name'])
|
||||
|
||||
@description(given="created modbus node ,groups and tags", when="write/read gtags", then="write/read success")
|
||||
def test_write_read_gtags(self, param):
|
||||
modbus_write_gtags = {"node": param[0], "groups": [{"group": "group", "tags" : [{"tag": "hold_uint16", "value": 1}, {"tag": "hold_string", "value": 'hello'},
|
||||
{"tag": "coil_bit_1", "value": 1}, {"tag": "hold_double_decimal", "value": 513.11}, {"tag": "hold_bytes", "value": [0x1, 0x2, 0x3, 0x4]}]},
|
||||
{"group": "group1", "tags" : [{"tag": "hold_int16", "value": 1}]}]}
|
||||
response = api.write_gtags(json=modbus_write_gtags)
|
||||
assert 200 == response.status_code
|
||||
assert error.NEU_ERR_SUCCESS == response.json()['error']
|
||||
time.sleep(1.0)
|
||||
assert 1 == api.read_tag(
|
||||
node=param[0], group='group', tag=hold_uint16[0]['name'])
|
||||
assert 1 == api.read_tag(
|
||||
node=param[0], group='group1', tag=hold_int16[0]['name'])
|
||||
|
||||
@description(given="created modbus device_error_test node/tag", when="read tag", then="read failed")
|
||||
def test_read_modbus_device_err(self, param):
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import sys
|
||||
|
||||
sys.path.append("tests/ft")
|
||||
@@ -0,0 +1,229 @@
|
||||
import neuron.api as api
|
||||
import neuron.error as error
|
||||
import neuron.config as config
|
||||
from neuron.common import *
|
||||
|
||||
hold_int16 = [{"name": "hold_int16", "address": "1!400001",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}]
|
||||
|
||||
global_config = {
|
||||
"nodes": [
|
||||
{
|
||||
"plugin": "MQTT",
|
||||
"name": "mqtt"
|
||||
},
|
||||
{
|
||||
"plugin": "Modbus TCP",
|
||||
"name": "modbus"
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"driver": "modbus",
|
||||
"group": "group",
|
||||
"tag_count": 1,
|
||||
"interval": 100
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"tags": [
|
||||
{
|
||||
"type": 3,
|
||||
"name": "hold_int16",
|
||||
"attribute": 3,
|
||||
"precision": 0,
|
||||
"decimal": 0.0,
|
||||
"address": "1!400001",
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "hold_int16_s",
|
||||
"attribute": 11,
|
||||
"precision": 0,
|
||||
"decimal": 0.0,
|
||||
"address": "1!400002",
|
||||
"description": "",
|
||||
"value": 1
|
||||
}
|
||||
],
|
||||
"driver": "modbus",
|
||||
"group": "group"
|
||||
}
|
||||
],
|
||||
"subscriptions": [
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"driver": "modbus",
|
||||
"group": "group"
|
||||
}
|
||||
],
|
||||
"app": "mqtt"
|
||||
}
|
||||
],
|
||||
"settings": [
|
||||
{
|
||||
"node": "mqtt",
|
||||
"params": {
|
||||
"client-id": "neuron_aBcDeF",
|
||||
"qos": 0,
|
||||
"format": 0,
|
||||
"write-req-topic": "/neuron/mqtt/write/req",
|
||||
"write-resp-topic": "/neuron/mqtt/write/resp",
|
||||
"offline-cache": False,
|
||||
"cache-sync-interval": 100,
|
||||
"host": "broker.emqx.io",
|
||||
"port": 1883,
|
||||
"username": "",
|
||||
"password": "",
|
||||
"ssl": False
|
||||
}
|
||||
},
|
||||
{
|
||||
"node": "modbus",
|
||||
"params": {
|
||||
"connection_mode": 0,
|
||||
"transport_mode": 0,
|
||||
"interval": 0,
|
||||
"host": "127.0.0.1",
|
||||
"port": 502,
|
||||
"timeout": 3000,
|
||||
"max_retries": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class TestHttp:
|
||||
|
||||
@description(given="running neuron", when="add driver/app node/group/tag, app subscribes driver group, and get global config", then="success")
|
||||
def test_get_global_config(self):
|
||||
response = api.put_global_config(json=global_config)
|
||||
assert 200 == response.status_code
|
||||
assert error.NEU_ERR_SUCCESS == response.json()['error']
|
||||
|
||||
response = api.get_global_config()
|
||||
assert 200 == response.status_code
|
||||
|
||||
config_data = response.json()
|
||||
|
||||
assert 'nodes' in config_data
|
||||
assert len(config_data['nodes']) == 2
|
||||
assert config_data['nodes'][0]['plugin'] == 'MQTT'
|
||||
assert config_data['nodes'][1]['plugin'] == 'Modbus TCP'
|
||||
|
||||
assert 'groups' in config_data
|
||||
assert len(config_data['groups']) == 1
|
||||
assert config_data['groups'][0]['driver'] == 'modbus'
|
||||
|
||||
assert 'tags' in config_data
|
||||
assert len(config_data['tags']) == 1
|
||||
assert config_data['tags'][0]['driver'] == 'modbus'
|
||||
assert len(config_data['tags'][0]['tags']) == 2
|
||||
|
||||
assert 'subscriptions' in config_data
|
||||
assert len(config_data['subscriptions']) == 1
|
||||
assert config_data['subscriptions'][0]['app'] == 'mqtt'
|
||||
|
||||
assert 'settings' in config_data
|
||||
assert len(config_data['settings']) == 2
|
||||
assert config_data['settings'][0]['node'] == 'mqtt'
|
||||
|
||||
response = api.del_node_check(node='modbus')
|
||||
|
||||
response = api.get_global_config()
|
||||
assert 200 == response.status_code
|
||||
|
||||
config_data = response.json()
|
||||
|
||||
assert 'nodes' in config_data
|
||||
assert len(config_data['nodes']) == 1
|
||||
assert config_data['nodes'][0]['plugin'] == 'MQTT'
|
||||
|
||||
assert 'groups' in config_data
|
||||
assert len(config_data['groups']) == 0
|
||||
|
||||
assert 'tags' in config_data
|
||||
assert len(config_data['tags']) == 0
|
||||
|
||||
assert 'subscriptions' in config_data
|
||||
assert len(config_data['subscriptions']) == 0
|
||||
|
||||
assert 'settings' in config_data
|
||||
assert len(config_data['settings']) == 1
|
||||
assert config_data['settings'][0]['node'] == 'mqtt'
|
||||
|
||||
@description(given="running neuron", when="get mqtt shcema", then="success")
|
||||
def test_get_plugin_schema(self):
|
||||
response = api.get_plugin_schema(plugin='mqtt')
|
||||
assert 200 == response.status_code
|
||||
|
||||
response = api.get_plugin_schema(plugin='modbus-tcp')
|
||||
assert 200 == response.status_code
|
||||
|
||||
response = api.get_plugin_schema(plugin='invalid')
|
||||
assert 404 == response.status_code
|
||||
assert response.json()['status'] == 'error'
|
||||
|
||||
@description(given="running neuron", when="get plugin", then="success")
|
||||
def test_get_plugin(self):
|
||||
response = api.get_plugin()
|
||||
assert 200 == response.status_code
|
||||
|
||||
@description(given="running neuron", when="get version", then="success")
|
||||
def test_get_version(self):
|
||||
response = api.get_version()
|
||||
assert 200 == response.status_code
|
||||
|
||||
@description(given="running neuron", when="test ndriver", then="failed because it is not supported yet")
|
||||
def test_ndriver(self):
|
||||
api.add_node_check(node='modbus', plugin=config.PLUGIN_MODBUS_TCP)
|
||||
api.add_group_check(node='modbus', group='group')
|
||||
api.add_tags_check(node='modbus', group='group', tags=hold_int16)
|
||||
response = api.subscribe_group(app='mqtt', driver='modbus', group='group')
|
||||
assert 200 == response.status_code
|
||||
assert error.NEU_ERR_SUCCESS == response.json()['error']
|
||||
|
||||
response = api.post_ndriver_map(ndriver='mqtt', driver='modbus', group='group')
|
||||
assert 400 == response.status_code
|
||||
|
||||
response = api.get_ndriver_map(ndriver='mqtt')
|
||||
assert 400 == response.status_code
|
||||
|
||||
ndriver_tag_param = {"ndriver": "mqtt", "driver": "modbus", "group": "group", "tags": [
|
||||
{"name": "hold_int16", "params": {"address": "1!400002"}}]}
|
||||
response = api.put_ndriver_tag_param(json=ndriver_tag_param)
|
||||
assert 200 == response.status_code
|
||||
|
||||
ndriver_tag_info = {"ndriver": "mqtt", "driver": "modbus", "group": "group", "tags": [
|
||||
{"name": "hold_int16", "address": "1!400002"}]}
|
||||
response = api.put_ndriver_tag_info(json=ndriver_tag_info)
|
||||
assert 200 == response.status_code
|
||||
|
||||
response = api.get_ndriver_tag(ndriver='mqtt', driver='modbus', group='group')
|
||||
assert 200 == response.status_code
|
||||
|
||||
response = api.delete_ndriver_map(ndriver='mqtt', driver='modbus', group='group')
|
||||
assert 200 == response.status_code
|
||||
|
||||
@description(given="running neuron", when="test jwt error", then="failed")
|
||||
def test_jwt_err(self):
|
||||
response = api.change_password(new_password='123456', jwt='invalid')
|
||||
assert 401 == response.status_code
|
||||
|
||||
response = api.get_hwtoken(jwt='invalid')
|
||||
assert 404 == response.status_code
|
||||
|
||||
response = api.get_license(jwt='invalid')
|
||||
assert 404 == response.status_code
|
||||
|
||||
response = api.upload_license(license='abaaba', jwt='invalid')
|
||||
assert 404 == response.status_code
|
||||
|
||||
response = api.upload_virtual_license(license='abaaba', jwt='invalid')
|
||||
assert 404 == response.status_code
|
||||
|
||||
response = api.delete_virtual_license(jwt='invalid')
|
||||
assert 404 == response.status_code
|
||||
@@ -121,4 +121,8 @@ class TestLog:
|
||||
response = api.get_nodes_state('modbus-tcp-1')
|
||||
assert 200 == response.status_code
|
||||
assert "notice" == response.json()['neuron_core']
|
||||
assert "info" == response.json()['log_level']
|
||||
assert "info" == response.json()['log_level']
|
||||
|
||||
response = api.get_nodes_state(node='')
|
||||
assert 200 == response.status_code
|
||||
assert "notice" == response.json()['neuron_core']
|
||||
@@ -194,6 +194,9 @@ def write_tag(node, group, tag, value):
|
||||
def write_tags(node, group, tag_values):
|
||||
return requests.post(url=config.BASE_URL + "/api/v2/write/tags", headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "tags": tag_values})
|
||||
|
||||
def write_gtags(json):
|
||||
return requests.post(url=config.BASE_URL + "/api/v2/write/gtags", headers={"Authorization": config.default_jwt}, json=json)
|
||||
|
||||
|
||||
def add_plugin(library_name, so_file, schema_file):
|
||||
return requests.post(url=config.BASE_URL + "/api/v2/plugin", json={"library": library_name, "so_file": so_file, "schema_file": schema_file}, headers={"Authorization": config.default_jwt})
|
||||
@@ -293,6 +296,39 @@ def unsubscribe_group(app, driver, group):
|
||||
def get_metrics(category="global", node=""):
|
||||
return requests.get(url=config.BASE_URL + "/api/v2/metrics?category=" + category + "&node=" + node, headers={"Authorization": config.default_jwt})
|
||||
|
||||
def get_global_config():
|
||||
return requests.get(url=config.BASE_URL + "/api/v2/global/config", headers={"Authorization": config.default_jwt})
|
||||
|
||||
def put_global_config(json):
|
||||
return requests.put(url=config.BASE_URL + "/api/v2/global/config", headers={"Authorization": config.default_jwt}, json=json)
|
||||
|
||||
def get_plugin_schema(plugin):
|
||||
return requests.get(url=config.BASE_URL + "/api/v2/schema?schema_name=" + plugin, headers={"Authorization": config.default_jwt})
|
||||
|
||||
def get_plugin():
|
||||
return requests.get(url=config.BASE_URL + "/api/v2/plugin", headers={"Authorization": config.default_jwt})
|
||||
|
||||
def get_version():
|
||||
return requests.get(url=config.BASE_URL + "/api/v2/version", headers={"Authorization": config.default_jwt})
|
||||
|
||||
def post_ndriver_map(ndriver, driver, group):
|
||||
return requests.post(url=config.BASE_URL + "/api/v2/ndriver/map", headers={"Authorization": config.default_jwt}, json={"ndriver": ndriver, "driver": driver, "group":group})
|
||||
|
||||
def delete_ndriver_map(ndriver, driver, group):
|
||||
return requests.delete(url=config.BASE_URL + "/api/v2/ndriver/map", headers={"Authorization": config.default_jwt}, json={"ndriver": ndriver, "driver": driver, "group":group})
|
||||
|
||||
def get_ndriver_map(ndriver):
|
||||
return requests.get(url=config.BASE_URL + "/api/v2/ndriver/map?ndriver=" + ndriver, headers={"Authorization": config.default_jwt})
|
||||
|
||||
def put_ndriver_tag_param(json):
|
||||
return requests.put(url=config.BASE_URL + "/api/v2/ndriver/tag/param", headers={"Authorization": config.default_jwt}, json=json)
|
||||
|
||||
def put_ndriver_tag_info(json):
|
||||
return requests.put(url=config.BASE_URL + "/api/v2/ndriver/tag/info", headers={"Authorization": config.default_jwt}, json=json)
|
||||
|
||||
def get_ndriver_tag(ndriver, driver, group):
|
||||
return requests.get(url=config.BASE_URL + "/api/v2/ndriver/tag?ndriver=" + ndriver + "&driver=" + driver + "&group=" + group, headers={"Authorization": config.default_jwt})
|
||||
|
||||
# plugin setting
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user