diff --git a/.gitignore b/.gitignore index 4b621579..1883a5f8 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ neuron-sdk .vscode log.html output.xml -report.html \ No newline at end of file +report.html +*.cache \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a0114d5b..93111e72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,6 +162,7 @@ set(NEURON_SOURCES plugins/restful/otel_handle.c plugins/restful/cid_handle.c plugins/restful/system_handle.c + plugins/restful/datalayers_handle.c plugins/restful/rest.c plugins/restful/user.c) diff --git a/Install-dependencies.md b/Install-dependencies.md index 3a750bb3..4f4d73dd 100644 --- a/Install-dependencies.md +++ b/Install-dependencies.md @@ -82,3 +82,28 @@ $ ./autogen.sh $ ./configure --enable-shared=no CFLAGS=-fPIC CXXFLAGS=-fPIC $ make && sudo make install ``` + +[arrow](https://github.com/apache/arrow) +```shell +$ wget https://github.com/apache/arrow/releases/download/apache-arrow-19.0.1/apache-arrow-19.0.1.tar.gz +$ tar -xzvf apache-arrow-19.0.1.tar.gz +$ cd apache-arrow-19.0.1/cpp +$ mkdir build && cd build +$ cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DARROW_BUILD_SHARED=ON \ + -DARROW_COMPUTE=ON \ + -DARROW_CSV=ON \ + -DARROW_JSON=ON \ + -DARROW_PARQUET=ON \ + -DARROW_DATASET=ON \ + -DARROW_FLIGHT=ON \ + -DARROW_FLIGHT_SQL=ON \ + -DARROW_WITH_GRPC=ON \ + -DARROW_PROTOBUF_USE_SHARED=ON \ + -DProtobuf_ROOT=/usr \ + -DgRPC_ROOT=/usr \ + -GNinja +$ ninja +$ sudo ninja install +``` \ No newline at end of file diff --git a/include/neuron/msg.h b/include/neuron/msg.h index d70c2fc4..e1a6209e 100644 --- a/include/neuron/msg.h +++ b/include/neuron/msg.h @@ -64,6 +64,11 @@ typedef enum neu_reqresp_type { NEU_REQ_GET_SUB_DRIVER_TAGS, NEU_RESP_GET_SUB_DRIVER_TAGS, + NEU_REQ_GET_DATALAYERS_GROUPS, + NEU_RESP_GET_DATALAYERS_GROUPS, + NEU_REQ_GET_DATALAYERS_TAGS, + NEU_RESP_GET_DATALAYERS_TAGS, + NEU_REQ_NODE_INIT, NEU_REQ_NODE_UNINIT, NEU_RESP_NODE_UNINIT, @@ -190,6 +195,11 @@ static const char *neu_reqresp_type_string_t[] = { [NEU_REQ_GET_SUB_DRIVER_TAGS] = "NEU_REQ_GET_SUB_DRIVER_TAGS", [NEU_RESP_GET_SUB_DRIVER_TAGS] = "NEU_RESP_GET_SUB_DRIVER_TAGS", + [NEU_REQ_GET_DATALAYERS_GROUPS] = "NEU_REQ_GET_DATALAYERS_GROUPS", + [NEU_RESP_GET_DATALAYERS_GROUPS] = "NEU_RESP_GET_DATALAYERS_GROUPS", + [NEU_REQ_GET_DATALAYERS_TAGS] = "NEU_REQ_GET_DATALAYERS_TAGS", + [NEU_RESP_GET_DATALAYERS_TAGS] = "NEU_RESP_GET_DATALAYERS_TAGS", + [NEU_REQ_NODE_INIT] = "NEU_REQ_NODE_INIT", [NEU_REQ_NODE_UNINIT] = "NEU_REQ_NODE_UNINIT", [NEU_RESP_NODE_UNINIT] = "NEU_RESP_NODE_UNINIT", diff --git a/plugins/datalayers/CMakeLists.txt b/plugins/datalayers/CMakeLists.txt index 3312745e..de307314 100644 --- a/plugins/datalayers/CMakeLists.txt +++ b/plugins/datalayers/CMakeLists.txt @@ -24,25 +24,18 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src/persist/datalayers ) -if (NOT TARGET Arrow::Arrow) - target_link_libraries(${PROJECT_NAME} - ${ARROW_LIB} - ${ARROW_FLIGHT_LIB} - ${ARROW_FLIGHT_SQL_LIB} - stdc++ - gflags - ${CMAKE_THREAD_LIBS_INIT} - ) -else() - target_link_libraries(${PROJECT_NAME} - Arrow::Arrow - Arrow::Flight - Arrow::FlightSql - stdc++ - gflags - ${CMAKE_THREAD_LIBS_INIT} - ) -endif() +find_package(Arrow REQUIRED) +find_package(ArrowFlight REQUIRED) +find_package(ArrowFlightSql REQUIRED) + +target_link_libraries(${PROJECT_NAME} + Arrow::arrow_shared + ArrowFlight::arrow_flight_shared + ArrowFlightSql::arrow_flight_sql_shared + stdc++ + gflags + ${CMAKE_THREAD_LIBS_INIT} +) target_link_libraries(${PROJECT_NAME} neuron-base) target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/plugins/datalayers/datalayers_handle.c b/plugins/datalayers/datalayers_handle.c index 76a73762..7ed41bea 100644 --- a/plugins/datalayers/datalayers_handle.c +++ b/plugins/datalayers/datalayers_handle.c @@ -89,7 +89,8 @@ void task_queue_push(neu_plugin_t *plugin, db_write_task_t *task) if (plugin->task_queue.size > plugin->task_queue.max_size) { plugin->task_queue.max_size = plugin->task_queue.size; - NEU_PLUGIN_UPDATE_MAX_CACHED_QUEUE_SIZE_METRIC(plugin, plugin->task_queue.max_size); + NEU_PLUGIN_UPDATE_MAX_CACHED_QUEUE_SIZE_METRIC( + plugin, plugin->task_queue.max_size); } NEU_PLUGIN_UPDATE_CACHED_QUEUE_SIZE_METRIC(plugin, plugin->task_queue.size); } @@ -114,28 +115,37 @@ db_write_task_t *task_queue_pop(neu_plugin_t *plugin, task_queue_t *queue) static void db_write_task_cb(db_write_task_t *task, neu_plugin_t *plugin) { + int ret = 0; if (utarray_len(task->int_tags) > 0) { - client_insert(plugin->client, INT_TYPE, - utarray_eltptr(task->int_tags, 0), - utarray_len(task->int_tags)); + ret = client_insert(plugin->client, INT_TYPE, + utarray_eltptr(task->int_tags, 0), + utarray_len(task->int_tags)); } if (utarray_len(task->float_tags) > 0) { - client_insert(plugin->client, FLOAT_TYPE, - utarray_eltptr(task->float_tags, 0), - utarray_len(task->float_tags)); + ret = client_insert(plugin->client, FLOAT_TYPE, + utarray_eltptr(task->float_tags, 0), + utarray_len(task->float_tags)); } if (utarray_len(task->bool_tags) > 0) { - client_insert(plugin->client, BOOL_TYPE, - utarray_eltptr(task->bool_tags, 0), - utarray_len(task->bool_tags)); + ret = client_insert(plugin->client, BOOL_TYPE, + utarray_eltptr(task->bool_tags, 0), + utarray_len(task->bool_tags)); } if (utarray_len(task->string_tags) > 0) { - client_insert(plugin->client, STRING_TYPE, - utarray_eltptr(task->string_tags, 0), - utarray_len(task->string_tags)); + ret = client_insert(plugin->client, STRING_TYPE, + utarray_eltptr(task->string_tags, 0), + utarray_len(task->string_tags)); + } + + if (ret != 0) { + plog_error(plugin, "insert data to datalayers failed, disconnected"); + if (plugin->client) { + client_destroy(plugin->client); + plugin->client = NULL; + } } } @@ -252,46 +262,64 @@ int handle_trans_data(neu_plugin_t * plugin, case NEU_TYPE_UINT32: case NEU_TYPE_INT64: case NEU_TYPE_UINT64: { - datatag tag = { tag_meta->tag, - "group", - "tag_int", + datatag tag = { trans_data->driver, + trans_data->group, + tag_meta->tag, { .int_value = tag_meta->value.value.i64 }, INT_TYPE }; utarray_push_back(int_tags, &tag); } break; case NEU_TYPE_FLOAT: case NEU_TYPE_DOUBLE: { - datatag tag = { tag_meta->tag, - "group", - "tag_float", + datatag tag = { trans_data->driver, + trans_data->group, + tag_meta->tag, { .float_value = tag_meta->value.value.d64 }, FLOAT_TYPE }; utarray_push_back(float_tags, &tag); } break; case NEU_TYPE_BOOL: { - datatag tag = { tag_meta->tag, - "group", - "tag_bool", + datatag tag = { trans_data->driver, + trans_data->group, + tag_meta->tag, { .bool_value = tag_meta->value.value.boolean }, BOOL_TYPE }; utarray_push_back(bool_tags, &tag); } break; - case NEU_TYPE_STRING: { - datatag tag = { tag_meta->tag, - "group", - "tag_string", + case NEU_TYPE_STRING: + case NEU_TYPE_DATA_AND_TIME: + case NEU_TYPE_TIME: { + datatag tag = { trans_data->driver, + trans_data->group, + tag_meta->tag, { .string_value = tag_meta->value.value.str }, STRING_TYPE }; utarray_push_back(string_tags, &tag); } break; - default: { - datatag tag = { tag_meta->tag, - "group", - "tag_string", - { .string_value = tag_meta->value.value.str }, + case NEU_TYPE_BYTES: { + char formatted[NEU_VALUE_SIZE]; + int offset = 0; + + offset += + snprintf(formatted + offset, sizeof(formatted) - offset, "[ "); + + for (int i = 0; i < tag_meta->value.value.bytes.length; ++i) { + offset += snprintf( + formatted + offset, sizeof(formatted) - offset, "%u%s", + tag_meta->value.value.bytes.bytes[i], + (i == tag_meta->value.value.bytes.length - 1) ? " " : ", "); + } + + snprintf(formatted + offset, sizeof(formatted) - offset, "]"); + datatag tag = { trans_data->driver, + trans_data->group, + tag_meta->tag, + { .string_value = formatted }, STRING_TYPE }; utarray_push_back(string_tags, &tag); } break; + default: + break; } } diff --git a/plugins/datalayers/datalayers_plugin_intf.c b/plugins/datalayers/datalayers_plugin_intf.c index fd753c2d..ba94ba54 100644 --- a/plugins/datalayers/datalayers_plugin_intf.c +++ b/plugins/datalayers/datalayers_plugin_intf.c @@ -167,6 +167,12 @@ int datalayers_plugin_request(neu_plugin_t *plugin, neu_reqresp_head_t *head, switch (head->type) { case NEU_REQRESP_TRANS_DATA: { + if (plugin->client == NULL) { + plog_notice(plugin, "datalayers client is NULL, reconnect"); + + config_datalayers_client(plugin, &plugin->config); + } + error = handle_trans_data(plugin, data); break; } diff --git a/plugins/datalayers/datalayers_plugin_intf.h b/plugins/datalayers/datalayers_plugin_intf.h index 16e6e6b9..ba21b8b4 100644 --- a/plugins/datalayers/datalayers_plugin_intf.h +++ b/plugins/datalayers/datalayers_plugin_intf.h @@ -33,7 +33,8 @@ extern "C" { #define NEU_METRIC_MAX_CACHED_QUEUE_SIZE "max_cached_queue_size" #define NEU_METRIC_MAX_CACHED_QUEUE_SIZE_TYPE NEU_METRIC_TYPE_GAUAGE -#define NEU_METRIC_MAX_CACHED_QUEUE_SIZE_HELP "Max size of the cached message queue" +#define NEU_METRIC_MAX_CACHED_QUEUE_SIZE_HELP \ + "Max size of the cached message queue" #define NEU_METRIC_DISCARDED_MSGS "discarded_msgs" #define NEU_METRIC_DISCARDED_MSGS_TYPE NEU_METRIC_TYPE_COUNTER @@ -52,8 +53,9 @@ extern "C" { #define NEU_PLUGIN_UPDATE_CACHED_QUEUE_SIZE_METRIC(plugin, val) \ NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_CACHED_QUEUE_SIZE, val, NULL) -#define NEU_PLUGIN_UPDATE_MAX_CACHED_QUEUE_SIZE_METRIC(plugin, val) \ - NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_MAX_CACHED_QUEUE_SIZE, val, NULL) +#define NEU_PLUGIN_UPDATE_MAX_CACHED_QUEUE_SIZE_METRIC(plugin, val) \ + NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_MAX_CACHED_QUEUE_SIZE, val, \ + NULL) #define NEU_PLUGIN_UPDATE_DISCARDED_MSGS_METRIC(plugin, val) \ NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_DISCARDED_MSGS, val, NULL) diff --git a/plugins/restful/datalayers_handle.c b/plugins/restful/datalayers_handle.c new file mode 100644 index 00000000..521a743e --- /dev/null +++ b/plugins/restful/datalayers_handle.c @@ -0,0 +1,149 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2022 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 + +#include "parser/neu_json_datalayers.h" +#include "plugin.h" +#include "json/neu_json_error.h" +#include "json/neu_json_fn.h" + +#include "handle.h" +#include "utils/http.h" + +#include "datalayers_handle.h" + +void handle_datalayers_get_groups(nng_aio *aio) +{ + int ret = 0; + neu_plugin_t * plugin = neu_rest_get_plugin(); + neu_req_get_subscribe_group_t cmd = { 0 }; + neu_reqresp_head_t header = { + .ctx = aio, + .type = NEU_REQ_GET_DATALAYERS_GROUPS, + .otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM, + }; + + NEU_VALIDATE_JWT(aio); + + // required parameter + snprintf(cmd.app, sizeof(cmd.app), "%s", "datalayers"); + + // optional parameter + ret = neu_http_get_param_str(aio, "driver", cmd.driver, sizeof(cmd.driver)); + if (-1 == ret || (size_t) ret == sizeof(cmd.driver)) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_PARAM_IS_WRONG, { + neu_http_response(aio, error_code.error, result_error); + }) + return; + } + + // optional parameter + ret = neu_http_get_param_str(aio, "group", cmd.group, sizeof(cmd.group)); + if (-1 == ret || (size_t) ret == sizeof(cmd.driver)) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_PARAM_IS_WRONG, { + neu_http_response(aio, error_code.error, result_error); + }) + return; + } + + ret = neu_plugin_op(plugin, header, &cmd); + if (ret != 0) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, { + neu_http_response(aio, NEU_ERR_IS_BUSY, result_error); + }); + } +} + +void handle_datalayers_get_groups_resp(nng_aio * aio, + neu_resp_get_subscribe_group_t *groups) +{ + char * result = NULL; + neu_json_get_subscribe_resp_t sub_grp_configs = { 0 }; + + sub_grp_configs.n_group = utarray_len(groups->groups); + sub_grp_configs.groups = calloc( + sub_grp_configs.n_group, sizeof(neu_json_get_subscribe_resp_group_t)); + + utarray_foreach(groups->groups, neu_resp_subscribe_info_t *, group) + { + int index = utarray_eltidx(groups->groups, group); + sub_grp_configs.groups[index].driver = group->driver; + sub_grp_configs.groups[index].group = group->group; + sub_grp_configs.groups[index].params = group->params; + sub_grp_configs.groups[index].static_tags = group->static_tags; + } + + neu_json_encode_by_fn(&sub_grp_configs, + neu_json_encode_datalayers_get_groups_resp, &result); + + neu_http_ok(aio, result); + free(result); + free(sub_grp_configs.groups); + utarray_free(groups->groups); +} + +void handle_datalayers_get_tags(nng_aio *aio) +{ + int ret = 0; + neu_plugin_t * plugin = neu_rest_get_plugin(); + neu_req_get_sub_driver_tags_t cmd = { 0 }; + neu_reqresp_head_t header = { + .ctx = aio, + .type = NEU_REQ_GET_DATALAYERS_TAGS, + .otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM, + }; + + NEU_VALIDATE_JWT(aio); + + // required parameter + snprintf(cmd.app, sizeof(cmd.app), "%s", "datalayers"); + + ret = neu_plugin_op(plugin, header, &cmd); + if (ret != 0) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, { + neu_http_response(aio, NEU_ERR_IS_BUSY, result_error); + }); + } +} + +void handle_datalayers_get_tags_resp(nng_aio * aio, + neu_resp_get_sub_driver_tags_t *tags) +{ + char *result = NULL; + int ret = neu_json_encode_by_fn( + tags, neu_json_encode_datalayers_get_tags_resp, &result); + + if (ret != 0 || result == NULL) { + neu_http_response( + aio, 500, "{\"error\":4200,\"reason\":\"failed to encode tags\"}"); + return; + } + + neu_http_ok(aio, result); + + free(result); + if (tags) { + utarray_foreach(tags->infos, neu_resp_get_sub_driver_tags_info_t *, + info) + { + utarray_free(info->tags); + } + utarray_free(tags->infos); + } +} \ No newline at end of file diff --git a/plugins/restful/datalayers_handle.h b/plugins/restful/datalayers_handle.h new file mode 100644 index 00000000..432c4e1a --- /dev/null +++ b/plugins/restful/datalayers_handle.h @@ -0,0 +1,35 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2022 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_PLUGIN_REST_DATALAYERS_HANDLE_H_ +#define _NEU_PLUGIN_REST_DATALAYERS_HANDLE_H_ + +#include + +#include "adapter.h" + +void handle_datalayers_get_groups(nng_aio *aio); +void handle_datalayers_get_groups_resp(nng_aio * aio, + neu_resp_get_subscribe_group_t *groups); + +void handle_datalayers_get_tags(nng_aio *aio); +void handle_datalayers_get_tags_resp(nng_aio * aio, + neu_resp_get_sub_driver_tags_t *tags); + +#endif \ No newline at end of file diff --git a/plugins/restful/handle.c b/plugins/restful/handle.c index 7ff39ed9..17a68be7 100644 --- a/plugins/restful/handle.c +++ b/plugins/restful/handle.c @@ -26,6 +26,7 @@ #include "adapter_handle.h" #include "cid_handle.h" +#include "datalayers_handle.h" #include "datatag_handle.h" #include "global_config_handle.h" #include "group_config_handle.h" @@ -148,6 +149,12 @@ static struct neu_http_handler cors_handler[] = { { .url = "/api/v2/users", }, + { + .url = "/api/v2/datalayers/group", + }, + { + .url = "/api/v2/datalayers/tags", + }, }; static struct neu_http_handler rest_handlers[] = { @@ -494,6 +501,18 @@ static struct neu_http_handler rest_handlers[] = { .url = "/api/v2/users", .value.handler = handle_delete_user, }, + { + .method = NEU_HTTP_METHOD_GET, + .type = NEU_HTTP_HANDLER_FUNCTION, + .url = "/api/v2/datalayers/groups", + .value.handler = handle_datalayers_get_groups, + }, + { + .method = NEU_HTTP_METHOD_GET, + .type = NEU_HTTP_HANDLER_FUNCTION, + .url = "/api/v2/datalayers/tags", + .value.handler = handle_datalayers_get_tags, + }, }; 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 6bcbdcb5..b8189393 100644 --- a/plugins/restful/rest.c +++ b/plugins/restful/rest.c @@ -26,6 +26,7 @@ #include "adapter_handle.h" #include "argparse.h" +#include "datalayers_handle.h" #include "datatag_handle.h" #include "define.h" #include "global_config_handle.h" @@ -283,6 +284,20 @@ static int dashb_plugin_request(neu_plugin_t * plugin, neu_otel_scope_set_status_code2(scope, NEU_OTEL_STATUS_OK, 0); } break; + case NEU_RESP_GET_DATALAYERS_GROUPS: + handle_datalayers_get_groups_resp( + header->ctx, (neu_resp_get_subscribe_group_t *) data); + if (neu_otel_control_is_started() && trace) { + neu_otel_scope_set_status_code2(scope, NEU_OTEL_STATUS_OK, 0); + } + break; + case NEU_RESP_GET_DATALAYERS_TAGS: + handle_datalayers_get_tags_resp( + header->ctx, (neu_resp_get_sub_driver_tags_t *) data); + if (neu_otel_control_is_started() && trace) { + neu_otel_scope_set_status_code2(scope, NEU_OTEL_STATUS_OK, 0); + } + break; case NEU_RESP_GET_NODE_SETTING: handle_get_node_setting_resp(header->ctx, (neu_resp_get_node_setting_t *) data); diff --git a/src/adapter/adapter.c b/src/adapter/adapter.c index 7005242d..bc87c747 100644 --- a/src/adapter/adapter.c +++ b/src/adapter/adapter.c @@ -755,6 +755,8 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data) case NEU_RESP_GET_NODE_SETTING: case NEU_REQ_UPDATE_GROUP: case NEU_RESP_GET_SUBSCRIBE_GROUP: + case NEU_RESP_GET_DATALAYERS_GROUPS: + case NEU_RESP_GET_DATALAYERS_TAGS: case NEU_RESP_ADD_TAG: case NEU_RESP_ADD_GTAG: case NEU_RESP_UPDATE_TAG: diff --git a/src/base/msg_internal.h b/src/base/msg_internal.h index 537010a4..08fac744 100644 --- a/src/base/msg_internal.h +++ b/src/base/msg_internal.h @@ -30,108 +30,112 @@ extern "C" { #include "msg.h" -#define NEU_REQRESP_TYPE_MAP(XX) \ - XX(NEU_RESP_ERROR, neu_resp_error_t) \ - XX(NEU_REQ_READ_GROUP, neu_req_read_group_t) \ - XX(NEU_RESP_READ_GROUP, neu_resp_read_group_t) \ - XX(NEU_REQ_READ_GROUP_PAGINATE, neu_req_read_group_paginate_t) \ - XX(NEU_RESP_READ_GROUP_PAGINATE, neu_resp_read_group_paginate_t) \ - XX(NEU_REQ_TEST_READ_TAG, neu_req_test_read_tag_t) \ - XX(NEU_RESP_TEST_READ_TAG, neu_resp_test_read_tag_t) \ - XX(NEU_REQ_WRITE_TAG, neu_req_write_tag_t) \ - XX(NEU_REQ_WRITE_TAGS, neu_req_write_tags_t) \ - XX(NEU_REQ_WRITE_GTAGS, neu_req_write_gtags_t) \ - XX(NEU_REQ_SUBSCRIBE_GROUP, neu_req_subscribe_t) \ - XX(NEU_REQ_UNSUBSCRIBE_GROUP, neu_req_unsubscribe_t) \ - XX(NEU_REQ_UPDATE_SUBSCRIBE_GROUP, neu_req_subscribe_t) \ - XX(NEU_REQ_SUBSCRIBE_GROUPS, neu_req_subscribe_groups_t) \ - XX(NEU_REQ_GET_SUBSCRIBE_GROUP, neu_req_get_subscribe_group_t) \ - XX(NEU_RESP_GET_SUBSCRIBE_GROUP, neu_resp_get_subscribe_group_t) \ - XX(NEU_REQ_GET_SUB_DRIVER_TAGS, neu_req_get_sub_driver_tags_t) \ - XX(NEU_RESP_GET_SUB_DRIVER_TAGS, neu_resp_get_sub_driver_tags_t) \ - XX(NEU_REQ_NODE_INIT, neu_req_node_init_t) \ - XX(NEU_REQ_NODE_UNINIT, neu_req_node_uninit_t) \ - XX(NEU_RESP_NODE_UNINIT, neu_resp_node_uninit_t) \ - XX(NEU_REQ_ADD_NODE, neu_req_add_node_t) \ - XX(NEU_REQ_UPDATE_NODE, neu_req_update_node_t) \ - XX(NEU_REQ_DEL_NODE, neu_req_del_node_t) \ - XX(NEU_REQ_GET_NODE, neu_req_get_node_t) \ - XX(NEU_RESP_GET_NODE, neu_resp_get_node_t) \ - XX(NEU_REQ_NODE_SETTING, neu_req_node_setting_t) \ - XX(NEU_REQ_GET_NODE_SETTING, neu_req_get_node_setting_t) \ - XX(NEU_RESP_GET_NODE_SETTING, neu_resp_get_node_setting_t) \ - XX(NEU_REQ_GET_NODE_STATE, neu_req_get_node_state_t) \ - XX(NEU_RESP_GET_NODE_STATE, neu_resp_get_node_state_t) \ - XX(NEU_REQ_GET_NODES_STATE, neu_req_get_nodes_state_t) \ - XX(NEU_RESP_GET_NODES_STATE, neu_resp_get_nodes_state_t) \ - XX(NEU_REQ_NODE_CTL, neu_req_node_ctl_t) \ - XX(NEU_REQ_NODE_RENAME, neu_req_node_rename_t) \ - XX(NEU_RESP_NODE_RENAME, neu_resp_node_rename_t) \ - XX(NEU_REQ_ADD_GROUP, neu_req_add_group_t) \ - XX(NEU_REQ_DEL_GROUP, neu_req_del_group_t) \ - XX(NEU_REQ_UPDATE_GROUP, neu_req_update_group_t) \ - XX(NEU_REQ_UPDATE_DRIVER_GROUP, neu_req_update_group_t) \ - XX(NEU_RESP_UPDATE_DRIVER_GROUP, neu_resp_update_group_t) \ - XX(NEU_REQ_GET_GROUP, neu_req_get_group_t) \ - XX(NEU_RESP_GET_GROUP, neu_resp_get_group_t) \ - XX(NEU_REQ_GET_DRIVER_GROUP, neu_req_get_group_t) \ - XX(NEU_RESP_GET_DRIVER_GROUP, neu_resp_get_driver_group_t) \ - XX(NEU_REQ_ADD_TAG, neu_req_add_tag_t) \ - XX(NEU_RESP_ADD_TAG, neu_resp_add_tag_t) \ - XX(NEU_REQ_ADD_GTAG, neu_req_add_gtag_t) \ - XX(NEU_RESP_ADD_GTAG, neu_resp_add_tag_t) \ - XX(NEU_REQ_DEL_TAG, neu_req_del_tag_t) \ - XX(NEU_REQ_UPDATE_TAG, neu_req_update_tag_t) \ - XX(NEU_RESP_UPDATE_TAG, neu_resp_update_tag_t) \ - XX(NEU_REQ_GET_TAG, neu_req_get_tag_t) \ - XX(NEU_RESP_GET_TAG, neu_resp_get_tag_t) \ - XX(NEU_REQ_ADD_PLUGIN, neu_req_add_plugin_t) \ - XX(NEU_REQ_DEL_PLUGIN, neu_req_del_plugin_t) \ - XX(NEU_REQ_UPDATE_PLUGIN, neu_req_update_plugin_t) \ - XX(NEU_REQ_GET_PLUGIN, neu_req_get_plugin_t) \ - XX(NEU_RESP_GET_PLUGIN, neu_resp_get_plugin_t) \ - XX(NEU_REQRESP_TRANS_DATA, neu_reqresp_trans_data_t) \ - XX(NEU_REQRESP_NODES_STATE, neu_reqresp_nodes_state_t) \ - XX(NEU_REQRESP_NODE_DELETED, neu_reqresp_node_deleted_t) \ - XX(NEU_REQ_ADD_DRIVERS, neu_req_driver_array_t) \ - XX(NEU_REQ_UPDATE_LOG_LEVEL, neu_req_update_log_level_t) \ - XX(NEU_REQ_PRGFILE_UPLOAD, neu_req_prgfile_upload_t) \ - XX(NEU_REQ_PRGFILE_PROCESS, neu_req_prgfile_process_t) \ - XX(NEU_RESP_PRGFILE_PROCESS, neu_resp_prgfile_process_t) \ - XX(NEU_REQ_SCAN_TAGS, neu_req_scan_tags_t) \ - XX(NEU_RESP_SCAN_TAGS, neu_resp_scan_tags_t) \ - XX(NEU_REQ_CHECK_SCHEMA, neu_req_check_schema_t) \ - XX(NEU_RESP_CHECK_SCHEMA, neu_resp_check_schema_t) \ - XX(NEU_REQ_DRIVER_ACTION, neu_req_driver_action_t) \ - XX(NEU_RESP_DRIVER_ACTION, neu_resp_driver_action_t) \ - XX(NEU_REQ_DRIVER_DIRECTORY, neu_req_driver_directory_t) \ - XX(NEU_RESP_DRIVER_DIRECTORY, neu_resp_driver_directory_t) \ - XX(NEU_REQ_FUP_OPEN, neu_req_fup_open_t) \ - XX(NEU_RESP_FUP_OPEN, neu_resp_fup_open_t) \ - XX(NEU_REQ_FUP_DATA, neu_req_fup_data_t) \ - XX(NEU_RESP_FUP_DATA, neu_resp_fup_data_t) \ - XX(NEU_REQ_FDOWN_OPEN, neu_req_fdown_open_t) \ - XX(NEU_RESP_FDOWN_OPEN, neu_resp_fdown_open_t) \ - XX(NEU_REQ_FDOWN_DATA, neu_req_fdown_data_t) \ - XX(NEU_RESP_FDOWN_DATA, neu_resp_fdown_data_t) \ - XX(NEU_REQ_ADD_NODE_EVENT, neu_req_add_node_t) \ - XX(NEU_REQ_DEL_NODE_EVENT, neu_req_del_node_t) \ - XX(NEU_REQ_NODE_CTL_EVENT, neu_req_node_ctl_t) \ - XX(NEU_REQ_NODE_SETTING_EVENT, neu_req_node_setting_t) \ - XX(NEU_REQ_ADD_GROUP_EVENT, neu_req_add_group_t) \ - XX(NEU_REQ_DEL_GROUP_EVENT, neu_req_del_group_t) \ - XX(NEU_REQ_UPDATE_GROUP_EVENT, neu_req_update_group_t) \ - XX(NEU_REQ_ADD_TAG_EVENT, neu_req_add_tag_t) \ - XX(NEU_REQ_DEL_TAG_EVENT, neu_req_del_tag_t) \ - XX(NEU_REQ_UPDATE_TAG_EVENT, neu_req_update_tag_t) \ - XX(NEU_REQ_ADD_GTAG_EVENT, neu_req_add_gtag_t) \ - XX(NEU_REQ_ADD_PLUGIN_EVENT, neu_req_add_plugin_t) \ - XX(NEU_REQ_DEL_PLUGIN_EVENT, neu_req_del_plugin_t) \ - XX(NEU_REQ_SUBSCRIBE_GROUP_EVENT, neu_req_subscribe_t) \ - XX(NEU_REQ_UNSUBSCRIBE_GROUP_EVENT, neu_req_unsubscribe_t) \ - XX(NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT, neu_req_subscribe_t) \ - XX(NEU_REQ_SUBSCRIBE_GROUPS_EVENT, neu_req_subscribe_groups_t) \ - XX(NEU_RESP_WRITE_TAGS, neu_resp_write_tags_t) +#define NEU_REQRESP_TYPE_MAP(XX) \ + XX(NEU_RESP_ERROR, neu_resp_error_t) \ + XX(NEU_REQ_READ_GROUP, neu_req_read_group_t) \ + XX(NEU_RESP_READ_GROUP, neu_resp_read_group_t) \ + XX(NEU_REQ_READ_GROUP_PAGINATE, neu_req_read_group_paginate_t) \ + XX(NEU_RESP_READ_GROUP_PAGINATE, neu_resp_read_group_paginate_t) \ + XX(NEU_REQ_TEST_READ_TAG, neu_req_test_read_tag_t) \ + XX(NEU_RESP_TEST_READ_TAG, neu_resp_test_read_tag_t) \ + XX(NEU_REQ_WRITE_TAG, neu_req_write_tag_t) \ + XX(NEU_REQ_WRITE_TAGS, neu_req_write_tags_t) \ + XX(NEU_REQ_WRITE_GTAGS, neu_req_write_gtags_t) \ + XX(NEU_REQ_SUBSCRIBE_GROUP, neu_req_subscribe_t) \ + XX(NEU_REQ_UNSUBSCRIBE_GROUP, neu_req_unsubscribe_t) \ + XX(NEU_REQ_UPDATE_SUBSCRIBE_GROUP, neu_req_subscribe_t) \ + XX(NEU_REQ_SUBSCRIBE_GROUPS, neu_req_subscribe_groups_t) \ + XX(NEU_REQ_GET_SUBSCRIBE_GROUP, neu_req_get_subscribe_group_t) \ + XX(NEU_RESP_GET_SUBSCRIBE_GROUP, neu_resp_get_subscribe_group_t) \ + XX(NEU_REQ_GET_SUB_DRIVER_TAGS, neu_req_get_sub_driver_tags_t) \ + XX(NEU_RESP_GET_SUB_DRIVER_TAGS, neu_resp_get_sub_driver_tags_t) \ + XX(NEU_REQ_NODE_INIT, neu_req_node_init_t) \ + XX(NEU_REQ_NODE_UNINIT, neu_req_node_uninit_t) \ + XX(NEU_RESP_NODE_UNINIT, neu_resp_node_uninit_t) \ + XX(NEU_REQ_ADD_NODE, neu_req_add_node_t) \ + XX(NEU_REQ_UPDATE_NODE, neu_req_update_node_t) \ + XX(NEU_REQ_DEL_NODE, neu_req_del_node_t) \ + XX(NEU_REQ_GET_NODE, neu_req_get_node_t) \ + XX(NEU_RESP_GET_NODE, neu_resp_get_node_t) \ + XX(NEU_REQ_NODE_SETTING, neu_req_node_setting_t) \ + XX(NEU_REQ_GET_NODE_SETTING, neu_req_get_node_setting_t) \ + XX(NEU_RESP_GET_NODE_SETTING, neu_resp_get_node_setting_t) \ + XX(NEU_REQ_GET_NODE_STATE, neu_req_get_node_state_t) \ + XX(NEU_RESP_GET_NODE_STATE, neu_resp_get_node_state_t) \ + XX(NEU_REQ_GET_NODES_STATE, neu_req_get_nodes_state_t) \ + XX(NEU_RESP_GET_NODES_STATE, neu_resp_get_nodes_state_t) \ + XX(NEU_REQ_NODE_CTL, neu_req_node_ctl_t) \ + XX(NEU_REQ_NODE_RENAME, neu_req_node_rename_t) \ + XX(NEU_RESP_NODE_RENAME, neu_resp_node_rename_t) \ + XX(NEU_REQ_ADD_GROUP, neu_req_add_group_t) \ + XX(NEU_REQ_DEL_GROUP, neu_req_del_group_t) \ + XX(NEU_REQ_UPDATE_GROUP, neu_req_update_group_t) \ + XX(NEU_REQ_UPDATE_DRIVER_GROUP, neu_req_update_group_t) \ + XX(NEU_RESP_UPDATE_DRIVER_GROUP, neu_resp_update_group_t) \ + XX(NEU_REQ_GET_GROUP, neu_req_get_group_t) \ + XX(NEU_RESP_GET_GROUP, neu_resp_get_group_t) \ + XX(NEU_REQ_GET_DRIVER_GROUP, neu_req_get_group_t) \ + XX(NEU_RESP_GET_DRIVER_GROUP, neu_resp_get_driver_group_t) \ + XX(NEU_REQ_ADD_TAG, neu_req_add_tag_t) \ + XX(NEU_RESP_ADD_TAG, neu_resp_add_tag_t) \ + XX(NEU_REQ_ADD_GTAG, neu_req_add_gtag_t) \ + XX(NEU_RESP_ADD_GTAG, neu_resp_add_tag_t) \ + XX(NEU_REQ_DEL_TAG, neu_req_del_tag_t) \ + XX(NEU_REQ_UPDATE_TAG, neu_req_update_tag_t) \ + XX(NEU_RESP_UPDATE_TAG, neu_resp_update_tag_t) \ + XX(NEU_REQ_GET_TAG, neu_req_get_tag_t) \ + XX(NEU_RESP_GET_TAG, neu_resp_get_tag_t) \ + XX(NEU_REQ_ADD_PLUGIN, neu_req_add_plugin_t) \ + XX(NEU_REQ_DEL_PLUGIN, neu_req_del_plugin_t) \ + XX(NEU_REQ_UPDATE_PLUGIN, neu_req_update_plugin_t) \ + XX(NEU_REQ_GET_PLUGIN, neu_req_get_plugin_t) \ + XX(NEU_RESP_GET_PLUGIN, neu_resp_get_plugin_t) \ + XX(NEU_REQRESP_TRANS_DATA, neu_reqresp_trans_data_t) \ + XX(NEU_REQRESP_NODES_STATE, neu_reqresp_nodes_state_t) \ + XX(NEU_REQRESP_NODE_DELETED, neu_reqresp_node_deleted_t) \ + XX(NEU_REQ_ADD_DRIVERS, neu_req_driver_array_t) \ + XX(NEU_REQ_UPDATE_LOG_LEVEL, neu_req_update_log_level_t) \ + XX(NEU_REQ_PRGFILE_UPLOAD, neu_req_prgfile_upload_t) \ + XX(NEU_REQ_PRGFILE_PROCESS, neu_req_prgfile_process_t) \ + XX(NEU_RESP_PRGFILE_PROCESS, neu_resp_prgfile_process_t) \ + XX(NEU_REQ_SCAN_TAGS, neu_req_scan_tags_t) \ + XX(NEU_RESP_SCAN_TAGS, neu_resp_scan_tags_t) \ + XX(NEU_REQ_CHECK_SCHEMA, neu_req_check_schema_t) \ + XX(NEU_RESP_CHECK_SCHEMA, neu_resp_check_schema_t) \ + XX(NEU_REQ_DRIVER_ACTION, neu_req_driver_action_t) \ + XX(NEU_RESP_DRIVER_ACTION, neu_resp_driver_action_t) \ + XX(NEU_REQ_DRIVER_DIRECTORY, neu_req_driver_directory_t) \ + XX(NEU_RESP_DRIVER_DIRECTORY, neu_resp_driver_directory_t) \ + XX(NEU_REQ_FUP_OPEN, neu_req_fup_open_t) \ + XX(NEU_RESP_FUP_OPEN, neu_resp_fup_open_t) \ + XX(NEU_REQ_FUP_DATA, neu_req_fup_data_t) \ + XX(NEU_RESP_FUP_DATA, neu_resp_fup_data_t) \ + XX(NEU_REQ_FDOWN_OPEN, neu_req_fdown_open_t) \ + XX(NEU_RESP_FDOWN_OPEN, neu_resp_fdown_open_t) \ + XX(NEU_REQ_FDOWN_DATA, neu_req_fdown_data_t) \ + XX(NEU_RESP_FDOWN_DATA, neu_resp_fdown_data_t) \ + XX(NEU_REQ_ADD_NODE_EVENT, neu_req_add_node_t) \ + XX(NEU_REQ_DEL_NODE_EVENT, neu_req_del_node_t) \ + XX(NEU_REQ_NODE_CTL_EVENT, neu_req_node_ctl_t) \ + XX(NEU_REQ_NODE_SETTING_EVENT, neu_req_node_setting_t) \ + XX(NEU_REQ_ADD_GROUP_EVENT, neu_req_add_group_t) \ + XX(NEU_REQ_DEL_GROUP_EVENT, neu_req_del_group_t) \ + XX(NEU_REQ_UPDATE_GROUP_EVENT, neu_req_update_group_t) \ + XX(NEU_REQ_ADD_TAG_EVENT, neu_req_add_tag_t) \ + XX(NEU_REQ_DEL_TAG_EVENT, neu_req_del_tag_t) \ + XX(NEU_REQ_UPDATE_TAG_EVENT, neu_req_update_tag_t) \ + XX(NEU_REQ_ADD_GTAG_EVENT, neu_req_add_gtag_t) \ + XX(NEU_REQ_ADD_PLUGIN_EVENT, neu_req_add_plugin_t) \ + XX(NEU_REQ_DEL_PLUGIN_EVENT, neu_req_del_plugin_t) \ + XX(NEU_REQ_SUBSCRIBE_GROUP_EVENT, neu_req_subscribe_t) \ + XX(NEU_REQ_UNSUBSCRIBE_GROUP_EVENT, neu_req_unsubscribe_t) \ + XX(NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT, neu_req_subscribe_t) \ + XX(NEU_REQ_SUBSCRIBE_GROUPS_EVENT, neu_req_subscribe_groups_t) \ + XX(NEU_RESP_WRITE_TAGS, neu_resp_write_tags_t) \ + XX(NEU_REQ_GET_DATALAYERS_GROUPS, neu_req_get_subscribe_group_t) \ + XX(NEU_RESP_GET_DATALAYERS_GROUPS, neu_resp_get_subscribe_group_t) \ + XX(NEU_REQ_GET_DATALAYERS_TAGS, neu_req_get_sub_driver_tags_t) \ + XX(NEU_RESP_GET_DATALAYERS_TAGS, neu_resp_get_sub_driver_tags_t) static inline size_t neu_reqresp_size(neu_reqresp_type_e t) { diff --git a/src/core/manager.c b/src/core/manager.c index a2fdbdb6..bab4e217 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1035,6 +1035,47 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data) break; } + case NEU_REQ_GET_DATALAYERS_GROUPS: { + neu_req_get_subscribe_group_t *cmd = + (neu_req_get_subscribe_group_t *) &header[1]; + UT_array *groups = neu_manager_get_sub_group_deep_copy( + manager, cmd->app, cmd->driver, cmd->group); + neu_resp_get_subscribe_group_t resp = { .groups = groups }; + + strcpy(header->receiver, header->sender); + header->type = NEU_RESP_GET_DATALAYERS_GROUPS; + reply(manager, header, &resp); + break; + } + case NEU_REQ_GET_DATALAYERS_TAGS: { + neu_req_get_sub_driver_tags_t *cmd = + (neu_req_get_sub_driver_tags_t *) &header[1]; + neu_resp_get_sub_driver_tags_t resp = { 0 }; + UT_array *groups = neu_manager_get_sub_group(manager, cmd->app); + + utarray_new(resp.infos, neu_resp_get_sub_driver_tags_info_icd()); + utarray_foreach(groups, neu_resp_subscribe_info_t *, info) + { + neu_resp_get_sub_driver_tags_info_t in = { 0 }; + neu_adapter_t * driver = + neu_node_manager_find(manager->node_manager, info->driver); + assert(driver != NULL); + + strcpy(in.driver, info->driver); + strcpy(in.group, info->group); + neu_adapter_driver_get_value_tag((neu_adapter_driver_t *) driver, + info->group, &in.tags); + + utarray_push_back(resp.infos, &in); + } + utarray_free(groups); + + strcpy(header->receiver, header->sender); + header->type = NEU_RESP_GET_DATALAYERS_TAGS; + reply(manager, header, &resp); + + break; + } case NEU_REQ_GET_NODES_STATE: { neu_resp_get_nodes_state_t resp = { 0 }; UT_array *states = neu_node_manager_get_state(manager->node_manager); diff --git a/src/parser/neu_json_datalayers.c b/src/parser/neu_json_datalayers.c new file mode 100644 index 00000000..30654d98 --- /dev/null +++ b/src/parser/neu_json_datalayers.c @@ -0,0 +1,188 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2022 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. + **/ + +/* + * DO NOT EDIT THIS FILE MANUALLY! + * It was automatically generated by `json-autotype`. + */ + +#include +#include + +#include + +#include "msg.h" +#include "utils/log.h" +#include "json/json.h" + +#include "neu_json_datalayers.h" + +#include + +void generate_fixed_uuid(const char *input, char *out) +{ + unsigned char hash[MD5_DIGEST_LENGTH]; + MD5_CTX md5_ctx; + + MD5_Init(&md5_ctx); + MD5_Update(&md5_ctx, input, strlen(input)); + MD5_Final(hash, &md5_ctx); + + snprintf( + out, 37, + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], + hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], + hash[15]); +} + +int neu_json_encode_datalayers_get_groups_resp(void *object, void *param) +{ + int ret = 0; + neu_json_get_subscribe_resp_t *resp = + (neu_json_get_subscribe_resp_t *) param; + + json_t *node_array = json_array(); + + for (int i = 0; i < resp->n_group; i++) { + neu_json_get_subscribe_resp_group_t *g = &resp->groups[i]; + if (!g->driver || !g->group) + continue; + + char node_id[37]; + generate_fixed_uuid(g->driver, node_id); + + json_t *node_obj = NULL; + json_t *children_array = NULL; + + for (size_t j = 0; j < json_array_size(node_array); j++) { + node_obj = json_array_get(node_array, j); + if (strcmp(json_string_value(json_object_get(node_obj, "id")), node_id) == 0) { + break; + } + node_obj = NULL; + } + + if (!node_obj) { + node_obj = json_object(); + json_object_set_new(node_obj, "id", json_string(node_id)); + json_object_set_new(node_obj, "name", json_string(g->driver)); + json_object_set_new(node_obj, "category", json_integer(1)); + children_array = json_array(); + json_object_set_new(node_obj, "children", children_array); + json_array_append_new(node_array, node_obj); + } else { + children_array = json_object_get(node_obj, "children"); + } + + char group_id[37]; + char group_uuid_input[256]; + snprintf(group_uuid_input, sizeof(group_uuid_input), "%s-%s", g->driver, g->group); + generate_fixed_uuid(group_uuid_input, group_id); + + json_t *group_obj = json_object(); + json_object_set_new(group_obj, "id", json_string(group_id)); + json_object_set_new(group_obj, "name", json_string(g->group)); + json_object_set_new(group_obj, "category", json_integer(2)); + json_object_set_new(group_obj, "children", json_array()); + + json_array_append_new(children_array, group_obj); + } + + json_t *final_obj = json_object(); + json_object_set_new(final_obj, "error", json_integer(0)); + json_object_set_new(final_obj, "children", node_array); + + neu_json_elem_t elems[] = { { + .name = NULL, + .t = NEU_JSON_OBJECT, + .v.val_object = final_obj, + } }; + + ret = neu_json_encode_field(object, elems, NEU_JSON_ELEM_SIZE(elems)); + + json_decref(final_obj); + + return ret; +} + +int neu_json_encode_datalayers_get_tags_resp(void *json_object_param, + void *param) +{ + neu_resp_get_sub_driver_tags_t *resp = + (neu_resp_get_sub_driver_tags_t *) param; + json_t *group_array = json_array(); + + for (unsigned int i = 0; i < utarray_len(resp->infos); i++) { + neu_resp_get_sub_driver_tags_info_t *info = + (neu_resp_get_sub_driver_tags_info_t *) utarray_eltptr(resp->infos, + i); + + char group_uuid_input[256], group_id[37]; + snprintf(group_uuid_input, sizeof(group_uuid_input), "%s-%s", + info->driver, info->group); + generate_fixed_uuid(group_uuid_input, group_id); + + json_t *group_obj = json_object(); + json_object_set_new(group_obj, "id", json_string(group_id)); + json_object_set_new(group_obj, "name", json_string(info->group)); + json_object_set_new(group_obj, "category", json_integer(2)); + + json_t *tag_array = json_array(); + + if (info->tags) { + for (unsigned int j = 0; j < utarray_len(info->tags); j++) { + neu_datatag_t *tag = + (neu_datatag_t *) utarray_eltptr(info->tags, j); + + char tag_uuid_input[512], tag_id[37]; + snprintf(tag_uuid_input, sizeof(tag_uuid_input), "%s-%s-%s", + info->driver, info->group, tag->name); + generate_fixed_uuid(tag_uuid_input, tag_id); + + json_t *tag_obj = json_object(); + json_object_set_new(tag_obj, "id", json_string(tag_id)); + json_object_set_new(tag_obj, "name", json_string(tag->name)); + json_object_set_new(tag_obj, "type", json_integer(tag->type)); + json_object_set_new(tag_obj, "category", json_integer(3)); + json_object_set_new(tag_obj, "children", json_array()); + + json_array_append_new(tag_array, tag_obj); + } + } + + json_object_set_new(group_obj, "children", tag_array); + json_array_append_new(group_array, group_obj); + } + + json_t *final_obj = json_object(); + json_object_set_new(final_obj, "error", json_integer(0)); + json_object_set_new(final_obj, "children", group_array); + + neu_json_elem_t elems[] = { { + .name = NULL, + .t = NEU_JSON_OBJECT, + .v.val_object = final_obj, + } }; + + int ret = neu_json_encode_field(json_object_param, elems, + NEU_JSON_ELEM_SIZE(elems)); + json_decref(final_obj); + return ret; +} \ No newline at end of file diff --git a/src/parser/neu_json_datalayers.h b/src/parser/neu_json_datalayers.h new file mode 100644 index 00000000..375f89e4 --- /dev/null +++ b/src/parser/neu_json_datalayers.h @@ -0,0 +1,54 @@ +/** + * NEURON IIoT System for Industry 4.0 + * Copyright (C) 2020-2022 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. + **/ + +/* + * DO NOT EDIT THIS FILE MANUALLY! + * It was automatically generated by `json-autotype`. + */ + +#ifndef _NEU_JSON_API_NEU_JSON_DATALAYERS_H_ +#define _NEU_JSON_API_NEU_JSON_DATALAYERS_H_ + +#include "json/json.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *group; + char *driver; + char *params; + char *static_tags; +} neu_json_get_subscribe_resp_group_t; + +typedef struct { + int n_group; + neu_json_get_subscribe_resp_group_t *groups; +} neu_json_get_subscribe_resp_t; + +int neu_json_encode_datalayers_get_groups_resp(void *json_object, void *param); + +int neu_json_encode_datalayers_get_tags_resp(void *json_object, void *param); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/json.c b/src/utils/json.c index 185ec420..e34f10f7 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -337,7 +337,16 @@ static json_t *encode_object(json_t *object, neu_json_elem_t ele) break; } case NEU_JSON_OBJECT: - json_object_set_new(ob, ele.name, ele.v.val_object); + if (ele.name == NULL) { + const char *key; + json_t * value; + json_object_foreach(ele.v.val_object, key, value) + { + json_object_set(ob, key, value); + } + } else { + json_object_set_new(ob, ele.name, ele.v.val_object); + } break; default: break;