From cb143b8ebb719f675e3a03743004cd4c499c87f2 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Thu, 16 Mar 2023 15:22:54 +0800 Subject: [PATCH 1/3] feat: add error codes for template --- include/neuron/errcodes.h | 6 ++++++ src/utils/http.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/include/neuron/errcodes.h b/include/neuron/errcodes.h index 021d0a13..72ae98c7 100644 --- a/include/neuron/errcodes.h +++ b/include/neuron/errcodes.h @@ -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, diff --git a/src/utils/http.c b/src/utils/http.c index 62d378c4..bffacbee 100644 --- a/src/utils/http.c +++ b/src/utils/http.c @@ -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: From 6513c7d82a3441df0299964234fb7293edc721d1 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Thu, 16 Mar 2023 15:50:29 +0800 Subject: [PATCH 2/3] feat(core): add message type for template --- include/neuron/adapter.h | 68 ++++++++++++++++++++++++++++++++++++++++ include/neuron/define.h | 1 + src/adapter/adapter.c | 20 ++++++++++++ 3 files changed, 89 insertions(+) diff --git a/include/neuron/adapter.h b/include/neuron/adapter.h index 9744f11c..0de759e8 100644 --- a/include/neuron/adapter.h +++ b/include/neuron/adapter.h @@ -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; diff --git a/include/neuron/define.h b/include/neuron/define.h index 11acc2ca..de434296 100644 --- a/include/neuron/define.h +++ b/include/neuron/define.h @@ -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 diff --git a/src/adapter/adapter.c b/src/adapter/adapter.c index 402a2333..40f0f585 100644 --- a/src/adapter/adapter.c +++ b/src/adapter/adapter.c @@ -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); From 3af830c30fb9bef0aea0e33f7136c594ad079165 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Thu, 16 Mar 2023 15:17:21 +0800 Subject: [PATCH 3/3] feat(restful): add POST /api/v2/template --- CMakeLists.txt | 1 + plugins/restful/handle.c | 10 ++ plugins/restful/rest.c | 1 + plugins/restful/template_handle.c | 162 ++++++++++++++++++++++++++++++ plugins/restful/template_handle.h | 29 ++++++ 5 files changed, 203 insertions(+) create mode 100644 plugins/restful/template_handle.c create mode 100644 plugins/restful/template_handle.h diff --git a/CMakeLists.txt b/CMakeLists.txt index be842918..375d97dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/plugins/restful/handle.c b/plugins/restful/handle.c index 3c0b485d..724eb226 100644 --- a/plugins/restful/handle.c +++ b/plugins/restful/handle.c @@ -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) diff --git a/plugins/restful/rest.c b/plugins/restful/rest.c index ed3ef5a9..9c987003 100644 --- a/plugins/restful/rest.c +++ b/plugins/restful/rest.c @@ -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" diff --git a/plugins/restful/template_handle.c b/plugins/restful/template_handle.c new file mode 100644 index 00000000..2a10d710 --- /dev/null +++ b/plugins/restful/template_handle.c @@ -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); }); + } + }) +} diff --git a/plugins/restful/template_handle.h b/plugins/restful/template_handle.h new file mode 100644 index 00000000..a1a8d397 --- /dev/null +++ b/plugins/restful/template_handle.h @@ -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 + +#include "adapter.h" + +void handle_add_template(nng_aio *aio); + +#endif