mirror of
https://github.com/emqx/neuron.git
synced 2026-10-29 23:19:18 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97e986e14f | ||
|
|
64e265770e | ||
|
|
e919af04b0 | ||
|
|
5b00c22e70 | ||
|
|
c83b0498d6 | ||
|
|
b2c1c45c01 | ||
|
|
f1db3782b9 | ||
|
|
5e19ff78ff | ||
|
|
8fce63ae7b | ||
|
|
dc16ca62d3 | ||
|
|
76bbb2cbce | ||
|
|
1079af396e | ||
|
|
fed03422b3 | ||
|
|
c8a06bfc30 | ||
|
|
fc12d7fbff | ||
|
|
92f387ae7b | ||
|
|
7cb61f6fa5 | ||
|
|
72eb9c4219 | ||
|
|
faaef6c2e7 | ||
|
|
ff22e3413e | ||
|
|
393d85741a | ||
|
|
680a2839c2 | ||
|
|
5ee46fa972 | ||
|
|
ae94644430 | ||
|
|
f5c730dcfc | ||
|
|
488cccf521 | ||
|
|
a0d5851719 | ||
|
|
c518d6c196 | ||
|
|
c385103c9c | ||
|
|
f216b3f4e9 | ||
|
|
c768f45e9e | ||
|
|
fa55497b55 | ||
|
|
5336d1c250 | ||
|
|
dede8ee8f4 | ||
|
|
17e2015a9c | ||
|
|
3361284252 | ||
|
|
8f6d9d1c41 | ||
|
|
3f75222410 | ||
|
|
ddf5d252f6 | ||
|
|
6e467f5f27 | ||
|
|
fd1266bc9e | ||
|
|
d8b605ef1c | ||
|
|
c9122b5b7c | ||
|
|
8c11cb3466 | ||
|
|
80680c55f5 | ||
|
|
132c25b4ad | ||
|
|
cc7e5d092a | ||
|
|
2e3f6d6db2 | ||
|
|
43a95b7910 | ||
|
|
053be086b0 | ||
|
|
66dba0f69a | ||
|
|
c6752c5761 | ||
|
|
53f5c496ea | ||
|
|
1e28e4bc0e | ||
|
|
2bbcc6a154 | ||
|
|
00d6418288 |
@@ -7,6 +7,11 @@ on:
|
||||
types:
|
||||
- published
|
||||
|
||||
|
||||
env:
|
||||
BRANCH: v2.4
|
||||
|
||||
|
||||
jobs:
|
||||
clang_format_check:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -40,7 +45,7 @@ jobs:
|
||||
|
||||
ut:
|
||||
runs-on: ubuntu-20.04
|
||||
container: neugates/build:x86_64-main
|
||||
container: ghcr.io/neugates/build:x86_64-v2.4
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -61,7 +66,7 @@ jobs:
|
||||
|
||||
ft:
|
||||
runs-on: ubuntu-20.04
|
||||
container: neugates/build:x86_64-main
|
||||
container: ghcr.io/neugates/build:x86_64-v2.4
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -8,9 +8,9 @@ on:
|
||||
- published
|
||||
|
||||
env:
|
||||
VERSION: 2.4.0
|
||||
UI_VERSION: 2.4.0
|
||||
BRANCH: main
|
||||
VERSION: 2.4.4
|
||||
UI_VERSION: 2.4.3
|
||||
BRANCH: v2.4
|
||||
|
||||
jobs:
|
||||
cross-build:
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- [aarch64-linux-gnu, aarch64, arm64]
|
||||
- [arm-linux-gnueabihf, armv4, armhf]
|
||||
- [x86_64-linux-gnu, x86_64, amd64]
|
||||
container: neugates/build:${{ matrix.arch[1] }}-main
|
||||
container: ghcr.io/neugates/build:${{ matrix.arch[1] }}-v2.4
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
matrix:
|
||||
arch:
|
||||
- [x86_64-linux-gnu, x86_64, amd64]
|
||||
container: neugates/build:${{ matrix.arch[1] }}-main
|
||||
container: ghcr.io/neugates/build:${{ matrix.arch[1] }}-v2.4
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@@ -9,5 +9,5 @@ file_format = "%d [%V] %f:%L %m%n"
|
||||
|
||||
[rules]
|
||||
|
||||
*.* "./logs/%c.log", 100MB * 10 ~ "./logs/%c.#2s.log"; file_format
|
||||
*.* "./logs/%c.log", 50MB * 1 ~ "./logs/%c.#2s.log"; file_format
|
||||
*.* >stdout; stdout_format
|
||||
|
||||
@@ -40,6 +40,12 @@ typedef enum neu_conn_tty_baud {
|
||||
NEU_CONN_TTY_BAUD_9600,
|
||||
NEU_CONN_TTY_BAUD_4800,
|
||||
NEU_CONN_TTY_BAUD_2400,
|
||||
NEU_CONN_TTY_BAUD_1800,
|
||||
NEU_CONN_TTY_BAUD_1200,
|
||||
NEU_CONN_TTY_BAUD_600,
|
||||
NEU_CONN_TTY_BAUD_300,
|
||||
NEU_CONN_TTY_BAUD_200,
|
||||
NEU_CONN_TTY_BAUD_150,
|
||||
} neu_conn_tty_baud_e;
|
||||
|
||||
typedef enum neu_conn_tty_parity {
|
||||
|
||||
@@ -154,6 +154,7 @@ typedef struct {
|
||||
unsigned cpu_cores;
|
||||
size_t mem_total_bytes;
|
||||
size_t mem_used_bytes;
|
||||
size_t mem_cache_bytes;
|
||||
size_t disk_size_gibibytes;
|
||||
size_t disk_used_gibibytes;
|
||||
size_t disk_avail_gibibytes;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
-- Update default data-stream-processing node setting when
|
||||
-- the data-stream-processing node exists and is at init state.
|
||||
-- The init state implies the user has not provide any setting yet.
|
||||
INSERT INTO
|
||||
settings (node_name, setting)
|
||||
SELECT
|
||||
name,
|
||||
'{"params":{"host":"0.0.0.0","port":7081}}'
|
||||
FROM
|
||||
nodes
|
||||
WHERE
|
||||
name = 'data-stream-processing'
|
||||
and state = 1;
|
||||
|
||||
-- Update default data-stream-processing node to running state when
|
||||
-- the data-stream-processing node exists and is at init state.
|
||||
UPDATE
|
||||
nodes
|
||||
SET
|
||||
state = 3
|
||||
where
|
||||
name = 'data-stream-processing'
|
||||
and state = 1;
|
||||
|
||||
COMMIT;
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'MQTT'
|
||||
WHERE plugin_name = 'mqtt';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'eKuiper'
|
||||
WHERE plugin_name = 'ekuiper';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'SparkPlugB'
|
||||
WHERE plugin_name = 'sparkplugb';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Beckhoff ADS'
|
||||
WHERE plugin_name = 'ads';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Modbus TCP community'
|
||||
WHERE plugin_name = 'modbus-tcp';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Modbus RTU'
|
||||
WHERE plugin_name = 'modbus-rtu';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Modbus TCP'
|
||||
WHERE plugin_name = 'modbus-plus-tcp';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Modbus TCP QH'
|
||||
WHERE plugin_name = 'modbus-qh-tcp';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Siemens S7 ISOTCP'
|
||||
WHERE plugin_name = 's7comm';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Siemens S7 ISOTCP for 300/400'
|
||||
WHERE plugin_name = 's7comm_for_300';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'OPC UA'
|
||||
WHERE plugin_name = 'opcua';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Omron FINS TCP'
|
||||
WHERE plugin_name = 'fins';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Mitsubishi 3E'
|
||||
WHERE plugin_name = 'qna3e';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Mitsubishi 1E'
|
||||
WHERE plugin_name = 'a1e';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'IEC60870-5-104'
|
||||
WHERE plugin_name = 'iec104';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'BACnet/IP'
|
||||
WHERE plugin_name = 'bacnet';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'KNXnet/IP'
|
||||
WHERE plugin_name = 'knx';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'DLT645-2007'
|
||||
WHERE plugin_name = 'dlt645';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'NON A11'
|
||||
WHERE plugin_name = 'nona11';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'EtherNet/IP(CIP)'
|
||||
WHERE plugin_name = 'EtherNet-IP';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'Fanuc Focas Ethernet'
|
||||
WHERE plugin_name = 'focas';
|
||||
|
||||
UPDATE nodes
|
||||
SET plugin_name = 'File'
|
||||
WHERE plugin_name = 'file';
|
||||
|
||||
COMMIT;
|
||||
+20
-7
@@ -32,6 +32,10 @@ static void plugin_group_free(neu_plugin_group_t *pgp);
|
||||
|
||||
int file_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;
|
||||
int64_t rtt = NEU_METRIC_LAST_RTT_MS_MAX;
|
||||
|
||||
struct file_group_data *gd = NULL;
|
||||
int length = plugin->file_length;
|
||||
|
||||
@@ -56,6 +60,7 @@ int file_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group)
|
||||
dvalue.value.i32 = NEU_ERR_FILE_NOT_EXIST;
|
||||
goto dvalue_result;
|
||||
}
|
||||
|
||||
if ((f = fopen(tag->address, "rb+")) == NULL) {
|
||||
nlog_error("open file:%s", tag->address);
|
||||
dvalue.type = NEU_TYPE_ERROR;
|
||||
@@ -63,24 +68,30 @@ int file_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group)
|
||||
goto dvalue_result;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
int size = ftell(f);
|
||||
if (size >= length) {
|
||||
dvalue.type = NEU_TYPE_ERROR;
|
||||
dvalue.value.i32 = NEU_ERR_FILE_TOO_LONG;
|
||||
|
||||
fclose(f);
|
||||
goto dvalue_result;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_SET);
|
||||
int ret = fread(buf, sizeof(char), length, f);
|
||||
if (ret == 0) {
|
||||
nlog_error("read file failed:%s", tag->address);
|
||||
dvalue.type = NEU_TYPE_ERROR;
|
||||
dvalue.value.i32 = NEU_ERR_FILE_READ_FAILURE;
|
||||
goto dvalue_result;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
int size = ftell(f);
|
||||
if (size > length) {
|
||||
dvalue.type = NEU_TYPE_ERROR;
|
||||
dvalue.value.i32 = NEU_ERR_FILE_TOO_LONG;
|
||||
fclose(f);
|
||||
goto dvalue_result;
|
||||
}
|
||||
|
||||
dvalue.type = NEU_TYPE_STRING;
|
||||
strncpy(dvalue.value.str, buf, strlen(buf));
|
||||
rtt = 1;
|
||||
fclose(f);
|
||||
|
||||
dvalue_result:
|
||||
@@ -90,6 +101,8 @@ int file_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
update_metric(plugin->common.adapter, NEU_METRIC_LAST_RTT_MS, rtt, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
|
||||
// clang-format off
|
||||
#define METRIC_GLOBAL_TMPL \
|
||||
"# HELP distro OS distribution\n" \
|
||||
"distro %s\n" \
|
||||
"# HELP kernel OS kernel version\n" \
|
||||
"kernel %s\n" \
|
||||
"# HELP os_info OS distro and kernel version\n" \
|
||||
"# TYPE os_info gauge\n" \
|
||||
"os_info{version=\"%s\"} 0\n" \
|
||||
"os_info{kernel=\"%s\"} 0\n" \
|
||||
"# HELP cpu_percent Total CPU utilisation percentage\n" \
|
||||
"# TYPE cpu_percent gauge\n" \
|
||||
"cpu_percent %u\n" \
|
||||
@@ -47,6 +47,12 @@
|
||||
"# HELP mem_used_bytes Used memory in bytes\n" \
|
||||
"# TYPE mem_used_bytes gauge\n" \
|
||||
"mem_used_bytes %zu\n" \
|
||||
"# HELP mem_cache Memory buffer/cache size in bytes\n" \
|
||||
"# TYPE mem_cache gauge\n" \
|
||||
"mem_cache_bytes %zu\n" \
|
||||
"# HELP rss_bytes RSS (Resident Set Size) in bytes\n" \
|
||||
"# TYPE rss_bytes gauge\n" \
|
||||
"rss_bytes %zu\n" \
|
||||
"# HELP disk_size_gibibytes Disk size in gibibytes\n" \
|
||||
"# TYPE disk_size_gibibytes counter\n" \
|
||||
"disk_size_gibibytes %zu\n" \
|
||||
@@ -141,6 +147,7 @@ static inline void gen_global_metrics(const neu_metrics_t *metrics,
|
||||
{
|
||||
fprintf(stream, METRIC_GLOBAL_TMPL, metrics->distro, metrics->kernel,
|
||||
metrics->cpu_percent, metrics->cpu_cores, metrics->mem_total_bytes,
|
||||
metrics->mem_used_bytes, metrics->mem_cache_bytes,
|
||||
metrics->mem_used_bytes, metrics->disk_size_gibibytes,
|
||||
metrics->disk_used_gibibytes, metrics->disk_avail_gibibytes,
|
||||
metrics->core_dumped, metrics->uptime_seconds, metrics->north_nodes,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"client-id": {
|
||||
"name": "Client ID",
|
||||
"name_zh": "客户端ID",
|
||||
"description": "Neuron MQTT client id",
|
||||
"description_zh": "Neuron MQTT客户端ID",
|
||||
"name_zh": "客户端 ID",
|
||||
"description": "MQTT client ID",
|
||||
"description_zh": "MQTT 客户端 ID",
|
||||
"type": "string",
|
||||
"attribute": "required",
|
||||
"default": "${node-name}",
|
||||
@@ -27,7 +27,7 @@
|
||||
"name": "Heartbeat Interval",
|
||||
"name_zh": "心跳间隔",
|
||||
"description": "Interval in seconds between two heartbeat messages. Setting to zero will disable heartbeat monitoring.(seconds)",
|
||||
"description_zh": "两个心跳消息之间的间隔时间,设置为0将禁用心跳监控。(秒)",
|
||||
"description_zh": "每个心跳消息之间的间隔时间(秒),设置为 0 将禁用心跳消息。",
|
||||
"attribute": "required",
|
||||
"type": "int",
|
||||
"default": 0,
|
||||
@@ -51,7 +51,7 @@
|
||||
"name": "Broker Host",
|
||||
"name_zh": "服务器地址",
|
||||
"description": "MQTT broker host",
|
||||
"description_zh": "MQTT服务器地址",
|
||||
"description_zh": "MQTT 服务器地址",
|
||||
"attribute": "required",
|
||||
"type": "string",
|
||||
"default": "broker.emqx.io",
|
||||
@@ -63,7 +63,7 @@
|
||||
"name": "Broker Port",
|
||||
"name_zh": "服务器端口",
|
||||
"description": "MQTT broker port",
|
||||
"description_zh": "MQTT服务器端口",
|
||||
"description_zh": "MQTT 服务器端口",
|
||||
"attribute": "required",
|
||||
"type": "int",
|
||||
"default": 1883,
|
||||
@@ -75,8 +75,8 @@
|
||||
"username": {
|
||||
"name": "Username",
|
||||
"name_zh": "用户名",
|
||||
"description": "User name",
|
||||
"description_zh": "用户名",
|
||||
"description": "MQTT user name",
|
||||
"description_zh": "MQTT 用户名",
|
||||
"attribute": "optional",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
@@ -87,8 +87,8 @@
|
||||
"password": {
|
||||
"name": "Password",
|
||||
"name_zh": "密码",
|
||||
"description": "Password",
|
||||
"description_zh": "密码",
|
||||
"description": "MQTT user password",
|
||||
"description_zh": "MQTT 用户密码",
|
||||
"attribute": "optional",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
@@ -100,7 +100,7 @@
|
||||
"name": "SSL",
|
||||
"name_zh": "SSL",
|
||||
"description": "Enable SSL connection",
|
||||
"description_zh": "是否启用SSL连接",
|
||||
"description_zh": "是否启用 SSL 连接",
|
||||
"attribute": "optional",
|
||||
"type": "bool",
|
||||
"default": false,
|
||||
@@ -108,9 +108,9 @@
|
||||
},
|
||||
"ca": {
|
||||
"name": "CA",
|
||||
"name_zh": "CA证书",
|
||||
"description": "CA certificate file",
|
||||
"description_zh": "CA证书文件",
|
||||
"name_zh": "CA 证书",
|
||||
"description": "CA certificate which signs the server certificate",
|
||||
"description_zh": "签发服务器证书的 CA 证书",
|
||||
"attribute": "required",
|
||||
"type": "file",
|
||||
"condition": {
|
||||
@@ -124,8 +124,8 @@
|
||||
"cert": {
|
||||
"name": "Client Cert",
|
||||
"name_zh": "客户端证书",
|
||||
"description": "Client x509 certificate file",
|
||||
"description_zh": "客户端证书文件",
|
||||
"description": "Client x509 certificate when using two way authentication",
|
||||
"description_zh": "使用双向认证时,客户端的 x509 证书",
|
||||
"attribute": "optional",
|
||||
"type": "file",
|
||||
"condition": {
|
||||
@@ -139,8 +139,8 @@
|
||||
"key": {
|
||||
"name": "Client Private Key",
|
||||
"name_zh": "客户端私钥",
|
||||
"description": "Client private key file",
|
||||
"description_zh": "客户端私钥文件",
|
||||
"description": "Client private key when using two way authentication",
|
||||
"description_zh": "使用双向认证时,客户端的私钥",
|
||||
"attribute": "optional",
|
||||
"type": "file",
|
||||
"condition": {
|
||||
@@ -152,10 +152,10 @@
|
||||
}
|
||||
},
|
||||
"keypass": {
|
||||
"name": "Keypass",
|
||||
"name_zh": "私钥密码",
|
||||
"description": "Private key password",
|
||||
"description_zh": "私钥密码",
|
||||
"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": {
|
||||
|
||||
+62
-34
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"client-id": {
|
||||
"name": "Client ID",
|
||||
"name_zh": "客户端ID",
|
||||
"description": "Neuron MQTT client id",
|
||||
"description_zh": "Neuron MQTT客户端ID",
|
||||
"name_zh": "客户端 ID",
|
||||
"description": "MQTT client id",
|
||||
"description_zh": "MQTT 客户端 ID",
|
||||
"type": "string",
|
||||
"attribute": "required",
|
||||
"default": "${node-name}",
|
||||
@@ -15,46 +15,71 @@
|
||||
"name": "QoS Level",
|
||||
"name_zh": "QoS 等级",
|
||||
"description": "MQTT QoS level for message delivery",
|
||||
"description_zh": "MQTT消息传输使用的服务质量等级",
|
||||
"type": "int",
|
||||
"description_zh": "MQTT 消息传输使用的服务质量等级",
|
||||
"type": "map",
|
||||
"attribute": "optional",
|
||||
"default": 0,
|
||||
"valid": {
|
||||
"min": 0,
|
||||
"max": 2
|
||||
"map": [
|
||||
{
|
||||
"key": "QoS 0",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"key": "QoS 1",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"key": "QoS 2",
|
||||
"value": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"format": {
|
||||
"name": "Upload Format",
|
||||
"name_zh": "上报数据格式",
|
||||
"description": "JSON format of the data reported in the upload topic. In values mode, data are split into `values` and `errors` sub objects. In tags mode, tag data are put in a single array.",
|
||||
"description_zh": "上报数据的JSON格式。在values模式下,数据被分为`values`和`errors`两个子对象。在tags模式下,tag数据被放在一个数组中。",
|
||||
"description": "JSON format of the data reported. In values-mode, data are split into `values` and `errors` sub objects. In tags-mode, tag data are put in a single array.",
|
||||
"description_zh": "上报数据的 JSON 格式。在 values-format 格式下,数据被分为 `values` 和 `errors` 两个子对象。在 tags-format 格式下,数据被放在一个数组中。",
|
||||
"attribute": "required",
|
||||
"type": "map",
|
||||
"default": 0,
|
||||
"valid": {
|
||||
"map": [
|
||||
{
|
||||
"key": "format-values",
|
||||
"key": "values-format",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"key": "format-tags",
|
||||
"key": "tags-format",
|
||||
"value": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"offline-cache": {
|
||||
"name": "Offline Data Caching",
|
||||
"name_zh": "离线缓存",
|
||||
"description": "Offline caching switch. Cache MQTT messages when offline, and sync cached messages when back online.",
|
||||
"description_zh": "离线缓存开关。连接断开时缓存 MQTT 消息,连接重建时同步缓存的 MQTT 消息到服务器。",
|
||||
"attribute": "optional",
|
||||
"type": "bool",
|
||||
"default": false,
|
||||
"valid": {}
|
||||
},
|
||||
"cache-mem-size": {
|
||||
"name": "Cache Memory Size (MB)",
|
||||
"name_zh": "缓存内存大小(MB)",
|
||||
"description": "Max in-memory cache size in megabytes when MQTT connection exception occurs. Should be smaller than cache disk size.",
|
||||
"description_zh": "当MQTT连接异常时,最大的内存缓存大小(单位:MB)。应该小于缓存磁盘大小。",
|
||||
"description_zh": "当 MQTT 连接异常时,最大的内存缓存大小(单位:MB)。应该小于缓存磁盘大小。",
|
||||
"type": "int",
|
||||
"attribute": "required",
|
||||
"default": 0,
|
||||
"condition": {
|
||||
"field": "offline-cache",
|
||||
"value": true
|
||||
},
|
||||
"valid": {
|
||||
"min": 0,
|
||||
"min": 1,
|
||||
"max": 1024
|
||||
}
|
||||
},
|
||||
@@ -62,12 +87,15 @@
|
||||
"name": "Cache Disk Size (MB)",
|
||||
"name_zh": "缓存磁盘大小(MB)",
|
||||
"description": "Max in-disk cache size in megabytes when MQTT connection exception occurs. Should be larger than cache memory size. If nonzero, cache memory size should also be nonzero.",
|
||||
"description_zh": "当MQTT连接异常时,最大的磁盘缓存大小(单位:MB)。应该大于缓存内存大小。如果不为0,缓存内存大小也不应该为0。",
|
||||
"description_zh": "当 MQTT 连接异常时,最大的磁盘缓存大小(单位:MB)。应该大于缓存内存大小。如果不为 0,缓存内存大小也应该不为 0。",
|
||||
"type": "int",
|
||||
"attribute": "required",
|
||||
"default": 0,
|
||||
"condition": {
|
||||
"field": "offline-cache",
|
||||
"value": true
|
||||
},
|
||||
"valid": {
|
||||
"min": 0,
|
||||
"min": 1,
|
||||
"max": 10240
|
||||
}
|
||||
},
|
||||
@@ -75,7 +103,7 @@
|
||||
"name": "Broker Host",
|
||||
"name_zh": "服务器地址",
|
||||
"description": "MQTT broker host",
|
||||
"description_zh": "MQTT服务器地址",
|
||||
"description_zh": "MQTT 服务器地址",
|
||||
"attribute": "required",
|
||||
"type": "string",
|
||||
"default": "broker.emqx.io",
|
||||
@@ -87,7 +115,7 @@
|
||||
"name": "Broker Port",
|
||||
"name_zh": "服务器端口",
|
||||
"description": "MQTT broker port",
|
||||
"description_zh": "MQTT服务器端口",
|
||||
"description_zh": "MQTT 服务器端口",
|
||||
"attribute": "required",
|
||||
"type": "int",
|
||||
"default": 1883,
|
||||
@@ -99,8 +127,8 @@
|
||||
"username": {
|
||||
"name": "Username",
|
||||
"name_zh": "用户名",
|
||||
"description": "User name",
|
||||
"description_zh": "用户名",
|
||||
"description": "MQTT user name",
|
||||
"description_zh": "MQTT 用户名",
|
||||
"attribute": "optional",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
@@ -111,8 +139,8 @@
|
||||
"password": {
|
||||
"name": "Password",
|
||||
"name_zh": "密码",
|
||||
"description": "Password",
|
||||
"description_zh": "密码",
|
||||
"description": "MQTT user password",
|
||||
"description_zh": "MQTT 用户密码",
|
||||
"attribute": "optional",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
@@ -124,7 +152,7 @@
|
||||
"name": "SSL",
|
||||
"name_zh": "SSL",
|
||||
"description": "Enable SSL connection",
|
||||
"description_zh": "是否启用SSL连接",
|
||||
"description_zh": "是否启用 SSL 连接",
|
||||
"attribute": "optional",
|
||||
"type": "bool",
|
||||
"default": false,
|
||||
@@ -132,9 +160,9 @@
|
||||
},
|
||||
"ca": {
|
||||
"name": "CA",
|
||||
"name_zh": "CA证书",
|
||||
"description": "CA certificate file",
|
||||
"description_zh": "CA证书文件",
|
||||
"name_zh": "CA 证书",
|
||||
"description": "CA certificate which signs the server certificate",
|
||||
"description_zh": "签发服务器证书的 CA 证书",
|
||||
"attribute": "required",
|
||||
"type": "file",
|
||||
"condition": {
|
||||
@@ -148,8 +176,8 @@
|
||||
"cert": {
|
||||
"name": "Client Cert",
|
||||
"name_zh": "客户端证书",
|
||||
"description": "Client x509 certificate file",
|
||||
"description_zh": "客户端证书文件",
|
||||
"description": "Client x509 certificate when using two way authentication",
|
||||
"description_zh": "使用双向认证时,客户端的 x509 证书",
|
||||
"attribute": "optional",
|
||||
"type": "file",
|
||||
"condition": {
|
||||
@@ -163,8 +191,8 @@
|
||||
"key": {
|
||||
"name": "Client Private Key",
|
||||
"name_zh": "客户端私钥",
|
||||
"description": "Client private key file",
|
||||
"description_zh": "客户端私钥文件",
|
||||
"description": "Client private key when using two way authentication",
|
||||
"description_zh": "使用双向认证时,客户端的私钥",
|
||||
"attribute": "optional",
|
||||
"type": "file",
|
||||
"condition": {
|
||||
@@ -177,9 +205,9 @@
|
||||
},
|
||||
"keypass": {
|
||||
"name": "Client Private Key Password",
|
||||
"name_zh": "私钥密码",
|
||||
"description": "Client private key password",
|
||||
"description_zh": "私钥密码",
|
||||
"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": {
|
||||
|
||||
+85
-33
@@ -115,6 +115,79 @@ static inline int parse_ssl_params(neu_plugin_t *plugin, const char *setting,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_cache_params(neu_plugin_t *plugin, const char *setting,
|
||||
neu_json_elem_t *offline_cache,
|
||||
neu_json_elem_t *cache_mem_size,
|
||||
neu_json_elem_t *cache_disk_size)
|
||||
{
|
||||
int ret = 0;
|
||||
char *err_param = NULL;
|
||||
bool flag_present = true; // whether setting has `offline-cache`
|
||||
|
||||
// offline-cache flag, optional
|
||||
ret = neu_parse_param(setting, NULL, 1, offline_cache);
|
||||
if (0 != ret) {
|
||||
plog_info(plugin, "setting no offline cache flag");
|
||||
flag_present = false; // `offline-cache` not present in setting
|
||||
}
|
||||
|
||||
if (flag_present && !offline_cache->v.val_bool) {
|
||||
// cache explicitly disabled in setting
|
||||
cache_mem_size->v.val_int = 0;
|
||||
cache_disk_size->v.val_int = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// we are here because one of the following:
|
||||
// 1. `offline-cache` presents to be true in setting
|
||||
// 2. no `offline-cache` in setting
|
||||
// we require `cache_mem_size` and `cache_disk_size` to present in both
|
||||
// cases, especially in case 2 for backward compatibility.
|
||||
|
||||
ret = neu_parse_param(setting, &err_param, 2, cache_mem_size,
|
||||
cache_disk_size);
|
||||
if (0 != ret) {
|
||||
plog_error(plugin, "parsing setting fail, key: `%s`", err_param);
|
||||
free(err_param);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_mem_size->v.val_int > 1024 ||
|
||||
(flag_present && cache_mem_size->v.val_int < 1)) {
|
||||
plog_error(plugin, "setting invalid cache memory size: %" PRIi64,
|
||||
cache_mem_size->v.val_int);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_disk_size->v.val_int > 10240 ||
|
||||
(flag_present && cache_disk_size->v.val_int < 1)) {
|
||||
plog_error(plugin, "setting invalid cache disk size: %" PRIi64,
|
||||
cache_disk_size->v.val_int);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_mem_size->v.val_int > cache_disk_size->v.val_int) {
|
||||
plog_error(plugin,
|
||||
"setting cache memory size %" PRIi64
|
||||
" larger than cache disk size %" PRIi64,
|
||||
cache_mem_size->v.val_int, cache_disk_size->v.val_int);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == cache_mem_size->v.val_int && 0 != cache_disk_size->v.val_int) {
|
||||
plog_error(plugin,
|
||||
"setting cache disk size %" PRIi64 " without memory cache",
|
||||
cache_disk_size->v.val_int);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!flag_present) {
|
||||
offline_cache->v.val_bool = cache_mem_size->v.val_int > 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mqtt_config_parse(neu_plugin_t *plugin, const char *setting,
|
||||
mqtt_config_t *config)
|
||||
{
|
||||
@@ -130,6 +203,8 @@ int mqtt_config_parse(neu_plugin_t *plugin, const char *setting,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL, // for backward compatibility
|
||||
};
|
||||
neu_json_elem_t format = { .name = "format", .t = NEU_JSON_INT };
|
||||
neu_json_elem_t offline_cache = { .name = "offline-cache",
|
||||
.t = NEU_JSON_BOOL };
|
||||
neu_json_elem_t cache_mem_size = { .name = "cache-mem-size",
|
||||
.t = NEU_JSON_INT };
|
||||
neu_json_elem_t cache_disk_size = { .name = "cache-disk-size",
|
||||
@@ -149,8 +224,8 @@ int mqtt_config_parse(neu_plugin_t *plugin, const char *setting,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = neu_parse_param(setting, &err_param, 7, &client_id, &format, &qos,
|
||||
&cache_mem_size, &cache_disk_size, &host, &port);
|
||||
ret = neu_parse_param(setting, &err_param, 5, &client_id, &format, &qos,
|
||||
&host, &port);
|
||||
if (0 != ret) {
|
||||
plog_error(plugin, "parsing setting fail, key: `%s`", err_param);
|
||||
goto error;
|
||||
@@ -176,32 +251,10 @@ int mqtt_config_parse(neu_plugin_t *plugin, const char *setting,
|
||||
goto error;
|
||||
}
|
||||
|
||||
// cache memory size, required
|
||||
if (cache_mem_size.v.val_int > 1024) {
|
||||
plog_error(plugin, "setting invalid cache memory size: %" PRIi64,
|
||||
cache_mem_size.v.val_int);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// cache disk size, required
|
||||
if (cache_disk_size.v.val_int > 10240) {
|
||||
plog_error(plugin, "setting invalid cache disk size: %" PRIi64,
|
||||
cache_disk_size.v.val_int);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (cache_mem_size.v.val_int > cache_disk_size.v.val_int) {
|
||||
plog_error(plugin,
|
||||
"setting cache memory size %" PRIi64
|
||||
" larger than cache disk size %" PRIi64,
|
||||
cache_mem_size.v.val_int, cache_disk_size.v.val_int);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (0 == cache_mem_size.v.val_int && 0 != cache_disk_size.v.val_int) {
|
||||
plog_error(plugin,
|
||||
"setting cache disk size %" PRIi64 " without memory cache",
|
||||
cache_disk_size.v.val_int);
|
||||
// offline cache
|
||||
ret = parse_cache_params(plugin, setting, &offline_cache, &cache_mem_size,
|
||||
&cache_disk_size);
|
||||
if (0 != ret) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -234,11 +287,10 @@ int mqtt_config_parse(neu_plugin_t *plugin, const char *setting,
|
||||
goto error;
|
||||
}
|
||||
|
||||
config->client_id = client_id.v.val_str;
|
||||
config->qos = qos.v.val_int;
|
||||
config->format = format.v.val_int;
|
||||
config->cache =
|
||||
0 != cache_mem_size.v.val_int || 0 != cache_disk_size.v.val_int;
|
||||
config->client_id = client_id.v.val_str;
|
||||
config->qos = qos.v.val_int;
|
||||
config->format = format.v.val_int;
|
||||
config->cache = offline_cache.v.val_bool;
|
||||
config->cache_mem_size = cache_mem_size.v.val_int * MB;
|
||||
config->cache_disk_size = cache_disk_size.v.val_int * MB;
|
||||
config->host = host.v.val_str;
|
||||
|
||||
@@ -42,8 +42,6 @@
|
||||
#include "log_handle.h"
|
||||
#include "utils/utarray.h"
|
||||
|
||||
UT_array *collect_log_files();
|
||||
|
||||
void handle_logs_files(nng_aio *aio)
|
||||
{
|
||||
void * data = NULL;
|
||||
@@ -114,94 +112,43 @@ void handle_log_level(nng_aio *aio)
|
||||
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
|
||||
aio, neu_json_update_log_level_req_t,
|
||||
neu_json_decode_update_log_level_req, {
|
||||
char node_name[NEU_NODE_NAME_LEN] = { 0 };
|
||||
int ret = 0;
|
||||
neu_reqresp_head_t header = { 0 };
|
||||
neu_req_update_log_level_t cmd = { 0 };
|
||||
zlog_category_t * ct = zlog_get_category(req->node_name);
|
||||
zlog_category_t * neuron = zlog_get_category("neuron");
|
||||
|
||||
UT_array *log_files = collect_log_files();
|
||||
|
||||
utarray_foreach(log_files, char **, log_file)
|
||||
{
|
||||
if (strncmp(*log_file, req->node_name, strlen(*log_file) - 4) ==
|
||||
0) {
|
||||
strcpy(node_name, req->node_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(node_name) == 0) {
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_NOT_EXIST, {
|
||||
ret = zlog_level_switch(ct, ZLOG_LEVEL_DEBUG);
|
||||
if (ret != 0) {
|
||||
nlog_error("Modify node log level fail, node_name:%s, "
|
||||
"ret: %d,",
|
||||
req->node_name, ret);
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_EINTERNAL, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
} else {
|
||||
int ret = 0;
|
||||
neu_reqresp_head_t header = { 0 };
|
||||
neu_req_update_log_level_t cmd = { 0 };
|
||||
zlog_category_t * ct = zlog_get_category(node_name);
|
||||
zlog_category_t * neuron = zlog_get_category("neuron");
|
||||
|
||||
ret = zlog_level_switch(ct, ZLOG_LEVEL_DEBUG);
|
||||
if (ret != 0) {
|
||||
nlog_error("Modify node log level fail, node_name:%s, "
|
||||
"ret: %d,",
|
||||
node_name, ret);
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_EINTERNAL, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
}
|
||||
|
||||
ret = zlog_level_switch(neuron, ZLOG_LEVEL_DEBUG);
|
||||
if (ret != 0) {
|
||||
nlog_error("Modify neuron log level fail, ret: %d", ret);
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_EINTERNAL, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
}
|
||||
|
||||
header.ctx = aio;
|
||||
header.type = NEU_REQ_UPDATE_LOG_LEVEL;
|
||||
strcpy(cmd.node, req->node_name);
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
utarray_free(log_files);
|
||||
ret = zlog_level_switch(neuron, ZLOG_LEVEL_DEBUG);
|
||||
if (ret != 0) {
|
||||
nlog_error("Modify neuron log level fail, ret: %d", ret);
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_EINTERNAL, {
|
||||
neu_http_response(aio, error_code.error, result_error);
|
||||
});
|
||||
}
|
||||
|
||||
header.ctx = aio;
|
||||
header.type = NEU_REQ_UPDATE_LOG_LEVEL;
|
||||
strcpy(cmd.node, req->node_name);
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static inline bool ends_with(const char *str, const char *suffix)
|
||||
{
|
||||
size_t m = strlen(str);
|
||||
size_t n = strlen(suffix);
|
||||
return m >= n && !strcmp(str + m - n, suffix);
|
||||
}
|
||||
|
||||
UT_array *collect_log_files()
|
||||
{
|
||||
DIR *dp = opendir("./logs");
|
||||
if (NULL == dp) {
|
||||
nlog_error("open logs directory fail");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UT_array *log_files = NULL;
|
||||
utarray_new(log_files, &ut_str_icd);
|
||||
|
||||
struct dirent *de = NULL;
|
||||
while (NULL != (de = readdir(dp))) {
|
||||
char *name = de->d_name;
|
||||
if (ends_with(de->d_name, ".log")) {
|
||||
utarray_push_back(log_files, &name);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
|
||||
return log_files;
|
||||
}
|
||||
|
||||
int read_file(const char *file_name, void **datap, size_t *lenp)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
@@ -302,6 +302,8 @@ void neu_adapter_driver_write_tag(neu_adapter_driver_t *driver,
|
||||
(double) (cmd->value.value.d64 / tag->decimal);
|
||||
} else if (cmd->value.type == NEU_TYPE_DOUBLE) {
|
||||
cmd->value.value.d64 = cmd->value.value.d64 / tag->decimal;
|
||||
} else if (cmd->value.type == NEU_TYPE_FLOAT) {
|
||||
cmd->value.value.f32 = cmd->value.value.f32 / tag->decimal;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -360,8 +362,11 @@ void neu_adapter_driver_write_tag(neu_adapter_driver_t *driver,
|
||||
}
|
||||
break;
|
||||
case NEU_TYPE_FLOAT:
|
||||
cmd->value.type = NEU_TYPE_FLOAT;
|
||||
cmd->value.value.f32 = (float) cmd->value.value.d64;
|
||||
if (NEU_TYPE_FLOAT != cmd->value.type) {
|
||||
cmd->value.value.f32 = (float) cmd->value.value.d64;
|
||||
cmd->value.type = NEU_TYPE_FLOAT;
|
||||
}
|
||||
|
||||
switch (tag->option.value32.endian) {
|
||||
case NEU_DATATAG_ENDIAN_LB32:
|
||||
neu_ntohs_p((uint16_t *) cmd->value.value.bytes);
|
||||
@@ -998,7 +1003,8 @@ static int read_report_group(int64_t timestamp, int64_t timeout,
|
||||
break;
|
||||
}
|
||||
|
||||
if ((timestamp - value.timestamp) > timeout) {
|
||||
if (!neu_tag_attribute_test(tag, NEU_ATTRIBUTE_STATIC) &&
|
||||
(timestamp - value.timestamp) > timeout) {
|
||||
datas[index].value.type = NEU_TYPE_ERROR;
|
||||
datas[index].value.value.i32 = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
|
||||
} else {
|
||||
|
||||
@@ -101,6 +101,11 @@ static inline size_t memory_used()
|
||||
return parse_memory_fields(3);
|
||||
}
|
||||
|
||||
static inline size_t memory_cache()
|
||||
{
|
||||
return parse_memory_fields(6);
|
||||
}
|
||||
|
||||
static inline int disk_usage(size_t *size_p, size_t *used_p, size_t *avail_p)
|
||||
{
|
||||
struct statvfs buf = {};
|
||||
@@ -276,6 +281,7 @@ void neu_metrics_visist(neu_metrics_cb_t cb, void *data)
|
||||
{
|
||||
unsigned cpu = cpu_usage();
|
||||
size_t mem_used = memory_used();
|
||||
size_t mem_cache = memory_cache();
|
||||
size_t disk_size = 0, disk_used = 0, disk_avail = 0;
|
||||
disk_usage(&disk_size, &disk_used, &disk_avail);
|
||||
bool core_dumped = has_core_dumps();
|
||||
@@ -284,6 +290,7 @@ void neu_metrics_visist(neu_metrics_cb_t cb, void *data)
|
||||
g_metrics_.cpu_percent = cpu;
|
||||
g_metrics_.cpu_cores = get_nprocs();
|
||||
g_metrics_.mem_used_bytes = mem_used;
|
||||
g_metrics_.mem_cache_bytes = mem_cache;
|
||||
g_metrics_.disk_size_gibibytes = disk_size;
|
||||
g_metrics_.disk_used_gibibytes = disk_used;
|
||||
g_metrics_.disk_avail_gibibytes = disk_avail;
|
||||
|
||||
+62
-11
@@ -69,6 +69,8 @@ struct neu_conn {
|
||||
static void conn_tcp_server_add_client(neu_conn_t *conn, int fd,
|
||||
struct sockaddr_in client);
|
||||
static void conn_tcp_server_del_client(neu_conn_t *conn, int fd);
|
||||
static int conn_tcp_server_replace_client(neu_conn_t *conn, int fd,
|
||||
struct sockaddr_in client);
|
||||
|
||||
static void conn_tcp_server_listen(neu_conn_t *conn);
|
||||
static void conn_tcp_server_stop(neu_conn_t *conn);
|
||||
@@ -180,16 +182,6 @@ int neu_conn_tcp_server_accept(neu_conn_t *conn)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->tcp_server.n_client >= conn->param.params.tcp_server.max_link) {
|
||||
close(fd);
|
||||
zlog_warn(conn->param.log, "%s:%d accpet max link: %d, reject",
|
||||
conn->param.params.tcp_server.ip,
|
||||
conn->param.params.tcp_server.port,
|
||||
conn->param.params.tcp_server.max_link);
|
||||
pthread_mutex_unlock(&conn->mtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->block) {
|
||||
struct timeval tv = {
|
||||
.tv_sec = conn->param.params.tcp_server.timeout / 1000,
|
||||
@@ -199,7 +191,23 @@ int neu_conn_tcp_server_accept(neu_conn_t *conn)
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
|
||||
}
|
||||
|
||||
conn_tcp_server_add_client(conn, fd, client);
|
||||
if (conn->tcp_server.n_client >= conn->param.params.tcp_server.max_link) {
|
||||
int free_fd = conn_tcp_server_replace_client(conn, fd, client);
|
||||
if (free_fd > 0) {
|
||||
zlog_warn(conn->param.log, "replace old client %d with %d", free_fd,
|
||||
fd);
|
||||
} else {
|
||||
close(fd);
|
||||
zlog_warn(conn->param.log, "%s:%d accpet max link: %d, reject",
|
||||
conn->param.params.tcp_server.ip,
|
||||
conn->param.params.tcp_server.port,
|
||||
conn->param.params.tcp_server.max_link);
|
||||
pthread_mutex_unlock(&conn->mtx);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
conn_tcp_server_add_client(conn, fd, client);
|
||||
}
|
||||
|
||||
conn->is_connected = true;
|
||||
conn->connected(conn->data, fd);
|
||||
@@ -728,6 +736,30 @@ static void conn_connect(neu_conn_t *conn)
|
||||
cfsetospeed(&tty_opt, B2400);
|
||||
cfsetispeed(&tty_opt, B2400);
|
||||
break;
|
||||
case NEU_CONN_TTY_BAUD_1800:
|
||||
cfsetospeed(&tty_opt, B1800);
|
||||
cfsetispeed(&tty_opt, B1800);
|
||||
break;
|
||||
case NEU_CONN_TTY_BAUD_1200:
|
||||
cfsetospeed(&tty_opt, B1200);
|
||||
cfsetispeed(&tty_opt, B1200);
|
||||
break;
|
||||
case NEU_CONN_TTY_BAUD_600:
|
||||
cfsetospeed(&tty_opt, B600);
|
||||
cfsetispeed(&tty_opt, B600);
|
||||
break;
|
||||
case NEU_CONN_TTY_BAUD_300:
|
||||
cfsetospeed(&tty_opt, B300);
|
||||
cfsetispeed(&tty_opt, B300);
|
||||
break;
|
||||
case NEU_CONN_TTY_BAUD_200:
|
||||
cfsetospeed(&tty_opt, B200);
|
||||
cfsetispeed(&tty_opt, B200);
|
||||
break;
|
||||
case NEU_CONN_TTY_BAUD_150:
|
||||
cfsetospeed(&tty_opt, B150);
|
||||
cfsetispeed(&tty_opt, B150);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (conn->param.params.tty_client.parity) {
|
||||
@@ -867,6 +899,25 @@ static void conn_tcp_server_del_client(neu_conn_t *conn, int fd)
|
||||
}
|
||||
}
|
||||
|
||||
static int conn_tcp_server_replace_client(neu_conn_t *conn, int fd,
|
||||
struct sockaddr_in client)
|
||||
{
|
||||
for (int i = 0; i < conn->param.params.tcp_server.max_link; i++) {
|
||||
if (conn->tcp_server.clients[i].fd > 0) {
|
||||
int ret = conn->tcp_server.clients[i].fd;
|
||||
|
||||
close(conn->tcp_server.clients[i].fd);
|
||||
conn->tcp_server.clients[i].fd = 0;
|
||||
|
||||
conn->tcp_server.clients[i].fd = fd;
|
||||
conn->tcp_server.clients[i].client = client;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int neu_conn_stream_consume(neu_conn_t *conn, void *context,
|
||||
neu_conn_stream_consume_fn fn)
|
||||
{
|
||||
|
||||
@@ -150,6 +150,7 @@ static void connect_cb(nng_pipe p, nng_pipe_ev ev, void *arg);
|
||||
|
||||
static inline task_t *client_alloc_task(neu_mqtt_client_t *client);
|
||||
static inline void client_free_task(neu_mqtt_client_t *client, task_t *task);
|
||||
static inline size_t client_task_free_list_len(neu_mqtt_client_t *client);
|
||||
static inline void client_add_subscription(neu_mqtt_client_t *client,
|
||||
subscription_t * sub);
|
||||
static int client_send_sub_msg(neu_mqtt_client_t *client,
|
||||
@@ -545,6 +546,16 @@ static inline void client_free_task(neu_mqtt_client_t *client, task_t *task)
|
||||
DL_PREPEND(client->task_free_list, task);
|
||||
}
|
||||
|
||||
static inline size_t client_task_free_list_len(neu_mqtt_client_t *client)
|
||||
{
|
||||
size_t count = 0;
|
||||
task_t *elt = NULL;
|
||||
// count by iterating the list,
|
||||
// this won't be a problem as a short free list is expected
|
||||
DL_COUNT(client->task_free_list, elt, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline void client_add_subscription(neu_mqtt_client_t *client,
|
||||
subscription_t * sub)
|
||||
{
|
||||
@@ -1149,6 +1160,12 @@ int neu_mqtt_client_close(neu_mqtt_client_t *client)
|
||||
}
|
||||
|
||||
nng_mtx_lock(client->mtx);
|
||||
// wait for all tasks
|
||||
while (client_task_free_list_len(client) != client->task_count) {
|
||||
nng_mtx_unlock(client->mtx);
|
||||
nng_msleep(100);
|
||||
nng_mtx_lock(client->mtx);
|
||||
}
|
||||
client->open = false;
|
||||
nng_mtx_unlock(client->mtx);
|
||||
|
||||
|
||||
@@ -50,11 +50,6 @@ typedef struct plugin_entity {
|
||||
UT_hash_handle hh;
|
||||
} plugin_entity_t;
|
||||
|
||||
typedef struct {
|
||||
char *name_old;
|
||||
char *name_new;
|
||||
} plugin_name_t;
|
||||
|
||||
struct neu_plugin_manager {
|
||||
plugin_entity_t *plugins;
|
||||
};
|
||||
@@ -239,41 +234,6 @@ int neu_plugin_manager_find(neu_plugin_manager_t *mgr, const char *plugin_name,
|
||||
plugin_entity_t *plugin = NULL;
|
||||
int ret = -1;
|
||||
|
||||
static const plugin_name_t name[] = {
|
||||
{ "mqtt", "MQTT" },
|
||||
{ "ekuiper", "eKuiper" },
|
||||
{ "modbus-tcp", "Modbus TCP community" },
|
||||
{ "a1e", "Mitsubishi 1E" },
|
||||
{ "ads", "Beckhoff ADS" },
|
||||
{ "bacnet", "BACnet/IP" },
|
||||
{ "dlt645", "DLT645-2007" },
|
||||
{ "EtherNet-IP", "EtherNet/IP(CIP)" },
|
||||
{ "fins", "Omron FINS TCP" },
|
||||
{ "focas", "Fanuc Focas Ethernet" },
|
||||
{ "iec104", "IEC60870-5-104" },
|
||||
{ "knx", "KNXnet/IP" },
|
||||
{ "modbus-qh-tcp", "Modbus TCP QH" },
|
||||
{ "modbus-rtu", "Modbus RTU" },
|
||||
{ "modbus-plus-tcp", "Modbus TCP" },
|
||||
{ "nona11", "NON A11" },
|
||||
{ "opcua", "OPC UA" },
|
||||
{ "qna3e", "Mitsubishi 3E" },
|
||||
{ "s7comm", "Siemens S7 ISOTCP" },
|
||||
{ "s7comm_for_300", "Siemens S7 ISOTCP for 300/400" },
|
||||
{ "sparkplugb", "SparkPlugB" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
int i = 0;
|
||||
while (name[i].name_old != NULL) {
|
||||
if (strcmp(plugin_name, name[i].name_old) == 0) {
|
||||
plugin_name = name[i].name_new;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
HASH_FIND_STR(mgr->plugins, plugin_name, plugin);
|
||||
if (plugin != NULL) {
|
||||
ret = 0;
|
||||
|
||||
@@ -105,9 +105,6 @@ int neu_json_decode_global_config_req_tags(
|
||||
}
|
||||
|
||||
req->n_tag = json_array_size(tag_array);
|
||||
if (req->n_tag <= 0) {
|
||||
goto decode_fail;
|
||||
}
|
||||
|
||||
req->tags = calloc(req->n_tag, sizeof(*req->tags));
|
||||
if (NULL == req->tags) {
|
||||
|
||||
@@ -311,9 +311,6 @@ int neu_json_decode_get_driver_group_resp_json(
|
||||
}
|
||||
|
||||
resp->n_group = json_array_size(grp_array);
|
||||
if (resp->n_group <= 0) {
|
||||
goto decode_fail;
|
||||
}
|
||||
|
||||
resp->groups = calloc(resp->n_group, sizeof(*resp->groups));
|
||||
if (NULL == resp->groups) {
|
||||
|
||||
Reference in New Issue
Block a user