mirror of
https://github.com/emqx/neuron.git
synced 2026-10-29 23:19:18 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a554f0cb8 | ||
|
|
a44c5f7d24 | ||
|
|
d5db733b7b | ||
|
|
fce430023c | ||
|
|
a82428a482 | ||
|
|
4850eba649 | ||
|
|
8e62bc1b22 | ||
|
|
896eb3a52e | ||
|
|
1539dd065a | ||
|
|
574c34a085 | ||
|
|
ba8d56fdd0 | ||
|
|
8795028313 | ||
|
|
05d83878db | ||
|
|
d031a0ee71 | ||
|
|
969a302b58 | ||
|
|
57d5a51aad | ||
|
|
c46795ce30 | ||
|
|
ef9e505517 | ||
|
|
24d3ce2667 | ||
|
|
3c71082121 | ||
|
|
0d1c2b93c0 |
@@ -12,7 +12,7 @@ $ cd zlog
|
||||
$ make && sudo make install
|
||||
```
|
||||
|
||||
[jansson](https://github.com/akheron/jansson)
|
||||
[jansson](https://github.com/neugates/jansson.git)
|
||||
```shell
|
||||
$ git clone https://github.com/neugates/jansson.git
|
||||
$ cd jansson && mkdir build && cd build
|
||||
|
||||
@@ -2,27 +2,27 @@
|
||||
"tag_regex": [
|
||||
{
|
||||
"type": 3,
|
||||
"regex": "[0-9]+![3-4][0-9]+(#B|#L|)$"
|
||||
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
|
||||
},
|
||||
{
|
||||
"type": 4,
|
||||
"regex": "[0-9]+![3-4][0-9]+(#B|#L|)$"
|
||||
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
|
||||
},
|
||||
{
|
||||
"type": 5,
|
||||
"regex": "[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
|
||||
"regex": "^[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
|
||||
},
|
||||
{
|
||||
"type": 6,
|
||||
"regex": "[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
|
||||
"regex": "^[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
|
||||
},
|
||||
{
|
||||
"type": 9,
|
||||
"regex": "[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
|
||||
"regex": "^[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
|
||||
},
|
||||
{
|
||||
"type": 11,
|
||||
"regex": "[0-9]+!([0-1][0-9]+|[3-4][0-9]+.([0-9]|[0-1][0-5]))$"
|
||||
"regex": "^[0-9]+!([0-1][0-9]+|[3-4][0-9]+\\.([0-9]|[0-1][0-5]))$"
|
||||
}
|
||||
],
|
||||
"host": {
|
||||
|
||||
@@ -168,7 +168,7 @@ int modbus_value_handle(void *ctx, uint8_t slave_id, uint16_t n_byte,
|
||||
neu_value16_u v16 = { 0 };
|
||||
v16.value = htons(*(uint16_t *) dvalue.value.bytes);
|
||||
dvalue.value.u8 =
|
||||
neu_value16_get_bit(v16, 15 - (*p_tag)->option.bit.bit);
|
||||
neu_value16_get_bit(v16, (*p_tag)->option.bit.bit);
|
||||
break;
|
||||
}
|
||||
case MODBUS_AREA_COIL:
|
||||
|
||||
@@ -65,7 +65,7 @@ static uint64_t mktimestamp(struct tm dt)
|
||||
uint64_t ret;
|
||||
int i = 0;
|
||||
|
||||
ret = (dt.tm_year - 1970) * 365 * 24 * 3600;
|
||||
ret = ((uint64_t) dt.tm_year - 1970) * 365 * 24 * 3600;
|
||||
ret +=
|
||||
(mon_yday[isleap(dt.tm_year)][dt.tm_mon] + dt.tm_mday - 1) * 24 * 3600;
|
||||
ret += dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -43,10 +44,95 @@ int get_plugin_names(const license_t *lic, UT_array *plugin_names);
|
||||
static inline char *get_license_path()
|
||||
{
|
||||
char *s = NULL;
|
||||
neu_asprintf(&s, "%s/%s", g_config_dir, LICENSE_FNAME);
|
||||
neu_asprintf(&s, "persistence/%s", LICENSE_FNAME);
|
||||
return s;
|
||||
}
|
||||
|
||||
static int copy_file(const char *from, const char *to)
|
||||
{
|
||||
int rv = 0;
|
||||
char * buf = NULL;
|
||||
FILE * fp = NULL;
|
||||
struct stat statbuf = {};
|
||||
|
||||
if (0 != stat(from, &statbuf)) {
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
buf = malloc(statbuf.st_size);
|
||||
if (NULL == buf) {
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
fp = fopen(from, "rb");
|
||||
if (NULL == fp) {
|
||||
rv = NEU_ERR_EINTERNAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((size_t) statbuf.st_size != fread(buf, 1, statbuf.st_size, fp)) {
|
||||
rv = NEU_ERR_EINTERNAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fp = fopen(to, "w");
|
||||
if (NULL == fp) {
|
||||
rv = NEU_ERR_EINTERNAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((size_t) statbuf.st_size != fwrite(buf, 1, statbuf.st_size, fp)) {
|
||||
rv = NEU_ERR_EINTERNAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int copy_license_file_if_necessary()
|
||||
{
|
||||
struct stat statbuf = {};
|
||||
char * license_path = get_license_path();
|
||||
|
||||
if (NULL == license_path) {
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
if (0 == stat(license_path, &statbuf)) {
|
||||
free(license_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nlog_warn("license `%s` not found", license_path);
|
||||
|
||||
char *fallback_path = NULL;
|
||||
neu_asprintf(&fallback_path, "%s/%s", g_config_dir, LICENSE_FNAME);
|
||||
if (NULL == fallback_path) {
|
||||
free(license_path);
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
if (0 != stat(fallback_path, &statbuf)) {
|
||||
// no fallback license file
|
||||
free(license_path);
|
||||
free(fallback_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nlog_warn("fallback to `%s`", fallback_path);
|
||||
int rv = copy_file(fallback_path, license_path);
|
||||
|
||||
free(license_path);
|
||||
free(fallback_path);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void handle_get_license(nng_aio *aio)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <nng/nng.h>
|
||||
|
||||
int copy_license_file_if_necessary();
|
||||
void handle_get_license(nng_aio *aio);
|
||||
void handle_set_license(nng_aio *aio);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "group_config_handle.h"
|
||||
#include "handle.h"
|
||||
#include "http.h"
|
||||
#include "license_handle.h"
|
||||
#include "plugin_handle.h"
|
||||
#include "proxy.h"
|
||||
#include "rest.h"
|
||||
@@ -145,6 +146,12 @@ static neu_plugin_t *dashb_plugin_open(void)
|
||||
const struct neu_rest_handler *rest_handlers = NULL;
|
||||
const struct neu_rest_handler *cors = NULL;
|
||||
|
||||
// copy license file for backward compatibility
|
||||
if (0 != copy_license_file_if_necessary()) {
|
||||
free(plugin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
neu_plugin_common_init(&plugin->common);
|
||||
|
||||
plugin->handle_ctx = neu_rest_init_ctx(plugin);
|
||||
|
||||
@@ -542,16 +542,20 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
neu_adapter_driver_add_tag((neu_adapter_driver_t *) adapter,
|
||||
cmd->group, &cmd->tags[i]);
|
||||
if (ret == 0) {
|
||||
adapter_storage_add_tag(adapter->persister, cmd->driver,
|
||||
cmd->group, &cmd->tags[i]);
|
||||
resp.index += 1;
|
||||
|
||||
} else {
|
||||
resp.error = ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resp.index) {
|
||||
// we have added some tags, try to persist
|
||||
adapter_storage_add_tags(adapter->persister, cmd->driver,
|
||||
cmd->group, cmd->tags, resp.index);
|
||||
}
|
||||
|
||||
for (int i = 0; i < cmd->n_tag; i++) {
|
||||
free(cmd->tags[i].address);
|
||||
free(cmd->tags[i].name);
|
||||
|
||||
@@ -77,6 +77,25 @@ void adapter_storage_add_tag(neu_persister_t *persister, const char *node,
|
||||
}
|
||||
}
|
||||
|
||||
void adapter_storage_add_tags(neu_persister_t *persister, const char *node,
|
||||
const char *group, const neu_datatag_t *tags,
|
||||
size_t n)
|
||||
{
|
||||
if (0 == n) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (1 == n) {
|
||||
return adapter_storage_add_tag(persister, node, group, &tags[0]);
|
||||
}
|
||||
|
||||
int rv = neu_persister_store_tags(persister, node, group, tags, n);
|
||||
if (0 != rv) {
|
||||
nlog_error("fail store %zu tags:[%s ... %s] adapter:%s grp:%s", n,
|
||||
tags->name, tags[n - 1].name, node, group);
|
||||
}
|
||||
}
|
||||
|
||||
void adapter_storage_update_tag(neu_persister_t *persister, const char *node,
|
||||
const char *group, const neu_datatag_t *tag)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,9 @@ void adapter_storage_del_group(neu_persister_t *persister, const char *node,
|
||||
const char *group);
|
||||
void adapter_storage_add_tag(neu_persister_t *persister, const char *node,
|
||||
const char *group, const neu_datatag_t *tag);
|
||||
void adapter_storage_add_tags(neu_persister_t *persister, const char *node,
|
||||
const char *group, const neu_datatag_t *tags,
|
||||
size_t n);
|
||||
void adapter_storage_update_tag(neu_persister_t *persister, const char *node,
|
||||
const char *group, const neu_datatag_t *tag);
|
||||
void adapter_storage_del_tag(neu_persister_t *persister, const char *node,
|
||||
|
||||
@@ -559,7 +559,8 @@ static void publish_callback(void ** p_reconnect_state,
|
||||
topic_name[published->topic_name_size] = '\0';
|
||||
|
||||
if (NULL != client->log) {
|
||||
zlog_debug(client->log, "received publish('%s'): %s", topic_name,
|
||||
zlog_debug(client->log, "received publish('%s'): %.*s", topic_name,
|
||||
(int) published->application_message_size,
|
||||
(const char *) published->application_message);
|
||||
}
|
||||
|
||||
|
||||
@@ -311,6 +311,10 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
}
|
||||
|
||||
manager_storage_del_node(manager, cmd->node);
|
||||
if (neu_adapter_get_type(adapter) == NEU_NA_TYPE_APP) {
|
||||
neu_subscribe_manager_unsub_all(manager->subscribe_manager,
|
||||
cmd->node);
|
||||
}
|
||||
header->type = NEU_REQ_NODE_UNINIT;
|
||||
forward_msg(manager, msg, header->receiver);
|
||||
if (neu_adapter_get_type(adapter) == NEU_NA_TYPE_DRIVER) {
|
||||
|
||||
@@ -127,6 +127,23 @@ UT_array *neu_subscribe_manager_get(neu_subscribe_mgr_t *mgr, const char *app)
|
||||
return groups;
|
||||
}
|
||||
|
||||
void neu_subscribe_manager_unsub_all(neu_subscribe_mgr_t *mgr, const char *app)
|
||||
{
|
||||
sub_elem_t *el = NULL, *tmp = NULL;
|
||||
|
||||
HASH_ITER(hh, mgr->ss, el, tmp)
|
||||
{
|
||||
utarray_foreach(el->apps, neu_app_subscribe_t *, sub_app)
|
||||
{
|
||||
if (strcmp(sub_app->app_name, app) == 0) {
|
||||
neu_subscribe_manager_unsub(mgr, el->key.driver, app,
|
||||
el->key.group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int neu_subscribe_manager_sub(neu_subscribe_mgr_t *mgr, const char *driver,
|
||||
const char *app, const char *group, nng_pipe pipe)
|
||||
{
|
||||
|
||||
@@ -41,6 +41,7 @@ UT_array *neu_subscribe_manager_find(neu_subscribe_mgr_t *mgr,
|
||||
UT_array *neu_subscribe_manager_find_by_driver(neu_subscribe_mgr_t *mgr,
|
||||
const char * driver);
|
||||
UT_array *neu_subscribe_manager_get(neu_subscribe_mgr_t *mgr, const char *app);
|
||||
void neu_subscribe_manager_unsub_all(neu_subscribe_mgr_t *mgr, const char *app);
|
||||
int neu_subscribe_manager_sub(neu_subscribe_mgr_t *mgr, const char *driver,
|
||||
const char *app, const char *group,
|
||||
nng_pipe pipe);
|
||||
|
||||
@@ -629,6 +629,14 @@ neu_persister_t *neu_persister_create(const char *dir_name)
|
||||
sqlite3_close(persister->db);
|
||||
goto error;
|
||||
}
|
||||
if (SQLITE_OK !=
|
||||
sqlite3_exec(persister->db, "PRAGMA journal_mode=WAL", NULL, NULL,
|
||||
NULL)) {
|
||||
nlog_error("db journal_mode WAL fail: %s",
|
||||
sqlite3_errmsg(persister->db));
|
||||
sqlite3_close(persister->db);
|
||||
goto error;
|
||||
}
|
||||
if (0 != apply_schemas(persister->db, g_config_dir)) {
|
||||
goto error;
|
||||
}
|
||||
@@ -908,6 +916,109 @@ int neu_persister_store_tag(neu_persister_t *persister, const char *driver_name,
|
||||
tag->description);
|
||||
}
|
||||
|
||||
int neu_persister_store_tags(neu_persister_t *persister,
|
||||
const char *driver_name, const char *group_name,
|
||||
const neu_datatag_t *tags, size_t n)
|
||||
{
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
const char * query = "INSERT INTO tags (driver_name, group_name, name, "
|
||||
"address, attribute, precision, type, decimal, "
|
||||
"description) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
if (SQLITE_OK != sqlite3_exec(persister->db, "BEGIN", NULL, NULL, NULL)) {
|
||||
nlog_error("begin transaction fail: %s", sqlite3_errmsg(persister->db));
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
if (SQLITE_OK !=
|
||||
sqlite3_prepare_v2(persister->db, query, -1, &stmt, NULL)) {
|
||||
nlog_error("prepare `%s` fail: %s", query,
|
||||
sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
const neu_datatag_t *tag = &tags[i];
|
||||
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_text(stmt, 1, driver_name, -1, NULL)) {
|
||||
nlog_error("bind `%s` with driver_name=`%s` fail: %s", query,
|
||||
driver_name, sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_text(stmt, 2, group_name, -1, NULL)) {
|
||||
nlog_error("bind `%s` with group_name=`%s` fail: %s", query,
|
||||
group_name, sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_text(stmt, 3, tag->name, -1, NULL)) {
|
||||
nlog_error("bind `%s` with name=`%s` fail: %s", query, tag->name,
|
||||
sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_text(stmt, 4, tag->address, -1, NULL)) {
|
||||
nlog_error("bind `%s` with address=`%s` fail: %s", query,
|
||||
tag->address, sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_int(stmt, 5, tag->attribute)) {
|
||||
nlog_error("bind `%s` with attribute=`%i` fail: %s", query,
|
||||
tag->attribute, sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_int(stmt, 6, tag->precision)) {
|
||||
nlog_error("bind `%s` with precision=`%i` fail: %s", query,
|
||||
tag->precision, sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_int(stmt, 7, tag->type)) {
|
||||
nlog_error("bind `%s` with type=`%i` fail: %s", query, tag->type,
|
||||
sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_bind_double(stmt, 8, tag->decimal)) {
|
||||
nlog_error("bind `%s` with decimal=`%f` fail: %s", query,
|
||||
tag->decimal, sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_OK !=
|
||||
sqlite3_bind_text(stmt, 9, tag->description, -1, NULL)) {
|
||||
nlog_error("bind `%s` with description=`%s` fail: %s", query,
|
||||
tag->description, sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (SQLITE_DONE != sqlite3_step(stmt)) {
|
||||
nlog_error("sqlite3_step fail: %s", sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (SQLITE_OK != sqlite3_exec(persister->db, "COMMIT", NULL, NULL, NULL)) {
|
||||
nlog_error("commit transaction fail: %s",
|
||||
sqlite3_errmsg(persister->db));
|
||||
goto error;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
nlog_info("rollback transaction");
|
||||
sqlite3_exec(persister->db, "ROLLBACK", NULL, NULL, NULL);
|
||||
sqlite3_finalize(stmt);
|
||||
return NEU_ERR_EINTERNAL;
|
||||
}
|
||||
|
||||
int neu_persister_load_tags(neu_persister_t *persister, const char *driver_name,
|
||||
const char *group_name, UT_array **tags)
|
||||
{
|
||||
|
||||
@@ -161,6 +161,10 @@ int neu_persister_load_plugins(neu_persister_t *persister,
|
||||
int neu_persister_store_tag(neu_persister_t *persister, const char *driver_name,
|
||||
const char *group_name, const neu_datatag_t *tag);
|
||||
|
||||
int neu_persister_store_tags(neu_persister_t *persister,
|
||||
const char *driver_name, const char *group_name,
|
||||
const neu_datatag_t *tags, size_t n);
|
||||
|
||||
/**
|
||||
* Load node tag infos.
|
||||
* @param persister persiter object.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2.2.1
|
||||
2.2.3
|
||||
Reference in New Issue
Block a user