mirror of
https://github.com/emqx/neuron.git
synced 2026-10-28 14:07:20 +08:00
Merge pull request #1119 from eeff/eeff/dev
feat(restful): add POST /api/v2/template
This commit is contained in:
@@ -120,6 +120,7 @@ set(NEURON_SOURCES
|
||||
plugins/restful/global_config_handle.c
|
||||
plugins/restful/group_config_handle.c
|
||||
plugins/restful/plugin_handle.c
|
||||
plugins/restful/template_handle.c
|
||||
plugins/restful/version_handle.c
|
||||
plugins/restful/rest.c
|
||||
plugins/restful/user.c)
|
||||
|
||||
@@ -88,6 +88,13 @@ typedef enum neu_reqresp_type {
|
||||
NEU_REQ_GET_PLUGIN,
|
||||
NEU_RESP_GET_PLUGIN,
|
||||
|
||||
NEU_REQ_ADD_TEMPLATE,
|
||||
NEU_REQ_DEL_TEMPLATE,
|
||||
NEU_REQ_GET_TEMPLATE,
|
||||
NEU_RESP_GET_TEMPLATE,
|
||||
NEU_REQ_GET_TEMPLATES,
|
||||
NEU_RESP_GET_TEMPLATES,
|
||||
|
||||
NEU_REQRESP_TRANS_DATA,
|
||||
NEU_REQRESP_NODES_STATE,
|
||||
NEU_REQRESP_NODE_DELETED,
|
||||
@@ -158,6 +165,13 @@ static const char *neu_reqresp_type_string_t[] = {
|
||||
[NEU_REQ_GET_PLUGIN] = "NEU_REQ_GET_PLUGIN",
|
||||
[NEU_RESP_GET_PLUGIN] = "NEU_RESP_GET_PLUGIN",
|
||||
|
||||
[NEU_REQ_ADD_TEMPLATE] = "NEU_REQ_ADD_TEMPLATE",
|
||||
[NEU_REQ_DEL_TEMPLATE] = "NEU_REQ_DEL_TEMPLATE",
|
||||
[NEU_REQ_GET_TEMPLATE] = "NEU_REQ_GET_TEMPLATE",
|
||||
[NEU_RESP_GET_TEMPLATE] = "NEU_RESP_GET_TEMPLATE",
|
||||
[NEU_REQ_GET_TEMPLATES] = "NEU_REQ_GET_TEMPLATES",
|
||||
[NEU_RESP_GET_TEMPLATES] = "NEU_RESP_GET_TEMPLATES",
|
||||
|
||||
[NEU_REQRESP_TRANS_DATA] = "NEU_REQRESP_TRANS_DATA",
|
||||
[NEU_REQRESP_NODES_STATE] = "NEU_REQRESP_NODES_STATE",
|
||||
[NEU_REQRESP_NODE_DELETED] = "NEU_REQRESP_NODE_DELETED",
|
||||
@@ -417,6 +431,60 @@ typedef struct {
|
||||
UT_array *states; // array of neu_nodes_state_t
|
||||
} neu_resp_get_nodes_state_t, neu_reqresp_nodes_state_t;
|
||||
|
||||
typedef struct {
|
||||
char name[NEU_GROUP_NAME_LEN];
|
||||
uint32_t interval;
|
||||
uint16_t n_tag;
|
||||
neu_datatag_t *tags;
|
||||
} neu_reqresp_template_group_t;
|
||||
|
||||
static inline void
|
||||
neu_reqresp_template_group_fini(neu_reqresp_template_group_t *grp)
|
||||
{
|
||||
for (uint16_t i = 0; i < grp->n_tag; ++i) {
|
||||
neu_tag_fini(&grp->tags[i]);
|
||||
}
|
||||
free(grp->tags);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char name[NEU_TEMPLATE_NAME_LEN];
|
||||
char plugin[NEU_PLUGIN_NAME_LEN];
|
||||
uint16_t n_group;
|
||||
neu_reqresp_template_group_t *groups;
|
||||
} neu_reqresp_template_t;
|
||||
|
||||
static inline void neu_reqresp_template_fini(neu_reqresp_template_t *tmpl)
|
||||
{
|
||||
for (uint16_t i = 0; i < tmpl->n_group; ++i) {
|
||||
neu_reqresp_template_group_fini(&tmpl->groups[i]);
|
||||
}
|
||||
free(tmpl->groups);
|
||||
}
|
||||
|
||||
typedef neu_reqresp_template_t neu_req_add_template_t;
|
||||
|
||||
typedef struct {
|
||||
char name[NEU_TEMPLATE_NAME_LEN];
|
||||
} neu_req_del_template_t;
|
||||
|
||||
typedef neu_req_del_template_t neu_req_get_template_t;
|
||||
|
||||
typedef neu_reqresp_template_t neu_resp_get_template_t;
|
||||
|
||||
typedef struct {
|
||||
} neu_req_get_templates_t;
|
||||
|
||||
typedef struct {
|
||||
char name[NEU_TEMPLATE_NAME_LEN];
|
||||
char plugin[NEU_PLUGIN_NAME_LEN];
|
||||
} neu_resp_template_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t n_templates;
|
||||
neu_resp_template_info_t *templates;
|
||||
} neu_resp_get_templates_t;
|
||||
|
||||
typedef struct neu_req_update_license {
|
||||
} neu_req_update_license_t;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define NEU_PLUGIN_NAME_LEN 32
|
||||
#define NEU_PLUGIN_LIBRARY_LEN 32
|
||||
#define NEU_PLUGIN_DESCRIPTION_LEN 512
|
||||
#define NEU_TEMPLATE_NAME_LEN 128
|
||||
#define NEU_DRIVER_TAG_CACHE_EXPIRE_TIME 15
|
||||
#define NEU_APP_SUBSCRIBE_MSG_SIZE 4
|
||||
#define NEU_TAG_FLOAG_PRECISION_MAX 17
|
||||
|
||||
@@ -94,6 +94,10 @@ typedef enum {
|
||||
NEU_ERR_LICENSE_TOKEN_NOT_MATCH = 2406,
|
||||
NEU_ERR_LICENSE_BAD_CLOCK = 2407,
|
||||
|
||||
NEU_ERR_TEMPLATE_EXIST = 2500,
|
||||
NEU_ERR_TEMPLATE_NOT_FOUND = 2501,
|
||||
NEU_ERR_TEMPLATE_NAME_TOO_LONG = 2502,
|
||||
|
||||
// common error codes for plugins
|
||||
NEU_ERR_PLUGIN_READ_FAILURE = 3000,
|
||||
NEU_ERR_PLUGIN_WRITE_FAILURE = 3001,
|
||||
@@ -106,6 +110,8 @@ typedef enum {
|
||||
NEU_ERR_PLUGIN_NOT_RUNNING = 3010,
|
||||
NEU_ERR_PLUGIN_TAG_NOT_READY = 3011,
|
||||
NEU_ERR_PLUGIN_PACKET_OUT_OF_ORDER = 3012,
|
||||
NEU_ERR_PLUGIN_NAME_TOO_LONG = 3013,
|
||||
NEU_ERR_PLUGIN_NOT_FOUND = 3014,
|
||||
|
||||
NEU_ERR_MQTT_FAILURE = 4000,
|
||||
NEU_ERR_MQTT_NO_CERTFILESET = 4001,
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "normal_handle.h"
|
||||
#include "plugin_handle.h"
|
||||
#include "rw_handle.h"
|
||||
#include "template_handle.h"
|
||||
#include "utils/http.h"
|
||||
#include "version_handle.h"
|
||||
|
||||
@@ -108,6 +109,9 @@ static struct neu_http_handler cors_handler[] = {
|
||||
{
|
||||
.url = "/api/v2/global/config",
|
||||
},
|
||||
{
|
||||
.url = "/api/v2/template",
|
||||
},
|
||||
};
|
||||
|
||||
static struct neu_http_handler rest_handlers[] = {
|
||||
@@ -335,6 +339,12 @@ static struct neu_http_handler rest_handlers[] = {
|
||||
.url = "/api/v2/global/config",
|
||||
.value.handler = handle_put_global_config,
|
||||
},
|
||||
{
|
||||
.method = NEU_HTTP_METHOD_POST,
|
||||
.type = NEU_HTTP_HANDLER_FUNCTION,
|
||||
.url = "/api/v2/template",
|
||||
.value.handler = handle_add_template,
|
||||
},
|
||||
};
|
||||
|
||||
void neu_rest_handler(const struct neu_http_handler **handlers, uint32_t *size)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "plugin_handle.h"
|
||||
#include "rest.h"
|
||||
#include "rw_handle.h"
|
||||
#include "template_handle.h"
|
||||
#include "utils/http.h"
|
||||
#include "utils/log.h"
|
||||
#include "utils/neu_jwt.h"
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* NEURON IIoT System for Industry 4.0
|
||||
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#include "define.h"
|
||||
#include "errcodes.h"
|
||||
#include "tag.h"
|
||||
#include "utils/http.h"
|
||||
#include "utils/http_handler.h"
|
||||
#include "utils/log.h"
|
||||
#include "json/neu_json_error.h"
|
||||
#include "json/neu_json_fn.h"
|
||||
|
||||
#include "parser/neu_json_template.h"
|
||||
|
||||
#include "handle.h"
|
||||
|
||||
static int set_tag_by_json(neu_datatag_t *tag, neu_json_tag_t *json_tag)
|
||||
{
|
||||
if (strlen(json_tag->name) >= NEU_TAG_NAME_LEN) {
|
||||
return NEU_ERR_TAG_NAME_TOO_LONG;
|
||||
}
|
||||
|
||||
if (strlen(json_tag->address) >= NEU_TAG_ADDRESS_LEN) {
|
||||
return NEU_ERR_TAG_ADDRESS_TOO_LONG;
|
||||
}
|
||||
|
||||
if (NULL == json_tag->description &&
|
||||
NULL == (json_tag->description = strdup(""))) {
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
tag->name = json_tag->name;
|
||||
tag->type = json_tag->type;
|
||||
tag->address = json_tag->address;
|
||||
tag->attribute = json_tag->attribute;
|
||||
tag->precision = json_tag->precision;
|
||||
tag->decimal = json_tag->decimal;
|
||||
tag->description = json_tag->description;
|
||||
|
||||
if (NEU_ATTRIBUTE_STATIC & json_tag->attribute) {
|
||||
neu_tag_set_static_value_json(tag, json_tag->t, &json_tag->value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int move_template_json(neu_req_add_template_t *cmd,
|
||||
neu_json_template_t * req)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (strlen(req->name) >= NEU_NODE_NAME_LEN) {
|
||||
return NEU_ERR_NODE_NAME_TOO_LONG;
|
||||
}
|
||||
|
||||
if (strlen(req->plugin) >= NEU_PLUGIN_NAME_LEN) {
|
||||
return NEU_ERR_PLUGIN_NAME_TOO_LONG;
|
||||
}
|
||||
|
||||
cmd->n_group = req->groups.len;
|
||||
cmd->groups = calloc(cmd->n_group, sizeof(*cmd->groups));
|
||||
if (NULL == cmd->groups) {
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < req->groups.len; i++) {
|
||||
neu_json_template_group_t * req_grp = &req->groups.groups[i];
|
||||
neu_reqresp_template_group_t *cmd_grp = &cmd->groups[i];
|
||||
|
||||
if (strlen(req_grp->name) >= NEU_GROUP_NAME_LEN) {
|
||||
ret = NEU_ERR_GROUP_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (req_grp->interval < NEU_GROUP_INTERVAL_LIMIT) {
|
||||
ret = NEU_ERR_GROUP_PARAMETER_INVALID;
|
||||
goto error;
|
||||
}
|
||||
|
||||
cmd_grp->n_tag = req_grp->tags.len;
|
||||
cmd_grp->tags = calloc(cmd_grp->n_tag, sizeof(*cmd_grp->tags));
|
||||
if (NULL == cmd_grp->tags) {
|
||||
ret = NEU_ERR_EINTERNAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
strncpy(cmd_grp->name, req_grp->name, sizeof(cmd_grp->name));
|
||||
cmd_grp->interval = req_grp->interval;
|
||||
|
||||
for (int j = 0; j < req_grp->tags.len; ++j) {
|
||||
neu_datatag_t * tag = &cmd_grp->tags[j];
|
||||
neu_json_tag_t *req_tag = &req_grp->tags.tags[j];
|
||||
if (0 != (ret = set_tag_by_json(tag, req_tag))) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(cmd->name, req->name, sizeof(cmd->name));
|
||||
strncpy(cmd->plugin, req->plugin, sizeof(cmd->plugin));
|
||||
|
||||
for (int i = 0; i < req->groups.len; ++i) {
|
||||
for (int j = 0; j < req->groups.groups[i].tags.len; ++j) {
|
||||
// ownership moved
|
||||
req->groups.groups[i].tags.tags[j].name = NULL;
|
||||
req->groups.groups[i].tags.tags[j].address = NULL;
|
||||
req->groups.groups[i].tags.tags[j].description = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
for (int i = 0; i < cmd->n_group && cmd->groups[i].tags; ++i) {
|
||||
free(cmd->groups[i].tags);
|
||||
}
|
||||
free(cmd->groups);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void handle_add_template(nng_aio *aio)
|
||||
{
|
||||
neu_plugin_t *plugin = neu_rest_get_plugin();
|
||||
|
||||
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
|
||||
aio, neu_json_template_t, neu_json_decode_template, {
|
||||
int ret = 0;
|
||||
|
||||
neu_reqresp_head_t header = { 0 };
|
||||
header.type = NEU_REQ_ADD_TEMPLATE;
|
||||
header.ctx = aio;
|
||||
|
||||
neu_req_add_template_t cmd = { 0 };
|
||||
ret = move_template_json(&cmd, req);
|
||||
if (0 == ret) {
|
||||
if (0 != neu_plugin_op(plugin, header, &cmd)) {
|
||||
ret = NEU_ERR_IS_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != ret) {
|
||||
NEU_JSON_RESPONSE_ERROR(
|
||||
ret, { neu_http_response(aio, ret, result_error); });
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* NEURON IIoT System for Industry 4.0
|
||||
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#ifndef _NEU_TEMPLATE_HANDLE_H_
|
||||
#define _NEU_TEMPLATE_HANDLE_H_
|
||||
|
||||
#include <nng/nng.h>
|
||||
|
||||
#include "adapter.h"
|
||||
|
||||
void handle_add_template(nng_aio *aio);
|
||||
|
||||
#endif
|
||||
@@ -391,6 +391,8 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
case NEU_RESP_GET_TAG:
|
||||
case NEU_RESP_GET_NODE:
|
||||
case NEU_RESP_GET_PLUGIN:
|
||||
case NEU_RESP_GET_TEMPLATE:
|
||||
case NEU_RESP_GET_TEMPLATES:
|
||||
case NEU_RESP_GET_GROUP:
|
||||
case NEU_RESP_ERROR:
|
||||
case NEU_REQRESP_TRANS_DATA:
|
||||
@@ -1127,6 +1129,24 @@ void *neu_msg_gen(neu_reqresp_head_t *header, void *data)
|
||||
case NEU_RESP_GET_PLUGIN:
|
||||
data_size = sizeof(neu_resp_get_plugin_t);
|
||||
break;
|
||||
case NEU_REQ_ADD_TEMPLATE:
|
||||
data_size = sizeof(neu_req_add_template_t);
|
||||
break;
|
||||
case NEU_REQ_DEL_TEMPLATE:
|
||||
data_size = sizeof(neu_req_del_template_t);
|
||||
break;
|
||||
case NEU_REQ_GET_TEMPLATE:
|
||||
data_size = sizeof(neu_req_get_template_t);
|
||||
break;
|
||||
case NEU_RESP_GET_TEMPLATE:
|
||||
data_size = sizeof(neu_resp_get_template_t);
|
||||
break;
|
||||
case NEU_REQ_GET_TEMPLATES:
|
||||
data_size = sizeof(neu_req_get_templates_t);
|
||||
break;
|
||||
case NEU_RESP_GET_TEMPLATES:
|
||||
data_size = sizeof(neu_resp_get_templates_t);
|
||||
break;
|
||||
case NEU_REQ_ADD_NODE:
|
||||
case NEU_REQ_ADD_NODE_EVENT:
|
||||
data_size = sizeof(neu_req_add_node_t);
|
||||
|
||||
@@ -325,6 +325,7 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content)
|
||||
case NEU_ERR_GROUP_NAME_TOO_LONG:
|
||||
case NEU_ERR_INVALID_PASSWORD_LEN:
|
||||
case NEU_ERR_DUPLICATE_PASSWORD:
|
||||
case NEU_ERR_TEMPLATE_NAME_TOO_LONG:
|
||||
status = NNG_HTTP_STATUS_BAD_REQUEST;
|
||||
break;
|
||||
case NEU_ERR_FILE_NOT_EXIST:
|
||||
@@ -337,6 +338,8 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content)
|
||||
case NEU_ERR_GROUP_NOT_EXIST:
|
||||
case NEU_ERR_GROUP_NOT_SUBSCRIBE:
|
||||
case NEU_ERR_COMMAND_EXECUTION_FAILED:
|
||||
case NEU_ERR_TEMPLATE_NOT_FOUND:
|
||||
case NEU_ERR_PLUGIN_NOT_FOUND:
|
||||
status = NNG_HTTP_STATUS_NOT_FOUND;
|
||||
break;
|
||||
case NEU_ERR_NODE_EXIST:
|
||||
@@ -350,6 +353,7 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content)
|
||||
case NEU_ERR_GROUP_NOT_ALLOW:
|
||||
case NEU_ERR_LIBRARY_NOT_ALLOW_CREATE_INSTANCE:
|
||||
case NEU_ERR_NODE_NOT_ALLOW_DELETE:
|
||||
case NEU_ERR_TEMPLATE_EXIST:
|
||||
status = NNG_HTTP_STATUS_CONFLICT;
|
||||
break;
|
||||
case NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT:
|
||||
|
||||
Reference in New Issue
Block a user