Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/cn/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ Neuron 将为 IIoT 平台提供一系列 API 服务,用于查询基本信息

**type** 必需

**plugin** 可选
**plugin** 可选,支持逗号分隔多个插件名,如 `plugin=Modbus TCP,Modbus RTU`

**node** 可选

Expand Down
2 changes: 1 addition & 1 deletion docs/api/english/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ Neuron provide a series of API services for IIoT platform, to query the basic in

**type** required

**plugin** optional
**plugin** optional, support multiple plugin names separated by comma, e.g. `plugin=Modbus TCP,Modbus RTU`

**node** optional

Expand Down
1 change: 1 addition & 0 deletions include/neuron/define.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#define NEU_DEFAULT_GROUP_INTERVAL 100
#define NEU_NODE_NAME_LEN 128
#define NEU_PLUGIN_NAME_LEN 32
#define NEU_PLUGIN_FILTER_MAX 16
#define NEU_NODE_TAGS_LEN 256
#define NEU_PLUGIN_LIBRARY_LEN 64
#define NEU_PLUGIN_DESCRIPTION_LEN 512
Expand Down
3 changes: 2 additions & 1 deletion include/neuron/msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,8 @@ typedef struct neu_req_del_node {

typedef struct neu_req_get_node {
neu_node_type_e type;
char plugin[NEU_PLUGIN_NAME_LEN];
int n_plugin;
char plugin[NEU_PLUGIN_FILTER_MAX][NEU_PLUGIN_NAME_LEN];
char node[NEU_NODE_NAME_LEN];

struct {
Expand Down
45 changes: 38 additions & 7 deletions plugins/restful/adapter_handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,10 @@ void handle_del_adapter(nng_aio *aio)

void handle_get_adapter(nng_aio *aio)
{
int ret = 0;
char plugin_name[NEU_PLUGIN_NAME_LEN] = { 0 };
char node_name[NEU_NODE_NAME_LEN] = { 0 };
char group_name[NEU_GROUP_NAME_LEN] = { 0 };
int ret = 0;
char plugin_name[NEU_PLUGIN_FILTER_MAX * NEU_PLUGIN_NAME_LEN] = { 0 };
char node_name[NEU_NODE_NAME_LEN] = { 0 };
char group_name[NEU_GROUP_NAME_LEN] = { 0 };

neu_plugin_t * plugin = neu_rest_get_plugin();
neu_node_type_e node_type = { 0 };
Expand All @@ -226,9 +226,40 @@ void handle_get_adapter(nng_aio *aio)
return;
}

if (neu_http_get_param_str(aio, "plugin", plugin_name,
sizeof(plugin_name)) > 0) {
strncpy(cmd.plugin, plugin_name, NEU_PLUGIN_NAME_LEN - 1);
ssize_t plugin_len =
neu_http_get_param_str(aio, "plugin", plugin_name, sizeof(plugin_name));
if (plugin_len > 0) {
if (plugin_len >= (ssize_t) sizeof(plugin_name)) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_PARAM_IS_WRONG, {
neu_http_response(aio, error_code.error, result_error);
})
return;
}

char *save = NULL;
char *p = strtok_r(plugin_name, ",", &save);
while (p != NULL) {
while (' ' == *p || '\t' == *p) {
p++;
}
size_t len = strlen(p);
while (len > 0 && (' ' == p[len - 1] || '\t' == p[len - 1])) {
p[--len] = '\0';
}
if (len == 0) {
p = strtok_r(NULL, ",", &save);
continue;
}
if (cmd.n_plugin >= NEU_PLUGIN_FILTER_MAX) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_PARAM_IS_WRONG, {
neu_http_response(aio, error_code.error, result_error);
})
return;
}
strncpy(cmd.plugin[cmd.n_plugin], p, NEU_PLUGIN_NAME_LEN - 1);
cmd.n_plugin++;
p = strtok_r(NULL, ",", &save);
}
}

