Compare commits

...
53 Commits
Author SHA1 Message Date
fengzeroz 96986ce10b Merge pull request #2653 from fengzeroz/v2.11
version: 2.11.5
2025-12-30 14:28:22 +08:00
fengzero 867ab69ff4 version: 2.11.5 2025-12-30 06:27:36 +00:00
fengzeroz f402cf3858 Merge pull request #2649 from fengzeroz/v2.11
fix(group): free group context with old group
2025-12-25 10:05:22 +08:00
fengzero bd1651f12a fix(group): free group context with old group 2025-12-25 02:03:28 +00:00
fengzeroz 160f5eb293 Merge pull request #2638 from fengzeroz/v2.11
fix(connection): close fd if ip invalid
2025-12-19 15:03:08 +08:00
fengzero 31ee80f64e fix(connection): close fd if ip invalid 2025-12-19 07:02:09 +00:00
fengzeroz af8cc2ee2d Merge pull request #2635 from ZhouBox/v2.11
[v2.11]metrics:add debug log
2025-12-12 17:44:01 +08:00
xiang.zhou 84cfeadf52 metrics:add debug log 2025-12-12 17:41:38 +08:00
fengzeroz e84fe85eee Merge pull request #2628 from fengzeroz/v2.11
cid: parse VisString65
2025-12-09 15:01:56 +08:00
fengzero c0c3cb11b3 cid: parse VisString65 2025-12-09 06:59:47 +00:00
fengzeroz 93c2061b9b Merge pull request #2620 from ZhouBox/v2.11
[v2.11]ekuiper:add warn log
2025-11-20 10:01:15 +08:00
xiang.zhou 3fac458370 ekuiper:add warn log 2025-11-19 16:38:29 +08:00
fengzeroz 09c21bde58 Merge pull request #2613 from ZhouBox/v2.11
[v2.11]ekuiper:add log
2025-11-19 11:03:29 +08:00
xiang.zhou f5191248b5 ekuiper:add log 2025-11-19 10:51:06 +08:00
fengzeroz bfcd62252f Merge pull request #2608 from fengzeroz/v2.11
rm unused node cache sql
2025-11-12 10:16:57 +08:00
fengzero 38f8409175 rm unused node cache sql 2025-11-12 02:15:51 +00:00
fengzeroz b05942da86 Merge pull request #2584 from fengzeroz/v2.11
replace tar with zip db data
2025-10-20 11:30:08 +08:00
fengzero cf7b4e7548 replace tar with zip db data 2025-10-20 03:28:39 +00:00
fengzeroz 267d5e0a0a Merge pull request #2577 from fengzeroz/v2.11
connect(udpto): get local port
2025-10-14 11:31:19 +08:00
fengzero f163d8acc5 connect(udpto): get local port 2025-10-14 03:29:52 +00:00
fengzeroz 45ddf88326 Merge pull request #2572 from fengzeroz/v2.11
V2.11
2025-10-13 15:23:11 +08:00
fengzero cad4570146 connect: get udp bind port 2025-10-13 07:20:09 +00:00
fengzero 7871ef1128 api: export db 2025-10-13 07:20:09 +00:00
fengzeroz 92a948a483 Merge pull request #2565 from hxy7yx/v2.11-1
[v2.11]feat(monitor):add plugin monitor
2025-09-11 10:02:30 +08:00
hxy 84c4cd9e91 feat(monitor):add plugin monitor 2025-09-09 23:42:18 -07:00
fengzeroz ebc4d9f05f Merge pull request #2563 from fengzeroz/v2.11
V2.11
2025-09-09 10:52:33 +08:00
fengzero ff2fc4fe79 file string value size 2025-09-09 02:51:08 +00:00
fengzero 5a2676b162 file 2025-09-09 02:50:22 +00:00
fengzeroz 710948464c Merge pull request #2551 from fengzeroz/v2.11
conn: disconnect when connected and recv error
2025-08-27 14:41:43 +08:00
fengzero 4e601a8eed conn: disconnect when connected and recv error 2025-08-27 06:39:50 +00:00
fengzeroz b7d85049be Merge pull request #2547 from fengzeroz/v2.11
get subs: match sub string
2025-08-21 13:54:37 +08:00
fengzero f1b8dd89dc get subs: match sub string 2025-08-21 05:53:51 +00:00
fengzeroz b14a221eab Merge pull request #2544 from fengzeroz/v2.11
subs api: response ok when request empty
2025-08-21 11:04:03 +08:00
fengzero cb16765b98 subs api: response ok when request empty 2025-08-21 02:59:37 +00:00
fengzeroz 8a57237285 Merge pull request #2541 from fengzeroz/v2.11
app: get all groups
2025-08-20 14:38:56 +08:00
fengzero a107c0aebb app: get all groups 2025-08-20 06:11:30 +00:00
fengzeroz 6328fd12da Merge pull request #2535 from fengzeroz/v2.11
event name
2025-08-19 15:24:44 +08:00
fengzero 69d9c2cc3b event name 2025-08-19 06:46:59 +00:00
fengzeroz f32ced4628 Merge pull request #2531 from ZhouBox/v2.11
[v2.11]json:object array support
2025-08-08 15:53:43 +08:00
xiang.zhou 210a123cba json:object array support 2025-08-08 15:03:00 +08:00
fengzeroz e8cf3e4891 Merge pull request #2526 from ZhouBox/v2.11
[v2.11]memery leak
2025-07-23 16:12:36 +08:00
xiang.zhou d0c69b28b1 memery leak 2025-07-23 15:45:58 +08:00
xiang.zhou da4757a91f memery leak 2025-07-23 15:45:56 +08:00
fengzeroz c6c176069d Merge pull request #2519 from fengzeroz/v2.11
version: 2.11.4
2025-07-10 13:46:56 +08:00
fengzero 1eedb1e4cf version: 2.11.4 2025-07-10 05:46:23 +00:00
fengzeroz 73441f5102 Merge pull request #2518 from ZhouBox/v2.11
[v2.11]mem op when driver report callback
2025-07-08 14:18:33 +08:00
xiang.zhou 2cc9a68548 mem op when driver report callback 2025-07-08 13:53:56 +08:00
fengzeroz 9d586dff2d Merge pull request #2516 from ZhouBox/v2.11
[V2.11] group filter & sort
2025-07-08 13:45:34 +08:00
xiang.zhou 217799aadf filter node name 2025-07-08 10:25:12 +08:00
xiang.zhou 67c5b17816 node&group support filter 2025-07-08 10:23:11 +08:00
fengzero 3bf7a10ac9 get nodes: query state/link, sort delay 2025-07-08 10:23:04 +08:00
fengzeroz e7bd8262f6 Merge pull request #2509 from fengzeroz/v2.11
report: pre alloc memory
2025-06-26 11:15:04 +08:00
fengzero e089d7965e report: pre alloc memory 2025-06-26 03:13:25 +00:00
66 changed files with 3786 additions and 277 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ on:
- published
env:
VERSION: 2.11.3
VERSION: 2.11.5
UI_VERSION: 2.6.1
BRANCH: v2.11
+2
View File
@@ -185,6 +185,8 @@ file(COPY ${CMAKE_SOURCE_DIR}/default_plugins.json DESTINATION ${CMAKE_BINARY_DI
add_subdirectory(plugins/modbus)
add_subdirectory(plugins/mqtt)
add_subdirectory(plugins/ekuiper)
add_subdirectory(plugins/file)
add_subdirectory(plugins/monitor)
add_subdirectory(simulator)
+2 -1
View File
@@ -303,6 +303,7 @@ int neu_conn_tcp_server_wait_msg(neu_conn_t *conn, int fd, void *context,
int is_ipv4(const char *ip);
int is_ipv6(const char *ip);
bool neu_conn_is_connected(neu_conn_t *conn);
bool neu_conn_is_connected(neu_conn_t *conn);
uint16_t neu_conn_udp_act_port(neu_conn_t *conn);
#endif
+9 -1
View File
@@ -24,7 +24,7 @@
#define NEU_VERSION_MAJOR 2
#define NEU_VERSION_MINOR 11
#define NEU_VERSION_FIX 3
#define NEU_VERSION_FIX 5
#define NEU_GET_VERSION_MAJOR(V) ((0xffff0000 & V) >> 16)
#define NEU_GET_VERSION_MINOR(V) ((0x0000ff00 & V) >> 8)
@@ -124,6 +124,14 @@
}); \
} while (0)
#define CHECK_NODE_MONITOR_ERR \
do { \
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_NOT_ALLOW_UPDATE, { \
neu_http_response(aio, NEU_ERR_NODE_NOT_ALLOW_UPDATE, \
result_error); \
}); \
} while (0)
extern int default_log_level;
extern bool disable_jwt;
extern char host_port[32];
+1 -1
View File
@@ -35,7 +35,7 @@ typedef struct neu_events neu_events_t;
* thread.
* @return the newly created event.
*/
neu_events_t *neu_event_new(void);
neu_events_t *neu_event_new(const char *name);
/**
* @brief Close a event.
+134 -35
View File
@@ -60,6 +60,8 @@ typedef enum neu_reqresp_type {
NEU_REQ_SUBSCRIBE_GROUPS,
NEU_REQ_GET_SUBSCRIBE_GROUP,
NEU_RESP_GET_SUBSCRIBE_GROUP,
NEU_REQ_GET_DRIVER_SUBSCRIBE_GROUP,
NEU_RESP_GET_DRIVER_SUBSCRIBE_GROUP,
NEU_REQ_GET_SUB_DRIVER_TAGS,
NEU_RESP_GET_SUB_DRIVER_TAGS,
@@ -128,6 +130,27 @@ typedef enum neu_reqresp_type {
NEU_REQ_DRIVER_ACTION,
NEU_RESP_DRIVER_ACTION,
NEU_REQ_ADD_NODE_EVENT,
NEU_REQ_DEL_NODE_EVENT,
NEU_REQ_NODE_CTL_EVENT,
NEU_REQ_NODE_SETTING_EVENT,
NEU_REQ_ADD_GROUP_EVENT,
NEU_REQ_DEL_GROUP_EVENT,
NEU_REQ_UPDATE_GROUP_EVENT,
NEU_REQ_ADD_TAG_EVENT,
NEU_REQ_DEL_TAG_EVENT,
NEU_REQ_UPDATE_TAG_EVENT,
NEU_REQ_ADD_GTAG_EVENT,
NEU_REQ_ADD_PLUGIN_EVENT,
NEU_REQ_DEL_PLUGIN_EVENT,
NEU_REQ_SUBSCRIBE_GROUP_EVENT,
NEU_REQ_UNSUBSCRIBE_GROUP_EVENT,
NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT,
NEU_REQ_SUBSCRIBE_GROUPS_EVENT,
} neu_reqresp_type_e;
static const char *neu_reqresp_type_string_t[] = {
@@ -143,14 +166,17 @@ static const char *neu_reqresp_type_string_t[] = {
[NEU_REQ_WRITE_TAGS] = "NEU_REQ_WRITE_TAGS",
[NEU_REQ_WRITE_GTAGS] = "NEU_REQ_WRITE_GTAGS",
[NEU_REQ_SUBSCRIBE_GROUP] = "NEU_REQ_SUBSCRIBE_GROUP",
[NEU_REQ_UNSUBSCRIBE_GROUP] = "NEU_REQ_UNSUBSCRIBE_GROUP",
[NEU_REQ_UPDATE_SUBSCRIBE_GROUP] = "NEU_REQ_UPDATE_SUBSCRIBE_GROUP",
[NEU_REQ_SUBSCRIBE_GROUPS] = "NEU_REQ_SUBSCRIBE_GROUPS",
[NEU_REQ_GET_SUBSCRIBE_GROUP] = "NEU_REQ_GET_SUBSCRIBE_GROUP",
[NEU_RESP_GET_SUBSCRIBE_GROUP] = "NEU_RESP_GET_SUBSCRIBE_GROUP",
[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_SUBSCRIBE_GROUP] = "NEU_REQ_SUBSCRIBE_GROUP",
[NEU_REQ_UNSUBSCRIBE_GROUP] = "NEU_REQ_UNSUBSCRIBE_GROUP",
[NEU_REQ_UPDATE_SUBSCRIBE_GROUP] = "NEU_REQ_UPDATE_SUBSCRIBE_GROUP",
[NEU_REQ_SUBSCRIBE_GROUPS] = "NEU_REQ_SUBSCRIBE_GROUPS",
[NEU_REQ_GET_SUBSCRIBE_GROUP] = "NEU_REQ_GET_SUBSCRIBE_GROUP",
[NEU_RESP_GET_SUBSCRIBE_GROUP] = "NEU_RESP_GET_SUBSCRIBE_GROUP",
[NEU_REQ_GET_DRIVER_SUBSCRIBE_GROUP] = "NEU_REQ_GET_DRIVER_SUBSCRIBE_GROUP",
[NEU_RESP_GET_DRIVER_SUBSCRIBE_GROUP] =
"NEU_RESP_GET_DRIVER_SUBSCRIBE_GROUP",
[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_NODE_INIT] = "NEU_REQ_NODE_INIT",
[NEU_REQ_NODE_UNINIT] = "NEU_REQ_NODE_UNINIT",
@@ -216,6 +242,25 @@ static const char *neu_reqresp_type_string_t[] = {
[NEU_REQ_DRIVER_ACTION] = "NEU_REQ_DRIVER_ACTION",
[NEU_RESP_DRIVER_ACTION] = "NEU_RESP_DRIVER_ACTION",
[NEU_REQ_ADD_NODE_EVENT] = "NEU_REQ_ADD_NODE_EVENT",
[NEU_REQ_DEL_NODE_EVENT] = "NEU_REQ_DEL_NODE_EVENT",
[NEU_REQ_NODE_CTL_EVENT] = "NEU_REQ_NODE_CTL_EVENT",
[NEU_REQ_NODE_SETTING_EVENT] = "NEU_REQ_NODE_SETTING_EVENT",
[NEU_REQ_ADD_GROUP_EVENT] = "NEU_REQ_ADD_GROUP_EVENT",
[NEU_REQ_DEL_GROUP_EVENT] = "NEU_REQ_DEL_GROUP_EVENT",
[NEU_REQ_UPDATE_GROUP_EVENT] = "NEU_REQ_UPDATE_GROUP_EVENT",
[NEU_REQ_ADD_TAG_EVENT] = "NEU_REQ_ADD_TAG_EVENT",
[NEU_REQ_DEL_TAG_EVENT] = "NEU_REQ_DEL_TAG_EVENT",
[NEU_REQ_UPDATE_TAG_EVENT] = "NEU_REQ_UPDATE_TAG_EVENT",
[NEU_REQ_ADD_GTAG_EVENT] = "NEU_REQ_ADD_GTAG_EVENT",
[NEU_REQ_ADD_PLUGIN_EVENT] = "NEU_REQ_ADD_PLUGIN_EVENT",
[NEU_REQ_DEL_PLUGIN_EVENT] = "NEU_REQ_DEL_PLUGIN_EVENT",
[NEU_REQ_SUBSCRIBE_GROUP_EVENT] = "NEU_REQ_SUBSCRIBE_GROUP_EVENT",
[NEU_REQ_UNSUBSCRIBE_GROUP_EVENT] = "NEU_REQ_UNSUBSCRIBE_GROUP_EVENT",
[NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT] =
"NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT",
[NEU_REQ_SUBSCRIBE_GROUPS_EVENT] = "NEU_REQ_SUBSCRIBE_GROUPS_EVENT",
};
inline static const char *neu_reqresp_type_string(neu_reqresp_type_e type)
@@ -238,6 +283,7 @@ typedef struct neu_reqresp_head {
char receiver[NEU_NODE_NAME_LEN];
uint8_t otel_trace_type;
uint32_t len;
bool monitor;
} neu_reqresp_head_t;
typedef struct neu_resp_error {
@@ -326,11 +372,21 @@ typedef struct neu_req_get_node {
neu_node_type_e type;
char plugin[NEU_PLUGIN_NAME_LEN];
char node[NEU_NODE_NAME_LEN];
struct {
bool q_state;
int state;
bool q_link;
int link;
bool s_delay;
char q_group_name[NEU_GROUP_NAME_LEN];
} query;
} neu_req_get_node_t;
typedef struct neu_resp_node_info {
char node[NEU_NODE_NAME_LEN];
char plugin[NEU_PLUGIN_NAME_LEN];
int64_t delay;
char node[NEU_NODE_NAME_LEN];
char plugin[NEU_PLUGIN_NAME_LEN];
} neu_resp_node_info_t;
typedef struct neu_resp_get_node {
@@ -368,6 +424,7 @@ typedef struct neu_req_del_group {
typedef struct neu_req_get_group {
char driver[NEU_NODE_NAME_LEN];
char q_group[NEU_GROUP_NAME_LEN];
} neu_req_get_group_t;
typedef struct neu_resp_group_info {
@@ -536,6 +593,11 @@ typedef struct neu_req_get_subscribe_group {
char group[NEU_GROUP_NAME_LEN];
} neu_req_get_subscribe_group_t;
typedef struct neu_req_get_driver_subscribe_group {
char app[NEU_NODE_NAME_LEN];
char name[NEU_NODE_NAME_LEN];
} neu_req_get_driver_subscribe_group_t;
typedef struct {
char app[NEU_NODE_NAME_LEN];
} neu_req_get_sub_driver_tags_t;
@@ -548,6 +610,13 @@ typedef struct neu_resp_subscribe_info {
char *static_tags;
} neu_resp_subscribe_info_t;
typedef struct neu_resp_driver_subscribe_info {
char driver[NEU_NODE_NAME_LEN];
char app[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
bool subscribed;
} neu_resp_driver_subscribe_info_t;
static inline void neu_resp_subscribe_info_fini(neu_resp_subscribe_info_t *info)
{
free(info->params);
@@ -571,7 +640,8 @@ typedef struct {
} neu_resp_get_sub_driver_tags_t;
typedef struct neu_resp_get_subscribe_group {
UT_array *groups; // array neu_resp_subscribe_info_t
UT_array *groups; // array neu_resp_subscribe_info_t or
// neu_resp_driver_subscribe_info_t
} neu_resp_get_subscribe_group_t;
typedef struct neu_req_node_setting {
@@ -722,10 +792,11 @@ typedef struct neu_resp_tag_value {
typedef neu_resp_tag_value_t neu_tag_value_t;
typedef struct neu_resp_tag_value_meta {
char tag[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
neu_tag_meta_t metas[NEU_TAG_META_SIZE];
neu_datatag_t datatag;
char tag[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
neu_tag_meta_t *metas;
int n_meta;
neu_datatag_t datatag;
} neu_resp_tag_value_meta_t;
static inline UT_icd *neu_resp_tag_value_meta_icd()
@@ -786,10 +857,11 @@ typedef struct {
} neu_resp_read_group_t;
typedef struct neu_resp_tag_value_meta_paginate {
char tag[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
neu_tag_meta_t metas[NEU_TAG_META_SIZE];
neu_datatag_t datatag;
char tag[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
neu_tag_meta_t *metas;
int n_meta;
neu_datatag_t datatag;
} neu_resp_tag_value_meta_paginate_t;
static inline UT_icd *neu_resp_tag_value_meta_paginate_icd()
@@ -820,6 +892,13 @@ static inline void neu_resp_read_free(neu_resp_read_group_t *resp)
tag_value->value.type < NEU_TYPE_ARRAY_STRING) {
free(tag_value->value.value.bools.bools);
}
if (tag_value->metas != NULL) {
for (int i = 0; i < tag_value->n_meta; i++) {
neu_free_dvalue(&tag_value->metas[i].value);
}
free(tag_value->metas);
}
}
free(resp->driver);
free(resp->group);
@@ -837,6 +916,13 @@ neu_resp_read_paginate_free(neu_resp_read_group_paginate_t *resp)
tag_value->value.type < NEU_TYPE_ARRAY_STRING) {
free(tag_value->value.value.bools.bools);
}
if (tag_value->metas != NULL) {
for (int i = 0; i < tag_value->n_meta; i++) {
neu_free_dvalue(&tag_value->metas[i].value);
}
free(tag_value->metas);
}
}
free(resp->driver);
free(resp->group);
@@ -914,6 +1000,13 @@ static inline void neu_trans_data_free(neu_reqresp_trans_data_t *data)
tag_value->value.type < NEU_TYPE_ARRAY_STRING) {
free(tag_value->value.value.bools.bools);
}
if (tag_value->metas != NULL) {
for (int i = 0; i < tag_value->n_meta; i++) {
neu_free_dvalue(&tag_value->metas[i].value);
}
free(tag_value->metas);
}
}
utarray_free(data->tags);
free(data->group);
@@ -932,18 +1025,21 @@ static inline void neu_tag_value_to_json(neu_resp_tag_value_meta_t *tag_value,
tag_json->name = tag_value->tag;
tag_json->error = 0;
for (int k = 0; k < NEU_TAG_META_SIZE; k++) {
if (strlen(tag_value->metas[k].name) > 0) {
tag_json->n_meta++;
} else {
break;
}
}
// for (int k = 0; k < NEU_TAG_META_SIZE; k++) {
// if (strlen(tag_value->metas[k].name) > 0) {
// tag_json->n_meta++;
// } else {
// break;
// }
// }
tag_json->n_meta = tag_value->n_meta;
if (tag_json->n_meta > 0) {
tag_json->metas = (neu_json_tag_meta_t *) calloc(
tag_json->n_meta, sizeof(neu_json_tag_meta_t));
}
neu_json_metas_to_json(tag_value->metas, NEU_TAG_META_SIZE, tag_json);
neu_json_metas_to_json(tag_value->metas, tag_value->n_meta, tag_json);
tag_json->datatag.bias = tag_value->datatag.bias;
@@ -1141,18 +1237,21 @@ neu_tag_value_to_json_paginate(neu_resp_tag_value_meta_paginate_t *tag_value,
memcpy(tag_json->datatag.meta, tag_value->datatag.meta,
NEU_TAG_META_LENGTH);
for (int k = 0; k < NEU_TAG_META_SIZE; k++) {
if (strlen(tag_value->metas[k].name) > 0) {
tag_json->n_meta++;
} else {
break;
}
}
// for (int k = 0; k < NEU_TAG_META_SIZE; k++) {
// if (strlen(tag_value->metas[k].name) > 0) {
// tag_json->n_meta++;
// } else {
// break;
// }
// }
tag_json->n_meta = tag_value->n_meta;
if (tag_json->n_meta > 0) {
tag_json->metas = (neu_json_tag_meta_t *) calloc(
tag_json->n_meta, sizeof(neu_json_tag_meta_t));
}
neu_json_metas_to_json_paginate(tag_value->metas, NEU_TAG_META_SIZE,
neu_json_metas_to_json_paginate(tag_value->metas, tag_value->n_meta,
tag_json);
switch (tag_value->value.type) {
+1 -1
View File
@@ -155,7 +155,7 @@ typedef struct {
uint8_t * ptr;
} neu_value_ptr_t;
#define NEU_VALUE_SIZE 256
#define NEU_VALUE_SIZE 1024
#define NEU_ARRAY_SIZE 128
typedef struct {
+2
View File
@@ -114,6 +114,8 @@ inline static cid_basictype_e decode_basictype(const char *btype)
ret = VisString64;
} else if (strcmp(btype, "VisString255") == 0) {
ret = VisString255;
} else if (strcmp(btype, "VisString65") == 0) {
ret = Unicode255;
} else if (strcmp(btype, "Octet64") == 0) {
ret = Octet64;
} else if (strcmp(btype, "Struct") == 0) {
-36
View File
@@ -1,36 +0,0 @@
/**
* 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.
**/
--- fix primary key ---
BEGIN;
DROP TABLE IF EXISTS old_node_cache;
ALTER TABLE node_cache RENAME TO old_node_cache;
CREATE TABLE IF NOT EXISTS node_cache (
node_name TEXT PRIMARY KEY,
CACHE TEXT NOT NULL,
FOREIGN KEY (node_name) REFERENCES nodes (name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT OR REPLACE INTO node_cache SELECT * FROM old_node_cache;
DROP TABLE old_node_cache;
COMMIT;
+13
View File
@@ -234,9 +234,22 @@ void recv_data_callback(void *arg)
if (req->singular) {
rv = send_write_tag_req(plugin, &req->single, json_str, trace_flag,
trace_id, span_id);
if (rv == 0) {
plog_notice(plugin, "write tag %s.%s on node %s", req->single.group,
req->single.tag, req->single.node);
}
} else {
rv = send_write_tags_req(plugin, &req->plural, json_str, trace_flag,
trace_id, span_id);
if (rv == 0) {
if (req->plural.n_tag == 0) {
plog_warn(plugin, "no tags to write on node %s",
req->plural.node);
} else {
plog_notice(plugin, "write %d tags on node %s",
req->plural.n_tag, req->plural.node);
}
}
}
if (0 != rv) {
+11
View File
@@ -0,0 +1,11 @@
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/plugins")
set(CMAKE_BUILD_RPATH ./)
file(COPY ${CMAKE_SOURCE_DIR}/plugins/file/file.json DESTINATION ${CMAKE_BINARY_DIR}/plugins/schema/)
set(PLUGIN_NAME plugin-file)
set(PLUGIN_SOURCES file_plugin.c)
add_library(${PLUGIN_NAME} SHARED)
target_include_directories(${PLUGIN_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include/neuron)
target_sources(${PLUGIN_NAME} PRIVATE ${PLUGIN_SOURCES})
target_link_libraries(${PLUGIN_NAME} neuron-base)
+9
View File
@@ -0,0 +1,9 @@
{
"tag_regex": [
{
"type": 13,
"regex": ""
}
],
"group_interval": 1000
}
+247
View File
@@ -0,0 +1,247 @@
/**
* 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 <errno.h>
#include <stdlib.h>
#include <neuron.h>
#include "errcodes.h"
struct neu_plugin {
neu_plugin_common_t common;
// neu_events_t *events;
// int file_length;
};
static neu_plugin_t *driver_open(void);
static int driver_close(neu_plugin_t *plugin);
static int driver_init(neu_plugin_t *plugin, bool load);
static int driver_uninit(neu_plugin_t *plugin);
static int driver_start(neu_plugin_t *plugin);
static int driver_stop(neu_plugin_t *plugin);
static int driver_config(neu_plugin_t *plugin, const char *config);
static int driver_request(neu_plugin_t *plugin, neu_reqresp_head_t *head,
void *data);
static int driver_tag_validator(const neu_datatag_t *tag);
static int driver_validate_tag(neu_plugin_t *plugin, neu_datatag_t *tag);
static int driver_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group);
static int driver_write(neu_plugin_t *plugin, void *req, neu_datatag_t *tag,
neu_value_u value);
static const neu_plugin_intf_funs_t plugin_intf_funs = {
.open = driver_open,
.close = driver_close,
.init = driver_init,
.uninit = driver_uninit,
.start = driver_start,
.stop = driver_stop,
.setting = driver_config,
.request = driver_request,
.driver.validate_tag = driver_validate_tag,
.driver.group_timer = driver_group_timer,
.driver.group_sync = NULL,
.driver.write_tag = driver_write,
.driver.tag_validator = driver_tag_validator,
.driver.write_tags = NULL,
.driver.test_read_tag = NULL,
.driver.add_tags = NULL,
.driver.load_tags = NULL,
.driver.del_tags = NULL,
};
const neu_plugin_module_t neu_plugin_module = {
.version = NEURON_PLUGIN_VER_1_0,
.schema = "file",
.module_name = "File",
.module_descr = "The plugin is used to read and write files.",
.module_descr_zh = "该插件用于读写文件。",
.intf_funs = &plugin_intf_funs,
.kind = NEU_PLUGIN_KIND_SYSTEM,
.type = NEU_NA_TYPE_DRIVER,
.display = true,
.single = false,
};
static neu_plugin_t *driver_open(void)
{
neu_plugin_t *plugin = calloc(1, sizeof(neu_plugin_t));
neu_plugin_common_init(&plugin->common);
return plugin;
}
static int driver_close(neu_plugin_t *plugin)
{
free(plugin);
return 0;
}
static int driver_init(neu_plugin_t *plugin, bool load)
{
(void) load;
plog_notice(plugin, "%s init success", plugin->common.name);
return 0;
}
static int driver_uninit(neu_plugin_t *plugin)
{
plog_notice(plugin, "%s uninit success", plugin->common.name);
return 0;
}
static int driver_start(neu_plugin_t *plugin)
{
neu_adapter_update_metric_cb_t update_metric =
plugin->common.adapter_callbacks->update_metric;
update_metric(plugin->common.adapter, NEU_METRIC_LAST_RTT_MS, 1, NULL);
plugin->common.link_state = NEU_NODE_LINK_STATE_CONNECTED;
plog_notice(plugin, "start `%s` plugin success", plugin->common.name);
return 0;
}
static int driver_stop(neu_plugin_t *plugin)
{
neu_adapter_update_metric_cb_t update_metric =
plugin->common.adapter_callbacks->update_metric;
update_metric(plugin->common.adapter, NEU_METRIC_LAST_RTT_MS, 9999, NULL);
plugin->common.link_state = NEU_NODE_LINK_STATE_DISCONNECTED;
plog_notice(plugin, "stop `%s` plugin success", plugin->common.name);
return 0;
}
static int driver_config(neu_plugin_t *plugin, const char *config)
{
(void) plugin;
(void) config;
return 0;
}
static int driver_request(neu_plugin_t *plugin, neu_reqresp_head_t *head,
void *data)
{
(void) plugin;
(void) head;
(void) data;
return 0;
}
static int driver_tag_validator(const neu_datatag_t *tag)
{
(void) tag;
return 0;
}
static int driver_validate_tag(neu_plugin_t *plugin, neu_datatag_t *tag)
{
if (tag->type != NEU_TYPE_STRING) {
return NEU_ERR_TAG_TYPE_NOT_SUPPORT;
}
plog_notice(plugin, "validate tag success, name:%s, address:%s, type:%d ",
tag->name, tag->address, tag->type);
return 0;
}
static int driver_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group)
{
neu_adapter_update_metric_cb_t update_metric =
plugin->common.adapter_callbacks->update_metric;
utarray_foreach(group->tags, neu_datatag_t *, tag)
{
neu_dvalue_t dvalue = { 0 };
FILE *fp = fopen(tag->address, "r");
if (fp == NULL) {
dvalue.type = NEU_TYPE_ERROR;
if (errno == ENOENT) {
dvalue.value.i32 = NEU_ERR_FILE_NOT_EXIST;
} else {
dvalue.value.i32 = NEU_ERR_FILE_OPEN_FAILURE;
}
} else {
char *buf = calloc(1, 1024);
int ret = fread(buf, 1, 1024, fp);
if (ret < 0) {
dvalue.type = NEU_TYPE_ERROR;
dvalue.value.i32 = NEU_ERR_FILE_READ_FAILURE;
} else {
dvalue.type = NEU_TYPE_STRING;
strncpy(dvalue.value.str, buf, NEU_VALUE_SIZE - 1);
}
fclose(fp);
free(buf);
}
plugin->common.adapter_callbacks->driver.update(
plugin->common.adapter, group->group_name, tag->name, dvalue);
}
update_metric(plugin->common.adapter, NEU_METRIC_SEND_BYTES, 0, NULL);
update_metric(plugin->common.adapter, NEU_METRIC_RECV_BYTES, 0, NULL);
update_metric(plugin->common.adapter, NEU_METRIC_LAST_RTT_MS, 1, NULL);
update_metric(plugin->common.adapter, NEU_METRIC_GROUP_LAST_SEND_MSGS, 1,
group->group_name);
return 0;
}
static int driver_write(neu_plugin_t *plugin, void *req, neu_datatag_t *tag,
neu_value_u value)
{
FILE *fp = fopen(tag->address, "w");
if (fp == NULL) {
if (errno == ENOENT) {
plugin->common.adapter_callbacks->driver.write_response(
plugin->common.adapter, req, NEU_ERR_FILE_NOT_EXIST);
} else {
plugin->common.adapter_callbacks->driver.write_response(
plugin->common.adapter, req, NEU_ERR_FILE_OPEN_FAILURE);
}
} else {
if (tag->type == NEU_TYPE_STRING) {
size_t ret = fwrite(value.str, 1, strlen(value.str), fp);
if (ret != strlen(value.str)) {
plugin->common.adapter_callbacks->driver.write_response(
plugin->common.adapter, req, NEU_ERR_FILE_WRITE_FAILURE);
}
} else {
plugin->common.adapter_callbacks->driver.write_response(
plugin->common.adapter, req, NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH);
}
fclose(fp);
plugin->common.adapter_callbacks->driver.write_response(
plugin->common.adapter, req, 0);
}
return 0;
}
+1 -1
View File
@@ -102,7 +102,7 @@ static int driver_init(neu_plugin_t *plugin, bool load)
{
(void) load;
plugin->protocol = MODBUS_PROTOCOL_RTU;
plugin->events = neu_event_new();
plugin->events = neu_event_new(plugin->common.name);
plugin->stack = modbus_stack_create((void *) plugin, MODBUS_PROTOCOL_RTU,
modbus_send_msg, modbus_value_handle,
modbus_write_resp);
+1 -1
View File
@@ -105,7 +105,7 @@ static int driver_init(neu_plugin_t *plugin, bool load)
{
(void) load;
plugin->protocol = MODBUS_PROTOCOL_TCP;
plugin->events = neu_event_new();
plugin->events = neu_event_new(plugin->common.name);
plugin->stack = modbus_stack_create((void *) plugin, MODBUS_PROTOCOL_TCP,
modbus_send_msg, modbus_value_handle,
modbus_write_resp);
+20
View File
@@ -0,0 +1,20 @@
# neuron monitor plugin
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/plugins")
file(COPY ${CMAKE_SOURCE_DIR}/plugins/monitor/monitor.json DESTINATION ${CMAKE_BINARY_DIR}/plugins/schema/)
set(src
monitor.c
monitor_config.c
mqtt_handle.c
)
add_library(plugin-monitor SHARED ${src})
target_include_directories(plugin-monitor PRIVATE
${CMAKE_SOURCE_DIR}/include/neuron
${CMAKE_SOURCE_DIR}/src
)
target_link_libraries(plugin-monitor neuron-base nng)
target_link_libraries(plugin-monitor ${CMAKE_THREAD_LIBS_INIT})
+431
View File
@@ -0,0 +1,431 @@
/**
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "errcodes.h"
#include "event/event.h"
#include "monitor.h"
#include "mqtt_handle.h"
#include "utils/http_handler.h"
#include "utils/log.h"
extern const neu_plugin_module_t neu_plugin_module;
static struct neu_plugin *g_monitor_plugin_;
static void connect_cb(void *data)
{
neu_plugin_t *plugin = data;
plugin->common.link_state = NEU_NODE_LINK_STATE_CONNECTED;
plog_notice(plugin, "plugin `%s` connected", neu_plugin_module.module_name);
}
static void disconnect_cb(void *data)
{
neu_plugin_t *plugin = data;
plugin->common.link_state = NEU_NODE_LINK_STATE_DISCONNECTED;
plog_notice(plugin, "plugin `%s` disconnected",
neu_plugin_module.module_name);
}
static int config_mqtt_client(neu_plugin_t *plugin, neu_mqtt_client_t *client,
const monitor_config_t *config)
{
int rv = 0;
if (NULL == client) {
return 0;
}
// set log category as soon as possible to ease debugging
rv = neu_mqtt_client_set_zlog_category(client, plugin->common.log);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_set_zlog_category fail");
return -1;
}
rv = neu_mqtt_client_set_addr(client, config->host, config->port);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_set_host fail");
return -1;
}
rv = neu_mqtt_client_set_id(client, config->client_id);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_set_id fail");
return -1;
}
rv = neu_mqtt_client_set_connect_cb(client, connect_cb, plugin);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_set_connect_cb fail");
return -1;
}
rv = neu_mqtt_client_set_disconnect_cb(client, disconnect_cb, plugin);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_set_disconnect_cb fail");
return -1;
}
if (NULL != config->username) {
rv = neu_mqtt_client_set_user(client, config->username,
config->password);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_set_user fail");
}
}
rv = neu_mqtt_client_set_tls(client, config->ssl, config->ca, config->cert,
config->key, config->keypass);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_set_tsl fail");
return -1;
}
return rv;
}
static int heartbeat_timer_cb(void *data)
{
neu_plugin_t *plugin = data;
neu_reqresp_head_t header = {
.type = NEU_REQ_GET_NODES_STATE,
.ctx = plugin,
};
neu_req_get_nodes_state_t cmd = {};
return neu_plugin_op(plugin, header, &cmd);
}
static inline void stop_heartbeart_timer(neu_plugin_t *plugin)
{
if (plugin->heartbeat_timer) {
neu_event_del_timer(plugin->events, plugin->heartbeat_timer);
plugin->heartbeat_timer = NULL;
plog_notice(plugin, "heartbeat timer stopped");
}
}
static int start_hearbeat_timer(neu_plugin_t *plugin, uint64_t interval)
{
neu_event_timer_t *timer = NULL;
if (0 == interval) {
plog_info(plugin, "heartbeat disabled");
goto end;
}
if (NULL == plugin->events) {
plugin->events = neu_event_new(plugin->common.name);
if (NULL == plugin->events) {
plog_error(plugin, "neu_event_new fail");
return NEU_ERR_EINTERNAL;
}
}
neu_event_timer_param_t param = {
.second = interval,
.millisecond = 0,
.cb = heartbeat_timer_cb,
.usr_data = plugin,
};
timer = neu_event_add_timer(plugin->events, param);
if (NULL == timer) {
plog_error(plugin, "neu_event_add_timer fail");
return NEU_ERR_EINTERNAL;
}
end:
if (plugin->heartbeat_timer) {
neu_event_del_timer(plugin->events, plugin->heartbeat_timer);
}
plugin->heartbeat_timer = timer;
plog_notice(plugin, "start_hearbeat_timer interval: %" PRIu64, interval);
return 0;
}
static void uninit_timers_and_mqtt(neu_plugin_t *plugin)
{
stop_heartbeart_timer(plugin);
if (NULL != plugin->events) {
neu_event_close(plugin->events);
plugin->events = NULL;
}
if (NULL != plugin->config) {
monitor_config_fini(plugin->config);
free(plugin->config);
plugin->config = NULL;
}
if (NULL != plugin->mqtt_client) {
neu_mqtt_client_close(plugin->mqtt_client);
neu_mqtt_client_free(plugin->mqtt_client);
plugin->mqtt_client = NULL;
}
}
static neu_plugin_t *monitor_plugin_open(void)
{
neu_plugin_t *plugin = calloc(1, sizeof(neu_plugin_t));
if (NULL == plugin) {
return NULL;
}
neu_plugin_common_init(&plugin->common);
g_monitor_plugin_ = plugin;
return plugin;
}
static int monitor_plugin_close(neu_plugin_t *plugin)
{
int rv = 0;
plog_notice(plugin, "Success to free plugin: %s",
neu_plugin_module.module_name);
free(plugin);
return rv;
}
static int monitor_plugin_init(neu_plugin_t *plugin, bool load)
{
int rv = 0;
(void) plugin;
(void) load;
plog_notice(plugin, "Initialize plugin: %s", neu_plugin_module.module_name);
return rv;
}
static int monitor_plugin_uninit(neu_plugin_t *plugin)
{
int rv = 0;
uninit_timers_and_mqtt(plugin);
plog_notice(plugin, "Uninitialize plugin: %s",
neu_plugin_module.module_name);
return rv;
}
static int monitor_plugin_config(neu_plugin_t *plugin, const char *setting)
{
int rv = 0;
const char * plugin_name = neu_plugin_module.module_name;
monitor_config_t config = { 0 };
rv = monitor_config_parse(plugin, setting, &config);
if (0 != rv) {
plog_error(plugin, "monitor_config_parse fail");
return NEU_ERR_NODE_SETTING_INVALID;
}
if (NULL == plugin->config) {
plugin->config = calloc(1, sizeof(*plugin->config));
if (NULL == plugin->config) {
plog_error(plugin, "calloc monitor config fail");
rv = NEU_ERR_EINTERNAL;
goto error;
}
}
if (NULL == plugin->mqtt_client) {
plugin->mqtt_client = neu_mqtt_client_new(NEU_MQTT_VERSION_V311);
if (NULL == plugin->mqtt_client) {
plog_error(plugin, "neu_mqtt_client_new fail");
rv = NEU_ERR_EINTERNAL;
goto error;
}
} else if (neu_mqtt_client_is_open(plugin->mqtt_client)) {
rv = neu_mqtt_client_close(plugin->mqtt_client);
if (0 != rv) {
plog_error(plugin, "neu_mqtt_client_close fail");
rv = NEU_ERR_EINTERNAL;
goto error;
}
}
rv = config_mqtt_client(plugin, plugin->mqtt_client, &config);
if (0 != rv) {
rv = NEU_ERR_MQTT_INIT_FAILURE;
goto error;
}
if (plugin->started && 0 != neu_mqtt_client_open(plugin->mqtt_client)) {
plog_error(plugin, "neu_mqtt_client_open fail");
rv = NEU_ERR_MQTT_CONNECT_FAILURE;
goto error;
}
if (plugin->started &&
0 != start_hearbeat_timer(plugin, config.heartbeat_interval)) {
plog_error(plugin, "start_hearbeat_timer fail");
rv = NEU_ERR_EINTERNAL;
goto error;
}
monitor_config_fini(plugin->config);
memmove(plugin->config, &config, sizeof(config));
// `config` moved, do not call monitor_config_fini
plog_notice(plugin, "config plugin `%s` success", plugin_name);
return 0;
error:
plog_error(plugin, "config plugin `%s` fail", plugin_name);
monitor_config_fini(&config);
return rv;
}
static int monitor_plugin_request(neu_plugin_t * plugin,
neu_reqresp_head_t *header, void *data)
{
(void) plugin;
switch (header->type) {
case NEU_RESP_ERROR: {
neu_resp_error_t *resp_err = (neu_resp_error_t *) data;
nlog_warn("recv error code: %d", resp_err->error);
break;
}
case NEU_RESP_GET_NODES_STATE: {
handle_nodes_state(header->ctx, (neu_resp_get_nodes_state_t *) data);
break;
}
case NEU_REQ_ADD_NODE_EVENT:
case NEU_REQ_DEL_NODE_EVENT:
case NEU_REQ_NODE_CTL_EVENT:
case NEU_REQ_NODE_SETTING_EVENT:
case NEU_REQ_ADD_GROUP_EVENT:
case NEU_REQ_DEL_GROUP_EVENT:
case NEU_REQ_UPDATE_GROUP_EVENT:
case NEU_REQ_ADD_TAG_EVENT:
case NEU_REQ_DEL_TAG_EVENT:
case NEU_REQ_UPDATE_TAG_EVENT:
case NEU_REQ_ADD_GTAG_EVENT:
case NEU_REQ_ADD_PLUGIN_EVENT:
case NEU_REQ_DEL_PLUGIN_EVENT:
case NEU_REQ_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UNSUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_SUBSCRIBE_GROUPS_EVENT: {
handle_events(plugin, header->type, data);
break;
}
default:
nlog_warn("recv unsupported msg: %s",
neu_reqresp_type_string(header->type));
break;
}
return 0;
}
static int monitor_plugin_start(neu_plugin_t *plugin)
{
int rv = 0;
const char *plugin_name = neu_plugin_module.module_name;
if (NULL == plugin->mqtt_client) {
plog_notice(plugin, "mqtt client is NULL");
goto end;
}
if (0 != neu_mqtt_client_open(plugin->mqtt_client)) {
plog_error(plugin, "neu_mqtt_client_open fail");
rv = NEU_ERR_MQTT_CONNECT_FAILURE;
goto end;
}
if (0 != start_hearbeat_timer(plugin, plugin->config->heartbeat_interval)) {
plog_error(plugin, "start_hearbeat_timer fail");
neu_mqtt_client_close(plugin->mqtt_client);
rv = NEU_ERR_EINTERNAL;
goto end;
}
end:
if (0 == rv) {
plugin->started = true;
plog_notice(plugin, "start plugin `%s` success", plugin_name);
} else {
plog_error(plugin, "start plugin `%s` failed, error %d", plugin_name,
rv);
}
return 0;
}
static int monitor_plugin_stop(neu_plugin_t *plugin)
{
if (plugin->mqtt_client) {
neu_mqtt_client_close(plugin->mqtt_client);
plog_notice(plugin, "mqtt client closed");
}
stop_heartbeart_timer(plugin);
plugin->started = false;
plog_notice(plugin, "stop plugin `%s` success",
neu_plugin_module.module_name);
return 0;
}
static const neu_plugin_intf_funs_t plugin_intf_funs = {
.open = monitor_plugin_open,
.close = monitor_plugin_close,
.init = monitor_plugin_init,
.uninit = monitor_plugin_uninit,
.start = monitor_plugin_start,
.stop = monitor_plugin_stop,
.setting = monitor_plugin_config,
.request = monitor_plugin_request,
};
#define DEFAULT_MONITOR_PLUGIN_DESCR \
"Builtin plugin for Neuron monitoring and alerting"
#define DEFAULT_MONITOR_PLUGIN_DESCR_ZH "内置监控与告警插件"
const neu_plugin_module_t neu_plugin_module = {
.version = NEURON_PLUGIN_VER_1_0,
.schema = "monitor",
.module_name = "Monitor",
.module_descr = DEFAULT_MONITOR_PLUGIN_DESCR,
.module_descr_zh = DEFAULT_MONITOR_PLUGIN_DESCR_ZH,
.intf_funs = &plugin_intf_funs,
.kind = NEU_PLUGIN_KIND_SYSTEM,
.type = NEU_NA_TYPE_APP,
.display = true,
.single = true,
.single_name = "monitor",
};
neu_plugin_t *neu_monitor_get_plugin()
{
return g_monitor_plugin_;
}
+45
View File
@@ -0,0 +1,45 @@
/**
* 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_MONITOR_H
#define NEU_PLUGIN_MONITOR_H
#include <pthread.h>
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>
#include "adapter.h"
#include "connection/mqtt_client.h"
#include "event/event.h"
#include "monitor_config.h"
#include "plugin.h"
struct neu_plugin {
neu_plugin_common_t common;
bool started;
neu_events_t * events;
neu_event_timer_t * heartbeat_timer;
monitor_config_t * config;
neu_mqtt_client_t * mqtt_client;
};
neu_plugin_t *neu_monitor_get_plugin();
#endif
+169
View File
@@ -0,0 +1,169 @@
{
"client-id": {
"name": "Client ID",
"name_zh": "客户端 ID",
"description": "MQTT client ID",
"description_zh": "MQTT 客户端 ID",
"type": "string",
"attribute": "required",
"default": "neuron_monitor_${random_str}",
"valid": {
"length": 255
}
},
"event-topic-prefix": {
"name": "Event Topic Prefix",
"name_zh": "事件主题前缀",
"description": "Prefix of the topics to which publish event messages.",
"description_zh": "事件消息发布的主题前缀",
"type": "string",
"attribute": "required",
"default": "/neuron/monitor/${random_str}",
"valid": {
"length": 255
}
},
"heartbeat-interval": {
"name": "Heartbeat Interval",
"name_zh": "心跳间隔",
"description": "Interval in seconds between two heartbeat messages. Setting to zero will disable heartbeat monitoring.(seconds)",
"description_zh": "每个心跳消息之间的间隔时间(秒),设置为 0 将禁用心跳消息。",
"attribute": "required",
"type": "int",
"default": 0,
"valid": {
"min": 0
}
},
"heartbeat-topic": {
"name": "Heartbeat Topic",
"name_zh": "心跳主题",
"description": "Topic to which publish heartbeat messages.",
"description_zh": "心跳消息发布的主题",
"type": "string",
"attribute": "required",
"default": "/neuron/heartbeat/${random_str}",
"valid": {
"length": 255
}
},
"host": {
"name": "Broker Host",
"name_zh": "服务器地址",
"description": "MQTT broker host",
"description_zh": "MQTT 服务器地址",
"attribute": "required",
"type": "string",
"default": "broker.emqx.io",
"valid": {
"length": 255
}
},
"port": {
"name": "Broker Port",
"name_zh": "服务器端口",
"description": "MQTT broker port",
"description_zh": "MQTT 服务器端口",
"attribute": "required",
"type": "int",
"default": 1883,
"valid": {
"min": 1024,
"max": 65535
}
},
"username": {
"name": "Username",
"name_zh": "用户名",
"description": "MQTT user name",
"description_zh": "MQTT 用户名",
"attribute": "optional",
"type": "string",
"default": "",
"valid": {
"length": 255
}
},
"password": {
"name": "Password",
"name_zh": "密码",
"description": "MQTT user password",
"description_zh": "MQTT 用户密码",
"attribute": "optional",
"type": "string",
"default": "",
"valid": {
"length": 255
}
},
"ssl": {
"name": "SSL",
"name_zh": "SSL",
"description": "Enable SSL connection",
"description_zh": "是否启用 SSL 连接",
"attribute": "optional",
"type": "bool",
"default": false,
"valid": {}
},
"ca": {
"name": "CA",
"name_zh": "CA 证书",
"description": "CA certificate which signs the server certificate",
"description_zh": "签发服务器证书的 CA 证书",
"attribute": "optional",
"type": "file",
"condition": {
"field": "ssl",
"value": true
},
"valid": {
"length": 81960
}
},
"cert": {
"name": "Client Cert",
"name_zh": "客户端证书",
"description": "Client x509 certificate when using two way authentication",
"description_zh": "使用双向认证时,客户端的 x509 证书",
"attribute": "optional",
"type": "file",
"condition": {
"field": "ssl",
"value": true
},
"valid": {
"length": 81960
}
},
"key": {
"name": "Client Private Key",
"name_zh": "客户端私钥",
"description": "Client private key when using two way authentication",
"description_zh": "使用双向认证时,客户端的私钥",
"attribute": "optional",
"type": "file",
"condition": {
"field": "ssl",
"value": true
},
"valid": {
"length": 81960
}
},
"keypass": {
"name": "Client Private Key Password",
"name_zh": "客户端私钥密码",
"description": "Client private key password when using two way authentication with an encrypted client private key",
"description_zh": "使用加密的客户端私钥进行双向认证时,客户端私钥的密码",
"attribute": "optional",
"type": "string",
"condition": {
"field": "ssl",
"value": true
},
"valid": {
"length": 256
}
}
}
+482
View File
@@ -0,0 +1,482 @@
/**
* 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 "json/json.h"
#include "json/neu_json_param.h"
#include "utils/asprintf.h"
#include "utils/base64.h"
#include "utils/log.h"
#include "monitor.h"
#include "monitor_config.h"
#define MB 1000000
static inline int decode_b64_param(neu_plugin_t *plugin, neu_json_elem_t *el)
{
int len = 0;
char *s = (char *) neu_decode64(&len, el->v.val_str);
if (NULL == s) {
plog_error(plugin, "setting %s invalid base64", el->name);
return -1;
}
if (0 == len) {
plog_error(plugin, "setting empty %s", el->name);
free(s);
return -1;
}
free(el->v.val_str);
el->v.val_str = s;
return 0;
}
static inline int parse_b64_param(neu_plugin_t *plugin, const char *setting,
neu_json_elem_t *el)
{
if (0 != neu_parse_param(setting, NULL, 1, el)) {
plog_error(plugin, "setting no %s", el->name);
return -1;
}
if (0 != decode_b64_param(plugin, el)) {
free(el->v.val_str);
el->v.val_str = NULL;
return -1;
}
return 0;
}
static inline int parse_ssl_params(neu_plugin_t *plugin, const char *setting,
neu_json_elem_t *ssl, neu_json_elem_t *ca,
neu_json_elem_t *cert, neu_json_elem_t *key,
neu_json_elem_t *keypass)
{
// ssl, optional
int ret = neu_parse_param(setting, NULL, 1, ssl);
if (0 != ret) {
plog_notice(plugin, "setting no ssl");
return 0;
}
if (false == ssl->v.val_bool) {
plog_notice(plugin, "setting ssl disabled");
return 0;
}
// ca, optional
ret = neu_parse_param(setting, NULL, 1, ca);
if (0 != ret) {
plog_notice(plugin, "setting no ca");
return 0;
}
if (0 != decode_b64_param(plugin, ca)) {
return -1;
}
// cert, optional
ret = neu_parse_param(setting, NULL, 1, cert);
if (0 != ret) {
plog_notice(plugin, "setting no cert");
return 0;
}
if (0 != decode_b64_param(plugin, cert)) {
return -1;
}
// key, required if cert enable
ret = parse_b64_param(plugin, setting, key);
if (0 != ret) {
return -1;
}
// keypass, optional
ret = neu_parse_param(setting, NULL, 1, keypass);
if (0 != ret) {
plog_notice(plugin, "setting no keypass");
} else if (0 == strlen(keypass->v.val_str)) {
plog_error(plugin, "setting invalid keypass");
return -1;
}
return 0;
}
static int make_event_topics(monitor_config_t *config, const char *prefix)
{
char *node_add_topic = NULL;
char *node_del_topic = NULL;
char *node_ctl_topic = NULL;
char *node_setting_topic = NULL;
char *group_add_topic = NULL;
char *group_del_topic = NULL;
char *group_update_topic = NULL;
char *tag_add_topic = NULL;
char *tag_del_topic = NULL;
char *tag_update_topic = NULL;
char *gtag_add_topic = NULL;
char *plugin_add_topic = NULL;
char *plugin_del_topic = NULL;
char *group_subscribe_topic = NULL;
char *group_unsubscribe_topic = NULL;
char *group_update_subscribe_topic = NULL;
char *groups_subscribe_topic = NULL;
neu_asprintf(&node_add_topic, "%s/node/add", prefix);
if (NULL == node_add_topic) {
goto error;
}
neu_asprintf(&node_del_topic, "%s/node/delete", prefix);
if (NULL == node_del_topic) {
goto error;
}
neu_asprintf(&node_ctl_topic, "%s/node/ctl", prefix);
if (NULL == node_ctl_topic) {
goto error;
}
neu_asprintf(&node_setting_topic, "%s/node/setting", prefix);
if (NULL == node_setting_topic) {
goto error;
}
neu_asprintf(&group_add_topic, "%s/group/add", prefix);
if (NULL == group_add_topic) {
goto error;
}
neu_asprintf(&group_del_topic, "%s/group/delete", prefix);
if (NULL == group_del_topic) {
goto error;
}
neu_asprintf(&group_update_topic, "%s/group/update", prefix);
if (NULL == group_update_topic) {
goto error;
}
neu_asprintf(&tag_add_topic, "%s/tag/add", prefix);
if (NULL == tag_add_topic) {
goto error;
}
neu_asprintf(&tag_del_topic, "%s/tag/delete", prefix);
if (NULL == tag_del_topic) {
goto error;
}
neu_asprintf(&tag_update_topic, "%s/tag/update", prefix);
if (NULL == tag_update_topic) {
goto error;
}
neu_asprintf(&gtag_add_topic, "%s/gtag/add", prefix);
if (NULL == gtag_add_topic) {
goto error;
}
neu_asprintf(&plugin_add_topic, "%s/plugin/add", prefix);
if (NULL == plugin_add_topic) {
goto error;
}
neu_asprintf(&plugin_del_topic, "%s/plugin/delete", prefix);
if (NULL == plugin_del_topic) {
goto error;
}
neu_asprintf(&group_subscribe_topic, "%s/group/subscribe", prefix);
if (NULL == group_subscribe_topic) {
goto error;
}
neu_asprintf(&group_unsubscribe_topic, "%s/group/unsubscribe", prefix);
if (NULL == group_unsubscribe_topic) {
goto error;
}
neu_asprintf(&group_update_subscribe_topic, "%s/group/update/subscribe",
prefix);
if (NULL == group_update_subscribe_topic) {
goto error;
}
neu_asprintf(&groups_subscribe_topic, "%s/groups/subscribe", prefix);
if (NULL == groups_subscribe_topic) {
goto error;
}
config->node_add_topic = node_add_topic;
config->node_del_topic = node_del_topic;
config->node_ctl_topic = node_ctl_topic;
config->node_setting_topic = node_setting_topic;
config->group_add_topic = group_add_topic;
config->group_del_topic = group_del_topic;
config->group_update_topic = group_update_topic;
config->tag_add_topic = tag_add_topic;
config->tag_del_topic = tag_del_topic;
config->tag_update_topic = tag_update_topic;
config->gtag_add_topic = gtag_add_topic;
config->plugin_add_topic = plugin_add_topic;
config->plugin_del_topic = plugin_del_topic;
config->group_subscribe_topic = group_subscribe_topic;
config->group_unsubscribe_topic = group_unsubscribe_topic;
config->group_update_subscribe_topic = group_update_subscribe_topic;
config->groups_subscribe_topic = groups_subscribe_topic;
return 0;
error:
free(groups_subscribe_topic);
free(group_update_subscribe_topic);
free(group_unsubscribe_topic);
free(group_subscribe_topic);
free(plugin_del_topic);
free(plugin_add_topic);
free(gtag_add_topic);
free(tag_update_topic);
free(tag_del_topic);
free(tag_add_topic);
free(group_update_topic);
free(group_del_topic);
free(group_add_topic);
free(node_setting_topic);
free(node_ctl_topic);
free(node_del_topic);
free(node_add_topic);
return -1;
}
int monitor_config_parse(neu_plugin_t *plugin, const char *setting,
monitor_config_t *config)
{
int ret = 0;
char * err_param = NULL;
const char *placeholder = "********";
neu_json_elem_t client_id = { .name = "client-id", .t = NEU_JSON_STR };
neu_json_elem_t event_topic_prefix = { .name = "event-topic-prefix",
.t = NEU_JSON_STR };
neu_json_elem_t heartbeat_interval = { .name = "heartbeat-interval",
.t = NEU_JSON_INT };
neu_json_elem_t heartbeat_topic = { .name = "heartbeat-topic",
.t = NEU_JSON_STR };
neu_json_elem_t host = { .name = "host", .t = NEU_JSON_STR };
neu_json_elem_t port = { .name = "port", .t = NEU_JSON_INT };
neu_json_elem_t username = { .name = "username", .t = NEU_JSON_STR };
neu_json_elem_t password = { .name = "password", .t = NEU_JSON_STR };
neu_json_elem_t ssl = { .name = "ssl", .t = NEU_JSON_BOOL };
neu_json_elem_t ca = { .name = "ca", .t = NEU_JSON_STR };
neu_json_elem_t cert = { .name = "cert", .t = NEU_JSON_STR };
neu_json_elem_t key = { .name = "key", .t = NEU_JSON_STR };
neu_json_elem_t keypass = { .name = "keypass", .t = NEU_JSON_STR };
if (NULL == setting || NULL == config) {
plog_error(plugin, "invalid argument, null pointer");
return -1;
}
ret =
neu_parse_param(setting, &err_param, 6, &client_id, &event_topic_prefix,
&heartbeat_interval, &heartbeat_topic, &host, &port);
if (0 != ret) {
plog_error(plugin, "parsing setting fail, key: `%s`", err_param);
goto error;
}
// client-id, required
if (0 == strlen(client_id.v.val_str)) {
plog_error(plugin, "setting empty client-id");
goto error;
}
// heartbeat-interval, required
if (0 > heartbeat_interval.v.val_int) {
plog_error(plugin, "setting negative heartbeat-interval:%" PRIi64,
heartbeat_interval.v.val_int);
goto error;
}
// heartbeat-topic, required
if (0 == strlen(heartbeat_topic.v.val_str)) {
plog_error(plugin, "setting empty heartbeat-topic");
goto error;
}
// host, required
if (0 == strlen(host.v.val_str)) {
plog_error(plugin, "setting invalid host: `%s`", host.v.val_str);
goto error;
}
// port, required
if (0 == port.v.val_int || port.v.val_int > 65535) {
plog_error(plugin, "setting invalid port: %" PRIi64, port.v.val_int);
goto error;
}
// username, optional
ret = neu_parse_param(setting, NULL, 1, &username);
if (0 != ret) {
plog_notice(plugin, "setting no username");
}
// password, optional
ret = neu_parse_param(setting, NULL, 1, &password);
if (0 != ret) {
plog_notice(plugin, "setting no password");
}
ret = parse_ssl_params(plugin, setting, &ssl, &ca, &cert, &key, &keypass);
if (0 != ret) {
goto error;
}
ret = make_event_topics(config, event_topic_prefix.v.val_str);
if (0 != ret) {
plog_error(plugin, "make event topics fail");
goto error;
}
config->client_id = client_id.v.val_str;
config->event_topic_prefix = event_topic_prefix.v.val_str;
config->heartbeat_interval = heartbeat_interval.v.val_int;
config->heartbeat_topic = heartbeat_topic.v.val_str;
config->host = host.v.val_str;
config->port = port.v.val_int;
config->username = username.v.val_str;
config->password = password.v.val_str;
config->ssl = ssl.v.val_bool;
config->ca = ca.v.val_str;
config->cert = cert.v.val_str;
config->key = key.v.val_str;
config->keypass = keypass.v.val_str;
plog_notice(plugin, "config client-id : %s", config->client_id);
plog_notice(plugin, "config event-topic-prefix: %s",
config->event_topic_prefix);
plog_notice(plugin, "config heartbeat-interval: %" PRIu64,
config->heartbeat_interval);
plog_notice(plugin, "config heartbeat-topic : %s",
config->heartbeat_topic);
plog_notice(plugin, "config host : %s", config->host);
plog_notice(plugin, "config port : %" PRIu16, config->port);
if (config->username) {
plog_notice(plugin, "config username : %s", config->username);
}
if (config->password) {
plog_notice(plugin, "config password : %s",
0 == strlen(config->password) ? "" : placeholder);
}
plog_notice(plugin, "config ssl : %d", config->ssl);
if (config->ca) {
plog_notice(plugin, "config ca : %s", placeholder);
}
if (config->cert) {
plog_notice(plugin, "config cert : %s", placeholder);
}
if (config->key) {
plog_notice(plugin, "config key : %s", placeholder);
}
if (config->keypass) {
plog_notice(plugin, "config keypass : %s", placeholder);
}
plog_notice(plugin, "node add event topic : %s",
config->node_add_topic);
plog_notice(plugin, "node del event topic : %s",
config->node_del_topic);
plog_notice(plugin, "node ctl event topic : %s",
config->node_ctl_topic);
plog_notice(plugin, "node setting event topic : %s",
config->node_setting_topic);
plog_notice(plugin, "group add topic : %s",
config->group_add_topic);
plog_notice(plugin, "group del topic : %s",
config->group_del_topic);
plog_notice(plugin, "group update topic : %s",
config->group_update_topic);
plog_notice(plugin, "tag add topic : %s", config->tag_add_topic);
plog_notice(plugin, "tag del topic : %s", config->tag_del_topic);
plog_notice(plugin, "tag update topic : %s",
config->tag_update_topic);
return 0;
error:
free(err_param);
free(event_topic_prefix.v.val_str);
free(heartbeat_topic.v.val_str);
free(host.v.val_str);
free(username.v.val_str);
free(password.v.val_str);
free(ca.v.val_str);
free(cert.v.val_str);
free(key.v.val_str);
free(keypass.v.val_str);
return -1;
}
void monitor_config_fini(monitor_config_t *config)
{
if (NULL == config) {
return;
}
free(config->client_id);
free(config->event_topic_prefix);
free(config->heartbeat_topic);
free(config->host);
free(config->username);
free(config->password);
free(config->ca);
free(config->cert);
free(config->key);
free(config->keypass);
free(config->node_add_topic);
free(config->node_del_topic);
free(config->node_ctl_topic);
free(config->node_setting_topic);
free(config->group_add_topic);
free(config->group_del_topic);
free(config->group_update_topic);
free(config->tag_add_topic);
free(config->tag_del_topic);
free(config->tag_update_topic);
free(config->groups_subscribe_topic);
free(config->group_update_subscribe_topic);
free(config->group_unsubscribe_topic);
free(config->group_subscribe_topic);
free(config->plugin_del_topic);
free(config->plugin_add_topic);
free(config->gtag_add_topic);
memset(config, 0, sizeof(*config));
}
+75
View File
@@ -0,0 +1,75 @@
/**
* 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 NEURON_PLUGIN_MONITOR_CONFIG_H
#define NEURON_PLUGIN_MONITOR_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdlib.h>
#include "plugin.h"
typedef struct {
char * client_id; // client id
char * event_topic_prefix; // event topic prefix
uint64_t heartbeat_interval; // heartbeat interval
char * heartbeat_topic; // heartbeat topic
char * host; // broker host
uint16_t port; // broker port
char * username; // user name
char * password; // user password
bool ssl; // ssl flag
char * ca; // CA
char * cert; // client cert
char * key; // client key
char * keypass; // client key password
// event topics generated according to event_topic_prefix
char *node_add_topic;
char *node_del_topic;
char *node_ctl_topic;
char *node_setting_topic;
char *group_add_topic;
char *group_del_topic;
char *group_update_topic;
char *tag_add_topic;
char *tag_del_topic;
char *tag_update_topic;
char *gtag_add_topic;
char *plugin_add_topic;
char *plugin_del_topic;
char *group_subscribe_topic;
char *group_unsubscribe_topic;
char *group_update_subscribe_topic;
char *groups_subscribe_topic;
} monitor_config_t;
int monitor_config_parse(neu_plugin_t *plugin, const char *setting,
monitor_config_t *config);
void monitor_config_fini(monitor_config_t *config);
#ifdef __cplusplus
}
#endif
#endif
+439
View File
@@ -0,0 +1,439 @@
/**
* 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 "connection/mqtt_client.h"
#include "errcodes.h"
#include "version.h"
#include "json/neu_json_mqtt.h"
#include "json/neu_json_rw.h"
#include "parser/neu_json_group_config.h"
#include "parser/neu_json_node.h"
#include "parser/neu_json_plugin.h"
#include "parser/neu_json_tag.h"
#include "monitor.h"
#include "mqtt_handle.h"
static char *generate_heartbeat_json(neu_plugin_t *plugin, UT_array *states)
{
(void) plugin;
char * version = NEURON_VERSION;
neu_json_states_head_t header = { .version = version,
.timpstamp = global_timestamp };
neu_json_states_t json = { 0 };
char * json_str = NULL;
json.n_state = utarray_len(states);
json.states = calloc(json.n_state, sizeof(neu_json_node_state_t));
if (NULL == json.states) {
return NULL;
}
utarray_foreach(states, neu_nodes_state_t *, state)
{
int index = utarray_eltidx(states, state);
json.states[index].node = state->node;
json.states[index].link = state->state.link;
json.states[index].running = state->state.running;
}
neu_json_encode_with_mqtt(&json, neu_json_encode_states_resp, &header,
neu_json_encode_state_header_resp, &json_str);
free(json.states);
return json_str;
}
static char *generate_event_json(neu_plugin_t *plugin, neu_reqresp_type_e event,
void *data, char **topic_p)
{
char *json_str = NULL;
union {
neu_json_add_node_req_t add_node;
neu_json_del_node_req_t del_node;
neu_json_node_ctl_req_t node_ctl;
neu_json_node_setting_req_t node_setting;
neu_json_add_group_config_req_t add_grp;
neu_json_del_group_config_req_t del_grp;
neu_json_update_group_config_req_t update_grp;
neu_json_add_tags_req_t add_tags;
neu_json_del_tags_req_t del_tags;
neu_json_subscribe_req_t sub_grp;
neu_json_unsubscribe_req_t unsub_grp;
neu_json_subscribe_groups_req_t sub_grps;
neu_json_add_plugin_req_t add_plugin;
neu_json_del_plugin_req_t del_plugin;
neu_json_add_gtags_req_t add_gtag;
} json_req = {};
switch (event) {
case NEU_REQ_ADD_NODE_EVENT: {
neu_req_add_node_t *add_node = data;
json_req.add_node.name = add_node->node;
json_req.add_node.plugin = add_node->plugin;
*topic_p = plugin->config->node_add_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_add_node_req,
&json_str);
break;
}
case NEU_REQ_DEL_NODE_EVENT: {
neu_req_del_node_t *del_node = data;
json_req.del_node.name = del_node->node;
*topic_p = plugin->config->node_del_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_del_node_req,
&json_str);
break;
}
case NEU_REQ_NODE_CTL_EVENT: {
neu_req_node_ctl_t *node_ctl = data;
json_req.node_ctl.node = node_ctl->node;
json_req.node_ctl.cmd = node_ctl->ctl;
*topic_p = plugin->config->node_ctl_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_node_ctl_req,
&json_str);
break;
}
case NEU_REQ_NODE_SETTING_EVENT: {
neu_req_node_setting_t *node_setting = data;
json_req.node_setting.node = node_setting->node;
json_req.node_setting.setting = node_setting->setting;
*topic_p = plugin->config->node_setting_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_node_setting_req,
&json_str);
break;
}
case NEU_REQ_ADD_GROUP_EVENT: {
neu_req_add_group_t *add_grp = data;
json_req.add_grp.node = add_grp->driver;
json_req.add_grp.group = add_grp->group;
json_req.add_grp.interval = add_grp->interval;
*topic_p = plugin->config->group_add_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_add_group_config_req,
&json_str);
break;
}
case NEU_REQ_DEL_GROUP_EVENT: {
neu_req_del_group_t *del_grp = data;
json_req.del_grp.node = del_grp->driver;
json_req.del_grp.group = del_grp->group;
*topic_p = plugin->config->group_del_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_del_group_config_req,
&json_str);
break;
}
case NEU_REQ_UPDATE_GROUP_EVENT: {
neu_req_update_group_t *update_grp = data;
json_req.update_grp.node = update_grp->driver;
json_req.update_grp.group = update_grp->group;
json_req.update_grp.new_name = update_grp->new_name;
json_req.update_grp.set_interval =
update_grp->interval >= NEU_GROUP_INTERVAL_LIMIT;
json_req.update_grp.interval = update_grp->interval;
*topic_p = plugin->config->group_update_topic;
neu_json_encode_by_fn(
&json_req, neu_json_encode_update_group_config_req, &json_str);
break;
}
case NEU_REQ_ADD_TAG_EVENT:
case NEU_REQ_UPDATE_TAG_EVENT: {
neu_req_add_tag_t *add_tag = data;
json_req.add_tags.node = add_tag->driver;
json_req.add_tags.group = add_tag->group;
json_req.add_tags.n_tag = add_tag->n_tag;
json_req.add_tags.tags =
calloc(add_tag->n_tag, sizeof(*json_req.add_tags.tags));
if (NULL == json_req.add_tags.tags) {
plog_error(plugin, "calloc fail");
break;
}
for (uint16_t i = 0; i < add_tag->n_tag; ++i) {
json_req.add_tags.tags[i].type = add_tag->tags[i].type;
json_req.add_tags.tags[i].name = add_tag->tags[i].name;
json_req.add_tags.tags[i].attribute = add_tag->tags[i].attribute;
json_req.add_tags.tags[i].address = add_tag->tags[i].address;
json_req.add_tags.tags[i].decimal = add_tag->tags[i].decimal;
json_req.add_tags.tags[i].precision = add_tag->tags[i].precision;
json_req.add_tags.tags[i].description =
add_tag->tags[i].description;
json_req.add_tags.tags[i].t = NEU_JSON_UNDEFINE;
}
*topic_p = NEU_REQ_ADD_TAG_EVENT == event
? plugin->config->tag_add_topic
: plugin->config->tag_update_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_add_tags_req,
&json_str);
free(json_req.add_tags.tags);
break;
}
case NEU_REQ_DEL_TAG_EVENT: {
neu_req_del_tag_t *del_tag = data;
json_req.del_tags.node = del_tag->driver;
json_req.del_tags.group = del_tag->group;
json_req.del_tags.n_tags = del_tag->n_tag;
json_req.del_tags.tags =
calloc(del_tag->n_tag, sizeof(*json_req.del_tags.tags));
if (NULL == json_req.del_tags.tags) {
plog_error(plugin, "calloc fail");
break;
}
for (uint16_t i = 0; i < del_tag->n_tag; ++i) {
json_req.del_tags.tags[i] = del_tag->tags[i];
}
*topic_p = plugin->config->tag_del_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_del_tags_req,
&json_str);
free(json_req.del_tags.tags);
break;
}
case NEU_REQ_ADD_GTAG_EVENT: {
neu_req_add_gtag_t *add_gtag = data;
json_req.add_gtag.node = add_gtag->driver;
json_req.add_gtag.n_group = add_gtag->n_group;
json_req.add_gtag.groups =
calloc(add_gtag->n_group, sizeof(*json_req.add_gtag.groups));
for (u_int16_t i = 0; i < add_gtag->n_group; i++) {
json_req.add_gtag.groups[i].group =
strdup(add_gtag->groups[i].group);
json_req.add_gtag.groups[i].n_tag = add_gtag->groups[i].n_tag;
json_req.add_gtag.groups[i].interval = add_gtag->groups[i].interval;
json_req.add_gtag.groups[i].tags =
calloc(add_gtag->groups[i].n_tag,
sizeof(*json_req.add_gtag.groups->tags));
for (u_int16_t j = 0; j < add_gtag->groups[i].n_tag; j++) {
json_req.add_gtag.groups[i].tags[j].type =
add_gtag->groups[i].tags[j].type;
json_req.add_gtag.groups[i].tags[j].name =
add_gtag->groups[i].tags[j].name;
json_req.add_gtag.groups[i].tags[j].attribute =
add_gtag->groups[i].tags[j].attribute;
json_req.add_gtag.groups[i].tags[j].address =
add_gtag->groups[i].tags[j].address;
json_req.add_gtag.groups[i].tags[j].decimal =
add_gtag->groups[i].tags[j].decimal;
json_req.add_gtag.groups[i].tags[j].precision =
add_gtag->groups[i].tags[j].precision;
json_req.add_gtag.groups[i].tags[j].description =
add_gtag->groups[i].tags[j].description;
}
}
*topic_p = plugin->config->gtag_add_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_add_gtags_req,
&json_str);
free(json_req.add_tags.tags);
break;
}
case NEU_REQ_ADD_PLUGIN_EVENT: {
neu_req_add_plugin_t *add_plugin = data;
json_req.add_plugin.library = add_plugin->library;
json_req.add_plugin.schema_file = add_plugin->schema_file;
json_req.add_plugin.so_file = add_plugin->so_file;
*topic_p = plugin->config->plugin_add_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_add_plugin_req,
&json_str);
break;
}
case NEU_REQ_DEL_PLUGIN_EVENT: {
neu_req_del_plugin_t *del_plugin = data;
json_req.del_plugin.plugin = del_plugin->plugin;
*topic_p = plugin->config->plugin_del_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_del_plugin_req,
&json_str);
break;
}
case NEU_REQ_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT: {
neu_req_subscribe_t *subscribe_grp = data;
json_req.sub_grp.group = subscribe_grp->group;
json_req.sub_grp.app = subscribe_grp->app;
json_req.sub_grp.driver = subscribe_grp->driver;
json_req.sub_grp.params = subscribe_grp->params;
*topic_p = NEU_REQ_SUBSCRIBE_GROUP_EVENT == event
? plugin->config->group_subscribe_topic
: plugin->config->group_update_subscribe_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_subscribe_req,
&json_str);
break;
}
case NEU_REQ_UNSUBSCRIBE_GROUP_EVENT: {
neu_req_unsubscribe_t *unsubscribe_grp = data;
json_req.unsub_grp.group = unsubscribe_grp->group;
json_req.unsub_grp.app = unsubscribe_grp->app;
json_req.unsub_grp.driver = unsubscribe_grp->driver;
*topic_p = plugin->config->group_unsubscribe_topic;
neu_json_encode_by_fn(&json_req, neu_json_encode_unsubscribe_req,
&json_str);
break;
}
case NEU_REQ_SUBSCRIBE_GROUPS_EVENT: {
break;
}
default: {
plog_error(plugin, "unsupported event:%s",
neu_reqresp_type_string(event));
return NULL;
}
}
return json_str;
}
static void publish_cb(int errcode, neu_mqtt_qos_e qos, char *topic,
uint8_t *payload, uint32_t len, void *data)
{
(void) qos;
(void) topic;
(void) len;
neu_plugin_t *plugin = data;
neu_adapter_update_metric_cb_t update_metric =
plugin->common.adapter_callbacks->update_metric;
if (0 == errcode) {
update_metric(plugin->common.adapter, NEU_METRIC_SEND_MSGS_TOTAL, 1,
NULL);
} else {
update_metric(plugin->common.adapter, NEU_METRIC_SEND_MSG_ERRORS_TOTAL,
1, NULL);
}
free(payload);
}
static inline int publish(neu_plugin_t *plugin, neu_mqtt_qos_e qos, char *topic,
char *payload, size_t payload_len)
{
neu_adapter_update_metric_cb_t update_metric =
plugin->common.adapter_callbacks->update_metric;
int rv = neu_mqtt_client_publish(
plugin->mqtt_client, qos, topic, (uint8_t *) payload,
(uint32_t) payload_len, plugin, publish_cb);
if (0 != rv) {
plog_error(plugin, "pub [%s, QoS%d] fail", topic, qos);
update_metric(plugin->common.adapter, NEU_METRIC_SEND_MSG_ERRORS_TOTAL,
1, NULL);
free(payload);
rv = NEU_ERR_MQTT_PUBLISH_FAILURE;
}
return rv;
}
int handle_nodes_state(neu_plugin_t *plugin, neu_reqresp_nodes_state_t *states)
{
int rv = 0;
char *json_str = NULL;
if (NULL == plugin->mqtt_client) {
rv = NEU_ERR_MQTT_IS_NULL;
goto end;
}
if (!neu_mqtt_client_is_connected(plugin->mqtt_client)) {
// cache disable and we are disconnected
rv = NEU_ERR_MQTT_FAILURE;
goto end;
}
json_str = generate_heartbeat_json(plugin, states->states);
if (NULL == json_str) {
plog_error(plugin, "generate heartbeat json fail");
rv = NEU_ERR_EINTERNAL;
goto end;
}
char * topic = plugin->config->heartbeat_topic;
neu_mqtt_qos_e qos = NEU_MQTT_QOS0;
rv = publish(plugin, qos, topic, json_str, strlen(json_str));
json_str = NULL;
end:
utarray_free(states->states);
return rv;
}
int handle_events(neu_plugin_t *plugin, neu_reqresp_type_e event, void *data)
{
int rv = 0;
char *json_str = NULL;
char *topic = NULL;
if (NULL == plugin->mqtt_client) {
rv = NEU_ERR_MQTT_IS_NULL;
goto end;
}
if (!neu_mqtt_client_is_connected(plugin->mqtt_client)) {
// cache disable and we are disconnected
rv = NEU_ERR_MQTT_FAILURE;
goto end;
}
json_str = generate_event_json(plugin, event, data, &topic);
if (NULL == json_str) {
plog_error(plugin, "generate event:%s json fail",
neu_reqresp_type_string(event));
rv = NEU_ERR_EINTERNAL;
goto end;
}
neu_mqtt_qos_e qos = NEU_MQTT_QOS0;
rv = publish(plugin, qos, topic, json_str, strlen(json_str));
json_str = NULL;
end:
switch (event) {
case NEU_REQ_NODE_SETTING_EVENT:
neu_req_node_setting_fini(data);
break;
case NEU_REQ_ADD_TAG_EVENT:
case NEU_REQ_UPDATE_TAG_EVENT:
neu_req_add_tag_fini(data);
break;
case NEU_REQ_DEL_TAG_EVENT:
neu_req_del_tag_fini(data);
break;
case NEU_REQ_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT:
break;
case NEU_REQ_SUBSCRIBE_GROUPS_EVENT:
neu_req_subscribe_groups_fini(data);
break;
case NEU_REQ_ADD_GTAG_EVENT: {
neu_req_add_gtag_t *add_gtag = data;
for (int i = 0; i < add_gtag->n_group; i++) {
for (int j = 0; j < add_gtag->groups[i].n_tag; j++) {
neu_tag_fini(&add_gtag->groups[i].tags[j]);
}
free(add_gtag->groups[i].tags);
}
free(add_gtag->groups);
break;
}
default:
break;
}
return rv;
}
+37
View File
@@ -0,0 +1,37 @@
/**
* 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 NEURON_PLUGIN_MONITOR_MQTT_HANDLE_H
#define NEURON_PLUGIN_MONITOR_MQTT_HANDLE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "neuron.h"
int handle_nodes_state(neu_plugin_t *plugin, neu_reqresp_nodes_state_t *states);
int handle_events(neu_plugin_t *plugin, neu_reqresp_type_e event, void *data);
#ifdef __cplusplus
}
#endif
#endif
+1 -1
View File
@@ -62,7 +62,7 @@ static int start_hearbeat_timer(neu_plugin_t *plugin, uint64_t interval)
}
if (NULL == plugin->events) {
plugin->events = neu_event_new();
plugin->events = neu_event_new(plugin->common.name);
if (NULL == plugin->events) {
plog_error(plugin, "neu_event_new fail");
return NEU_ERR_EINTERNAL;
+35
View File
@@ -44,6 +44,8 @@ void handle_add_adapter(nng_aio *aio)
aio, neu_json_add_node_req_t, neu_json_decode_add_node_req, {
if (strlen(req->name) >= NEU_NODE_NAME_LEN) {
CHECK_NODE_NAME_LENGTH_ERR;
} else if (strcmp(req->name, "monitor") == 0) {
CHECK_NODE_MONITOR_ERR;
} else {
int ret = 0;
neu_reqresp_head_t header = { 0 };
@@ -84,6 +86,11 @@ static inline int send_node_update_req(nng_aio * aio,
return NEU_ERR_NODE_NAME_EMPTY;
}
if (strcmp(req->new_name, "monitor") == 0 ||
strcmp(req->name, "monitor") == 0) {
return NEU_ERR_NODE_NOT_ALLOW_UPDATE;
}
neu_req_update_node_t cmd = { 0 };
strcpy(cmd.node, req->name);
strcpy(cmd.new_name, req->new_name);
@@ -145,6 +152,7 @@ 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 };
neu_plugin_t * plugin = neu_rest_get_plugin();
neu_node_type_e node_type = { 0 };
@@ -173,6 +181,33 @@ void handle_get_adapter(nng_aio *aio)
strcpy(cmd.node, node_name);
}
if (neu_http_get_param_str(aio, "group", group_name, sizeof(group_name)) >
0) {
strcpy(cmd.query.q_group_name, group_name);
}
uintmax_t query_state = 0;
if (neu_http_get_param_uintmax(aio, "state", &query_state) == 0) {
if (query_state == 1 || query_state == 2 || query_state == 3 ||
query_state == 4) {
cmd.query.q_state = true;
cmd.query.state = (int) query_state;
}
}
uintmax_t query_link = 0;
if (neu_http_get_param_uintmax(aio, "link", &query_link) == 0) {
if (query_link == 0 || query_link == 1) {
cmd.query.q_link = true;
cmd.query.link = (int) query_link;
}
}
uintmax_t sort_delay = 0;
if (neu_http_get_param_uintmax(aio, "delay", &sort_delay) == 0) {
cmd.query.s_delay = true;
}
cmd.type = node_type;
ret = neu_plugin_op(plugin, header, &cmd);
if (ret != 0) {
+1 -3
View File
@@ -120,9 +120,7 @@ static int add_setting(context_t *ctx, neu_json_node_setting_req_t *data);
static inline bool is_static_node(const char *name, const char *plugin)
{
(void) name;
(void) plugin;
return false;
return 0 == strcmp("monitor", name) && 0 == strcmp("Monitor", plugin);
}
static context_t *context_new(nng_aio *aio, context_type_e t)
+126 -7
View File
@@ -160,11 +160,12 @@ void handle_del_group_config(nng_aio *aio)
void handle_get_group_config(nng_aio *aio)
{
neu_plugin_t * plugin = neu_rest_get_plugin();
char node_name[NEU_NODE_NAME_LEN] = { 0 };
int ret = 0;
neu_req_get_group_t cmd = { 0 };
neu_reqresp_head_t header = {
neu_plugin_t * plugin = neu_rest_get_plugin();
char node_name[NEU_NODE_NAME_LEN] = { 0 };
char group_name[NEU_GROUP_NAME_LEN] = { 0 };
int ret = 0;
neu_req_get_group_t cmd = { 0 };
neu_reqresp_head_t header = {
.ctx = aio,
.type = NEU_REQ_GET_GROUP,
.otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM,
@@ -178,6 +179,11 @@ void handle_get_group_config(nng_aio *aio)
header.type = NEU_REQ_GET_DRIVER_GROUP;
}
if (neu_http_get_param_str(aio, "group", group_name, sizeof(group_name)) >
0) {
strcpy(cmd.q_group, group_name);
}
ret = neu_plugin_op(plugin, header, &cmd);
if (ret != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, {
@@ -400,10 +406,16 @@ void handle_grp_subscribes(nng_aio *aio)
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
aio, neu_json_subscribe_groups_req_t,
neu_json_decode_subscribe_groups_req, {
int ret = send_subscribe_groups(aio, req);
if (0 != ret) {
int ret = 0;
if (req->n_group == 0) {
NEU_JSON_RESPONSE_ERROR(
ret, { neu_http_response(aio, ret, result_error); });
} else {
ret = send_subscribe_groups(aio, req);
if (0 != ret) {
NEU_JSON_RESPONSE_ERROR(
ret, { neu_http_response(aio, ret, result_error); });
}
}
})
}
@@ -482,4 +494,111 @@ void handle_grp_get_subscribe_resp(nng_aio * aio,
free(result);
free(sub_grp_configs.groups);
utarray_free(groups->groups);
}
void handle_grp_get_subscribes(nng_aio *aio)
{
int ret = 0;
neu_plugin_t * plugin = neu_rest_get_plugin();
neu_req_get_driver_subscribe_group_t cmd = { 0 };
neu_reqresp_head_t header = {
.ctx = aio,
.type = NEU_REQ_GET_DRIVER_SUBSCRIBE_GROUP,
.otel_trace_type = NEU_OTEL_TRACE_TYPE_REST_COMM,
};
NEU_VALIDATE_JWT(aio);
// required parameter
ret = neu_http_get_param_str(aio, "app", cmd.app, sizeof(cmd.app));
if (ret <= 0) {
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, "name", cmd.name, sizeof(cmd.name));
if (-1 == ret || (size_t) ret == sizeof(cmd.name)) {
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_grp_get_subscribes_resp(nng_aio * aio,
neu_resp_get_subscribe_group_t *drivers)
{
char * result = NULL;
neu_json_get_driver_subscribe_resp_t drivers_resp = { 0 };
utarray_foreach(drivers->groups, neu_resp_driver_subscribe_info_t *, group)
{
// int index = utarray_eltidx(drivers->groups, group);
bool found = false;
for (int k = 0; k < drivers_resp.n_driver; k++) {
if (strcmp(drivers_resp.drivers[k].driver, group->driver) == 0) {
found = true;
drivers_resp.drivers[k].n_group++;
drivers_resp.drivers[k].groups = realloc(
drivers_resp.drivers[k].groups,
drivers_resp.drivers[k].n_group *
sizeof(neu_json_get_driver_subscribe_resp_group_t));
drivers_resp.drivers[k]
.groups[drivers_resp.drivers[k].n_group - 1]
.group = strdup(group->group);
drivers_resp.drivers[k]
.groups[drivers_resp.drivers[k].n_group - 1]
.subscribed = group->subscribed;
break;
}
}
if (!found) {
drivers_resp.n_driver++;
drivers_resp.drivers = realloc(
drivers_resp.drivers,
drivers_resp.n_driver *
sizeof(neu_json_get_driver_subscribe_resp_driver_t));
drivers_resp.drivers[drivers_resp.n_driver - 1].driver =
strdup(group->driver);
drivers_resp.drivers[drivers_resp.n_driver - 1].n_group = 1;
drivers_resp.drivers[drivers_resp.n_driver - 1].groups =
calloc(1, sizeof(neu_json_get_driver_subscribe_resp_group_t));
drivers_resp.drivers[drivers_resp.n_driver - 1].groups[0].group =
strdup(group->group);
drivers_resp.drivers[drivers_resp.n_driver - 1]
.groups[0]
.subscribed = group->subscribed;
}
}
neu_json_encode_by_fn(&drivers_resp,
neu_json_encode_get_driver_subscribe_resp, &result);
neu_http_ok(aio, result);
free(result);
for (int i = 0; i < drivers_resp.n_driver; i++) {
free(drivers_resp.drivers[i].driver);
for (int j = 0; j < drivers_resp.drivers[i].n_group; j++) {
free(drivers_resp.drivers[i].groups[j].group);
}
free(drivers_resp.drivers[i].groups);
}
free(drivers_resp.drivers);
utarray_free(drivers->groups);
}
+4
View File
@@ -39,4 +39,8 @@ void handle_grp_get_subscribe(nng_aio *aio);
void handle_grp_get_subscribe_resp(nng_aio * aio,
neu_resp_get_subscribe_group_t *groups);
void handle_grp_get_subscribes(nng_aio *aio);
void handle_grp_get_subscribes_resp(nng_aio * aio,
neu_resp_get_subscribe_group_t *groups);
#endif
+15
View File
@@ -148,6 +148,9 @@ static struct neu_http_handler cors_handler[] = {
{
.url = "/api/v2/users",
},
{
.url = "/api/v2/export/db",
},
};
static struct neu_http_handler rest_handlers[] = {
@@ -350,6 +353,12 @@ static struct neu_http_handler rest_handlers[] = {
.url = "/api/v2/subscribe",
.value.handler = handle_grp_get_subscribe,
},
{
.method = NEU_HTTP_METHOD_GET,
.type = NEU_HTTP_HANDLER_FUNCTION,
.url = "/api/v2/subscribes",
.value.handler = handle_grp_get_subscribes,
},
{
.method = NEU_HTTP_METHOD_POST,
.type = NEU_HTTP_HANDLER_FUNCTION,
@@ -494,6 +503,12 @@ 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/export/db",
.value.handler = handle_export_db,
},
};
void neu_rest_handler(const struct neu_http_handler **handlers, uint32_t *size)
+2 -2
View File
@@ -118,8 +118,8 @@ static int response(nng_aio *aio, char *content, enum nng_http_status status)
nng_http_res_set_status(res, status);
nng_http_req *nng_req = nng_aio_get_input(aio, 0);
nlog_info("%s %s [%d]", nng_http_req_get_method(nng_req),
nng_http_req_get_uri(nng_req), status);
nlog_notice("%s %s [%d]", nng_http_req_get_method(nng_req),
nng_http_req_get_uri(nng_req), status);
nng_aio_set_output(aio, 0, res);
nng_aio_finish(aio, 0);
+317
View File
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
@@ -35,6 +36,7 @@
#include "argparse.h"
#include "parser/neu_json_login.h"
#include "persist/persist_impl.h"
#include "json/neu_json_fn.h"
#include "handle.h"
@@ -459,6 +461,10 @@ static struct {
.plugin = "Modbus TCP",
.schema = "modbus-tcp",
},
{
.plugin = "Monitor",
.schema = "monitor",
},
{
.plugin = "MQTT",
.schema = "mqtt",
@@ -626,3 +632,314 @@ void handle_status(nng_aio *aio)
neu_http_response(aio, 0, result);
free(result);
}
int nodes_write_to_csv(const char *filename, UT_array *nodes)
{
FILE *f = fopen(filename, "a");
if (NULL == f) {
nlog_error("failed to open file:%s", filename);
return -1;
}
utarray_foreach(nodes, neu_persist_node_info_t *, node)
{
fprintf(f, "%s,%d,%d,%s\n", node->name, node->type, node->state,
node->plugin_name);
}
fclose(f);
return 0;
}
int settings_write_to_csv(const char *filename, const char *node_name,
const char *settings)
{
FILE *f = fopen(filename, "a");
if (NULL == f) {
nlog_error("failed to open file:%s", filename);
return -1;
}
fprintf(f, "%s,%s\n", node_name, settings);
fclose(f);
return 0;
}
int groups_write_to_csv(const char *filename, const char *driver_name,
UT_array *groups)
{
FILE *f = fopen(filename, "a");
if (NULL == f) {
nlog_error("failed to open file:%s", filename);
return -1;
}
utarray_foreach(groups, neu_persist_group_info_t *, group)
{
fprintf(f, "%s,%s,%d, NULL\n", driver_name, group->name,
group->interval);
}
fclose(f);
return 0;
}
int subscribes_write_to_csv(const char *filename, const char *app_name,
UT_array *subscribers)
{
FILE *f = fopen(filename, "a");
if (NULL == f) {
nlog_error("failed to open file:%s", filename);
return -1;
}
utarray_foreach(subscribers, neu_persist_subscription_info_t *, sub)
{
fprintf(f, "%s,%s,%s,%s,%s\n", app_name, sub->driver_name,
sub->group_name, sub->params, sub->static_tags);
}
fclose(f);
return 0;
}
int tags_write_to_csv(const char *filename, const char *node_name,
const char *group_name, UT_array *tags)
{
FILE *f = fopen(filename, "a");
if (NULL == f) {
nlog_error("failed to open file:%s", filename);
return -1;
}
utarray_foreach(tags, neu_datatag_t *, tag)
{
fprintf(f, "%s,%s,%s,%s,%d,%d,%f,%f,%d,%s,%s,NULL\n", node_name,
group_name, tag->name, tag->address, tag->attribute,
tag->precision, tag->decimal, tag->bias, tag->type,
tag->description, tag->format);
}
fclose(f);
return 0;
}
int write_csv_header()
{
FILE *f = fopen("nodes.csv", "w");
if (NULL == f) {
nlog_error("failed to open file:%s", "nodes.csv");
return -1;
}
fprintf(f, "name,type,state,plugin_name\n");
fclose(f);
f = fopen("settings.csv", "w");
if (NULL == f) {
nlog_error("failed to open file:%s", "settings.csv");
return -1;
}
fprintf(f, "node_name,setting\n");
fclose(f);
f = fopen("groups.csv", "w");
if (NULL == f) {
nlog_error("failed to open file:%s", "groups.csv");
return -1;
}
fprintf(f, "driver_name,name,interval,context\n");
fclose(f);
f = fopen("tags.csv", "w");
if (NULL == f) {
nlog_error("failed to open file:%s", "tags.csv");
return -1;
}
fprintf(f,
"driver_name,group_name,name,address,attribute,precision,"
"decimal,bias,type,description,format,value\n");
fclose(f);
f = fopen("subscribes.csv", "w");
if (NULL == f) {
nlog_error("failed to open file:%s", "subscribes.csv");
return -1;
}
fprintf(f, "app_name,driver_name,group_name,params,static_tags\n");
fclose(f);
return 0;
}
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);
}
void handle_export_db(nng_aio *aio)
{
write_csv_header();
UT_array *nodes = NULL;
int rv = neu_persister_load_nodes(&nodes);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
return;
}
rv = nodes_write_to_csv("nodes.csv", nodes);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
return;
}
utarray_foreach(nodes, neu_persist_node_info_t *, node)
{
char *settings = NULL;
rv = neu_persister_load_node_setting(node->name,
(const char **) &settings);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
return;
}
rv = settings_write_to_csv("settings.csv", node->name, settings);
free(settings);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
return;
}
}
utarray_foreach(nodes, neu_persist_node_info_t *, node)
{
if (node->type == 2) {
UT_array *subscribers = NULL;
rv = neu_persister_load_subscriptions(node->name, &subscribers);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
return;
}
rv = subscribes_write_to_csv("subscribes.csv", node->name,
subscribers);
utarray_free(subscribers);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
return;
}
}
}
utarray_foreach(nodes, neu_persist_node_info_t *, node)
{
UT_array *groups = NULL;
rv = neu_persister_load_groups(node->name, &groups);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
return;
}
rv = groups_write_to_csv("groups.csv", node->name, groups);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
return;
}
utarray_foreach(groups, neu_persist_group_info_t *, group)
{
UT_array *tags = NULL;
rv = neu_persister_load_tags(node->name, group->name, &tags);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
utarray_free(groups);
return;
}
rv = tags_write_to_csv("tags.csv", node->name, group->name, tags);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_WRITE_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
utarray_free(nodes);
utarray_free(groups);
return;
}
utarray_free(tags);
}
utarray_free(groups);
}
utarray_free(nodes);
system("rm -rf neuron.zip");
system("zip neuron.zip nodes.csv settings.csv groups.csv tags.csv "
"subscribes.csv");
void * data = NULL;
size_t len = 0;
rv = read_file("neuron.zip", &data, &len);
if (rv != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_FILE_READ_FAILURE, {
neu_http_response(aio, error_code.error, result_error);
});
return;
}
neu_http_response_file(aio, data, len,
"attachment; filename=\"neuron.zip\"");
free(data);
}
+2
View File
@@ -36,4 +36,6 @@ void handle_add_user(nng_aio *aio);
void handle_update_user(nng_aio *aio);
void handle_delete_user(nng_aio *aio);
void handle_export_db(nng_aio *aio);
#endif
+7
View File
@@ -279,6 +279,13 @@ 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_DRIVER_SUBSCRIBE_GROUP:
handle_grp_get_subscribes_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_NODE_SETTING:
handle_get_node_setting_resp(header->ctx,
(neu_resp_get_node_setting_t *) data);
+1 -1
View File
@@ -147,7 +147,7 @@ int main(int argc, char *argv[])
.params.tcp_server.stop_listen = stop_listen,
};
events = neu_event_new();
events = neu_event_new("modbus_simulator");
conn = neu_conn_new(&param, NULL, connected, disconnected);
signal(SIGINT, sig_handler);
+1 -1
View File
@@ -267,7 +267,7 @@ int main(int argc, char *argv[])
.params.tty_client.timeout = 3000,
};
events = neu_event_new();
events = neu_event_new("modbus_tty_simulator");
conn = neu_conn_new(&param, NULL, connected, disconnected);
neu_conn_start(conn);
+126 -21
View File
@@ -63,6 +63,8 @@ static int adapter_update_metric(neu_adapter_t *adapter,
const char *group);
inline static void reply(neu_adapter_t *adapter, neu_reqresp_head_t *header,
void *data);
inline static void notify_monitor(neu_adapter_t * adapter,
neu_reqresp_type_e event, void *data);
static const adapter_callbacks_t callback_funs = {
.command = adapter_command,
@@ -200,7 +202,7 @@ neu_adapter_t *neu_adapter_create(neu_adapter_info_t *info, bool load)
}
adapter->name = strdup(info->name);
adapter->events = neu_event_new();
adapter->events = neu_event_new("adapter");
adapter->state = NEU_NODE_RUNNING_STATE_INIT;
adapter->handle = info->handle;
adapter->cb_funs.command = callback_funs.command;
@@ -695,13 +697,21 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
switch (header->type) {
case NEU_REQ_SUBSCRIBE_GROUP: {
neu_req_subscribe_t *cmd = (neu_req_subscribe_t *) &header[1];
neu_req_subscribe_t *cmd = (neu_req_subscribe_t *) &header[1];
neu_resp_error_t error = { 0 };
if (adapter->module->type == NEU_NA_TYPE_DRIVER) {
neu_adapter_driver_subscribe((neu_adapter_driver_t *) adapter, cmd);
} else {
adapter->module->intf_funs->request(
adapter->plugin, (neu_reqresp_head_t *) header, &header[1]);
error.error = NEU_ERR_GROUP_NOT_ALLOW;
}
if (error.error == NEU_ERR_SUCCESS && header->monitor) {
notify_monitor(adapter, NEU_REQ_SUBSCRIBE_GROUP_EVENT, cmd);
}
neu_msg_free(msg);
break;
}
@@ -727,6 +737,7 @@ 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_DRIVER_SUBSCRIBE_GROUP:
case NEU_RESP_ADD_TAG:
case NEU_RESP_ADD_GTAG:
case NEU_RESP_UPDATE_TAG:
@@ -740,6 +751,23 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
case NEU_RESP_PRGFILE_PROCESS:
case NEU_RESP_CHECK_SCHEMA:
case NEU_RESP_DRIVER_ACTION:
case NEU_REQ_ADD_NODE_EVENT:
case NEU_REQ_DEL_NODE_EVENT:
case NEU_REQ_NODE_CTL_EVENT:
case NEU_REQ_NODE_SETTING_EVENT:
case NEU_REQ_ADD_GROUP_EVENT:
case NEU_REQ_DEL_GROUP_EVENT:
case NEU_REQ_UPDATE_GROUP_EVENT:
case NEU_REQ_ADD_TAG_EVENT:
case NEU_REQ_DEL_TAG_EVENT:
case NEU_REQ_UPDATE_TAG_EVENT:
case NEU_REQ_ADD_GTAG_EVENT:
case NEU_REQ_ADD_PLUGIN_EVENT:
case NEU_REQ_DEL_PLUGIN_EVENT:
case NEU_REQ_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UNSUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_SUBSCRIBE_GROUPS_EVENT:
adapter->module->intf_funs->request(
adapter->plugin, (neu_reqresp_head_t *) header, &header[1]);
neu_msg_free(msg);
@@ -989,7 +1017,12 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
error.error = neu_adapter_set_setting(adapter, cmd->setting);
if (error.error == NEU_ERR_SUCCESS) {
adapter_storage_setting(adapter->name, cmd->setting);
free(cmd->setting);
// ownership of `cmd->setting` transfer
if (header->monitor) {
notify_monitor(adapter, NEU_REQ_NODE_SETTING_EVENT, cmd);
} else {
free(cmd->setting);
}
} else {
free(cmd->setting);
}
@@ -1033,12 +1066,15 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}
case NEU_REQ_GET_GROUP: {
neu_req_get_group_t *cmd = (neu_req_get_group_t *) &header[1];
neu_msg_exchange(header);
if (adapter->module->type == NEU_NA_TYPE_DRIVER) {
neu_resp_get_group_t resp = {
.groups = neu_adapter_driver_get_group(
(neu_adapter_driver_t *) adapter)
(neu_adapter_driver_t *) adapter, cmd->q_group)
};
header->type = NEU_RESP_GET_GROUP;
reply(adapter, header, &resp);
@@ -1095,6 +1131,9 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
if (error.error == NEU_ERR_SUCCESS) {
adapter_storage_add_group(adapter->name, cmd->group, cmd->interval,
NULL);
if (header->monitor) {
notify_monitor(adapter, NEU_REQ_ADD_GROUP_EVENT, cmd);
}
}
neu_msg_exchange(header);
@@ -1118,6 +1157,9 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
if (resp.error == NEU_ERR_SUCCESS) {
adapter_storage_update_group(adapter->name, cmd->group,
cmd->new_name, cmd->interval);
if (header->monitor) {
notify_monitor(adapter, NEU_REQ_UPDATE_GROUP_EVENT, cmd);
}
}
strcpy(resp.driver, cmd->driver);
@@ -1144,6 +1186,9 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
if (error.error == NEU_ERR_SUCCESS) {
adapter_storage_del_group(cmd->driver, cmd->group);
if (header->monitor) {
notify_monitor(adapter, NEU_REQ_DEL_GROUP_EVENT, cmd);
}
}
neu_msg_exchange(header);
@@ -1164,6 +1209,10 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}
if (0 == error.error && header->monitor) {
notify_monitor(adapter, NEU_REQ_NODE_CTL_EVENT, cmd);
}
neu_msg_exchange(header);
header->type = NEU_RESP_ERROR;
reply(adapter, header, &error);
@@ -1203,10 +1252,14 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
error.error = NEU_ERR_GROUP_NOT_ALLOW;
}
for (uint16_t i = 0; i < cmd->n_tag; i++) {
free(cmd->tags[i]);
if (0 == error.error && header->monitor) {
notify_monitor(adapter, NEU_REQ_DEL_TAG_EVENT, cmd);
} else {
for (uint16_t i = 0; i < cmd->n_tag; i++) {
free(cmd->tags[i]);
}
free(cmd->tags);
}
free(cmd->tags);
neu_msg_exchange(header);
header->type = NEU_RESP_ERROR;
@@ -1256,25 +1309,33 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
}
}
for (uint16_t i = resp.index; i < cmd->n_tag; i++) {
neu_tag_fini(&cmd->tags[i]);
}
if (resp.index) {
// we have added some tags, try to persist
adapter_storage_add_tags(cmd->driver, cmd->group, cmd->tags,
resp.index);
cmd->n_tag = resp.index;
if (header->monitor) {
notify_monitor(adapter, NEU_REQ_ADD_TAG_EVENT, cmd);
} else {
neu_req_add_tag_fini(cmd);
}
} else {
free(cmd->tags);
}
for (uint16_t i = 0; i < cmd->n_tag; i++) {
neu_tag_fini(&cmd->tags[i]);
}
free(cmd->tags);
neu_msg_exchange(header);
header->type = NEU_RESP_ADD_TAG;
reply(adapter, header, &resp);
break;
}
case NEU_REQ_ADD_GTAG: {
neu_req_add_gtag_t *cmd = (neu_req_add_gtag_t *) &header[1];
neu_resp_add_tag_t resp = { 0 };
neu_req_add_gtag_t *cmd = (neu_req_add_gtag_t *) &header[1];
neu_resp_add_tag_t resp = { 0 };
int error = -1;
if (adapter->module->type != NEU_NA_TYPE_DRIVER) {
resp.error = NEU_ERR_GROUP_NOT_ALLOW;
@@ -1287,16 +1348,22 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
cmd->groups[i].tags,
cmd->groups[i].n_tag);
}
if (header->monitor) {
notify_monitor(adapter, NEU_REQ_ADD_GTAG_EVENT, cmd);
error = 0;
}
}
}
for (int i = 0; i < cmd->n_group; i++) {
for (int j = 0; j < cmd->groups[i].n_tag; j++) {
neu_tag_fini(&cmd->groups[i].tags[j]);
if (error != 0) {
for (int i = 0; i < cmd->n_group; i++) {
for (int j = 0; j < cmd->groups[i].n_tag; j++) {
neu_tag_fini(&cmd->groups[i].tags[j]);
}
free(cmd->groups[i].tags);
}
free(cmd->groups[i].tags);
free(cmd->groups);
}
free(cmd->groups);
neu_msg_exchange(header);
header->type = NEU_RESP_ADD_GTAG;
@@ -1335,10 +1402,19 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
resp.error = NEU_ERR_GROUP_NOT_ALLOW;
}
for (uint16_t i = 0; i < cmd->n_tag; i++) {
for (uint16_t i = resp.index; i < cmd->n_tag; i++) {
neu_tag_fini(&cmd->tags[i]);
}
free(cmd->tags);
if (resp.index > 0) {
cmd->n_tag = resp.index;
if (header->monitor) {
notify_monitor(adapter, NEU_REQ_UPDATE_TAG_EVENT, cmd);
} else {
neu_req_add_tag_fini(cmd);
}
} else {
free(cmd->tags);
}
neu_msg_exchange(header);
header->type = NEU_RESP_UPDATE_TAG;
@@ -1736,6 +1812,16 @@ neu_node_state_t neu_adapter_get_state(neu_adapter_t *adapter)
return state;
}
UT_array *neu_adapter_get_groups(neu_adapter_t *adapter, const char *filter)
{
if (adapter->module->type != NEU_NA_TYPE_DRIVER) {
return NULL;
} else {
return neu_adapter_driver_get_group((neu_adapter_driver_t *) adapter,
filter);
}
}
neu_event_timer_t *neu_adapter_add_timer(neu_adapter_t * adapter,
neu_event_timer_param_t param)
{
@@ -1803,3 +1889,22 @@ inline static void reply(neu_adapter_t *adapter, neu_reqresp_head_t *header,
strerror(errno), errno);
}
}
inline static void notify_monitor(neu_adapter_t * adapter,
neu_reqresp_type_e event, void *data)
{
neu_msg_t *msg = neu_msg_new(event, NULL, data);
if (NULL == msg) {
return;
}
neu_reqresp_head_t *header = neu_msg_get_header(msg);
strcpy(header->receiver, "monitor");
strncpy(header->sender, adapter->name, NEU_NODE_NAME_LEN);
int ret = neu_send_msg(adapter->control_fd, msg);
if (0 != ret) {
nlog_warn("notify %s of %s, error: %s(%d)", header->receiver,
neu_reqresp_type_string(header->type), strerror(errno),
errno);
neu_msg_free(msg);
}
}
+1
View File
@@ -95,6 +95,7 @@ void neu_adapter_del_timer(neu_adapter_t *adapter, neu_event_timer_t *timer);
int neu_adapter_set_setting(neu_adapter_t *adapter, const char *config);
int neu_adapter_get_setting(neu_adapter_t *adapter, char **config);
neu_node_state_t neu_adapter_get_state(neu_adapter_t *adapter);
UT_array *neu_adapter_get_groups(neu_adapter_t *adapter, const char *filter);
static inline void neu_adapter_reset_metrics(neu_adapter_t *adapter)
{
+43 -24
View File
@@ -45,7 +45,8 @@ struct elem {
neu_dvalue_t value;
neu_dvalue_t value_old;
neu_tag_meta_t metas[NEU_TAG_META_SIZE];
neu_tag_meta_t *metas;
int n_meta;
tkey_t key;
UT_hash_handle hh;
@@ -115,6 +116,13 @@ void neu_driver_cache_destroy(neu_driver_cache_t *cache)
free(elem->value.value.bools.bools);
}
if (elem->metas != NULL) {
for (int i = 0; i < elem->n_meta; i++) {
neu_free_dvalue(&elem->metas[i].value);
}
free(elem->metas);
}
free(elem);
}
@@ -764,9 +772,16 @@ void neu_driver_cache_update_change(neu_driver_cache_t *cache,
}
elem->value.type = value.type;
memset(elem->metas, 0, sizeof(neu_tag_meta_t) * NEU_TAG_META_SIZE);
for (int i = 0; i < n_meta; i++) {
memcpy(&elem->metas[i], &metas[i], sizeof(neu_tag_meta_t));
if (metas != NULL && n_meta != 0) {
if (elem->metas != NULL) {
free(elem->metas);
}
elem->metas = calloc(n_meta, sizeof(neu_tag_meta_t));
for (int i = 0; i < n_meta; i++) {
memcpy(&elem->metas[i], &metas[i], sizeof(neu_tag_meta_t));
}
elem->n_meta = n_meta;
}
}
@@ -784,7 +799,7 @@ void neu_driver_cache_update(neu_driver_cache_t *cache, const char *group,
int neu_driver_cache_meta_get(neu_driver_cache_t *cache, const char *group,
const char *tag, neu_driver_cache_value_t *value,
neu_tag_meta_t *metas, int n_meta)
neu_tag_meta_t **metas, int *n_meta)
{
struct elem *elem = NULL;
int ret = -1;
@@ -798,8 +813,14 @@ int neu_driver_cache_meta_get(neu_driver_cache_t *cache, const char *group,
value->value.type = elem->value.type;
value->value.precision = elem->value.precision;
assert(n_meta <= NEU_TAG_META_SIZE);
memcpy(metas, elem->metas, sizeof(neu_tag_meta_t) * NEU_TAG_META_SIZE);
// assert(n_meta <= NEU_TAG_META_SIZE);
if (elem->metas) {
*metas = calloc(elem->n_meta, sizeof(neu_tag_meta_t));
memcpy(*metas, elem->metas, sizeof(neu_tag_meta_t) * elem->n_meta);
} else {
*metas = NULL;
}
*n_meta = elem->n_meta;
switch (elem->value.type) {
case NEU_TYPE_INT8:
@@ -941,13 +962,6 @@ int neu_driver_cache_meta_get(neu_driver_cache_t *cache, const char *group,
break;
}
for (int i = 0; i < NEU_TAG_META_SIZE; i++) {
if (strlen(elem->metas[i].name) > 0) {
memcpy(&value->metas[i], &elem->metas[i],
sizeof(neu_tag_meta_t));
}
}
ret = 0;
}
@@ -959,7 +973,7 @@ int neu_driver_cache_meta_get(neu_driver_cache_t *cache, const char *group,
int neu_driver_cache_meta_get_changed(neu_driver_cache_t *cache,
const char *group, const char *tag,
neu_driver_cache_value_t *value,
neu_tag_meta_t *metas, int n_meta)
neu_tag_meta_t **metas, int *n_meta)
{
struct elem *elem = NULL;
int ret = -1;
@@ -973,8 +987,14 @@ int neu_driver_cache_meta_get_changed(neu_driver_cache_t *cache,
value->value.type = elem->value.type;
value->value.precision = elem->value.precision;
assert(n_meta <= NEU_TAG_META_SIZE);
memcpy(metas, elem->metas, sizeof(neu_tag_meta_t) * NEU_TAG_META_SIZE);
// assert(n_meta <= NEU_TAG_META_SIZE);
if (elem->metas) {
*metas = calloc(elem->n_meta, sizeof(neu_tag_meta_t));
memcpy(*metas, elem->metas, sizeof(neu_tag_meta_t) * elem->n_meta);
} else {
*metas = NULL;
}
*n_meta = elem->n_meta;
switch (elem->value.type) {
case NEU_TYPE_INT8:
@@ -1116,13 +1136,6 @@ int neu_driver_cache_meta_get_changed(neu_driver_cache_t *cache,
break;
}
for (int i = 0; i < NEU_TAG_META_SIZE; i++) {
if (strlen(elem->metas[i].name) > 0) {
memcpy(&value->metas[i], &elem->metas[i],
sizeof(neu_tag_meta_t));
}
}
if (elem->value.type != NEU_TYPE_ERROR) {
elem->changed = false;
}
@@ -1165,6 +1178,12 @@ void neu_driver_cache_del(neu_driver_cache_t *cache, const char *group,
elem->value.type < NEU_TYPE_ARRAY_STRING) {
free(elem->value.value.bools.bools);
}
if (elem->metas != NULL) {
for (int i = 0; i < elem->n_meta; i++) {
neu_free_dvalue(&elem->metas[i].value);
}
free(elem->metas);
}
free(elem);
}
+4 -5
View File
@@ -50,17 +50,16 @@ void neu_driver_cache_update_trace(neu_driver_cache_t *cache, const char *group,
void *neu_driver_cache_get_trace(neu_driver_cache_t *cache, const char *group);
typedef struct {
neu_dvalue_t value;
int64_t timestamp;
neu_tag_meta_t metas[NEU_TAG_META_SIZE];
neu_dvalue_t value;
int64_t timestamp;
} neu_driver_cache_value_t;
int neu_driver_cache_meta_get(neu_driver_cache_t *cache, const char *group,
const char *tag, neu_driver_cache_value_t *value,
neu_tag_meta_t *metas, int n_meta);
neu_tag_meta_t **metas, int *n_meta);
int neu_driver_cache_meta_get_changed(neu_driver_cache_t *cache,
const char *group, const char *tag,
neu_driver_cache_value_t *value,
neu_tag_meta_t *metas, int n_meta);
neu_tag_meta_t **metas, int *n_meta);
#endif
+38 -15
View File
@@ -375,6 +375,13 @@ static void update_im(neu_adapter_t *adapter, const char *group,
} else {
neu_free_dvalue(&tag_value->value);
}
if (tag_value->metas != NULL) {
for (int i = 0; i < tag_value->n_meta; i++) {
neu_free_dvalue(&tag_value->metas[i].value);
}
free(tag_value->metas);
}
}
utarray_free(data->tags);
free(data->group);
@@ -427,7 +434,7 @@ neu_adapter_driver_t *neu_adapter_driver_create()
neu_adapter_driver_t *driver = calloc(1, sizeof(neu_adapter_driver_t));
driver->cache = neu_driver_cache_new();
driver->driver_events = neu_event_new();
driver->driver_events = neu_event_new("driver");
driver->adapter.cb_funs.driver.update = update;
driver->adapter.cb_funs.driver.write_response = write_response;
driver->adapter.cb_funs.driver.update_im = update_im;
@@ -1622,6 +1629,10 @@ int neu_adapter_driver_update_group(neu_adapter_driver_t *driver,
if (NULL != new_name && 0 != strcmp(name, new_name)) {
char *new_name_cp1 = strdup(new_name);
char *new_name_cp2 = strdup(new_name);
if (find->grp.group_free != NULL) {
find->grp.group_free(&find->grp);
find->grp.group_free = NULL;
}
if (new_name_cp1 && new_name_cp2 &&
0 == neu_group_set_name(find->group, new_name)) {
HASH_DEL(driver->groups, find);
@@ -1757,7 +1768,8 @@ int neu_adapter_driver_group_exist(neu_adapter_driver_t *driver,
return ret;
}
UT_array *neu_adapter_driver_get_group(neu_adapter_driver_t *driver)
UT_array *neu_adapter_driver_get_group(neu_adapter_driver_t *driver,
const char * filter)
{
group_t * el = NULL, *tmp = NULL;
UT_array *groups = NULL;
@@ -1767,13 +1779,16 @@ UT_array *neu_adapter_driver_get_group(neu_adapter_driver_t *driver)
HASH_ITER(hh, driver->groups, el, tmp)
{
neu_resp_group_info_t info = { 0 };
info.interval = neu_group_get_interval(el->group);
info.tag_count = neu_group_tag_size(el->group);
strncpy(info.name, el->name, sizeof(info.name));
if (strlen(filter) == 0 || strstr(el->name, filter) != NULL) {
neu_resp_group_info_t info = { 0 };
utarray_push_back(groups, &info);
info.interval = neu_group_get_interval(el->group);
info.tag_count = neu_group_tag_size(el->group);
strncpy(info.name, el->name, sizeof(info.name));
utarray_push_back(groups, &info);
}
}
return groups;
@@ -2126,6 +2141,7 @@ static int report_callback(void *usr_data)
data->driver = strdup(group->driver->adapter.name);
data->group = strdup(group->name);
utarray_new(data->tags, neu_resp_tag_value_meta_icd());
utarray_reserve(data->tags, utarray_len(tags));
void *trace_ctx =
neu_driver_cache_get_trace(group->driver->cache, group->name);
@@ -2217,6 +2233,13 @@ static int report_callback(void *usr_data)
} else {
neu_free_dvalue(&tag_value->value);
}
if (tag_value->metas != NULL) {
for (int i = 0; i < tag_value->n_meta; i++) {
neu_free_dvalue(&tag_value->metas[i].value);
}
free(tag_value->metas);
}
}
utarray_free(data->tags);
free(data->group);
@@ -2421,15 +2444,15 @@ static void read_report_group(int64_t timestamp, int64_t timeout,
if (neu_tag_attribute_test(tag, NEU_ATTRIBUTE_SUBSCRIBE)) {
if (neu_driver_cache_meta_get_changed(cache, group, tag->name,
&value, tag_value.metas,
NEU_TAG_META_SIZE) != 0) {
&value, &tag_value.metas,
&tag_value.n_meta) != 0) {
nlog_debug("tag: %s not changed", tag->name);
continue;
}
} else {
if (neu_driver_cache_meta_get(cache, group, tag->name, &value,
tag_value.metas,
NEU_TAG_META_SIZE) != 0) {
&tag_value.metas,
&tag_value.n_meta) != 0) {
strcpy(tag_value.tag, tag->name);
tag_value.value.type = NEU_TYPE_ERROR;
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_NOT_READY;
@@ -2616,8 +2639,8 @@ static void read_group(int64_t timestamp, int64_t timeout,
tag_value.datatag.bias = tag->bias;
if (neu_driver_cache_meta_get(cache, group, tag->name, &value,
tag_value.metas,
NEU_TAG_META_SIZE) != 0) {
&tag_value.metas,
&tag_value.n_meta) != 0) {
tag_value.value.type = NEU_TYPE_ERROR;
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_NOT_READY;
@@ -2804,8 +2827,8 @@ static void read_group_paginate(int64_t timestamp, int64_t timeout,
}
if (neu_driver_cache_meta_get(cache, group, tag->name, &value,
tag_value.metas,
NEU_TAG_META_SIZE) != 0) {
&tag_value.metas,
&tag_value.n_meta) != 0) {
tag_value.value.type = NEU_TYPE_ERROR;
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_NOT_READY;
+2 -1
View File
@@ -54,7 +54,8 @@ int neu_adapter_driver_del_group(neu_adapter_driver_t *driver,
const char * name);
int neu_adapter_driver_group_exist(neu_adapter_driver_t *driver,
const char * name);
UT_array *neu_adapter_driver_get_group(neu_adapter_driver_t *driver);
UT_array *neu_adapter_driver_get_group(neu_adapter_driver_t *driver,
const char * filter);
uint16_t neu_adapter_driver_group_count(neu_adapter_driver_t *driver);
uint16_t neu_adapter_driver_new_group_count(neu_adapter_driver_t *driver,
neu_req_add_gtag_t * cmd);
+4 -3
View File
@@ -18,6 +18,7 @@
**/
#include <dirent.h>
#include <errno.h>
#include <pthread.h>
#include <sys/statvfs.h>
#include <sys/sysinfo.h>
@@ -45,7 +46,7 @@ static void find_os_info()
FILE *f = popen(cmd, "r");
if (NULL == f) {
nlog_error("popen command fail");
nlog_error("popen command fail(%s)", strerror(errno));
return;
}
@@ -100,7 +101,7 @@ static size_t parse_memory_fields(int col)
f = popen(buf, "r");
if (NULL == f) {
nlog_error("popen command fail");
nlog_error("popen command fail(%s)", strerror(errno));
return 0;
}
@@ -135,7 +136,7 @@ static inline size_t neuron_memory_used()
f = popen(buf, "r");
if (NULL == f) {
nlog_error("popen command fail");
nlog_error("popen command fail(%s)", strerror(errno));
return 0;
}
+94 -74
View File
@@ -30,80 +30,100 @@ 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)
#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_DRIVER_SUBSCRIBE_GROUP, \
neu_req_get_driver_subscribe_group_t) \
XX(NEU_RESP_GET_DRIVER_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_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)
static inline size_t neu_reqresp_size(neu_reqresp_type_e t)
{
+25 -1
View File
@@ -69,6 +69,8 @@ struct neu_conn {
uint8_t *buf;
uint16_t buf_size;
uint16_t offset;
uint16_t udp_act_port;
};
static void conn_tcp_server_add_client(neu_conn_t *conn, int fd,
@@ -503,7 +505,8 @@ ssize_t neu_conn_recv(neu_conn_t *conn, uint8_t *buf, ssize_t len)
conn->param.log,
"tcp conn fd: %d, recv buf len %zd, ret: %zd, errno: %s(%d)",
conn->fd, len, ret, strerror(errno), errno);
if (ret == 0 || (ret == -1 && errno != EAGAIN)) {
if (ret == 0 ||
(conn->connection_ok && ret == -1 && errno != EAGAIN)) {
conn_disconnect(conn);
}
}
@@ -868,6 +871,7 @@ static void conn_connect(neu_conn_t *conn)
} else {
zlog_error(conn->param.log, "invalid ip: %s",
conn->param.params.tcp_server.ip);
close(fd);
return;
}
@@ -938,6 +942,7 @@ static void conn_connect(neu_conn_t *conn)
} else {
zlog_error(conn->param.log, "invalid ip: %s",
conn->param.params.tcp_server.ip);
close(fd);
return;
}
@@ -950,6 +955,13 @@ static void conn_connect(neu_conn_t *conn)
return;
}
struct sockaddr_in local_addr = { 0 };
socklen_t local_addr_len = sizeof(local_addr);
if (getsockname(fd, (struct sockaddr *) &local_addr, &local_addr_len) ==
0) {
conn->udp_act_port = ntohs(local_addr.sin_port);
}
if (is_ipv4(conn->param.params.udp.dst_ip)) {
struct sockaddr_in remote = {
.sin_family = AF_INET,
@@ -1053,6 +1065,13 @@ static void conn_connect(neu_conn_t *conn)
return;
}
struct sockaddr_in local_addr = { 0 };
socklen_t local_addr_len = sizeof(local_addr);
if (getsockname(fd, (struct sockaddr *) &local_addr, &local_addr_len) ==
0) {
conn->udp_act_port = ntohs(local_addr.sin_port);
}
conn->is_connected = true;
conn->fd = fd;
@@ -1464,4 +1483,9 @@ int is_ipv6(const char *ip)
bool neu_conn_is_connected(neu_conn_t *conn)
{
return conn->is_connected;
}
uint16_t neu_conn_udp_act_port(neu_conn_t *conn)
{
return conn->udp_act_port;
}
+1 -1
View File
@@ -137,7 +137,7 @@ neu_conn_eth_t *neu_conn_eth_init(const char *interface, void *ctx)
conn_eth->ic = &in_conns[i];
in_conns[i].interface = strdup(interface);
in_conns[i].events = neu_event_new();
in_conns[i].events = neu_event_new("eth_conn");
in_conns[i].count += 1;
get_mac(conn_eth, interface);
+1 -1
View File
@@ -907,7 +907,7 @@ static inline int client_start_timer(neu_mqtt_client_t *client)
return 0;
}
events = neu_event_new();
events = neu_event_new("mqtt_client");
if (NULL == events) {
return -1;
}
+99 -10
View File
@@ -63,6 +63,8 @@ inline static void forward_msg_copy(neu_manager_t * manager,
neu_reqresp_head_t *header,
const char * node);
inline static void notify_monitor(neu_manager_t * manager,
neu_reqresp_type_e event, void *data);
static void start_static_adapter(neu_manager_t *manager, const char *name);
static int update_timestamp(void *usr_data);
static void start_single_adapter(neu_manager_t *manager, const char *name,
@@ -96,7 +98,7 @@ neu_manager_t *neu_manager_create()
.type = NEU_EVENT_TIMER_NOBLOCK,
};
manager->events = neu_event_new();
manager->events = neu_event_new("manager");
manager->plugin_manager = neu_plugin_manager_create();
manager->node_manager = neu_node_manager_create();
manager->subscribe_manager = neu_subscribe_manager_create();
@@ -230,10 +232,12 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
return 0;
}
header = neu_msg_get_header(msg);
header = neu_msg_get_header(msg);
header->monitor = neu_node_manager_find(manager->node_manager, "monitor");
nlog_info("manager recv msg from: %s to %s, type: %s", header->sender,
header->receiver, neu_reqresp_type_string(header->type));
nlog_info("manager recv msg from: %s to %s, type: %s, monitor: %d",
header->sender, header->receiver,
neu_reqresp_type_string(header->type), header->monitor);
switch (header->type) {
case NEU_REQ_NODE_INIT: {
neu_req_node_init_t *init = (neu_req_node_init_t *) &header[1];
@@ -418,6 +422,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
if (error == NEU_ERR_SUCCESS) {
manager_strorage_plugin(manager);
// notify_monitor(manager, NEU_REQ_ADD_PLUGIN_EVENT, cmd);
}
free(so_tmp_path);
@@ -435,7 +440,8 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
neu_resp_error_t e = { 0 };
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, cmd->plugin, "",
false, false, 0, false, 0, "");
if (nodes != NULL) {
if (utarray_len(nodes) > 0) {
@@ -454,6 +460,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
if (error == NEU_ERR_SUCCESS) {
manager_strorage_plugin(manager);
// notify_monitor(manager, NEU_REQ_DEL_PLUGIN_EVENT, cmd);
}
header->type = NEU_RESP_ERROR;
@@ -616,7 +623,8 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
}
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, module_name, "",
false, false, 0, false, 0, "");
if (nodes != NULL) {
if (utarray_len(nodes) > 0) {
@@ -734,6 +742,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
if (cmd->setting) {
adapter_storage_setting(cmd->node, cmd->setting);
}
notify_monitor(manager, NEU_REQ_ADD_NODE_EVENT, cmd);
}
neu_req_add_node_fini(cmd);
@@ -816,6 +825,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
utarray_free(subscriptions);
}
notify_monitor(manager, NEU_REQ_DEL_NODE_EVENT, cmd);
neu_reqresp_node_deleted_t resp = { 0 };
strcpy(resp.node, header->receiver);
// notify MQTT about node removal
@@ -866,9 +876,11 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}
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);
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);
neu_resp_get_node_t resp = { .nodes = nodes };
header->type = NEU_RESP_GET_NODE;
@@ -955,6 +967,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
manager_storage_update_subscribe(manager, cmd->app, cmd->driver,
cmd->group, cmd->params,
cmd->static_tags);
notify_monitor(manager, NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT, cmd);
} else {
free(cmd->params);
}
@@ -977,6 +990,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
forward_msg_copy(manager, header, cmd->driver);
manager_storage_unsubscribe(manager, cmd->app, cmd->driver,
cmd->group);
notify_monitor(manager, NEU_REQ_UNSUBSCRIBE_GROUP_EVENT, cmd);
}
header->type = NEU_RESP_ERROR;
@@ -996,6 +1010,18 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_DRIVER_SUBSCRIBE_GROUP: {
neu_req_get_driver_subscribe_group_t *cmd =
(neu_req_get_driver_subscribe_group_t *) &header[1];
UT_array *groups =
neu_manager_get_driver_groups(manager, cmd->app, cmd->name);
neu_resp_get_subscribe_group_t resp = { .groups = groups };
strcpy(header->receiver, header->sender);
header->type = NEU_RESP_GET_DRIVER_SUBSCRIBE_GROUP;
reply(manager, header, &resp);
break;
}
case NEU_REQ_GET_SUB_DRIVER_TAGS: {
neu_req_get_sub_driver_tags_t *cmd =
(neu_req_get_sub_driver_tags_t *) &header[1];
@@ -1324,7 +1350,8 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}
case NEU_REQ_NODE_SETTING: {
case NEU_REQ_NODE_SETTING:
case NEU_REQ_NODE_SETTING_EVENT: {
neu_req_node_setting_t *cmd = (neu_req_node_setting_t *) &header[1];
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
@@ -1435,6 +1462,27 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
break;
}
case NEU_REQ_ADD_NODE_EVENT:
case NEU_REQ_DEL_NODE_EVENT:
case NEU_REQ_NODE_CTL_EVENT:
case NEU_REQ_ADD_GROUP_EVENT:
case NEU_REQ_DEL_GROUP_EVENT:
case NEU_REQ_UPDATE_GROUP_EVENT:
case NEU_REQ_ADD_TAG_EVENT:
case NEU_REQ_DEL_TAG_EVENT:
case NEU_REQ_UPDATE_TAG_EVENT:
case NEU_REQ_ADD_GTAG_EVENT:
case NEU_REQ_ADD_PLUGIN_EVENT:
case NEU_REQ_DEL_PLUGIN_EVENT:
case NEU_REQ_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP_EVENT:
case NEU_REQ_UNSUBSCRIBE_GROUP_EVENT:
case NEU_REQ_SUBSCRIBE_GROUPS_EVENT: {
if (neu_node_manager_find(manager->node_manager, header->receiver)) {
forward_msg(manager, header, header->receiver);
}
break;
}
default:
nlog_warn("unknown msg type: %d", header->type);
assert(false);
@@ -1672,3 +1720,44 @@ static bool mv_tmp_schema_file(neu_plugin_kind_e kind, const char *tmp_path,
return false;
}
struct notify_monitor_ctx {
neu_manager_t * manager;
neu_reqresp_type_e event;
void * data;
};
inline static void notify_monitor(neu_manager_t * manager,
neu_reqresp_type_e event, void *data)
{
struct notify_monitor_ctx ctx = {
.manager = manager,
.event = event,
.data = data,
};
// monitor not ready, ignore
neu_node_manager_t *mgr = manager->node_manager;
struct sockaddr_un addr = neu_node_manager_get_addr(mgr, "monitor");
if (0 == addr.sun_path) {
return;
}
// message header
neu_msg_t *msg = neu_msg_new(ctx.event, NULL, ctx.data);
if (NULL == msg) {
return;
}
neu_reqresp_head_t *header = neu_msg_get_header(msg);
strcpy(header->sender, "manager");
strcpy(header->receiver, "monitor");
int ret = neu_send_msg_to(manager->server_fd, &addr, msg);
if (0 != ret) {
nlog_warn("notify %s of %s, error: %s(%d)", header->receiver,
neu_reqresp_type_string(header->type), strerror(errno),
errno);
neu_msg_free(msg);
}
return;
}
+60 -3
View File
@@ -114,9 +114,13 @@ 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 *plugin, 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);
return neu_node_manager_filter(manager->node_manager, type, plugin, 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,
@@ -182,7 +186,7 @@ UT_array *neu_manager_get_driver_group(neu_manager_t *manager)
neu_adapter_t *adapter =
neu_node_manager_find(manager->node_manager, driver->node);
UT_array *groups =
neu_adapter_driver_get_group((neu_adapter_driver_t *) adapter);
neu_adapter_driver_get_group((neu_adapter_driver_t *) adapter, "");
utarray_foreach(groups, neu_resp_group_info_t *, g)
{
@@ -233,6 +237,10 @@ int neu_manager_subscribe(neu_manager_t *manager, const char *app,
const char *params, const char *static_tags,
uint16_t *app_port)
{
if (neu_node_manager_is_monitor(manager->node_manager, app)) {
return NEU_ERR_NODE_NOT_ALLOW_SUBSCRIBE;
}
neu_adapter_t *adapter = neu_node_manager_find(manager->node_manager, app);
if (adapter == NULL) {
@@ -372,6 +380,55 @@ UT_array *neu_manager_get_sub_group_deep_copy(neu_manager_t *manager,
return subs;
}
UT_array *neu_manager_get_driver_groups(neu_manager_t *manager, const char *app,
const char *name)
{
UT_icd icd = { sizeof(neu_resp_driver_subscribe_info_t), NULL, NULL, NULL };
UT_array *result = NULL;
UT_array *sub_groups =
neu_subscribe_manager_get(manager->subscribe_manager, app, NULL, NULL);
UT_array *driver_groups = neu_manager_get_driver_group(manager);
utarray_new(result, &icd);
utarray_foreach(driver_groups, neu_resp_driver_group_info_t *, grp)
{
neu_resp_driver_subscribe_info_t info = { 0 };
if (name != NULL && strlen(name) > 0) {
if (strstr(grp->driver, name) != NULL ||
strstr(grp->group, name) != NULL) {
strcpy(info.app, app);
strcpy(info.driver, grp->driver);
strcpy(info.group, grp->group);
info.subscribed = false;
}
} else {
strcpy(info.app, app);
strcpy(info.driver, grp->driver);
strcpy(info.group, grp->group);
info.subscribed = false;
}
if (strlen(info.driver) > 0 && strlen(info.group) > 0) {
utarray_foreach(sub_groups, neu_resp_subscribe_info_t *, sub)
{
if (strcmp(sub->driver, info.driver) == 0 &&
strcmp(sub->group, info.group) == 0) {
info.subscribed = true;
break;
}
}
utarray_push_back(result, &info);
}
}
utarray_free(sub_groups);
utarray_free(driver_groups);
return result;
}
int neu_manager_get_node_info(neu_manager_t *manager, const char *name,
neu_persist_node_info_t *info)
{
+6 -1
View File
@@ -56,7 +56,10 @@ int neu_manager_add_node(neu_manager_t *manager, const char *node_name,
neu_node_running_state_e state, 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 *plugin, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link,
const char *q_group_name);
int neu_manager_update_node_name(neu_manager_t *manager, const char *node,
const char *new_name);
int neu_manager_update_group_name(neu_manager_t *manager, const char *driver,
@@ -82,6 +85,8 @@ UT_array *neu_manager_get_sub_group_deep_copy(neu_manager_t *manager,
const char * app,
const char * driver,
const char * group);
UT_array *neu_manager_get_driver_groups(neu_manager_t *manager, const char *app,
const char *name);
int neu_manager_get_node_info(neu_manager_t *manager, const char *name,
neu_persist_node_info_t *info);
+102 -1
View File
@@ -32,6 +32,7 @@ typedef struct node_entity {
bool is_static;
bool display;
bool single;
bool is_monitor;
struct sockaddr_un addr;
UT_hash_handle hh;
@@ -39,11 +40,17 @@ typedef struct node_entity {
struct neu_node_manager {
node_entity_t *nodes;
UT_array * monitors;
};
neu_node_manager_t *neu_node_manager_create()
{
neu_node_manager_t *node_manager = calloc(1, sizeof(neu_node_manager_t));
if (node_manager) {
utarray_new(node_manager->monitors, &ut_ptr_icd);
}
return node_manager;
}
@@ -58,6 +65,7 @@ void neu_node_manager_destroy(neu_node_manager_t *mgr)
free(el);
}
utarray_free(mgr->monitors);
free(mgr);
}
@@ -68,9 +76,15 @@ int neu_node_manager_add(neu_node_manager_t *mgr, neu_adapter_t *adapter)
node->adapter = adapter;
node->name = strdup(adapter->name);
node->display = true;
node->is_monitor =
(0 == strcmp(node->adapter->module->module_name, "Monitor"));
HASH_ADD_STR(mgr->nodes, name, node);
if (node->is_monitor) {
utarray_push_back(mgr->monitors, &node);
}
return 0;
}
@@ -147,6 +161,10 @@ void neu_node_manager_del(neu_node_manager_t *mgr, const char *name)
HASH_FIND_STR(mgr->nodes, name, node);
if (node != NULL) {
HASH_DEL(mgr->nodes, node);
if (node->is_monitor) {
utarray_erase(mgr->monitors, utarray_eltidx(mgr->monitors, node),
1);
}
free(node->name);
free(node);
}
@@ -194,8 +212,24 @@ UT_array *neu_node_manager_get(neu_node_manager_t *mgr, int type)
return array;
}
static int neu_resp_node_info_sort(const void *a, const void *b)
{
const neu_resp_node_info_t *info_a = (const neu_resp_node_info_t *) a;
const neu_resp_node_info_t *info_b = (const neu_resp_node_info_t *) b;
if (info_a->delay < info_b->delay) {
return -1;
} else if (info_a->delay > info_b->delay) {
return 1;
}
return 0;
}
UT_array *neu_node_manager_filter(neu_node_manager_t *mgr, int type,
const char *plugin, const char *node)
const char *plugin, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link,
const char *q_group_name)
{
UT_array * array = NULL;
UT_icd icd = { sizeof(neu_resp_node_info_t), NULL, NULL, NULL };
@@ -215,14 +249,57 @@ UT_array *neu_node_manager_filter(neu_node_manager_t *mgr, int type,
strstr(el->adapter->name, node) == NULL) {
continue;
}
if (q_state) {
if (el->adapter->state !=
(neu_node_running_state_e) state) {
continue;
}
}
if (q_link) {
neu_node_state_t node_state =
neu_adapter_get_state(el->adapter);
if (node_state.link != (neu_node_link_state_e) link) {
continue;
}
}
if (strlen(q_group_name) > 0) {
if (strstr(el->adapter->name, q_group_name) == NULL) {
UT_array *groups =
neu_adapter_get_groups(el->adapter, q_group_name);
if (NULL == groups || utarray_len(groups) == 0) {
if (groups != NULL) {
utarray_free(groups);
}
continue;
} else {
utarray_free(groups);
}
}
}
neu_resp_node_info_t info = { 0 };
strcpy(info.node, el->adapter->name);
strcpy(info.plugin, el->adapter->module->module_name);
if (sort_delay) {
neu_metric_entry_t *e = NULL;
if (NULL != el->adapter->metrics) {
HASH_FIND_STR(el->adapter->metrics->entries,
NEU_METRIC_LAST_RTT_MS, e);
}
info.delay = NULL != e ? e->value : 0;
} else {
info.delay = 0;
}
utarray_push_back(array, &info);
}
}
}
if (sort_delay) {
utarray_sort(array, neu_resp_node_info_sort);
}
return array;
}
@@ -348,6 +425,30 @@ struct sockaddr_un neu_node_manager_get_addr(neu_node_manager_t *mgr,
return addr;
}
bool neu_node_manager_is_monitor(neu_node_manager_t *mgr, const char *name)
{
node_entity_t *node = NULL;
HASH_FIND_STR(mgr->nodes, name, node);
return node ? node->is_monitor : false;
}
/*int neu_node_manager_for_each_monitor(neu_node_manager_t *mgr,
int (*cb)(const char * name,
struct sockaddr_un addr,
void * data),
void *data)
{
int rv = 0;
utarray_foreach(mgr->monitors, node_entity_t **, node)
{
rv = cb((*node)->name, (*node)->addr, data);
if (0 != rv) {
break;
}
}
return rv;
}*/
UT_array *neu_node_manager_get_state(neu_node_manager_t *mgr)
{
UT_icd icd = { sizeof(neu_nodes_state_t), NULL, NULL, NULL };
+6 -1
View File
@@ -49,7 +49,10 @@ 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 *plugin, const char *node,
bool sort_delay, bool q_state, int state,
bool q_link, int link,
const char *q_group_name);
UT_array *neu_node_manager_get_all(neu_node_manager_t *mgr);
// neu_adapter_t array
@@ -64,6 +67,8 @@ UT_array *neu_node_manager_get_addrs_all(neu_node_manager_t *mgr);
struct sockaddr_un neu_node_manager_get_addr(neu_node_manager_t *mgr,
const char * name);
bool neu_node_manager_is_monitor(neu_node_manager_t *mgr, const char *name);
// neu_nodes_state_t array
UT_array *neu_node_manager_get_state(neu_node_manager_t *mgr);
+21 -16
View File
@@ -72,6 +72,7 @@ struct neu_events {
int epoll_fd;
pthread_t thread;
bool stop;
char * name;
pthread_mutex_t mtx;
int n_event;
@@ -122,8 +123,8 @@ static void *event_loop(void *arg)
}
if (ret == -1 || events->stop) {
zlog_warn(neuron, "event loop exit, errno: %s(%d), stop: %d",
strerror(errno), errno, events->stop);
zlog_warn(neuron, "event loop(%s) exit, errno: %s(%d), stop: %d",
events->name, strerror(errno), errno, events->stop);
break;
}
@@ -177,17 +178,18 @@ static void *event_loop(void *arg)
return NULL;
};
neu_events_t *neu_event_new(void)
neu_events_t *neu_event_new(const char *name)
{
neu_events_t *events = calloc(1, sizeof(struct neu_events));
events->epoll_fd = epoll_create(1);
nlog_notice("create epoll: %d(%d)", events->epoll_fd, errno);
nlog_notice("create epoll(%s): %d(%d)", name, events->epoll_fd, errno);
assert(events->epoll_fd > 0);
events->stop = false;
events->n_event = 0;
events->name = strdup(name);
pthread_mutex_init(&events->mtx, NULL);
pthread_create(&events->thread, NULL, event_loop, events);
@@ -199,6 +201,7 @@ int neu_event_close(neu_events_t *events)
{
events->stop = true;
close(events->epoll_fd);
free(events->name);
pthread_join(events->thread, NULL);
pthread_mutex_destroy(&events->mtx);
@@ -220,7 +223,8 @@ neu_event_timer_t *neu_event_add_timer(neu_events_t * events,
};
int index = get_free_event(events);
if (index < 0) {
zlog_fatal(neuron, "no free event: %d", events->epoll_fd);
zlog_fatal(neuron, "no free event(%s): %d", events->name,
events->epoll_fd);
}
assert(index >= 0);
@@ -251,18 +255,19 @@ neu_event_timer_t *neu_event_add_timer(neu_events_t * events,
zlog_notice(neuron,
"add timer, second: %" PRId64 ", millisecond: %" PRId64
", timer: %d in epoll %d, "
", timer: %d in epoll(%s) %d, "
"ret: %d, index: %d",
timer.second, timer.millisecond, timer_fd, events->epoll_fd,
ret, index);
timer.second, timer.millisecond, timer_fd, events->name,
events->epoll_fd, ret, index);
return timer_ctx;
}
int neu_event_del_timer(neu_events_t *events, neu_event_timer_t *timer)
{
zlog_notice(neuron, "del timer: %d from epoll: %d, index: %d", timer->fd,
events->epoll_fd, timer->event_data->index);
zlog_notice(neuron, "del timer: %d from epoll(%s): %d, index: %d",
timer->fd, events->name, events->epoll_fd,
timer->event_data->index);
timer->stop = true;
epoll_ctl(events->epoll_fd, EPOLL_CTL_DEL, timer->fd, NULL);
@@ -281,8 +286,8 @@ neu_event_io_t *neu_event_add_io(neu_events_t *events, neu_event_io_param_t io)
int ret = 0;
int index = get_free_event(events);
nlog_notice("add io, fd: %d, epoll: %d, index: %d", io.fd, events->epoll_fd,
index);
nlog_notice("add io, fd: %d, epoll(%s): %d, index: %d", io.fd, events->name,
events->epoll_fd, index);
assert(index >= 0);
neu_event_io_t *io_ctx = &events->event_datas[index].ctx.io;
@@ -303,8 +308,8 @@ neu_event_io_t *neu_event_add_io(neu_events_t *events, neu_event_io_param_t io)
ret = epoll_ctl(events->epoll_fd, EPOLL_CTL_ADD, io.fd, &event);
nlog_notice("add io, fd: %d, epoll: %d, ret: %d(%d), index: %d", io.fd,
events->epoll_fd, ret, errno, index);
nlog_notice("add io, fd: %d, epoll(%s): %d, ret: %d(%d), index: %d", io.fd,
events->name, events->epoll_fd, ret, errno, index);
assert(ret == 0);
return io_ctx;
@@ -316,8 +321,8 @@ int neu_event_del_io(neu_events_t *events, neu_event_io_t *io)
return 0;
}
zlog_notice(neuron, "del io: %d from epoll: %d, index: %d", io->fd,
events->epoll_fd, io->event_data->index);
zlog_notice(neuron, "del io: %d from epoll(%s): %d, index: %d", io->fd,
events->name, events->epoll_fd, io->event_data->index);
epoll_ctl(events->epoll_fd, EPOLL_CTL_DEL, io->fd, NULL);
free_event(events, io->event_data->index);
+1 -1
View File
@@ -1113,7 +1113,7 @@ static int otel_timer_cb(void *data)
void neu_otel_start()
{
if (otel_event == NULL) {
otel_event = neu_event_new();
otel_event = neu_event_new("otel_event");
}
if (otel_timer == NULL) {
+179
View File
@@ -32,6 +32,30 @@
#include "neu_json_group_config.h"
int neu_json_encode_add_group_config_req(void *json_object, void *param)
{
int ret = 0;
neu_json_add_group_config_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
},
{
.name = "group",
.t = NEU_JSON_STR,
.v.val_str = req->group,
},
{
.name = "interval",
.t = NEU_JSON_INT,
.v.val_int = req->interval,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_add_group_config_req(
char *buf, neu_json_add_group_config_req_t **result)
{
@@ -90,6 +114,25 @@ void neu_json_decode_add_group_config_req_free(
free(req);
}
int neu_json_encode_del_group_config_req(void *json_object, void *param)
{
int ret = 0;
neu_json_del_group_config_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
},
{
.name = "group",
.t = NEU_JSON_STR,
.v.val_str = req->group,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_del_group_config_req(
char *buf, neu_json_del_group_config_req_t **result)
{
@@ -362,11 +405,88 @@ int neu_json_encode_get_subscribe_resp(void *object, void *param)
return ret;
}
int neu_json_encode_get_driver_subscribe_resp(void *object, void *param)
{
neu_json_get_driver_subscribe_resp_t *resp =
(neu_json_get_driver_subscribe_resp_t *) param;
void *driver_array = neu_json_array();
for (int i = 0; i < resp->n_driver; i++) {
if (resp->drivers[i].n_group == 0) {
continue;
}
json_t *ob = json_object();
void * group_array = neu_json_array();
json_object_set_new(ob, "name", json_string(resp->drivers[i].driver));
for (int j = 0; j < resp->drivers[i].n_group; j++) {
json_t *group_ob = json_object();
json_object_set_new(group_ob, "name",
json_string(resp->drivers[i].groups[j].group));
json_object_set_new(
group_ob, "subscribed",
json_boolean(resp->drivers[i].groups[j].subscribed));
json_array_append_new(group_array, group_ob);
}
json_object_set_new(ob, "groups", group_array);
json_array_append_new(driver_array, ob);
}
neu_json_elem_t resp_elems[] = { {
.name = "drivers",
.t = NEU_JSON_OBJECT,
.v.val_object = driver_array,
} };
return neu_json_encode_field(object, resp_elems,
NEU_JSON_ELEM_SIZE(resp_elems));
}
static inline int dump_params(void *root, char **const result)
{
return neu_json_dump_key(root, "params", result, false);
}
int neu_json_encode_subscribe_req(void *json_object, void *param)
{
int ret = 0;
neu_json_subscribe_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "app",
.t = NEU_JSON_STR,
.v.val_str = req->app,
},
{
.name = "group",
.t = NEU_JSON_STR,
.v.val_str = req->group,
},
{
.name = "driver",
.t = NEU_JSON_STR,
.v.val_str = req->driver,
},
{
.name = "params",
.t = NEU_JSON_OBJECT,
.v.val_object = req->params
? json_loads(req->params, 0, NULL)
: NULL,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_subscribe_req(char *buf, neu_json_subscribe_req_t **result)
{
int ret = 0;
@@ -437,6 +557,30 @@ void neu_json_decode_subscribe_req_free(neu_json_subscribe_req_t *req)
free(req);
}
int neu_json_encode_unsubscribe_req(void *json_object, void *param)
{
int ret = 0;
neu_json_unsubscribe_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "app",
.t = NEU_JSON_STR,
.v.val_str = req->app,
},
{
.name = "group",
.t = NEU_JSON_STR,
.v.val_str = req->group,
},
{
.name = "driver",
.t = NEU_JSON_STR,
.v.val_str = req->driver,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_unsubscribe_req(char * buf,
neu_json_unsubscribe_req_t **result)
{
@@ -496,6 +640,41 @@ void neu_json_decode_unsubscribe_req_free(neu_json_unsubscribe_req_t *req)
free(req);
}
int neu_json_encode_update_group_config_req(void *json_object, void *param)
{
int ret = 0;
neu_json_update_group_config_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
},
{
.name = "group",
.t = NEU_JSON_STR,
.v.val_str = req->group,
},
{
.name = "new_name",
.t = NEU_JSON_STR,
.v.val_str = req->new_name,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
if (0 != ret) {
return ret;
}
if (req->set_interval) {
neu_json_elem_t interval_elem = {
.name = "interval",
.t = NEU_JSON_INT,
.v.val_int = req->interval,
};
ret = neu_json_encode_field(json_object, &interval_elem, 1);
}
return ret;
}
int neu_json_decode_update_group_config_req(
char *buf, neu_json_update_group_config_req_t **result)
{
+23
View File
@@ -37,6 +37,7 @@ typedef struct {
int64_t interval;
} neu_json_add_group_config_req_t, neu_json_update_group_req_t;
int neu_json_encode_add_group_config_req(void *json_object, void *param);
int neu_json_decode_add_group_config_req(
char *buf, neu_json_add_group_config_req_t **result);
void neu_json_decode_add_group_config_req_free(
@@ -50,6 +51,7 @@ typedef struct {
int64_t interval;
} neu_json_update_group_config_req_t;
int neu_json_encode_update_group_config_req(void *json_object, void *param);
int neu_json_decode_update_group_config_req(
char *buf, neu_json_update_group_config_req_t **result);
void neu_json_decode_update_group_config_req_free(
@@ -60,6 +62,7 @@ typedef struct {
char *node;
} neu_json_del_group_config_req_t;
int neu_json_encode_del_group_config_req(void *json_object, void *param);
int neu_json_decode_del_group_config_req(
char *buf, neu_json_del_group_config_req_t **result);
void neu_json_decode_del_group_config_req_free(
@@ -110,6 +113,24 @@ typedef struct {
int neu_json_encode_get_subscribe_resp(void *json_object, void *param);
typedef struct {
char *group;
bool subscribed;
} neu_json_get_driver_subscribe_resp_group_t;
typedef struct {
char * driver;
int n_group;
neu_json_get_driver_subscribe_resp_group_t *groups;
} neu_json_get_driver_subscribe_resp_driver_t;
typedef struct {
int n_driver;
neu_json_get_driver_subscribe_resp_driver_t *drivers;
} neu_json_get_driver_subscribe_resp_t;
int neu_json_encode_get_driver_subscribe_resp(void *json_object, void *param);
typedef struct {
char *group;
char *app;
@@ -118,6 +139,7 @@ typedef struct {
char *static_tags;
} neu_json_subscribe_req_t;
int neu_json_encode_subscribe_req(void *json_object, void *param);
int neu_json_decode_subscribe_req(char *buf, neu_json_subscribe_req_t **result);
void neu_json_decode_subscribe_req_free(neu_json_subscribe_req_t *req);
@@ -127,6 +149,7 @@ typedef struct {
char *driver;
} neu_json_unsubscribe_req_t;
int neu_json_encode_unsubscribe_req(void *json_object, void *param);
int neu_json_decode_unsubscribe_req(char * buf,
neu_json_unsubscribe_req_t **result);
void neu_json_decode_unsubscribe_req_free(neu_json_unsubscribe_req_t *req);
+69
View File
@@ -137,6 +137,20 @@ void neu_json_decode_add_node_req_free(neu_json_add_node_req_t *req)
}
}
int neu_json_encode_del_node_req(void *json_object, void *param)
{
int ret = 0;
neu_json_del_node_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "name",
.t = NEU_JSON_STR,
.v.val_str = req->name,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_del_node_req(char *buf, neu_json_del_node_req_t **result)
{
int ret = 0;
@@ -416,6 +430,25 @@ void neu_json_decode_get_nodes_resp_free(neu_json_get_nodes_resp_t *resp)
}
}
int neu_json_encode_update_node_req(void *json_object, void *param)
{
int ret = 0;
neu_json_update_node_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "name",
.t = NEU_JSON_STR,
.v.val_str = req->name,
},
{
.name = "new_name",
.t = NEU_JSON_INT,
.v.val_str = req->new_name,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_update_node_req(char * buf,
neu_json_update_node_req_t **result)
{
@@ -468,6 +501,25 @@ void neu_json_decode_update_node_req_free(neu_json_update_node_req_t *req)
}
}
int neu_json_encode_node_ctl_req(void *json_object, void *param)
{
int ret = 0;
neu_json_node_ctl_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
},
{
.name = "cmd",
.t = NEU_JSON_INT,
.v.val_int = req->cmd,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_node_ctl_req(char *buf, neu_json_node_ctl_req_t **result)
{
int ret = 0;
@@ -516,6 +568,23 @@ void neu_json_decode_node_ctl_req_free(neu_json_node_ctl_req_t *req)
free(req);
}
int neu_json_encode_node_setting_req(void *json_object, void *param)
{
int ret = 0;
neu_json_node_setting_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
if (0 == ret) {
ret = neu_json_load_key(json_object, "params", req->setting, true);
}
return ret;
}
int neu_json_decode_node_setting_req(char * buf,
neu_json_node_setting_req_t **result)
{
+4
View File
@@ -49,6 +49,7 @@ typedef struct {
char *name;
} neu_json_del_node_req_t;
int neu_json_encode_del_node_req(void *json_object, void *param);
int neu_json_decode_del_node_req(char *buf, neu_json_del_node_req_t **result);
void neu_json_decode_del_node_req_free(neu_json_del_node_req_t *req);
@@ -104,6 +105,7 @@ typedef struct {
char *new_name;
} neu_json_update_node_req_t;
int neu_json_encode_update_node_req(void *json_object, void *param);
int neu_json_decode_update_node_req(char * buf,
neu_json_update_node_req_t **result);
void neu_json_decode_update_node_req_free(neu_json_update_node_req_t *req);
@@ -113,6 +115,7 @@ typedef struct {
int64_t cmd;
} neu_json_node_ctl_req_t;
int neu_json_encode_node_ctl_req(void *json_object, void *param);
int neu_json_decode_node_ctl_req(char *buf, neu_json_node_ctl_req_t **result);
void neu_json_decode_node_ctl_req_free(neu_json_node_ctl_req_t *req);
@@ -121,6 +124,7 @@ typedef struct {
char *setting;
} neu_json_node_setting_req_t;
int neu_json_encode_node_setting_req(void *json_object, void *param);
int neu_json_decode_node_setting_req(char * buf,
neu_json_node_setting_req_t **result);
void neu_json_decode_node_setting_req_free(neu_json_node_setting_req_t *req);
+32
View File
@@ -29,6 +29,22 @@
#include "neu_json_plugin.h"
int neu_json_encode_add_plugin_req(void *json_object, void *param)
{
int ret = 0;
neu_json_add_plugin_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "library",
.t = NEU_JSON_STR,
.v.val_str = req->library,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_add_plugin_req(char * buf,
neu_json_add_plugin_req_t **result)
{
@@ -86,6 +102,22 @@ void neu_json_decode_add_plugin_req_free(neu_json_add_plugin_req_t *req)
free(req);
}
int neu_json_encode_del_plugin_req(void *json_object, void *param)
{
int ret = 0;
neu_json_add_plugin_req_t *req = param;
neu_json_elem_t req_elems[] = { {
.name = "library",
.t = NEU_JSON_STR,
.v.val_str = req->library,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_del_plugin_req(char * buf,
neu_json_del_plugin_req_t **result)
{
+2
View File
@@ -39,6 +39,7 @@ typedef struct {
typedef neu_json_add_plugin_req_t neu_json_update_plugin_req_t;
int neu_json_encode_add_plugin_req(void *json_object, void *param);
int neu_json_decode_add_plugin_req(char * buf,
neu_json_add_plugin_req_t **result);
void neu_json_decode_add_plugin_req_free(neu_json_add_plugin_req_t *req);
@@ -47,6 +48,7 @@ typedef struct {
char *plugin;
} neu_json_del_plugin_req_t;
int neu_json_encode_del_plugin_req(void *json_object, void *param);
int neu_json_decode_del_plugin_req(char * buf,
neu_json_del_plugin_req_t **result);
void neu_json_decode_del_plugin_req_free(neu_json_del_plugin_req_t *req);
+107
View File
@@ -262,6 +262,43 @@ void neu_json_decode_tag_array_fini(neu_json_tag_array_t *arr)
free(arr->tags);
}
int neu_json_encode_add_tags_req(void *json_object, void *param)
{
int ret = 0;
neu_json_add_tags_req_t *req = param;
void * tag_array = neu_json_array();
if (NULL == tag_array) {
return -1;
}
neu_json_tag_array_t arr = {
.len = req->n_tag,
.tags = req->tags,
};
ret = neu_json_encode_tag_array(tag_array, &arr);
if (0 != ret) {
neu_json_encode_free(tag_array);
return ret;
}
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
},
{
.name = "group",
.t = NEU_JSON_STR,
.v.val_str = req->group,
},
{
.name = "tags",
.t = NEU_JSON_OBJECT,
.v.val_object = tag_array,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_add_tags_req(char *buf, neu_json_add_tags_req_t **result)
{
int ret = 0;
@@ -534,6 +571,38 @@ void neu_json_decode_gtag_array_fini(neu_json_gtag_array_t *arr)
free(arr->gtags);
}
int neu_json_encode_add_gtags_req(void *json_object, void *param)
{
int ret = 0;
neu_json_add_gtags_req_t *req = param;
neu_json_gtag_array_t gtag_array = { .len = req->n_group,
.gtags = req->groups };
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
json_t *groups_json = json_array();
if (NULL == groups_json ||
0 != json_object_set_new(json_object, "groups", groups_json)) {
return -1;
}
neu_json_encode_gtag_array(groups_json, &gtag_array);
for (int i = 0; i < req->n_group; i++) {
free(req->groups[i].group);
free(req->groups[i].tags);
}
free(req->groups);
return ret;
}
int neu_json_decode_add_gtags_req(char *buf, neu_json_add_gtags_req_t **result)
{
int ret = 0;
@@ -630,6 +699,44 @@ int neu_json_encode_au_gtags_resp(void *json_object, void *param)
return ret;
}
int neu_json_encode_del_tags_req(void *json_object, void *param)
{
int ret = 0;
neu_json_del_tags_req_t * req = param;
void * tag_array = neu_json_array();
neu_json_del_tags_req_name_t *p_name = req->tags;
for (int i = 0; i < req->n_tags; i++) {
neu_json_elem_t tag_elems[] = {
{
.name = NULL,
.t = NEU_JSON_STR,
.v.val_str = *p_name,
},
};
tag_array = neu_json_encode_array_value(tag_array, tag_elems,
NEU_JSON_ELEM_SIZE(tag_elems));
p_name++;
}
neu_json_elem_t req_elems[] = { {
.name = "node",
.t = NEU_JSON_STR,
.v.val_str = req->node,
},
{
.name = "group",
.t = NEU_JSON_STR,
.v.val_str = req->group,
},
{
.name = "tags",
.t = NEU_JSON_OBJECT,
.v.val_object = tag_array,
} };
ret = neu_json_encode_field(json_object, req_elems,
NEU_JSON_ELEM_SIZE(req_elems));
return ret;
}
int neu_json_decode_del_tags_req(char *buf, neu_json_del_tags_req_t **result)
{
int ret = 0;
+3
View File
@@ -65,6 +65,7 @@ typedef struct {
neu_json_tag_t *tags;
} neu_json_add_tags_req_t;
int neu_json_encode_add_tags_req(void *json_object, void *param);
int neu_json_decode_add_tags_req(char *buf, neu_json_add_tags_req_t **result);
void neu_json_decode_add_tags_req_free(neu_json_add_tags_req_t *req);
@@ -101,6 +102,7 @@ typedef struct {
neu_json_gtag_t *groups;
} neu_json_add_gtags_req_t;
int neu_json_encode_add_gtags_req(void *json_object, void *param);
int neu_json_decode_add_gtags_req(char *buf, neu_json_add_gtags_req_t **result);
void neu_json_decode_add_gtags_req_free(neu_json_add_gtags_req_t *req);
@@ -120,6 +122,7 @@ typedef struct {
neu_json_del_tags_req_name_t *tags;
} neu_json_del_tags_req_t;
int neu_json_encode_del_tags_req(void *json_object, void *param);
int neu_json_decode_del_tags_req(char *buf, neu_json_del_tags_req_t **result);
void neu_json_decode_del_tags_req_free(neu_json_del_tags_req_t *req);
+37
View File
@@ -510,4 +510,41 @@ int neu_http_post_otel_trace(uint8_t *data, int len)
nng_http_conn_close(conn);
nng_aio_free(aio);
return status;
}
int neu_http_response_file(nng_aio *aio, void *data, size_t len,
const char *disposition)
{
nng_http_res *res = NULL;
int rv = 0;
if (((rv = nng_http_res_alloc(&res)) != 0) ||
((rv = nng_http_res_set_status(res, NNG_HTTP_STATUS_OK)) != 0) ||
((rv = nng_http_res_set_header(res, "Content-Type",
"application/octet-stream")) != 0) ||
((rv = nng_http_res_set_header(res, "Content-Disposition",
disposition)) != 0) ||
((rv = nng_http_res_set_header(res, "Access-Control-Allow-Origin",
"*")) != 0) ||
((rv = nng_http_res_set_header(res, "Access-Control-Allow-Methods",
"POST,GET,PUT,DELETE,OPTIONS")) != 0) ||
((rv = nng_http_res_set_header(res, "Access-Control-Allow-Headers",
"*")) != 0) ||
((rv = nng_http_res_set_header(res, "Access-Control-Expose-Headers",
"Content-Disposition")) != 0) ||
((rv = nng_http_res_copy_data(res, data, len)) != 0)) {
nng_http_res_free(res);
nng_aio_finish(aio, rv);
return -1;
}
nng_http_req *nng_req = nng_aio_get_input(aio, 0);
nlog_notice("%s %s [%d]", nng_http_req_get_method(nng_req),
nng_http_req_get_uri(nng_req), NNG_HTTP_STATUS_OK);
nng_aio_set_output(aio, 0, res);
nng_aio_finish(aio, 0);
return 0;
}
+4
View File
@@ -525,6 +525,10 @@ static int decode_object(json_t *root, neu_json_elem_t *ele)
ele->t = NEU_JSON_ARRAY_BOOL;
break;
}
if (json_is_object(value)) {
ele->t = NEU_JSON_OBJECT;
break;
}
}
} else if (json_is_object(ob)) {
ele->t = NEU_JSON_OBJECT;
+35
View File
@@ -610,6 +610,39 @@ class TestHttp:
response = api.get_status()
assert 200 == response.status_code
@description(given="running neuron", when="get node or group by filter", then="success")
def test_get_node_or_group_by_filter(self):
node_1 = "test1"
node_2 = "test2"
group_1 = "abcd1"
group_2 = "abdc2"
api.add_node_check(node_1, 'Modbus TCP')
api.add_node_check(node_2, 'Modbus TCP')
api.add_group_check(node_1, group_1, 1000)
api.add_group_check(node_1, group_2, 1000)
api.add_group_check(node_2, group_1, 1000)
# api.add_group_check(node_2, group_2, 1000)
response = api.get_nodes(1)
assert 2 == len(response.json()["nodes"])
response = api.get_nodes(1, group="dc")
assert 1 == len(response.json()["nodes"])
response = api.get_nodes(1, group="ab")
assert 2 == len(response.json()["nodes"])
response = api.get_nodes(1, group="test")
assert 2 == len(response.json()["nodes"])
response = api.get_nodes(1, group="test1")
assert 1 == len(response.json()["nodes"])
response = api.get_nodes(1, group="1234")
assert 0 == len(response.json()["nodes"])
response = api.get_group(node=node_1)
assert 2 == len(response.json()["groups"])
response = api.get_group(node=node_1, group="1")
assert 1 == len(response.json()["groups"])
response = api.get_group(node=node_2)
assert 1 == len(response.json()["groups"])
@description(given="running neuron", when="test jwt error", then="failed")
def test_jwt_err(self):
response = api.change_password(new_password='123456', jwt='invalid')
@@ -629,3 +662,5 @@ class TestHttp:
response = api.delete_virtual_license(jwt='invalid')
assert 404 == response.status_code
+12 -4
View File
@@ -79,8 +79,11 @@ 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):
return requests.get(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, params={"type": type})
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})
@gen_check
@@ -124,8 +127,13 @@ def update_group(node, group, new_name="", interval=0):
@gen_check
def get_group(node=""):
return requests.get(url=config.BASE_URL + f'/api/v2/group?node={node}', headers={"Authorization": config.default_jwt})
def get_group(node="", group=""):
if group == "":
return requests.get(url=config.BASE_URL + f'/api/v2/group?node={node}', headers={"Authorization": config.default_jwt})
else:
return requests.get(url=config.BASE_URL + f'/api/v2/group?node={node}&group={group}', headers={"Authorization": config.default_jwt})
@gen_check
+1 -1
View File
@@ -1 +1 @@
2.11.3
2.11.5