if (neu_http_get_param_str(aio, "node", node_name, sizeof(node_name)) > 0) {
Expand Down
16 changes: 11 additions & 5 deletions src/core/manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,11 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
neu_req_del_plugin_t *cmd = (neu_req_del_plugin_t *) &header[1];
neu_resp_error_t e = { 0 };

char plugins[1][NEU_PLUGIN_NAME_LEN] = { 0 };
strncpy(plugins[0], cmd->plugin, NEU_PLUGIN_NAME_LEN - 1);

UT_array *nodes = neu_manager_get_nodes(
manager, NEU_NA_TYPE_DRIVER | NEU_NA_TYPE_APP, cmd->plugin, "",
manager, NEU_NA_TYPE_DRIVER | NEU_NA_TYPE_APP, plugins, 1, "",
false, false, 0, false, 0, "");

if (nodes != NULL) {
Expand Down Expand Up @@ -690,8 +693,11 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}

char plugins[1][NEU_PLUGIN_NAME_LEN] = { 0 };
strncpy(plugins[0], module_name, NEU_PLUGIN_NAME_LEN - 1);

UT_array *nodes = neu_manager_get_nodes(
manager, NEU_NA_TYPE_DRIVER | NEU_NA_TYPE_APP, module_name, "",
manager, NEU_NA_TYPE_DRIVER | NEU_NA_TYPE_APP, plugins, 1, "",
false, false, 0, false, 0, "");

if (nodes != NULL) {
Expand Down Expand Up @@ -957,9 +963,9 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
case NEU_REQ_GET_NODE: {
neu_req_get_node_t *cmd = (neu_req_get_node_t *) &header[1];
UT_array * nodes = neu_manager_get_nodes(
manager, cmd->type, cmd->plugin, cmd->node, cmd->query.s_delay,
cmd->query.q_state, cmd->query.state, cmd->query.q_link,
cmd->query.link, cmd->query.q_group_name);
manager, cmd->type, cmd->plugin, cmd->n_plugin, cmd->node,
cmd->query.s_delay, cmd->query.q_state, cmd->query.state,
cmd->query.q_link, cmd->query.link, cmd->query.q_group_name);
neu_resp_get_node_t resp = { .nodes = nodes };

header->type = NEU_RESP_GET_NODE;
Expand Down
10 changes: 5 additions & 5 deletions src/core/manager_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,15 @@ int neu_manager_del_node(neu_manager_t *manager, const char *node_name)
neu_node_manager_del(manager->node_manager, node_name);
return NEU_ERR_SUCCESS;
}

UT_array *neu_manager_get_nodes(neu_manager_t *manager, int type,
const char *plugin, const char *node,
const char (*plugins)[NEU_PLUGIN_NAME_LEN],
int n_plugins, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link, const char *q_group_name)
{
return neu_node_manager_filter(manager->node_manager, type, plugin, node,
sort_delay, q_state, state, q_link, link,
q_group_name);
return neu_node_manager_filter(manager->node_manager, type, plugins,
n_plugins, node, sort_delay, q_state, state,
q_link, link, q_group_name);
}

int neu_manager_update_node_name(neu_manager_t *manager, const char *node,
Expand Down
3 changes: 2 additions & 1 deletion src/core/manager_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ int neu_manager_add_node(neu_manager_t *manager, const char *node_name,
bool load);
int neu_manager_del_node(neu_manager_t *manager, const char *node_name);
UT_array *neu_manager_get_nodes(neu_manager_t *manager, int type,
const char *plugin, const char *node,
const char (*plugins)[NEU_PLUGIN_NAME_LEN],
int n_plugins, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link,
const char *q_group_name);
Expand Down
18 changes: 14 additions & 4 deletions src/core/node_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ static bool find_tag_in_tags(const char *tags, const char *tag)
}

UT_array *neu_node_manager_filter(neu_node_manager_t *mgr, int type,
const char *plugin, const char *node,
const char (*plugins)[NEU_PLUGIN_NAME_LEN],
int n_plugins, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link,
const char *q_group_name)
Expand All @@ -287,9 +288,18 @@ UT_array *neu_node_manager_filter(neu_node_manager_t *mgr, int type,
{
if (!el->is_static && el->display) {
if (el->adapter->module->type & type) {
if (strlen(plugin) > 0 &&
strcmp(el->adapter->module->module_name, plugin) != 0) {
continue;
if (n_plugins > 0) {
bool matched = false;
for (int i = 0; i < n_plugins; i++) {
if (strcmp(el->adapter->module->module_name,
plugins[i]) == 0) {
matched = true;
break;
}
}
if (!matched) {
continue;
}
}
if (strlen(node) > 0) {
char *name_find = strstr(el->adapter->name, node);
Expand Down
3 changes: 2 additions & 1 deletion src/core/node_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ uint16_t neu_node_manager_size(neu_node_manager_t *mgr);
// neu_resp_node_info array
UT_array *neu_node_manager_get(neu_node_manager_t *mgr, int type);
UT_array *neu_node_manager_filter(neu_node_manager_t *mgr, int type,
const char *plugin, const char *node,
const char (*plugins)[NEU_PLUGIN_NAME_LEN],
int n_plugins, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link,
const char *q_group_name);
Expand Down
12 changes: 7 additions & 5 deletions tests/ft/neuron/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ def del_node(node, jwt=config.default_jwt):
return requests.delete(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, json={"name": node})


def get_nodes(type, jwt=config.default_jwt, group=""):
if group == "":
return requests.get(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, params={"type": type})
else:
return requests.get(url=config.BASE_URL + '/api/v2/node?group=' + group, headers={"Authorization": jwt}, params={"type": type})
def get_nodes(type, jwt=config.default_jwt, group="", plugins=None):
params = {"type": type}
if plugins:
params["plugin"] = ",".join(plugins)
if group != "":
params["group"] = group
return requests.get(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, params=params)


def get_nodes_by_tags(type, tags, jwt=config.default_jwt):
Expand Down
27 changes: 27 additions & 0 deletions tests/ft/node/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,33 @@ def test_get_app(self):
assert 200 == response.status_code
assert "mqtt" == response.json()['nodes'][0]["name"]

@description(given="a driver node", when="get driver node by single plugin", then="get success")
def test_get_driver_by_single_plugin(self):
response = api.get_nodes(type=NEU_NODE_DRIVER, plugins=[PLUGIN_MODBUS_TCP])
assert 200 == response.status_code
assert 1 == len(response.json()['nodes'])
assert "modbus-tcp" == response.json()['nodes'][0]["name"]

@description(given="driver and app nodes", when="get driver nodes by multiple plugins", then="get success")
def test_get_driver_by_multiple_plugins(self):
response = api.get_nodes(type=NEU_NODE_DRIVER, plugins=[PLUGIN_MODBUS_TCP, PLUGIN_MODBUS_RTU])
assert 200 == response.status_code
assert 1 == len(response.json()['nodes'])
assert "modbus-tcp" == response.json()['nodes'][0]["name"]

@description(given="driver node and non-existent plugin", when="get driver node by plugins with unmatched", then="get success")
def test_get_driver_by_plugin_with_unmatched(self):
response = api.get_nodes(type=NEU_NODE_DRIVER, plugins=[PLUGIN_MODBUS_TCP, "non-existent-plugin"])
assert 200 == response.status_code
assert 1 == len(response.json()['nodes'])
assert "modbus-tcp" == response.json()['nodes'][0]["name"]

@description(given="driver node", when="get driver node by plugins no match", then="get empty")
def test_get_driver_by_plugin_no_match(self):
response = api.get_nodes(type=NEU_NODE_DRIVER, plugins=[PLUGIN_MODBUS_RTU])
assert 200 == response.status_code
assert [] == response.json()['nodes']

@description(given="existent driver node", when="update the node name to empty string", then="update failed")
def test_update_node_name_to_empty(self):
response = api.update_node(node="modbus-tcp", new_name="")
Expand Down
Loading