mirror of
https://github.com/emqx/neuron.git
synced 2026-10-29 23:19:18 +08:00
Compare commits
41
Commits
2.10.3
...
2.9.0-beta1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dde3e8b84 | ||
|
|
a803228ded | ||
|
|
bf4f176f39 | ||
|
|
1c7a91394f | ||
|
|
dc07471634 | ||
|
|
5f4fed39a1 | ||
|
|
7f66db88c9 | ||
|
|
4a0835cf40 | ||
|
|
830d670358 | ||
|
|
b6cefdb5fa | ||
|
|
c00d085d85 | ||
|
|
1a972f57f4 | ||
|
|
fcbbacfd31 | ||
|
|
9f291833f1 | ||
|
|
76b6df700d | ||
|
|
b9c2739abb | ||
|
|
301c92bee7 | ||
|
|
05f21357b7 | ||
|
|
eab24cf1b5 | ||
|
|
8d72fc9e31 | ||
|
|
bd36224fba | ||
|
|
3f884cf6ba | ||
|
|
df2f6b74e5 | ||
|
|
bc4a23688b | ||
|
|
d29996506a | ||
|
|
34f071a8ee | ||
|
|
a3557cd0af | ||
|
|
31ece9eecc | ||
|
|
0512edbb52 | ||
|
|
87acec1ede | ||
|
|
144a925932 | ||
|
|
ba07160fc5 | ||
|
|
8927be9f81 | ||
|
|
c08e3b314a | ||
|
|
abbe8a8847 | ||
|
|
de4a53635c | ||
|
|
cb997d9cf6 | ||
|
|
af900bb0d4 | ||
|
|
050cf5aafe | ||
|
|
4f1f49de0f | ||
|
|
22339ee248 |
@@ -41,7 +41,7 @@ jobs:
|
||||
|
||||
ut:
|
||||
runs-on: ubuntu-20.04
|
||||
container: ghcr.io/neugates/build:x86_64-main
|
||||
container: ghcr.io/neugates/build:x86_64-v2.9
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -60,25 +60,9 @@ jobs:
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: create cov report
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install lcov
|
||||
mkdir -p cov_report
|
||||
./create_cov_report.sh ut
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
verbose: true
|
||||
fail_ci_if_error: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
directory: ./cov_report/
|
||||
files: ./cov_report/cov-ut.info
|
||||
|
||||
pft:
|
||||
runs-on: ubuntu-20.04
|
||||
container: ghcr.io/neugates/build:x86_64-main
|
||||
container: ghcr.io/neugates/build:x86_64-v2.9
|
||||
strategy:
|
||||
matrix:
|
||||
plugin: [core, ekuiper, modbus, mqtt, azure, metrics]
|
||||
@@ -122,20 +106,4 @@ jobs:
|
||||
pytest -s -v tests/ft/app/"test_azure.py"
|
||||
else
|
||||
pytest -s -v tests/ft/metrics/"test_metrics.py"
|
||||
fi
|
||||
|
||||
- name: create cov report
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install lcov
|
||||
mkdir -p cov_report
|
||||
./create_cov_report.sh ${{ matrix.plugin }}
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
verbose: true
|
||||
fail_ci_if_error: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
directory: ./cov_report/
|
||||
files: ./cov_report/cov-${{ matrix.plugin }}.info
|
||||
fi
|
||||
@@ -8,9 +8,9 @@ on:
|
||||
- published
|
||||
|
||||
env:
|
||||
VERSION: 2.7.0
|
||||
VERSION: 2.9.0
|
||||
UI_VERSION: 2.6.1
|
||||
BRANCH: main
|
||||
BRANCH: v2.9
|
||||
|
||||
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: ghcr.io/neugates/build:${{ matrix.arch[1] }}-main
|
||||
container: ghcr.io/neugates/build:${{ matrix.arch[1] }}-v2.9
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
matrix:
|
||||
arch:
|
||||
- [x86_64-linux-gnu, x86_64, amd64]
|
||||
container: ghcr.io/neugates/build:${{ matrix.arch[1] }}-main
|
||||
container: ghcr.io/neugates/build:${{ matrix.arch[1] }}-v2.9
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
+2
-1
@@ -114,7 +114,7 @@ target_include_directories(neuron-base
|
||||
PRIVATE include/neuron src)
|
||||
target_link_libraries(neuron-base libssl.a libcrypto.a)
|
||||
target_link_libraries(neuron-base nng libzlog.so jansson jwt
|
||||
${CMAKE_THREAD_LIBS_INIT})
|
||||
${CMAKE_THREAD_LIBS_INIT} -lm)
|
||||
add_dependencies(neuron-base neuron-version)
|
||||
|
||||
# dependency imposed by nng
|
||||
@@ -147,6 +147,7 @@ set(NEURON_SOURCES
|
||||
plugins/restful/group_config_handle.c
|
||||
plugins/restful/plugin_handle.c
|
||||
plugins/restful/version_handle.c
|
||||
plugins/restful/scan_handle.c
|
||||
plugins/restful/rest.c
|
||||
plugins/restful/user.c)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(COMPILER_PREFIX aarch64-linux-gnu)
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
set(LIBRARY_DIR /home/neuron/main/libs)
|
||||
set(LIBRARY_DIR /home/neuron/v2.9/libs)
|
||||
|
||||
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(COMPILER_PREFIX arm-linux-gnueabi)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv5tejl)
|
||||
set(LIBRARY_DIR /home/neuron/main/libs)
|
||||
set(LIBRARY_DIR /home/neuron/v2.9/libs)
|
||||
|
||||
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(COMPILER_PREFIX arm-linux-gnueabihf)
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
set(LIBRARY_DIR /home/neuron/main/libs)
|
||||
set(LIBRARY_DIR /home/neuron/v2.9/libs)
|
||||
|
||||
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(COMPILER_PREFIX x86_64-linux-gnu)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
set(LIBRARY_DIR /home/neuron/main/libs)
|
||||
set(LIBRARY_DIR /home/neuron/v2.9/libs)
|
||||
|
||||
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
|
||||
|
||||
@@ -65,6 +65,13 @@ typedef struct adapter_callbacks {
|
||||
void (*update_im)(neu_adapter_t *adapter, const char *group,
|
||||
const char *tag, neu_dvalue_t value,
|
||||
neu_tag_meta_t *metas, int n_meta);
|
||||
void (*scan_tags_response)(neu_adapter_t *adapter, void *r,
|
||||
int error, void *tags, neu_type_e type,
|
||||
bool is_array);
|
||||
void (*test_read_tag_response)(neu_adapter_t *adapter, void *r,
|
||||
neu_json_type_e t, neu_type_e type,
|
||||
neu_json_value_u value,
|
||||
int64_t error);
|
||||
} driver;
|
||||
};
|
||||
} adapter_callbacks_t;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NEU_VERSION_MAJOR 2
|
||||
#define NEU_VERSION_MINOR 7
|
||||
#define NEU_VERSION_MINOR 9
|
||||
#define NEU_VERSION_FIX 0
|
||||
|
||||
#define NEU_GET_VERSION_MAJOR(V) ((0xffff0000 & V) >> 16)
|
||||
|
||||
+21
-19
@@ -118,25 +118,27 @@ typedef enum {
|
||||
NEU_ERR_TEMPLATE_NAME_TOO_LONG = 2502,
|
||||
|
||||
// common error codes for plugins
|
||||
NEU_ERR_PLUGIN_READ_FAILURE = 3000,
|
||||
NEU_ERR_PLUGIN_WRITE_FAILURE = 3001,
|
||||
NEU_ERR_PLUGIN_DISCONNECTED = 3002,
|
||||
NEU_ERR_PLUGIN_TAG_NOT_ALLOW_READ = 3003,
|
||||
NEU_ERR_PLUGIN_TAG_NOT_ALLOW_WRITE = 3004,
|
||||
NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH = 3007,
|
||||
NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED = 3008,
|
||||
NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE = 3009,
|
||||
NEU_ERR_PLUGIN_NOT_RUNNING = 3010,
|
||||
NEU_ERR_PLUGIN_TAG_NOT_READY = 3011,
|
||||
NEU_ERR_PLUGIN_PACKET_OUT_OF_ORDER = 3012,
|
||||
NEU_ERR_PLUGIN_NAME_TOO_LONG = 3013,
|
||||
NEU_ERR_PLUGIN_NOT_FOUND = 3014,
|
||||
NEU_ERR_PLUGIN_DEVICE_NOT_RESPONSE = 3015,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_TEMPLATE = 3016,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_WRITE_TAGS = 3017,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_READ_SYNC = 3018,
|
||||
NEU_ERR_PLUGIN_TYPE_NOT_SUPPORT = 3019,
|
||||
NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE = 3020,
|
||||
NEU_ERR_PLUGIN_READ_FAILURE = 3000,
|
||||
NEU_ERR_PLUGIN_WRITE_FAILURE = 3001,
|
||||
NEU_ERR_PLUGIN_DISCONNECTED = 3002,
|
||||
NEU_ERR_PLUGIN_TAG_NOT_ALLOW_READ = 3003,
|
||||
NEU_ERR_PLUGIN_TAG_NOT_ALLOW_WRITE = 3004,
|
||||
NEU_ERR_PLUGIN_TAG_TYPE_MISMATCH = 3007,
|
||||
NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED = 3008,
|
||||
NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE = 3009,
|
||||
NEU_ERR_PLUGIN_NOT_RUNNING = 3010,
|
||||
NEU_ERR_PLUGIN_TAG_NOT_READY = 3011,
|
||||
NEU_ERR_PLUGIN_PACKET_OUT_OF_ORDER = 3012,
|
||||
NEU_ERR_PLUGIN_NAME_TOO_LONG = 3013,
|
||||
NEU_ERR_PLUGIN_NOT_FOUND = 3014,
|
||||
NEU_ERR_PLUGIN_DEVICE_NOT_RESPONSE = 3015,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_TEMPLATE = 3016,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_WRITE_TAGS = 3017,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_READ_SYNC = 3018,
|
||||
NEU_ERR_PLUGIN_TYPE_NOT_SUPPORT = 3019,
|
||||
NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE = 3020,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_SCAN_TAGS = 3021,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_TEST_READ_TAG = 3022,
|
||||
|
||||
NEU_ERR_MQTT_FAILURE = 4000,
|
||||
NEU_ERR_MQTT_NO_CERTFILESET = 4001,
|
||||
|
||||
@@ -62,6 +62,30 @@ typedef struct {
|
||||
|
||||
int neu_json_encode_read_resp(void *json_object, void *param);
|
||||
int neu_json_encode_read_resp1(void *json_object, void *param);
|
||||
int neu_json_encode_read_paginate_resp(void *json_object, void *param);
|
||||
|
||||
typedef struct {
|
||||
int64_t error;
|
||||
char * name;
|
||||
enum neu_json_type t;
|
||||
union neu_json_value value;
|
||||
uint8_t precision;
|
||||
int n_meta;
|
||||
neu_json_tag_meta_t *metas;
|
||||
neu_datatag_t datatag;
|
||||
} neu_json_read_paginate_resp_tag_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int current_page;
|
||||
unsigned int page_size;
|
||||
unsigned int total;
|
||||
} neu_json_read_meta_resp_t;
|
||||
|
||||
typedef struct {
|
||||
neu_json_read_meta_resp_t meta;
|
||||
int n_tag;
|
||||
neu_json_read_paginate_resp_tag_t *tags;
|
||||
} neu_json_read_paginate_resp_t;
|
||||
|
||||
typedef struct {
|
||||
char * group;
|
||||
@@ -134,10 +158,48 @@ typedef struct {
|
||||
int neu_json_decode_read_req(char *buf, neu_json_read_req_t **result);
|
||||
void neu_json_decode_read_req_free(neu_json_read_req_t *req);
|
||||
|
||||
typedef struct {
|
||||
char *group;
|
||||
char *node;
|
||||
char *name;
|
||||
char *desc;
|
||||
bool sync;
|
||||
int current_page;
|
||||
int page_size;
|
||||
bool is_error;
|
||||
} neu_json_read_paginate_req_t;
|
||||
|
||||
int neu_json_decode_read_paginate_req(char * buf,
|
||||
neu_json_read_paginate_req_t **result);
|
||||
void neu_json_decode_read_paginate_req_free(neu_json_read_paginate_req_t *req);
|
||||
|
||||
int neu_json_encode_read_periodic_resp(void *json_object, void *param);
|
||||
|
||||
void neu_json_metas_to_json(neu_tag_meta_t *metas, int n_meta,
|
||||
neu_json_read_resp_tag_t *json_tag);
|
||||
void neu_json_metas_to_json_paginate(
|
||||
neu_tag_meta_t *metas, int n_meta,
|
||||
neu_json_read_paginate_resp_tag_t *json_tag);
|
||||
|
||||
typedef struct {
|
||||
char * driver;
|
||||
char * group;
|
||||
char * tag;
|
||||
char * address;
|
||||
neu_attribute_e attribute;
|
||||
neu_type_e type;
|
||||
uint8_t precision;
|
||||
double decimal;
|
||||
double bias;
|
||||
neu_datatag_addr_option_u option;
|
||||
} neu_json_test_read_tag_req_t;
|
||||
|
||||
int neu_json_decode_test_read_tag_req(char * buf,
|
||||
neu_json_test_read_tag_req_t **result);
|
||||
|
||||
void neu_json_decode_test_read_tag_req_free(neu_json_test_read_tag_req_t *req);
|
||||
|
||||
int neu_json_encode_test_read_tag_resp(void *json_object, void *param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* NEURON IIoT System for Industry 4.0
|
||||
* Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
|
||||
/*
|
||||
* DO NOT EDIT THIS FILE MANUALLY!
|
||||
* It was automatically generated by `json-autotype`.
|
||||
*/
|
||||
|
||||
#ifndef _NEU_JSON_API_NEU_JSON_SCAN_H_
|
||||
#define _NEU_JSON_API_NEU_JSON_SCAN_H_
|
||||
|
||||
#include "json/json.h"
|
||||
|
||||
#include "tag.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *node;
|
||||
char *id;
|
||||
} neu_json_scan_tags_req_t;
|
||||
|
||||
int neu_json_decode_scan_tags_req(char *buf, neu_json_scan_tags_req_t **result);
|
||||
|
||||
void neu_json_decode_scan_tags_req_free(neu_json_scan_tags_req_t *req);
|
||||
|
||||
int neu_json_encode_scan_tags_resp(void *json_object, void *param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+264
-11
@@ -30,8 +30,10 @@ extern "C" {
|
||||
#include "json/neu_json_rw.h"
|
||||
|
||||
#include "define.h"
|
||||
#include "errcodes.h"
|
||||
#include "tag.h"
|
||||
#include "type.h"
|
||||
#include <math.h>
|
||||
|
||||
typedef struct {
|
||||
neu_node_running_state_e running;
|
||||
@@ -44,6 +46,10 @@ typedef enum neu_reqresp_type {
|
||||
|
||||
NEU_REQ_READ_GROUP,
|
||||
NEU_RESP_READ_GROUP,
|
||||
NEU_REQ_READ_GROUP_PAGINATE,
|
||||
NEU_RESP_READ_GROUP_PAGINATE,
|
||||
NEU_REQ_TEST_READ_TAG,
|
||||
NEU_RESP_TEST_READ_TAG,
|
||||
NEU_REQ_WRITE_TAG,
|
||||
NEU_REQ_WRITE_TAGS,
|
||||
NEU_REQ_WRITE_GTAGS,
|
||||
@@ -114,16 +120,22 @@ typedef enum neu_reqresp_type {
|
||||
NEU_REQ_PRGFILE_PROCESS,
|
||||
NEU_RESP_PRGFILE_PROCESS,
|
||||
|
||||
NEU_REQ_SCAN_TAGS,
|
||||
NEU_RESP_SCAN_TAGS,
|
||||
} neu_reqresp_type_e;
|
||||
|
||||
static const char *neu_reqresp_type_string_t[] = {
|
||||
[NEU_RESP_ERROR] = "NEU_RESP_ERROR",
|
||||
|
||||
[NEU_REQ_READ_GROUP] = "NEU_REQ_READ_GROUP",
|
||||
[NEU_RESP_READ_GROUP] = "NEU_RESP_READ_GROUP",
|
||||
[NEU_REQ_WRITE_TAG] = "NEU_REQ_WRITE_TAG",
|
||||
[NEU_REQ_WRITE_TAGS] = "NEU_REQ_WRITE_TAGS",
|
||||
[NEU_REQ_WRITE_GTAGS] = "NEU_REQ_WRITE_GTAGS",
|
||||
[NEU_REQ_READ_GROUP] = "NEU_REQ_READ_GROUP",
|
||||
[NEU_RESP_READ_GROUP] = "NEU_RESP_READ_GROUP",
|
||||
[NEU_REQ_READ_GROUP_PAGINATE] = "NEU_REQ_READ_GROUP_PAGINATE",
|
||||
[NEU_RESP_READ_GROUP_PAGINATE] = "NEU_RESP_READ_GROUP_PAGINATE",
|
||||
[NEU_REQ_TEST_READ_TAG] = "NEU_REQ_TEST_READ_TAG",
|
||||
[NEU_RESP_TEST_READ_TAG] = "NEU_RESP_TEST_READ_TAG",
|
||||
[NEU_REQ_WRITE_TAG] = "NEU_REQ_WRITE_TAG",
|
||||
[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",
|
||||
@@ -189,6 +201,9 @@ static const char *neu_reqresp_type_string_t[] = {
|
||||
[NEU_REQ_PRGFILE_UPLOAD] = "NEU_REQ_PRGFILE_UPLOAD",
|
||||
[NEU_REQ_PRGFILE_PROCESS] = "NEU_REQ_PRGFILE_PROCESS",
|
||||
[NEU_RESP_PRGFILE_PROCESS] = "NEU_RESP_PRGFILE_PROCESS",
|
||||
|
||||
[NEU_REQ_SCAN_TAGS] = "NEU_REQ_SCAN_TAGS",
|
||||
[NEU_RESP_SCAN_TAGS] = "NEU_RESP_SCAN_TAGS",
|
||||
};
|
||||
|
||||
inline static const char *neu_reqresp_type_string(neu_reqresp_type_e type)
|
||||
@@ -612,6 +627,26 @@ static inline void neu_req_read_group_fini(neu_req_read_group_t *req)
|
||||
free(req->desc);
|
||||
}
|
||||
|
||||
typedef struct neu_req_read_group_paginate {
|
||||
char *driver;
|
||||
char *group;
|
||||
char *name;
|
||||
char *desc;
|
||||
bool sync;
|
||||
int current_page;
|
||||
int page_size;
|
||||
bool is_error;
|
||||
} neu_req_read_group_paginate_t;
|
||||
|
||||
static inline void
|
||||
neu_req_read_group_paginate_fini(neu_req_read_group_paginate_t *req)
|
||||
{
|
||||
free(req->driver);
|
||||
free(req->group);
|
||||
free(req->name);
|
||||
free(req->desc);
|
||||
}
|
||||
|
||||
typedef struct neu_req_write_tag {
|
||||
char * driver;
|
||||
char * group;
|
||||
@@ -694,6 +729,30 @@ typedef struct {
|
||||
UT_array *tags; // neu_resp_tag_value_meta_t
|
||||
} 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;
|
||||
} neu_resp_tag_value_meta_paginate_t;
|
||||
|
||||
static inline UT_icd *neu_resp_tag_value_meta_paginate_icd()
|
||||
{
|
||||
static UT_icd icd = { sizeof(neu_resp_tag_value_meta_paginate_t), NULL,
|
||||
NULL, NULL };
|
||||
return &icd;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *driver;
|
||||
char *group;
|
||||
int current_page;
|
||||
int page_size;
|
||||
bool is_error;
|
||||
|
||||
UT_array *tags; // neu_resp_tag_value_meta_paginate_t
|
||||
} neu_resp_read_group_paginate_t;
|
||||
|
||||
static inline void neu_resp_read_free(neu_resp_read_group_t *resp)
|
||||
{
|
||||
utarray_foreach(resp->tags, neu_resp_tag_value_meta_t *, tag_value)
|
||||
@@ -707,6 +766,20 @@ static inline void neu_resp_read_free(neu_resp_read_group_t *resp)
|
||||
utarray_free(resp->tags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
neu_resp_read_paginate_free(neu_resp_read_group_paginate_t *resp)
|
||||
{
|
||||
utarray_foreach(resp->tags, neu_resp_tag_value_meta_t *, tag_value)
|
||||
{
|
||||
if (tag_value->value.type == NEU_TYPE_PTR) {
|
||||
free(tag_value->value.value.ptr.ptr);
|
||||
}
|
||||
}
|
||||
free(resp->driver);
|
||||
free(resp->group);
|
||||
utarray_free(resp->tags);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint16_t index;
|
||||
pthread_mutex_t mtx;
|
||||
@@ -841,14 +914,150 @@ static inline void neu_tag_value_to_json(neu_resp_tag_value_meta_t *tag_value,
|
||||
tag_json->value.val_int = tag_value->value.value.u64;
|
||||
break;
|
||||
case NEU_TYPE_FLOAT:
|
||||
tag_json->t = NEU_JSON_FLOAT;
|
||||
tag_json->value.val_float = tag_value->value.value.f32;
|
||||
tag_json->precision = tag_value->value.precision;
|
||||
if (isnan(tag_value->value.value.f32)) {
|
||||
tag_json->t = NEU_JSON_FLOAT;
|
||||
tag_json->value.val_float = tag_value->value.value.f32;
|
||||
tag_json->error = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
|
||||
} else {
|
||||
tag_json->t = NEU_JSON_FLOAT;
|
||||
tag_json->value.val_float = tag_value->value.value.f32;
|
||||
tag_json->precision = tag_value->value.precision;
|
||||
}
|
||||
break;
|
||||
case NEU_TYPE_DOUBLE:
|
||||
tag_json->t = NEU_JSON_DOUBLE;
|
||||
tag_json->value.val_double = tag_value->value.value.d64;
|
||||
tag_json->precision = tag_value->value.precision;
|
||||
if (isnan(tag_value->value.value.d64)) {
|
||||
tag_json->t = NEU_JSON_DOUBLE;
|
||||
tag_json->value.val_double = tag_value->value.value.d64;
|
||||
tag_json->error = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
|
||||
} else {
|
||||
tag_json->t = NEU_JSON_DOUBLE;
|
||||
tag_json->value.val_double = tag_value->value.value.d64;
|
||||
tag_json->precision = tag_value->value.precision;
|
||||
}
|
||||
break;
|
||||
case NEU_TYPE_BOOL:
|
||||
tag_json->t = NEU_JSON_BOOL;
|
||||
tag_json->value.val_bool = tag_value->value.value.boolean;
|
||||
break;
|
||||
case NEU_TYPE_BIT:
|
||||
tag_json->t = NEU_JSON_BIT;
|
||||
tag_json->value.val_bit = tag_value->value.value.u8;
|
||||
break;
|
||||
case NEU_TYPE_STRING:
|
||||
case NEU_TYPE_TIME:
|
||||
case NEU_TYPE_DATA_AND_TIME:
|
||||
tag_json->t = NEU_JSON_STR;
|
||||
tag_json->value.val_str = tag_value->value.value.str;
|
||||
break;
|
||||
case NEU_TYPE_PTR:
|
||||
tag_json->t = NEU_JSON_STR;
|
||||
tag_json->value.val_str = (char *) tag_value->value.value.ptr.ptr;
|
||||
break;
|
||||
case NEU_TYPE_BYTES:
|
||||
tag_json->t = NEU_JSON_BYTES;
|
||||
tag_json->value.val_bytes.length = tag_value->value.value.bytes.length;
|
||||
tag_json->value.val_bytes.bytes = tag_value->value.value.bytes.bytes;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
neu_tag_value_to_json_paginate(neu_resp_tag_value_meta_paginate_t *tag_value,
|
||||
neu_json_read_paginate_resp_tag_t * tag_json)
|
||||
{
|
||||
tag_json->name = tag_value->tag;
|
||||
tag_json->error = 0;
|
||||
|
||||
tag_json->datatag.name = strdup(tag_value->datatag.name);
|
||||
tag_json->datatag.address = strdup(tag_value->datatag.address);
|
||||
tag_json->datatag.attribute = tag_value->datatag.attribute;
|
||||
tag_json->datatag.type = tag_value->datatag.type;
|
||||
tag_json->datatag.precision = tag_value->datatag.precision;
|
||||
tag_json->datatag.decimal = tag_value->datatag.decimal;
|
||||
tag_json->datatag.bias = tag_value->datatag.bias;
|
||||
tag_json->datatag.description = strdup(tag_value->datatag.description);
|
||||
tag_json->datatag.option = tag_value->datatag.option;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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,
|
||||
tag_json);
|
||||
|
||||
switch (tag_value->value.type) {
|
||||
case NEU_TYPE_ERROR:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.i32;
|
||||
tag_json->error = tag_value->value.value.i32;
|
||||
break;
|
||||
case NEU_TYPE_UINT8:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.u8;
|
||||
break;
|
||||
case NEU_TYPE_INT8:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.i8;
|
||||
break;
|
||||
case NEU_TYPE_INT16:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.i16;
|
||||
break;
|
||||
case NEU_TYPE_INT32:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.i32;
|
||||
break;
|
||||
case NEU_TYPE_INT64:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.i64;
|
||||
break;
|
||||
case NEU_TYPE_WORD:
|
||||
case NEU_TYPE_UINT16:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.u16;
|
||||
break;
|
||||
case NEU_TYPE_DWORD:
|
||||
case NEU_TYPE_UINT32:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.u32;
|
||||
break;
|
||||
case NEU_TYPE_LWORD:
|
||||
case NEU_TYPE_UINT64:
|
||||
tag_json->t = NEU_JSON_INT;
|
||||
tag_json->value.val_int = tag_value->value.value.u64;
|
||||
break;
|
||||
case NEU_TYPE_FLOAT:
|
||||
if (isnan(tag_value->value.value.f32)) {
|
||||
tag_json->t = NEU_JSON_FLOAT;
|
||||
tag_json->value.val_float = tag_value->value.value.f32;
|
||||
tag_json->error = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
|
||||
} else {
|
||||
tag_json->t = NEU_JSON_FLOAT;
|
||||
tag_json->value.val_float = tag_value->value.value.f32;
|
||||
tag_json->precision = tag_value->value.precision;
|
||||
}
|
||||
break;
|
||||
case NEU_TYPE_DOUBLE:
|
||||
if (isnan(tag_value->value.value.d64)) {
|
||||
tag_json->t = NEU_JSON_DOUBLE;
|
||||
tag_json->value.val_double = tag_value->value.value.d64;
|
||||
tag_json->error = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
|
||||
} else {
|
||||
tag_json->t = NEU_JSON_DOUBLE;
|
||||
tag_json->value.val_double = tag_value->value.value.d64;
|
||||
tag_json->precision = tag_value->value.precision;
|
||||
}
|
||||
break;
|
||||
case NEU_TYPE_BOOL:
|
||||
tag_json->t = NEU_JSON_BOOL;
|
||||
@@ -923,6 +1132,50 @@ typedef struct {
|
||||
char reason[256];
|
||||
} neu_resp_prgfile_process_t;
|
||||
|
||||
typedef struct neu_req_scan_tags {
|
||||
char driver[NEU_NODE_NAME_LEN];
|
||||
char id[NEU_TAG_ADDRESS_LEN];
|
||||
} neu_req_scan_tags_t;
|
||||
|
||||
typedef struct {
|
||||
char name[NEU_TAG_NAME_LEN];
|
||||
char id[5 + 1 + NEU_TAG_ADDRESS_LEN]; // ns + ! + address
|
||||
uint8_t type;
|
||||
} neu_scan_tag_t;
|
||||
|
||||
typedef struct {
|
||||
UT_array * scan_tags;
|
||||
int32_t error;
|
||||
neu_type_e type;
|
||||
bool is_array;
|
||||
} neu_resp_scan_tags_t;
|
||||
|
||||
typedef struct {
|
||||
char name[NEU_TAG_NAME_LEN];
|
||||
char id[5 + 1 + NEU_TAG_ADDRESS_LEN];
|
||||
neu_type_e type;
|
||||
} neu_scan_tag_attribute_t;
|
||||
|
||||
typedef struct neu_req_test_rea_tag {
|
||||
char driver[NEU_NODE_NAME_LEN];
|
||||
char group[NEU_GROUP_NAME_LEN];
|
||||
char tag[NEU_TAG_NAME_LEN];
|
||||
char address[NEU_TAG_ADDRESS_LEN];
|
||||
neu_attribute_e attribute;
|
||||
neu_type_e type;
|
||||
uint8_t precision;
|
||||
double decimal;
|
||||
double bias;
|
||||
neu_datatag_addr_option_u option;
|
||||
} neu_req_test_read_tag_t;
|
||||
|
||||
typedef struct {
|
||||
neu_type_e type;
|
||||
neu_json_type_e t;
|
||||
neu_json_value_u value;
|
||||
int64_t error;
|
||||
} neu_resp_test_read_tag_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -108,6 +108,9 @@ typedef struct neu_plugin_intf_funs {
|
||||
neu_datatag_t *tags,
|
||||
int n_tag); // create tags by API
|
||||
int (*del_tags)(neu_plugin_t *plugin, int n_tag);
|
||||
int (*scan_tags)(neu_plugin_t *plugin, void *req, char *id);
|
||||
int (*test_read_tag)(neu_plugin_t *plugin, void *req,
|
||||
neu_datatag_t tag);
|
||||
} driver;
|
||||
};
|
||||
|
||||
|
||||
@@ -87,4 +87,6 @@ void neu_async_queue_remove(neu_async_queue_t *q, neu_async_queue_filter filter,
|
||||
*/
|
||||
void neu_async_queue_clean(neu_async_queue_t *q);
|
||||
|
||||
int neu_async_queue_len(neu_async_queue_t *q);
|
||||
|
||||
#endif
|
||||
@@ -322,9 +322,13 @@ static int ekuiper_plugin_request(neu_plugin_t * plugin,
|
||||
case NEU_REQRESP_TRANS_DATA: {
|
||||
neu_reqresp_trans_data_t *trans_data = data;
|
||||
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_5S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_30S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_60S, 1, NULL);
|
||||
if (plugin->started) {
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_5S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_30S, 1,
|
||||
NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_60S, 1,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (disconnected) {
|
||||
plog_debug(plugin, "not connected");
|
||||
|
||||
+271
-5
@@ -37,6 +37,9 @@ struct modbus_write_tags_data {
|
||||
static void plugin_group_free(neu_plugin_group_t *pgp);
|
||||
static int process_protocol_buf(neu_plugin_t *plugin, uint8_t slave_id,
|
||||
uint16_t response_size);
|
||||
static int process_protocol_buf_test(neu_plugin_t *plugin, void *req,
|
||||
modbus_point_t *point,
|
||||
uint16_t response_size);
|
||||
|
||||
void modbus_conn_connected(void *data, int fd)
|
||||
{
|
||||
@@ -125,10 +128,10 @@ int modbus_stack_read_retry(neu_plugin_t *plugin, struct modbus_group_data *gd,
|
||||
struct timespec t4 = { 0 };
|
||||
nanosleep(&t3, &t4);
|
||||
plog_notice(plugin, "Resend read req. Times:%hu", j + 1);
|
||||
int ret = modbus_stack_read(plugin->stack, gd->cmd_sort->cmd[i].slave_id,
|
||||
gd->cmd_sort->cmd[i].area,
|
||||
gd->cmd_sort->cmd[i].start_address,
|
||||
gd->cmd_sort->cmd[i].n_register, response_size);
|
||||
int ret = modbus_stack_read(
|
||||
plugin->stack, gd->cmd_sort->cmd[i].slave_id, gd->cmd_sort->cmd[i].area,
|
||||
gd->cmd_sort->cmd[i].start_address, gd->cmd_sort->cmd[i].n_register,
|
||||
response_size, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -175,7 +178,7 @@ int modbus_group_timer(neu_plugin_t *plugin, neu_plugin_group_t *group,
|
||||
int ret_r = modbus_stack_read(
|
||||
plugin->stack, gd->cmd_sort->cmd[i].slave_id,
|
||||
gd->cmd_sort->cmd[i].area, gd->cmd_sort->cmd[i].start_address,
|
||||
gd->cmd_sort->cmd[i].n_register, &response_size);
|
||||
gd->cmd_sort->cmd[i].n_register, &response_size, false);
|
||||
if (ret_r > 0) {
|
||||
ret_buf = process_protocol_buf(
|
||||
plugin, gd->cmd_sort->cmd[i].slave_id, response_size);
|
||||
@@ -453,6 +456,195 @@ int modbus_value_handle(void *ctx, uint8_t slave_id, uint16_t n_byte,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int modbus_value_handle_test(neu_plugin_t *plugin, void *req,
|
||||
modbus_point_t *point, uint16_t n_byte,
|
||||
uint8_t *bytes)
|
||||
{
|
||||
(void) req;
|
||||
neu_json_value_u jvalue = { 0 };
|
||||
neu_json_type_e jtype;
|
||||
|
||||
switch (point->area) {
|
||||
case MODBUS_AREA_HOLD_REGISTER:
|
||||
case MODBUS_AREA_INPUT_REGISTER:
|
||||
if (n_byte >= point->n_register * 2) {
|
||||
jvalue.val_bytes.bytes =
|
||||
(uint8_t *) malloc(point->n_register * 2 + 1);
|
||||
memcpy(jvalue.val_bytes.bytes, bytes, point->n_register * 2);
|
||||
jvalue.val_bytes.length = point->n_register * 2;
|
||||
}
|
||||
break;
|
||||
case MODBUS_AREA_COIL:
|
||||
case MODBUS_AREA_INPUT: {
|
||||
neu_value8_u u8 = { .value = bytes[0] };
|
||||
jvalue.val_bit = neu_value8_get_bit(u8, 0);
|
||||
} break;
|
||||
}
|
||||
|
||||
switch (point->type) {
|
||||
case NEU_TYPE_UINT16: {
|
||||
jtype = NEU_JSON_INT;
|
||||
uint16_t tmp_val16;
|
||||
memcpy(&tmp_val16, jvalue.val_bytes.bytes, sizeof(uint16_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jvalue.val_int = ntohs(tmp_val16);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_INT16: {
|
||||
jtype = NEU_JSON_INT;
|
||||
int16_t tmp_val16;
|
||||
memcpy(&tmp_val16, jvalue.val_bytes.bytes, sizeof(int16_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jvalue.val_int = (int16_t) ntohs(tmp_val16);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_FLOAT: {
|
||||
uint32_t tmp_valf;
|
||||
memcpy(&tmp_valf, jvalue.val_bytes.bytes, sizeof(uint32_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jtype = NEU_JSON_FLOAT;
|
||||
jvalue.val_int = ntohl(tmp_valf);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_INT32: {
|
||||
jtype = NEU_JSON_INT;
|
||||
int32_t tmp_val32;
|
||||
memcpy(&tmp_val32, jvalue.val_bytes.bytes, sizeof(int32_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jvalue.val_int = (int32_t) ntohl(tmp_val32);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_UINT32: {
|
||||
jtype = NEU_JSON_INT;
|
||||
uint32_t tmp_val32;
|
||||
memcpy(&tmp_val32, jvalue.val_bytes.bytes, sizeof(uint32_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jvalue.val_int = ntohl(tmp_val32);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_DOUBLE: {
|
||||
uint64_t tmp_vald;
|
||||
memcpy(&tmp_vald, jvalue.val_bytes.bytes, sizeof(uint64_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jtype = NEU_JSON_DOUBLE;
|
||||
jvalue.val_int = neu_ntohll(tmp_vald);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_INT64: {
|
||||
jtype = NEU_JSON_INT;
|
||||
int64_t tmp_val64;
|
||||
memcpy(&tmp_val64, jvalue.val_bytes.bytes, sizeof(int64_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jvalue.val_int = (int64_t) neu_ntohll(tmp_val64);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_UINT64: {
|
||||
jtype = NEU_JSON_INT;
|
||||
uint64_t tmp_val64;
|
||||
memcpy(&tmp_val64, jvalue.val_bytes.bytes, sizeof(uint64_t));
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jvalue.val_int = neu_ntohll(tmp_val64);
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_BIT: {
|
||||
switch (point->area) {
|
||||
case MODBUS_AREA_HOLD_REGISTER:
|
||||
case MODBUS_AREA_INPUT_REGISTER: {
|
||||
jtype = NEU_JSON_BIT;
|
||||
neu_value16_u v16 = { 0 };
|
||||
v16.value = htons(*(uint16_t *) jvalue.val_bytes.bytes);
|
||||
free(jvalue.val_bytes.bytes);
|
||||
jvalue.val_bit = neu_value16_get_bit(v16, point->option.bit.bit);
|
||||
break;
|
||||
}
|
||||
case MODBUS_AREA_COIL:
|
||||
case MODBUS_AREA_INPUT:
|
||||
jtype = NEU_JSON_INT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NEU_TYPE_STRING: {
|
||||
jtype = NEU_JSON_STR;
|
||||
size_t str_length = point->n_register * 2;
|
||||
jvalue.val_str = (char *) jvalue.val_bytes.bytes;
|
||||
jvalue.val_str[str_length] = '\0';
|
||||
|
||||
switch (point->option.string.type) {
|
||||
case NEU_DATATAG_STRING_TYPE_H:
|
||||
break;
|
||||
case NEU_DATATAG_STRING_TYPE_L:
|
||||
neu_datatag_string_ltoh(jvalue.val_str, str_length);
|
||||
break;
|
||||
case NEU_DATATAG_STRING_TYPE_D:
|
||||
break;
|
||||
case NEU_DATATAG_STRING_TYPE_E:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!neu_datatag_string_is_utf8(jvalue.val_str, str_length)) {
|
||||
jvalue.val_str[0] = '?';
|
||||
jvalue.val_str[1] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
plugin->common.adapter_callbacks->driver.test_read_tag_response(
|
||||
plugin->common.adapter, req, jtype, point->type, jvalue,
|
||||
NEU_ERR_SUCCESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int modbus_test_read_tag(neu_plugin_t *plugin, void *req, neu_datatag_t tag)
|
||||
{
|
||||
modbus_point_t point = { 0 };
|
||||
neu_json_value_u error_value;
|
||||
error_value.val_int = 0;
|
||||
|
||||
int err = modbus_tag_to_point(&tag, &point);
|
||||
if (err != NEU_ERR_SUCCESS) {
|
||||
plugin->common.adapter_callbacks->driver.test_read_tag_response(
|
||||
plugin->common.adapter, req, NEU_JSON_INT, NEU_TYPE_ERROR,
|
||||
error_value, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t response_size = 0;
|
||||
int ret = modbus_stack_read(plugin->stack, point.slave_id, point.area,
|
||||
point.start_address, point.n_register,
|
||||
&response_size, true);
|
||||
if (ret <= 0) {
|
||||
plugin->common.adapter_callbacks->driver.test_read_tag_response(
|
||||
plugin->common.adapter, req, NEU_JSON_INT, NEU_TYPE_ERROR,
|
||||
error_value, NEU_ERR_PLUGIN_READ_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = process_protocol_buf_test(plugin, req, &point, response_size);
|
||||
if (ret == 0) {
|
||||
plugin->common.adapter_callbacks->driver.test_read_tag_response(
|
||||
plugin->common.adapter, req, NEU_JSON_INT, NEU_TYPE_ERROR,
|
||||
error_value, NEU_ERR_PLUGIN_DEVICE_NOT_RESPONSE);
|
||||
return 0;
|
||||
} else if (ret == -1) {
|
||||
plugin->common.adapter_callbacks->driver.test_read_tag_response(
|
||||
plugin->common.adapter, req, NEU_JSON_INT, NEU_TYPE_ERROR,
|
||||
error_value, NEU_ERR_PLUGIN_PROTOCOL_DECODE_FAILURE);
|
||||
return 0;
|
||||
} else if (ret == -2) {
|
||||
plugin->common.adapter_callbacks->driver.test_read_tag_response(
|
||||
plugin->common.adapter, req, NEU_JSON_INT, NEU_TYPE_ERROR,
|
||||
error_value, NEU_ERR_PLUGIN_READ_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int modbus_write(neu_plugin_t *plugin, void *req, neu_datatag_t *tag,
|
||||
neu_value_u value, bool response)
|
||||
{
|
||||
@@ -713,4 +905,78 @@ static int process_protocol_buf(neu_plugin_t *plugin, uint8_t slave_id,
|
||||
}
|
||||
free(recv_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int process_protocol_buf_test(neu_plugin_t *plugin, void *req,
|
||||
modbus_point_t *point,
|
||||
uint16_t response_size)
|
||||
{
|
||||
uint8_t * recv_buf = calloc(response_size, 1);
|
||||
neu_protocol_unpack_buf_t pbuf = { 0 };
|
||||
ssize_t ret = 0;
|
||||
if (plugin->protocol == MODBUS_PROTOCOL_TCP) {
|
||||
if (plugin->is_server) {
|
||||
ret = neu_conn_tcp_server_recv(plugin->conn, plugin->client_fd,
|
||||
recv_buf,
|
||||
sizeof(struct modbus_header));
|
||||
} else {
|
||||
ret = neu_conn_recv(plugin->conn, recv_buf,
|
||||
sizeof(struct modbus_header));
|
||||
}
|
||||
|
||||
if (ret == 0 || ret == -1) {
|
||||
free(recv_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret == sizeof(struct modbus_header)) {
|
||||
struct modbus_header *header = (struct modbus_header *) recv_buf;
|
||||
int ret1 = 0;
|
||||
|
||||
if (htons(header->len) >
|
||||
response_size - sizeof(struct modbus_header)) {
|
||||
free(recv_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
plog_recv_protocol(plugin, recv_buf, ret);
|
||||
if (plugin->is_server) {
|
||||
ret1 = neu_conn_tcp_server_recv(
|
||||
plugin->conn, plugin->client_fd,
|
||||
recv_buf + sizeof(struct modbus_header),
|
||||
htons(header->len));
|
||||
} else {
|
||||
ret1 = neu_conn_recv(plugin->conn,
|
||||
recv_buf + sizeof(struct modbus_header),
|
||||
htons(header->len));
|
||||
}
|
||||
if (ret1 != htons(header->len)) {
|
||||
free(recv_buf);
|
||||
return -1;
|
||||
}
|
||||
ret += ret1;
|
||||
} else {
|
||||
free(recv_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
if (ret < 512) {
|
||||
plog_recv_protocol(plugin, recv_buf, ret);
|
||||
}
|
||||
neu_protocol_unpack_buf_init(&pbuf, recv_buf, ret);
|
||||
int ret_s = modbus_stack_recv_test(plugin, req, point, &pbuf);
|
||||
if (ret_s == MODBUS_DEVICE_ERR) {
|
||||
ret = ret_s;
|
||||
} else {
|
||||
if (ret != response_size) {
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = ret_s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(recv_buf);
|
||||
return ret;
|
||||
}
|
||||
@@ -63,5 +63,9 @@ int modbus_write_tag(neu_plugin_t *plugin, void *req, neu_datatag_t *tag,
|
||||
neu_value_u value);
|
||||
int modbus_write_tags(neu_plugin_t *plugin, void *req, UT_array *tags);
|
||||
int modbus_write_resp(void *ctx, void *req, int error);
|
||||
int modbus_test_read_tag(neu_plugin_t *plugin, void *req, neu_datatag_t tag);
|
||||
int modbus_value_handle_test(neu_plugin_t *plugin, void *req,
|
||||
modbus_point_t *point, uint16_t n_byte,
|
||||
uint8_t *bytes);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -177,9 +177,104 @@ int modbus_stack_recv(modbus_stack_t *stack, uint8_t slave_id,
|
||||
return neu_protocol_unpack_buf_used_size(buf);
|
||||
}
|
||||
|
||||
int modbus_stack_recv_test(neu_plugin_t *plugin, void *req,
|
||||
modbus_point_t * point,
|
||||
neu_protocol_unpack_buf_t *buf)
|
||||
{
|
||||
struct modbus_header header = { 0 };
|
||||
struct modbus_code code = { 0 };
|
||||
int ret = 0;
|
||||
|
||||
if (plugin->stack->protocol == MODBUS_PROTOCOL_TCP) {
|
||||
ret = modbus_header_unwrap(buf, &header);
|
||||
if (ret < 0) {
|
||||
plog_warn((neu_plugin_t *) plugin->stack->ctx,
|
||||
"try modbus rtu driver");
|
||||
}
|
||||
if (ret <= 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = modbus_code_unwrap(buf, &code);
|
||||
if (ret <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (code.slave_id != point->slave_id) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (code.function) {
|
||||
case MODBUS_READ_COIL:
|
||||
case MODBUS_READ_INPUT:
|
||||
case MODBUS_READ_HOLD_REG:
|
||||
case MODBUS_READ_INPUT_REG: {
|
||||
struct modbus_data data = { 0 };
|
||||
uint8_t * bytes = NULL;
|
||||
ret = modbus_data_unwrap(buf, &data);
|
||||
if (ret <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data.n_byte == 0xff) {
|
||||
bytes = neu_protocol_unpack_buf(buf,
|
||||
header.len -
|
||||
sizeof(struct modbus_code) -
|
||||
sizeof(struct modbus_data));
|
||||
if (bytes == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
modbus_value_handle_test(plugin, req, point, data.n_byte, bytes);
|
||||
} else {
|
||||
bytes = neu_protocol_unpack_buf(buf, data.n_byte);
|
||||
if (bytes == NULL) {
|
||||
return -1;
|
||||
}
|
||||
modbus_value_handle_test(plugin, req, point, data.n_byte, bytes);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MODBUS_WRITE_S_COIL:
|
||||
case MODBUS_WRITE_M_HOLD_REG:
|
||||
case MODBUS_WRITE_M_COIL: {
|
||||
struct modbus_address address = { 0 };
|
||||
ret = modbus_address_unwrap(buf, &address);
|
||||
if (ret <= 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MODBUS_READ_COIL_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_READ_INPUT_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_READ_HOLD_REG_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_READ_INPUT_REG_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_WRITE_S_COIL_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_WRITE_S_HOLD_REG_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_WRITE_M_HOLD_REG_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_WRITE_M_COIL_ERR:
|
||||
return MODBUS_DEVICE_ERR;
|
||||
case MODBUS_WRITE_S_HOLD_REG:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return neu_protocol_unpack_buf_used_size(buf);
|
||||
}
|
||||
|
||||
int modbus_stack_read(modbus_stack_t *stack, uint8_t slave_id,
|
||||
enum modbus_area area, uint16_t start_address,
|
||||
uint16_t n_reg, uint16_t *response_size)
|
||||
uint16_t n_reg, uint16_t *response_size, bool is_test)
|
||||
{
|
||||
static __thread uint8_t buf[16] = { 0 };
|
||||
static __thread neu_protocol_pack_buf_t pbuf = { 0 };
|
||||
@@ -229,7 +324,7 @@ int modbus_stack_read(modbus_stack_t *stack, uint8_t slave_id,
|
||||
|
||||
ret = stack->send_fn(stack->ctx, neu_protocol_pack_buf_used_size(&pbuf),
|
||||
neu_protocol_pack_buf_get(&pbuf));
|
||||
if (ret <= 0) {
|
||||
if (ret <= 0 && !is_test) {
|
||||
stack->value_fn(stack->ctx, 0, 0, NULL, NEU_ERR_PLUGIN_DISCONNECTED);
|
||||
plog_warn((neu_plugin_t *) stack->ctx, "send read req fail, %hhu!%hu",
|
||||
slave_id, start_address);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <neuron.h>
|
||||
|
||||
#include "modbus.h"
|
||||
#include "modbus_point.h"
|
||||
|
||||
typedef struct modbus_stack modbus_stack_t;
|
||||
|
||||
@@ -45,10 +46,13 @@ void modbus_stack_destroy(modbus_stack_t *stack);
|
||||
|
||||
int modbus_stack_recv(modbus_stack_t *stack, uint8_t slave_id,
|
||||
neu_protocol_unpack_buf_t *buf);
|
||||
int modbus_stack_recv_test(neu_plugin_t *plugin, void *req,
|
||||
modbus_point_t * point,
|
||||
neu_protocol_unpack_buf_t *buf);
|
||||
|
||||
int modbus_stack_read(modbus_stack_t *stack, uint8_t slave_id,
|
||||
enum modbus_area area, uint16_t start_address,
|
||||
uint16_t n_reg, uint16_t *response_size);
|
||||
uint16_t n_reg, uint16_t *response_size, bool is_test);
|
||||
int modbus_stack_write(modbus_stack_t *stack, void *req, uint8_t slave_id,
|
||||
enum modbus_area area, uint16_t start_address,
|
||||
uint16_t n_reg, uint8_t *bytes, uint8_t n_byte,
|
||||
|
||||
@@ -43,6 +43,8 @@ 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 int driver_write_tags(neu_plugin_t *plugin, void *req, UT_array *tags);
|
||||
static int driver_test_read_tag(neu_plugin_t *plugin, void *req,
|
||||
neu_datatag_t tag);
|
||||
|
||||
static const neu_plugin_intf_funs_t plugin_intf_funs = {
|
||||
.open = driver_open,
|
||||
@@ -59,6 +61,7 @@ static const neu_plugin_intf_funs_t plugin_intf_funs = {
|
||||
.driver.write_tag = driver_write,
|
||||
.driver.tag_validator = driver_tag_validator,
|
||||
.driver.write_tags = driver_write_tags,
|
||||
.driver.test_read_tag = driver_test_read_tag,
|
||||
.driver.add_tags = NULL,
|
||||
.driver.load_tags = NULL,
|
||||
.driver.del_tags = NULL,
|
||||
@@ -280,4 +283,10 @@ static int driver_write(neu_plugin_t *plugin, void *req, neu_datatag_t *tag,
|
||||
static int driver_write_tags(neu_plugin_t *plugin, void *req, UT_array *tags)
|
||||
{
|
||||
return modbus_write_tags(plugin, req, tags);
|
||||
}
|
||||
|
||||
static int driver_test_read_tag(neu_plugin_t *plugin, void *req,
|
||||
neu_datatag_t tag)
|
||||
{
|
||||
return modbus_test_read_tag(plugin, req, tag);
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
"description_zh": "MQTT 客户端 ID",
|
||||
"type": "string",
|
||||
"attribute": "required",
|
||||
"default": "neuron_${random_str}",
|
||||
"valid": {
|
||||
"length": 255
|
||||
}
|
||||
@@ -60,7 +59,6 @@
|
||||
"description_zh": "Neuron 向 AWS IoT Core 订阅的 MQTT 主题,用于接收点位写入请求。",
|
||||
"attribute": "required",
|
||||
"type": "string",
|
||||
"default": "/neuron/${node-name}/write/req",
|
||||
"valid": {
|
||||
"length": 255
|
||||
}
|
||||
@@ -72,7 +70,6 @@
|
||||
"description_zh": "Neuron 通过该 MQTT 主题将点位写入响应发布到 AWS IoT Core。",
|
||||
"attribute": "required",
|
||||
"type": "string",
|
||||
"default": "/neuron/${node-name}/write/resp",
|
||||
"valid": {
|
||||
"length": 255
|
||||
}
|
||||
|
||||
@@ -331,9 +331,13 @@ static int azure_plugin_request(neu_plugin_t *plugin, neu_reqresp_head_t *head,
|
||||
// error = handle_read_response(plugin, head->ctx, data);
|
||||
break;
|
||||
case NEU_REQRESP_TRANS_DATA: {
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_5S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_30S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_60S, 1, NULL);
|
||||
if (plugin->client && neu_mqtt_client_is_open(plugin->client)) {
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_5S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_30S, 1,
|
||||
NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_60S, 1,
|
||||
NULL);
|
||||
}
|
||||
error = azure_handle_trans_data(plugin, data);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"description_zh": "MQTT 客户端 ID",
|
||||
"type": "string",
|
||||
"attribute": "required",
|
||||
"default": "neuron_${random_str}",
|
||||
"valid": {
|
||||
"length": 255
|
||||
}
|
||||
@@ -63,6 +64,7 @@
|
||||
"description_zh": "接收点位写入请求的 MQTT 主题。",
|
||||
"attribute": "required",
|
||||
"type": "string",
|
||||
"default": "/neuron/${random_str}/write/req",
|
||||
"valid": {
|
||||
"length": 255
|
||||
}
|
||||
@@ -74,6 +76,7 @@
|
||||
"description_zh": "发送点位写入响应的 MQTT 主题。",
|
||||
"attribute": "required",
|
||||
"type": "string",
|
||||
"default": "/neuron/${random_str}/write/resp",
|
||||
"valid": {
|
||||
"length": 255
|
||||
}
|
||||
|
||||
@@ -374,9 +374,13 @@ int mqtt_plugin_request(neu_plugin_t *plugin, neu_reqresp_head_t *head,
|
||||
error = handle_read_response(plugin, head->ctx, data);
|
||||
break;
|
||||
case NEU_REQRESP_TRANS_DATA: {
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_5S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_30S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_60S, 1, NULL);
|
||||
if (plugin->client && neu_mqtt_client_is_open(plugin->client)) {
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_5S, 1, NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_30S, 1,
|
||||
NULL);
|
||||
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_TRANS_DATA_60S, 1,
|
||||
NULL);
|
||||
}
|
||||
error = handle_trans_data(plugin, data);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "normal_handle.h"
|
||||
#include "plugin_handle.h"
|
||||
#include "rw_handle.h"
|
||||
#include "scan_handle.h"
|
||||
#include "utils/http.h"
|
||||
#include "version_handle.h"
|
||||
|
||||
@@ -72,6 +73,12 @@ static struct neu_http_handler cors_handler[] = {
|
||||
{
|
||||
.url = "/api/v2/read",
|
||||
},
|
||||
{
|
||||
.url = "/api/v2/read/paginate",
|
||||
},
|
||||
{
|
||||
.url = "/api/v2/read/test",
|
||||
},
|
||||
{
|
||||
.url = "/api/v2/write",
|
||||
},
|
||||
@@ -117,6 +124,9 @@ static struct neu_http_handler cors_handler[] = {
|
||||
{
|
||||
.url = "/api/v2/metrics",
|
||||
},
|
||||
{
|
||||
.url = "/api/v2/scan/tags",
|
||||
},
|
||||
};
|
||||
|
||||
static struct neu_http_handler rest_handlers[] = {
|
||||
@@ -259,6 +269,18 @@ static struct neu_http_handler rest_handlers[] = {
|
||||
.url = "/api/v2/read",
|
||||
.value.handler = handle_read,
|
||||
},
|
||||
{
|
||||
.method = NEU_HTTP_METHOD_POST,
|
||||
.type = NEU_HTTP_HANDLER_FUNCTION,
|
||||
.url = "/api/v2/read/paginate",
|
||||
.value.handler = handle_read_paginate,
|
||||
},
|
||||
{
|
||||
.method = NEU_HTTP_METHOD_POST,
|
||||
.type = NEU_HTTP_HANDLER_FUNCTION,
|
||||
.url = "/api/v2/read/test",
|
||||
.value.handler = handle_test_read_tag,
|
||||
},
|
||||
{
|
||||
.method = NEU_HTTP_METHOD_POST,
|
||||
.type = NEU_HTTP_HANDLER_FUNCTION,
|
||||
@@ -379,6 +401,12 @@ static struct neu_http_handler rest_handlers[] = {
|
||||
.url = "/api/v2/metrics",
|
||||
.value.handler = handle_get_metric,
|
||||
},
|
||||
{
|
||||
.method = NEU_HTTP_METHOD_POST,
|
||||
.type = NEU_HTTP_HANDLER_FUNCTION,
|
||||
.url = "/api/v2/scan/tags",
|
||||
.value.handler = handle_scan_tags,
|
||||
},
|
||||
};
|
||||
|
||||
void neu_rest_handler(const struct neu_http_handler **handlers, uint32_t *size)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "plugin_handle.h"
|
||||
#include "rest.h"
|
||||
#include "rw_handle.h"
|
||||
#include "scan_handle.h"
|
||||
#include "utils/http.h"
|
||||
#include "utils/log.h"
|
||||
#include "utils/neu_jwt.h"
|
||||
@@ -223,6 +224,17 @@ static int dashb_plugin_request(neu_plugin_t * plugin,
|
||||
case NEU_RESP_READ_GROUP:
|
||||
handle_read_resp(header->ctx, (neu_resp_read_group_t *) data);
|
||||
break;
|
||||
case NEU_RESP_READ_GROUP_PAGINATE:
|
||||
handle_read_paginate_resp(header->ctx,
|
||||
(neu_resp_read_group_paginate_t *) data);
|
||||
break;
|
||||
case NEU_RESP_TEST_READ_TAG:
|
||||
handle_test_read_tag_resp(header->ctx,
|
||||
(neu_resp_test_read_tag_t *) data);
|
||||
break;
|
||||
case NEU_RESP_SCAN_TAGS:
|
||||
handle_scan_tags_resp(header->ctx, (neu_resp_scan_tags_t *) data);
|
||||
break;
|
||||
default:
|
||||
nlog_fatal("recv unhandle msg: %s",
|
||||
neu_reqresp_type_string(header->type));
|
||||
|
||||
@@ -80,6 +80,117 @@ void handle_read(nng_aio *aio)
|
||||
})
|
||||
}
|
||||
|
||||
void handle_read_paginate(nng_aio *aio)
|
||||
{
|
||||
neu_plugin_t *plugin = neu_rest_get_plugin();
|
||||
|
||||
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
|
||||
aio, neu_json_read_paginate_req_t, neu_json_decode_read_paginate_req, {
|
||||
int ret = 0;
|
||||
neu_reqresp_head_t header = { 0 };
|
||||
neu_req_read_group_paginate_t cmd = { 0 };
|
||||
int err_type;
|
||||
header.ctx = aio;
|
||||
header.type = NEU_REQ_READ_GROUP_PAGINATE;
|
||||
|
||||
if (strlen(req->node) >= NEU_NODE_NAME_LEN) {
|
||||
err_type = NEU_ERR_NODE_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (strlen(req->node) >= NEU_GROUP_NAME_LEN) {
|
||||
err_type = NEU_ERR_GROUP_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (strlen(req->node) >= NEU_TAG_NAME_LEN) {
|
||||
err_type = NEU_ERR_TAG_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
cmd.driver = req->node;
|
||||
cmd.group = req->group;
|
||||
cmd.name = req->name;
|
||||
cmd.desc = req->desc;
|
||||
cmd.sync = req->sync;
|
||||
cmd.current_page = req->current_page;
|
||||
cmd.page_size = req->page_size;
|
||||
cmd.is_error = req->is_error;
|
||||
req->node = NULL;
|
||||
req->group = NULL;
|
||||
ret = neu_plugin_op(plugin, header, &cmd);
|
||||
if (ret != 0) {
|
||||
neu_req_read_group_paginate_fini(&cmd);
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, {
|
||||
neu_http_response(aio, NEU_ERR_IS_BUSY, result_error);
|
||||
});
|
||||
}
|
||||
goto success;
|
||||
|
||||
error:
|
||||
NEU_JSON_RESPONSE_ERROR(
|
||||
err_type, { neu_http_response(aio, err_type, result_error); });
|
||||
|
||||
success:;
|
||||
})
|
||||
}
|
||||
|
||||
void handle_test_read_tag(nng_aio *aio)
|
||||
{
|
||||
neu_plugin_t *plugin = neu_rest_get_plugin();
|
||||
|
||||
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
|
||||
aio, neu_json_test_read_tag_req_t, neu_json_decode_test_read_tag_req, {
|
||||
int ret = 0;
|
||||
neu_reqresp_head_t header = { 0 };
|
||||
neu_req_test_read_tag_t cmd = { 0 };
|
||||
int err_type;
|
||||
header.ctx = aio;
|
||||
header.type = NEU_REQ_TEST_READ_TAG;
|
||||
|
||||
if (req->driver && strlen(req->driver) >= NEU_NODE_NAME_LEN) {
|
||||
err_type = NEU_ERR_NODE_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
if (req->group && strlen(req->group) >= NEU_GROUP_NAME_LEN) {
|
||||
err_type = NEU_ERR_GROUP_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
if (req->tag && strlen(req->tag) >= NEU_TAG_NAME_LEN) {
|
||||
err_type = NEU_ERR_TAG_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
if (req->address && strlen(req->address) >= NEU_TAG_ADDRESS_LEN) {
|
||||
err_type = NEU_ERR_TAG_ADDRESS_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
strcpy(cmd.driver, req->driver);
|
||||
strcpy(cmd.group, req->group);
|
||||
strcpy(cmd.tag, req->tag);
|
||||
strcpy(cmd.address, req->address);
|
||||
cmd.attribute = req->attribute;
|
||||
cmd.type = req->type;
|
||||
cmd.precision = req->precision;
|
||||
cmd.decimal = req->decimal;
|
||||
cmd.bias = req->bias;
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
goto success;
|
||||
|
||||
error:
|
||||
NEU_JSON_RESPONSE_ERROR(
|
||||
err_type, { neu_http_response(aio, err_type, result_error); });
|
||||
|
||||
success:;
|
||||
})
|
||||
}
|
||||
|
||||
void handle_write(nng_aio *aio)
|
||||
{
|
||||
neu_plugin_t *plugin = neu_rest_get_plugin();
|
||||
@@ -384,3 +495,122 @@ void handle_read_resp(nng_aio *aio, neu_resp_read_group_t *resp)
|
||||
free(api_res.tags);
|
||||
free(result);
|
||||
}
|
||||
|
||||
void handle_read_paginate_resp(nng_aio * aio,
|
||||
neu_resp_read_group_paginate_t *resp)
|
||||
{
|
||||
neu_json_read_paginate_resp_t api_res = { 0 };
|
||||
char * result = NULL;
|
||||
|
||||
if (resp->is_error) {
|
||||
UT_array *filtered_tags;
|
||||
utarray_new(filtered_tags, neu_resp_tag_value_meta_paginate_icd());
|
||||
|
||||
utarray_foreach(resp->tags, neu_resp_tag_value_meta_paginate_t *,
|
||||
tag_value)
|
||||
{
|
||||
if (tag_value->value.type == NEU_TYPE_ERROR) {
|
||||
neu_resp_tag_value_meta_paginate_t new_tag_value;
|
||||
memcpy(&new_tag_value, tag_value,
|
||||
sizeof(neu_resp_tag_value_meta_paginate_t));
|
||||
|
||||
new_tag_value.datatag.name = strdup(tag_value->datatag.name);
|
||||
new_tag_value.datatag.address =
|
||||
strdup(tag_value->datatag.address);
|
||||
new_tag_value.datatag.description =
|
||||
strdup(tag_value->datatag.description);
|
||||
|
||||
utarray_push_back(filtered_tags, &new_tag_value);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < utarray_len(resp->tags); ++i) {
|
||||
neu_resp_tag_value_meta_paginate_t *orig_tag_value;
|
||||
orig_tag_value =
|
||||
(neu_resp_tag_value_meta_paginate_t *) utarray_eltptr(
|
||||
resp->tags, i);
|
||||
if (orig_tag_value) {
|
||||
free(orig_tag_value->datatag.name);
|
||||
free(orig_tag_value->datatag.address);
|
||||
free(orig_tag_value->datatag.description);
|
||||
}
|
||||
}
|
||||
|
||||
utarray_free(resp->tags);
|
||||
resp->tags = filtered_tags;
|
||||
}
|
||||
|
||||
unsigned int total_tags = utarray_len(resp->tags);
|
||||
|
||||
api_res.meta.current_page = resp->current_page;
|
||||
api_res.meta.page_size = resp->page_size;
|
||||
api_res.meta.total = total_tags;
|
||||
|
||||
if (resp->current_page > 0 && resp->page_size > 0) {
|
||||
unsigned int start_index = (resp->current_page - 1) * resp->page_size;
|
||||
unsigned int end_index = start_index + resp->page_size;
|
||||
|
||||
if (start_index >= total_tags) {
|
||||
api_res.n_tag = 0;
|
||||
api_res.tags = calloc(1, sizeof(neu_json_read_paginate_resp_tag_t));
|
||||
} else {
|
||||
if (end_index > total_tags) {
|
||||
end_index = total_tags;
|
||||
}
|
||||
|
||||
api_res.n_tag = end_index - start_index;
|
||||
api_res.tags = calloc(api_res.n_tag,
|
||||
sizeof(neu_json_read_paginate_resp_tag_t));
|
||||
|
||||
for (unsigned int i = start_index; i < end_index; i++) {
|
||||
neu_resp_tag_value_meta_paginate_t *tag_value =
|
||||
(neu_resp_tag_value_meta_paginate_t *) utarray_eltptr(
|
||||
resp->tags, i);
|
||||
neu_tag_value_to_json_paginate(tag_value,
|
||||
&api_res.tags[i - start_index]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
api_res.n_tag = total_tags;
|
||||
api_res.tags =
|
||||
calloc(api_res.n_tag, sizeof(neu_json_read_paginate_resp_tag_t));
|
||||
int index = 0;
|
||||
|
||||
utarray_foreach(resp->tags, neu_resp_tag_value_meta_paginate_t *,
|
||||
tag_value)
|
||||
{
|
||||
neu_tag_value_to_json_paginate(tag_value, &api_res.tags[index++]);
|
||||
}
|
||||
}
|
||||
|
||||
neu_json_encode_by_fn(&api_res, neu_json_encode_read_paginate_resp,
|
||||
&result);
|
||||
|
||||
for (unsigned int i = 0; i < utarray_len(resp->tags); ++i) {
|
||||
neu_resp_tag_value_meta_paginate_t *final_tag_value;
|
||||
final_tag_value = (neu_resp_tag_value_meta_paginate_t *) utarray_eltptr(
|
||||
resp->tags, i);
|
||||
if (final_tag_value) {
|
||||
free(final_tag_value->datatag.name);
|
||||
free(final_tag_value->datatag.address);
|
||||
free(final_tag_value->datatag.description);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < api_res.n_tag; i++) {
|
||||
if (api_res.tags[i].n_meta > 0) {
|
||||
free(api_res.tags[i].metas);
|
||||
}
|
||||
}
|
||||
neu_http_ok(aio, result);
|
||||
free(api_res.tags);
|
||||
free(result);
|
||||
}
|
||||
|
||||
void handle_test_read_tag_resp(nng_aio *aio, neu_resp_test_read_tag_t *resp)
|
||||
{
|
||||
char *result = NULL;
|
||||
neu_json_encode_by_fn(resp, neu_json_encode_test_read_tag_resp, &result);
|
||||
neu_http_ok(aio, result);
|
||||
free(result);
|
||||
}
|
||||
@@ -27,9 +27,14 @@
|
||||
void handle_rw_init();
|
||||
void handle_rw_uninit();
|
||||
void handle_read(nng_aio *aio);
|
||||
void handle_read_paginate(nng_aio *aio);
|
||||
void handle_test_read_tag(nng_aio *aio);
|
||||
void handle_write(nng_aio *aio);
|
||||
void handle_write_tags(nng_aio *aio);
|
||||
void handle_write_gtags(nng_aio *aio);
|
||||
void handle_read_resp(nng_aio *aio, neu_resp_read_group_t *resp);
|
||||
void handle_read_paginate_resp(nng_aio * aio,
|
||||
neu_resp_read_group_paginate_t *resp);
|
||||
void handle_test_read_tag_resp(nng_aio *aio, neu_resp_test_read_tag_t *resp);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "plugin.h"
|
||||
#include "utils/log.h"
|
||||
#include "json/neu_json_fn.h"
|
||||
#include "json/neu_json_scan.h"
|
||||
|
||||
#include "handle.h"
|
||||
#include "utils/http.h"
|
||||
|
||||
#include "scan_handle.h"
|
||||
|
||||
void handle_scan_tags(nng_aio *aio)
|
||||
{
|
||||
neu_plugin_t *plugin = neu_rest_get_plugin();
|
||||
|
||||
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
|
||||
aio, neu_json_scan_tags_req_t, neu_json_decode_scan_tags_req, {
|
||||
neu_reqresp_head_t header = { 0 };
|
||||
neu_req_scan_tags_t cmd = { 0 };
|
||||
int err_type;
|
||||
|
||||
nng_http_req *nng_req = nng_aio_get_input(aio, 0);
|
||||
nlog_notice("<%p> req %s %s", aio, nng_http_req_get_method(nng_req),
|
||||
nng_http_req_get_uri(nng_req));
|
||||
header.ctx = aio;
|
||||
header.type = NEU_REQ_SCAN_TAGS;
|
||||
|
||||
if (NULL != req->node && NEU_NODE_NAME_LEN <= strlen(req->node)) {
|
||||
err_type = NEU_ERR_NODE_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (NULL != req->id && NEU_TAG_ADDRESS_LEN <= strlen(req->id)) {
|
||||
err_type = NEU_ERR_NODE_NAME_TOO_LONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (NULL != req->node) {
|
||||
strcpy(cmd.driver, req->node);
|
||||
}
|
||||
|
||||
if (NULL != req->id) {
|
||||
strcpy(cmd.id, req->id);
|
||||
}
|
||||
|
||||
if (0 != neu_plugin_op(plugin, header, &cmd)) {
|
||||
NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, {
|
||||
neu_http_response(aio, NEU_ERR_IS_BUSY, result_error);
|
||||
});
|
||||
}
|
||||
goto success;
|
||||
|
||||
error:
|
||||
NEU_JSON_RESPONSE_ERROR(
|
||||
err_type, { neu_http_response(aio, err_type, result_error); });
|
||||
|
||||
success:;
|
||||
})
|
||||
}
|
||||
|
||||
void handle_scan_tags_resp(nng_aio *aio, neu_resp_scan_tags_t *resp)
|
||||
{
|
||||
char *result = NULL;
|
||||
neu_json_encode_by_fn(resp, neu_json_encode_scan_tags_resp, &result);
|
||||
neu_http_ok(aio, result);
|
||||
free(result);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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_SCAN_HANDLE_H_
|
||||
#define _NEU_ACAN_HANDLE_H_
|
||||
|
||||
#include <nng/nng.h>
|
||||
|
||||
void handle_scan_tags(nng_aio *aio);
|
||||
void handle_scan_tags_resp(nng_aio *aio, neu_resp_scan_tags_t *resp);
|
||||
void handle_scan_tag(nng_aio *aio);
|
||||
|
||||
#endif
|
||||
@@ -444,6 +444,17 @@ static int adapter_command(neu_adapter_t *adapter, neu_reqresp_head_t header,
|
||||
strcpy(pheader->receiver, cmd->driver);
|
||||
break;
|
||||
}
|
||||
case NEU_REQ_READ_GROUP_PAGINATE: {
|
||||
neu_req_read_group_paginate_t *cmd =
|
||||
(neu_req_read_group_paginate_t *) data;
|
||||
strcpy(pheader->receiver, cmd->driver);
|
||||
break;
|
||||
}
|
||||
case NEU_REQ_TEST_READ_TAG: {
|
||||
neu_req_test_read_tag_t *cmd = (neu_req_test_read_tag_t *) data;
|
||||
strcpy(pheader->receiver, cmd->driver);
|
||||
break;
|
||||
}
|
||||
case NEU_REQ_WRITE_TAG: {
|
||||
neu_req_write_tag_t *cmd = (neu_req_write_tag_t *) data;
|
||||
strcpy(pheader->receiver, cmd->driver);
|
||||
@@ -523,6 +534,11 @@ static int adapter_command(neu_adapter_t *adapter, neu_reqresp_head_t header,
|
||||
strcpy(pheader->receiver, header.sender);
|
||||
break;
|
||||
}
|
||||
case NEU_REQ_SCAN_TAGS: {
|
||||
neu_req_scan_tags_t *cmd = (neu_req_scan_tags_t *) data;
|
||||
strcpy(pheader->receiver, cmd->driver);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -727,6 +743,30 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
|
||||
break;
|
||||
}
|
||||
case NEU_RESP_READ_GROUP_PAGINATE:
|
||||
adapter->module->intf_funs->request(
|
||||
adapter->plugin, (neu_reqresp_head_t *) header, &header[1]);
|
||||
neu_resp_read_paginate_free(
|
||||
(neu_resp_read_group_paginate_t *) &header[1]);
|
||||
neu_msg_free(msg);
|
||||
break;
|
||||
case NEU_REQ_READ_GROUP_PAGINATE: {
|
||||
neu_resp_error_t error = { 0 };
|
||||
|
||||
if (adapter->module->type == NEU_NA_TYPE_DRIVER) {
|
||||
neu_adapter_driver_read_group_paginate(
|
||||
(neu_adapter_driver_t *) adapter, header);
|
||||
} else {
|
||||
neu_req_read_group_paginate_fini(
|
||||
(neu_req_read_group_paginate_t *) &header[1]);
|
||||
error.error = NEU_ERR_GROUP_NOT_ALLOW;
|
||||
header->type = NEU_RESP_ERROR;
|
||||
neu_msg_exchange(header);
|
||||
reply(adapter, header, &error);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NEU_REQ_WRITE_TAG: {
|
||||
neu_resp_error_t error = { 0 };
|
||||
|
||||
@@ -1181,6 +1221,27 @@ static int adapter_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
adapter->plugin, (neu_reqresp_head_t *) header, &header[1]);
|
||||
break;
|
||||
}
|
||||
case NEU_REQ_SCAN_TAGS: {
|
||||
neu_adapter_driver_scan_tags((neu_adapter_driver_t *) adapter, header);
|
||||
break;
|
||||
}
|
||||
case NEU_RESP_SCAN_TAGS: {
|
||||
adapter->module->intf_funs->request(
|
||||
adapter->plugin, (neu_reqresp_head_t *) header, &header[1]);
|
||||
neu_msg_free(msg);
|
||||
break;
|
||||
}
|
||||
case NEU_REQ_TEST_READ_TAG: {
|
||||
neu_adapter_driver_test_read_tag((neu_adapter_driver_t *) adapter,
|
||||
header);
|
||||
break;
|
||||
}
|
||||
case NEU_RESP_TEST_READ_TAG: {
|
||||
adapter->module->intf_funs->request(
|
||||
adapter->plugin, (neu_reqresp_head_t *) header, &header[1]);
|
||||
neu_msg_free(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
nlog_warn("adapter: %s recv msg type error, type: %s", adapter->name,
|
||||
neu_reqresp_type_string(header->type));
|
||||
|
||||
+435
-15
@@ -92,6 +92,10 @@ static void read_group(int64_t timestamp, int64_t timeout,
|
||||
neu_tag_cache_type_e cache_type,
|
||||
neu_driver_cache_t *cache, const char *group,
|
||||
UT_array *tags, UT_array *tag_values);
|
||||
static void read_group_paginate(int64_t timestamp, int64_t timeout,
|
||||
neu_tag_cache_type_e cache_type,
|
||||
neu_driver_cache_t *cache, const char *group,
|
||||
UT_array *tags, UT_array *tag_values);
|
||||
static void read_report_group(int64_t timestamp, int64_t timeout,
|
||||
neu_tag_cache_type_e cache_type,
|
||||
neu_driver_cache_t *cache, const char *group,
|
||||
@@ -111,6 +115,33 @@ static inline void start_group_timer(neu_adapter_driver_t *driver,
|
||||
group_t * grp);
|
||||
static inline void stop_group_timer(neu_adapter_driver_t *driver, group_t *grp);
|
||||
|
||||
static void format_tag_value(neu_dvalue_t *value)
|
||||
{
|
||||
double scale = pow(10, 5);
|
||||
int64_t integer_part = (int64_t) value->value.d64;
|
||||
double decimal_part = value->value.d64 - integer_part;
|
||||
decimal_part *= scale;
|
||||
decimal_part = round(decimal_part);
|
||||
char str[6] = { 0 };
|
||||
snprintf(str, sizeof(str), "%05" PRId64 "", (int64_t) decimal_part);
|
||||
int i = 0, flag = 0;
|
||||
for (; i < 4; i++) {
|
||||
if (str[i] == '0' && str[i + 1] == '0') {
|
||||
flag = 1;
|
||||
break;
|
||||
} else if (str[i] == '9' && str[i + 1] == '9') {
|
||||
flag = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag != 0 && i != 0) {
|
||||
decimal_part = round(decimal_part / pow(10, 5 - i));
|
||||
value->value.d64 = (double) integer_part + decimal_part / pow(10, i);
|
||||
} else {
|
||||
value->value.d64 = (double) integer_part + decimal_part / scale;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_response(neu_adapter_t *adapter, void *r, neu_error error)
|
||||
{
|
||||
neu_reqresp_head_t *req = (neu_reqresp_head_t *) r;
|
||||
@@ -187,14 +218,8 @@ static void update_im(neu_adapter_t *adapter, const char *group,
|
||||
{
|
||||
neu_adapter_driver_t *driver = (neu_adapter_driver_t *) adapter;
|
||||
|
||||
if (tag == NULL || value.type == NEU_TYPE_ERROR) {
|
||||
nlog_warn("update_im tag is null or value is error %d",
|
||||
value.value.i32);
|
||||
return;
|
||||
}
|
||||
|
||||
UT_array *tags = neu_adapter_driver_get_ptag(driver, group, tag);
|
||||
if (tags == NULL) {
|
||||
if (tag == NULL) {
|
||||
nlog_warn("update_im tag is null");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -202,6 +227,14 @@ static void update_im(neu_adapter_t *adapter, const char *group,
|
||||
value, metas, n_meta, true);
|
||||
driver->adapter.cb_funs.update_metric(&driver->adapter,
|
||||
NEU_METRIC_TAG_READS_TOTAL, 1, NULL);
|
||||
if (value.type == NEU_TYPE_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
UT_array *tags = neu_adapter_driver_get_ptag(driver, group, tag);
|
||||
if (tags == NULL) {
|
||||
return;
|
||||
}
|
||||
neu_datatag_t *first = utarray_front(tags);
|
||||
|
||||
if (first == NULL ||
|
||||
@@ -294,16 +327,52 @@ static void update(neu_adapter_t *adapter, const char *group, const char *tag,
|
||||
update_with_meta(adapter, group, tag, value, NULL, 0);
|
||||
}
|
||||
|
||||
static void scan_tags_response(neu_adapter_t *adapter, void *r, neu_error error,
|
||||
void *tags, neu_type_e type, bool is_array)
|
||||
{
|
||||
neu_reqresp_head_t * req = (neu_reqresp_head_t *) r;
|
||||
neu_resp_scan_tags_t value = {
|
||||
.scan_tags = tags,
|
||||
.error = error,
|
||||
.type = type,
|
||||
.is_array = is_array,
|
||||
};
|
||||
req->type = NEU_RESP_SCAN_TAGS;
|
||||
nlog_notice("scan tags response <%p>", req->ctx);
|
||||
|
||||
adapter->cb_funs.response(adapter, req, &value);
|
||||
}
|
||||
|
||||
static void test_read_tag_response(neu_adapter_t *adapter, void *r,
|
||||
neu_json_type_e t, neu_type_e type,
|
||||
neu_json_value_u value, int64_t error)
|
||||
{
|
||||
neu_reqresp_head_t * req = (neu_reqresp_head_t *) r;
|
||||
neu_resp_test_read_tag_t dvalue = {
|
||||
.t = t,
|
||||
.type = type,
|
||||
.value = value,
|
||||
.error = error,
|
||||
};
|
||||
req->type = NEU_RESP_TEST_READ_TAG;
|
||||
nlog_notice("test reading tag response <%p>", req->ctx);
|
||||
|
||||
adapter->cb_funs.response(adapter, req, &dvalue);
|
||||
}
|
||||
|
||||
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->adapter.cb_funs.driver.update = update;
|
||||
driver->adapter.cb_funs.driver.write_response = write_response;
|
||||
driver->adapter.cb_funs.driver.update_im = update_im;
|
||||
driver->adapter.cb_funs.driver.update_with_meta = update_with_meta;
|
||||
driver->cache = neu_driver_cache_new();
|
||||
driver->driver_events = neu_event_new();
|
||||
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;
|
||||
driver->adapter.cb_funs.driver.update_with_meta = update_with_meta;
|
||||
driver->adapter.cb_funs.driver.scan_tags_response = scan_tags_response;
|
||||
driver->adapter.cb_funs.driver.test_read_tag_response =
|
||||
test_read_tag_response;
|
||||
|
||||
return driver;
|
||||
}
|
||||
@@ -497,6 +566,106 @@ void neu_adapter_driver_read_group(neu_adapter_driver_t *driver,
|
||||
driver->adapter.cb_funs.response(&driver->adapter, req, &resp);
|
||||
}
|
||||
|
||||
void neu_adapter_driver_read_group_paginate(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req)
|
||||
{
|
||||
neu_req_read_group_paginate_t *cmd =
|
||||
(neu_req_read_group_paginate_t *) &req[1];
|
||||
group_t *g = find_group(driver, cmd->group);
|
||||
if (g == NULL) {
|
||||
neu_resp_error_t error = { .error = NEU_ERR_GROUP_NOT_EXIST };
|
||||
req->type = NEU_RESP_ERROR;
|
||||
neu_req_read_group_paginate_fini(cmd);
|
||||
driver->adapter.cb_funs.response(&driver->adapter, req, &error);
|
||||
return;
|
||||
}
|
||||
|
||||
neu_resp_read_group_paginate_t resp = { 0 };
|
||||
neu_group_t * group = g->group;
|
||||
UT_array *tags = neu_group_query_read_tag(group, cmd->name, cmd->desc);
|
||||
|
||||
utarray_new(resp.tags, neu_resp_tag_value_meta_paginate_icd());
|
||||
|
||||
if (driver->adapter.state != NEU_NODE_RUNNING_STATE_RUNNING) {
|
||||
utarray_foreach(tags, neu_datatag_t *, tag)
|
||||
{
|
||||
neu_resp_tag_value_meta_paginate_t tag_value = { 0 };
|
||||
strcpy(tag_value.tag, tag->name);
|
||||
tag_value.value.type = NEU_TYPE_ERROR;
|
||||
tag_value.value.value.i32 = NEU_ERR_PLUGIN_NOT_RUNNING;
|
||||
|
||||
tag_value.datatag.name = strdup(tag->name);
|
||||
tag_value.datatag.address = strdup(tag->address);
|
||||
tag_value.datatag.attribute = tag->attribute;
|
||||
tag_value.datatag.type = tag->type;
|
||||
tag_value.datatag.precision = tag->precision;
|
||||
tag_value.datatag.decimal = tag->decimal;
|
||||
tag_value.datatag.bias = tag->bias;
|
||||
tag_value.datatag.description = strdup(tag->description);
|
||||
tag_value.datatag.option = tag->option;
|
||||
memcpy(tag_value.datatag.meta, tag->meta, NEU_TAG_META_LENGTH);
|
||||
|
||||
utarray_push_back(resp.tags, &tag_value);
|
||||
}
|
||||
} else if (cmd->sync) {
|
||||
if (NULL == driver->adapter.module->intf_funs->driver.group_sync) {
|
||||
// plugin does not support sync read
|
||||
utarray_foreach(tags, neu_datatag_t *, tag)
|
||||
{
|
||||
neu_resp_tag_value_meta_paginate_t tag_value = { 0 };
|
||||
strcpy(tag_value.tag, tag->name);
|
||||
tag_value.value.type = NEU_TYPE_ERROR;
|
||||
tag_value.value.value.i32 =
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_READ_SYNC;
|
||||
|
||||
tag_value.datatag.name = strdup(tag->name);
|
||||
tag_value.datatag.address = strdup(tag->address);
|
||||
tag_value.datatag.attribute = tag->attribute;
|
||||
tag_value.datatag.type = tag->type;
|
||||
tag_value.datatag.precision = tag->precision;
|
||||
tag_value.datatag.decimal = tag->decimal;
|
||||
tag_value.datatag.bias = tag->bias;
|
||||
tag_value.datatag.description = strdup(tag->description);
|
||||
tag_value.datatag.option = tag->option;
|
||||
memcpy(tag_value.datatag.meta, tag->meta, NEU_TAG_META_LENGTH);
|
||||
|
||||
utarray_push_back(resp.tags, &tag_value);
|
||||
}
|
||||
} else {
|
||||
// sync read to update cache
|
||||
driver->adapter.module->intf_funs->driver.group_sync(
|
||||
driver->adapter.plugin, &g->grp);
|
||||
// fetch updated data from cache
|
||||
read_group_paginate(
|
||||
global_timestamp,
|
||||
neu_group_get_interval(group) *
|
||||
NEU_DRIVER_TAG_CACHE_EXPIRE_TIME,
|
||||
neu_adapter_get_tag_cache_type(&driver->adapter), driver->cache,
|
||||
cmd->group, tags, resp.tags);
|
||||
}
|
||||
} else {
|
||||
read_group_paginate(global_timestamp,
|
||||
neu_group_get_interval(group) *
|
||||
NEU_DRIVER_TAG_CACHE_EXPIRE_TIME,
|
||||
neu_adapter_get_tag_cache_type(&driver->adapter),
|
||||
driver->cache, cmd->group, tags, resp.tags);
|
||||
}
|
||||
|
||||
resp.driver = cmd->driver;
|
||||
resp.group = cmd->group;
|
||||
resp.current_page = cmd->current_page;
|
||||
resp.page_size = cmd->page_size;
|
||||
resp.is_error = cmd->is_error;
|
||||
cmd->driver = NULL; // ownership moved
|
||||
cmd->group = NULL; // ownership moved
|
||||
|
||||
utarray_free(tags);
|
||||
neu_req_read_group_paginate_fini(cmd);
|
||||
|
||||
req->type = NEU_RESP_READ_GROUP_PAGINATE;
|
||||
driver->adapter.cb_funs.response(&driver->adapter, req, &resp);
|
||||
}
|
||||
|
||||
static void fix_value(neu_datatag_t *tag, neu_type_e value_type,
|
||||
neu_dvalue_t *value)
|
||||
{
|
||||
@@ -1918,7 +2087,7 @@ static void read_report_group(int64_t timestamp, int64_t timeout,
|
||||
if (neu_driver_cache_meta_get_changed(cache, group, tag->name,
|
||||
&value, tag_value.metas,
|
||||
NEU_TAG_META_SIZE) != 0) {
|
||||
nlog_info("tag: %s not changed", tag->name);
|
||||
nlog_debug("tag: %s not changed", tag->name);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
@@ -1942,6 +2111,14 @@ static void read_report_group(int64_t timestamp, int64_t timeout,
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((tag->type == NEU_TYPE_FLOAT && isnan(value.value.value.f32)) ||
|
||||
(tag->type == NEU_TYPE_DOUBLE && isnan(value.value.value.d64))) {
|
||||
tag_value.value.type = NEU_TYPE_ERROR;
|
||||
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
|
||||
utarray_push_back(tag_values, &tag_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (tag->type) {
|
||||
case NEU_TYPE_UINT16:
|
||||
case NEU_TYPE_INT16:
|
||||
@@ -2063,6 +2240,9 @@ static void read_report_group(int64_t timestamp, int64_t timeout,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tag->precision == 0 && tag->type == NEU_TYPE_DOUBLE) {
|
||||
format_tag_value(&tag_value.value);
|
||||
}
|
||||
}
|
||||
|
||||
utarray_push_back(tag_values, &tag_value);
|
||||
@@ -2220,6 +2400,181 @@ static void read_group(int64_t timestamp, int64_t timeout,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag->precision == 0 && tag->type == NEU_TYPE_DOUBLE) {
|
||||
format_tag_value(&tag_value.value);
|
||||
}
|
||||
}
|
||||
utarray_push_back(tag_values, &tag_value);
|
||||
}
|
||||
}
|
||||
|
||||
static void read_group_paginate(int64_t timestamp, int64_t timeout,
|
||||
neu_tag_cache_type_e cache_type,
|
||||
neu_driver_cache_t *cache, const char *group,
|
||||
UT_array *tags, UT_array *tag_values)
|
||||
{
|
||||
utarray_foreach(tags, neu_datatag_t *, tag)
|
||||
{
|
||||
neu_resp_tag_value_meta_paginate_t tag_value = { 0 };
|
||||
neu_driver_cache_value_t value = { 0 };
|
||||
|
||||
strcpy(tag_value.tag, tag->name);
|
||||
|
||||
tag_value.datatag.name = strdup(tag->name);
|
||||
tag_value.datatag.address = strdup(tag->address);
|
||||
tag_value.datatag.attribute = tag->attribute;
|
||||
tag_value.datatag.type = tag->type;
|
||||
tag_value.datatag.precision = tag->precision;
|
||||
tag_value.datatag.decimal = tag->decimal;
|
||||
tag_value.datatag.bias = tag->bias;
|
||||
tag_value.datatag.description = strdup(tag->description);
|
||||
tag_value.datatag.option = tag->option;
|
||||
memcpy(tag_value.datatag.meta, tag->meta, NEU_TAG_META_LENGTH);
|
||||
|
||||
if (neu_driver_cache_meta_get(cache, group, tag->name, &value,
|
||||
tag_value.metas,
|
||||
NEU_TAG_META_SIZE) != 0) {
|
||||
tag_value.value.type = NEU_TYPE_ERROR;
|
||||
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_NOT_READY;
|
||||
|
||||
utarray_push_back(tag_values, &tag_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value.value.type == NEU_TYPE_ERROR) {
|
||||
tag_value.value = value.value;
|
||||
utarray_push_back(tag_values, &tag_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (tag->type) {
|
||||
case NEU_TYPE_UINT16:
|
||||
case NEU_TYPE_INT16:
|
||||
switch (tag->option.value16.endian) {
|
||||
case NEU_DATATAG_ENDIAN_B16:
|
||||
value.value.value.u16 = htons(value.value.value.u16);
|
||||
break;
|
||||
case NEU_DATATAG_ENDIAN_L16:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NEU_TYPE_FLOAT:
|
||||
case NEU_TYPE_UINT32:
|
||||
case NEU_TYPE_INT32:
|
||||
switch (tag->option.value32.endian) {
|
||||
case NEU_DATATAG_ENDIAN_LB32: {
|
||||
uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes;
|
||||
uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2);
|
||||
|
||||
neu_htons_p(v1);
|
||||
neu_htons_p(v2);
|
||||
break;
|
||||
}
|
||||
case NEU_DATATAG_ENDIAN_BB32:
|
||||
value.value.value.u32 = htonl(value.value.value.u32);
|
||||
break;
|
||||
case NEU_DATATAG_ENDIAN_BL32:
|
||||
value.value.value.u32 = htonl(value.value.value.u32);
|
||||
uint16_t *v1 = (uint16_t *) value.value.value.bytes.bytes;
|
||||
uint16_t *v2 = (uint16_t *) (value.value.value.bytes.bytes + 2);
|
||||
|
||||
neu_htons_p(v1);
|
||||
neu_htons_p(v2);
|
||||
break;
|
||||
case NEU_DATATAG_ENDIAN_LL32:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NEU_TYPE_DOUBLE:
|
||||
case NEU_TYPE_INT64:
|
||||
case NEU_TYPE_UINT64:
|
||||
switch (tag->option.value64.endian) {
|
||||
case NEU_DATATAG_ENDIAN_B64:
|
||||
value.value.value.u64 = neu_htonll(value.value.value.u64);
|
||||
break;
|
||||
case NEU_DATATAG_ENDIAN_L64:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cache_type != NEU_TAG_CACHE_TYPE_NEVER &&
|
||||
!neu_tag_attribute_test(tag, NEU_ATTRIBUTE_STATIC) &&
|
||||
(timestamp - value.timestamp) > timeout) {
|
||||
if (value.value.type == NEU_TYPE_PTR) {
|
||||
free(value.value.value.ptr.ptr);
|
||||
}
|
||||
tag_value.value.type = NEU_TYPE_ERROR;
|
||||
tag_value.value.value.i32 = NEU_ERR_PLUGIN_TAG_VALUE_EXPIRED;
|
||||
} else {
|
||||
if (value.value.type == NEU_TYPE_PTR) {
|
||||
tag_value.value.type = NEU_TYPE_PTR;
|
||||
tag_value.value.value.ptr.length = value.value.value.ptr.length;
|
||||
tag_value.value.value.ptr.type = value.value.value.ptr.type;
|
||||
tag_value.value.value.ptr.ptr = value.value.value.ptr.ptr;
|
||||
} else {
|
||||
tag_value.value = value.value;
|
||||
}
|
||||
if (tag->decimal != 0 || tag->bias != 0) {
|
||||
tag_value.value.type = NEU_TYPE_DOUBLE;
|
||||
double decimal = tag->decimal != 0 ? tag->decimal : 1;
|
||||
double bias = tag->bias;
|
||||
switch (tag->type) {
|
||||
case NEU_TYPE_INT8:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.i8 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_UINT8:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.u8 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_INT16:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.i16 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_UINT16:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.u16 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_INT32:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.i32 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_UINT32:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.u32 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_INT64:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.i64 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_UINT64:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.u64 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_FLOAT:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.f32 * decimal + bias;
|
||||
break;
|
||||
case NEU_TYPE_DOUBLE:
|
||||
tag_value.value.value.d64 =
|
||||
(double) tag_value.value.value.d64 * decimal + bias;
|
||||
break;
|
||||
default:
|
||||
tag_value.value.type = tag->type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag->precision == 0 && tag->type == NEU_TYPE_DOUBLE) {
|
||||
format_tag_value(&tag_value.value);
|
||||
}
|
||||
}
|
||||
utarray_push_back(tag_values, &tag_value);
|
||||
}
|
||||
@@ -2289,4 +2644,69 @@ void neu_adapter_driver_unsubscribe(neu_adapter_driver_t * driver,
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&find->apps_mtx);
|
||||
}
|
||||
|
||||
void neu_adapter_driver_scan_tags(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req)
|
||||
{
|
||||
if (driver->adapter.state != NEU_NODE_RUNNING_STATE_RUNNING) {
|
||||
driver->adapter.cb_funs.driver.scan_tags_response(
|
||||
&driver->adapter, req, NEU_ERR_PLUGIN_NOT_RUNNING, NULL,
|
||||
NEU_TYPE_ERROR, false);
|
||||
|
||||
nlog_warn("%s not running", driver->adapter.name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (driver->adapter.module->intf_funs->driver.scan_tags == NULL) {
|
||||
driver->adapter.cb_funs.driver.scan_tags_response(
|
||||
&driver->adapter, req, NEU_ERR_PLUGIN_NOT_SUPPORT_SCAN_TAGS, NULL,
|
||||
NEU_TYPE_ERROR, false);
|
||||
|
||||
nlog_warn("%s not support scan tags", driver->adapter.name);
|
||||
return;
|
||||
}
|
||||
|
||||
neu_req_scan_tags_t *cmd = (neu_req_scan_tags_t *) &req[1];
|
||||
driver->adapter.module->intf_funs->driver.scan_tags(driver->adapter.plugin,
|
||||
req, cmd->id);
|
||||
}
|
||||
|
||||
void neu_adapter_driver_test_read_tag(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req)
|
||||
{
|
||||
neu_json_value_u error_value;
|
||||
error_value.val_int = 0;
|
||||
|
||||
if (driver->adapter.state != NEU_NODE_RUNNING_STATE_RUNNING) {
|
||||
driver->adapter.cb_funs.driver.test_read_tag_response(
|
||||
&driver->adapter, req, NEU_JSON_INT, NEU_TYPE_ERROR, error_value,
|
||||
NEU_ERR_PLUGIN_NOT_RUNNING);
|
||||
|
||||
nlog_warn("%s not running", driver->adapter.name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (driver->adapter.module->intf_funs->driver.test_read_tag == NULL) {
|
||||
driver->adapter.cb_funs.driver.test_read_tag_response(
|
||||
&driver->adapter, req, NEU_JSON_INT, NEU_TYPE_ERROR, error_value,
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_TEST_READ_TAG);
|
||||
|
||||
nlog_warn("%s not support testing reading", driver->adapter.name);
|
||||
return;
|
||||
}
|
||||
|
||||
neu_req_test_read_tag_t *cmd = (neu_req_test_read_tag_t *) &req[1];
|
||||
neu_datatag_t datatag;
|
||||
datatag.name = cmd->tag;
|
||||
datatag.address = cmd->address;
|
||||
datatag.attribute = cmd->attribute;
|
||||
datatag.type = cmd->type;
|
||||
datatag.precision = cmd->precision;
|
||||
datatag.decimal = cmd->decimal;
|
||||
datatag.bias = cmd->bias;
|
||||
datatag.option = cmd->option;
|
||||
|
||||
driver->adapter.module->intf_funs->driver.test_read_tag(
|
||||
driver->adapter.plugin, req, datatag);
|
||||
}
|
||||
@@ -33,6 +33,10 @@ void neu_adapter_driver_stop_group_timer(neu_adapter_driver_t *driver);
|
||||
|
||||
void neu_adapter_driver_read_group(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req);
|
||||
void neu_adapter_driver_read_group_paginate(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req);
|
||||
void neu_adapter_driver_test_read_tag(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req);
|
||||
|
||||
void neu_adapter_driver_write_tag(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req);
|
||||
@@ -87,4 +91,7 @@ void neu_adapter_driver_subscribe(neu_adapter_driver_t *driver,
|
||||
neu_req_subscribe_t * req);
|
||||
void neu_adapter_driver_unsubscribe(neu_adapter_driver_t * driver,
|
||||
neu_req_unsubscribe_t *req);
|
||||
|
||||
void neu_adapter_driver_scan_tags(neu_adapter_driver_t *driver,
|
||||
neu_reqresp_head_t * req);
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,10 @@ extern "C" {
|
||||
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) \
|
||||
@@ -93,7 +97,9 @@ extern "C" {
|
||||
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_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)
|
||||
|
||||
static inline size_t neu_reqresp_size(neu_reqresp_type_e t)
|
||||
{
|
||||
|
||||
@@ -125,7 +125,9 @@ void neu_conn_stop(neu_conn_t *conn)
|
||||
void neu_conn_start(neu_conn_t *conn)
|
||||
{
|
||||
pthread_mutex_lock(&conn->mtx);
|
||||
conn->stop = false;
|
||||
conn->state.recv_bytes = 0;
|
||||
conn->state.send_bytes = 0;
|
||||
conn->stop = false;
|
||||
pthread_mutex_unlock(&conn->mtx);
|
||||
}
|
||||
|
||||
|
||||
+14
-3
@@ -236,7 +236,8 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
break;
|
||||
}
|
||||
|
||||
if (init->state == NEU_NODE_RUNNING_STATE_RUNNING ||
|
||||
if (init->state == NEU_NODE_RUNNING_STATE_READY ||
|
||||
init->state == NEU_NODE_RUNNING_STATE_RUNNING ||
|
||||
init->state == NEU_NODE_RUNNING_STATE_STOPPED) {
|
||||
neu_adapter_t *adapter =
|
||||
neu_node_manager_find(manager->node_manager, init->node);
|
||||
@@ -699,8 +700,9 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
}
|
||||
case NEU_REQ_ADD_NODE: {
|
||||
neu_req_add_node_t *cmd = (neu_req_add_node_t *) &header[1];
|
||||
int error = neu_manager_add_node(manager, cmd->node, cmd->plugin,
|
||||
cmd->setting, false, false);
|
||||
int error =
|
||||
neu_manager_add_node(manager, cmd->node, cmd->plugin, cmd->setting,
|
||||
NEU_NODE_RUNNING_STATE_INIT, false);
|
||||
neu_resp_error_t e = { .error = error };
|
||||
|
||||
if (error == NEU_ERR_SUCCESS) {
|
||||
@@ -1007,6 +1009,7 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
case NEU_REQ_GET_GROUP:
|
||||
case NEU_REQ_GET_NODE_SETTING:
|
||||
case NEU_REQ_READ_GROUP:
|
||||
case NEU_REQ_READ_GROUP_PAGINATE:
|
||||
case NEU_REQ_WRITE_TAG:
|
||||
case NEU_REQ_WRITE_TAGS:
|
||||
case NEU_REQ_WRITE_GTAGS:
|
||||
@@ -1017,6 +1020,9 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
NULL) {
|
||||
if (NEU_REQ_READ_GROUP == header->type) {
|
||||
neu_req_read_group_fini((neu_req_read_group_t *) &header[1]);
|
||||
} else if (NEU_REQ_READ_GROUP_PAGINATE == header->type) {
|
||||
neu_req_read_group_paginate_fini(
|
||||
(neu_req_read_group_paginate_t *) &header[1]);
|
||||
} else if (NEU_REQ_WRITE_TAG == header->type) {
|
||||
neu_req_write_tag_fini((neu_req_write_tag_t *) &header[1]);
|
||||
} else if (NEU_REQ_WRITE_TAGS == header->type) {
|
||||
@@ -1036,6 +1042,8 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
}
|
||||
case NEU_REQ_PRGFILE_PROCESS:
|
||||
case NEU_REQ_PRGFILE_UPLOAD:
|
||||
case NEU_REQ_SCAN_TAGS:
|
||||
case NEU_REQ_TEST_READ_TAG:
|
||||
case NEU_REQ_GET_NODE_STATE: {
|
||||
if (neu_node_manager_find(manager->node_manager, header->receiver) ==
|
||||
NULL) {
|
||||
@@ -1244,7 +1252,10 @@ static int manager_loop(enum neu_event_io_type type, int fd, void *usr_data)
|
||||
case NEU_RESP_GET_NODE_SETTING:
|
||||
case NEU_RESP_ERROR:
|
||||
case NEU_RESP_READ_GROUP:
|
||||
case NEU_RESP_READ_GROUP_PAGINATE:
|
||||
case NEU_RESP_TEST_READ_TAG:
|
||||
case NEU_RESP_PRGFILE_PROCESS:
|
||||
case NEU_RESP_SCAN_TAGS:
|
||||
forward_msg(manager, header, header->receiver);
|
||||
break;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "json/json.h"
|
||||
|
||||
#include "define.h"
|
||||
#include "msg.h"
|
||||
#include "tag.h"
|
||||
|
||||
#include "json/neu_json_rw.h"
|
||||
@@ -81,6 +82,132 @@ int neu_json_encode_read_resp(void *json_object, void *param)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int neu_json_encode_read_paginate_resp(void *json_object, void *param)
|
||||
{
|
||||
int ret = 0;
|
||||
neu_json_read_paginate_resp_t *resp =
|
||||
(neu_json_read_paginate_resp_t *) param;
|
||||
|
||||
void * tag_array = neu_json_array();
|
||||
neu_json_read_paginate_resp_tag_t *p_tag = resp->tags;
|
||||
|
||||
for (int i = 0; i < resp->n_tag; i++) {
|
||||
neu_json_elem_t tag_elems[10 + NEU_TAG_META_SIZE] = { 0 };
|
||||
int if_precision = 0;
|
||||
|
||||
tag_elems[0].name = "name";
|
||||
tag_elems[0].t = NEU_JSON_STR;
|
||||
tag_elems[0].v.val_str = p_tag->name;
|
||||
|
||||
tag_elems[1].name = "type";
|
||||
tag_elems[1].t = NEU_JSON_INT;
|
||||
tag_elems[1].v.val_int = p_tag->datatag.type;
|
||||
|
||||
tag_elems[2].name = "address";
|
||||
tag_elems[2].t = NEU_JSON_STR;
|
||||
tag_elems[2].v.val_str = p_tag->datatag.address;
|
||||
|
||||
tag_elems[3].name = "attribute";
|
||||
tag_elems[3].t = NEU_JSON_INT;
|
||||
tag_elems[3].v.val_int = p_tag->datatag.attribute;
|
||||
|
||||
tag_elems[4].name = "description";
|
||||
tag_elems[4].t = NEU_JSON_STR;
|
||||
tag_elems[4].v.val_str = p_tag->datatag.description;
|
||||
|
||||
tag_elems[5].name = "precision";
|
||||
tag_elems[5].t = NEU_JSON_INT;
|
||||
tag_elems[5].v.val_int = p_tag->datatag.precision;
|
||||
|
||||
tag_elems[6].name = "decimal";
|
||||
tag_elems[6].t = NEU_JSON_DOUBLE;
|
||||
tag_elems[6].v.val_double = p_tag->datatag.decimal;
|
||||
|
||||
tag_elems[7].name = "bias";
|
||||
tag_elems[7].t = NEU_JSON_DOUBLE;
|
||||
tag_elems[7].v.val_double = p_tag->datatag.bias;
|
||||
|
||||
if (p_tag->error != 0) {
|
||||
tag_elems[8].name = "error";
|
||||
tag_elems[8].t = NEU_JSON_INT;
|
||||
tag_elems[8].v.val_int = p_tag->error;
|
||||
} else {
|
||||
tag_elems[8].name = "value";
|
||||
tag_elems[8].t = p_tag->t;
|
||||
tag_elems[8].v = p_tag->value;
|
||||
tag_elems[8].precision = p_tag->precision;
|
||||
|
||||
if (p_tag->t == NEU_JSON_FLOAT || p_tag->t == NEU_JSON_DOUBLE) {
|
||||
if_precision = 1;
|
||||
tag_elems[9].name = "precision";
|
||||
tag_elems[9].t = NEU_JSON_INT;
|
||||
tag_elems[9].v.val_int =
|
||||
p_tag->precision > 0 ? p_tag->precision : 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < p_tag->n_meta; k++) {
|
||||
tag_elems[if_precision + 9 + k].name = p_tag->metas[k].name;
|
||||
tag_elems[if_precision + 9 + k].t = p_tag->metas[k].t;
|
||||
tag_elems[if_precision + 9 + k].v = p_tag->metas[k].value;
|
||||
}
|
||||
|
||||
tag_array = neu_json_encode_array(tag_array, tag_elems,
|
||||
9 + if_precision + p_tag->n_meta);
|
||||
|
||||
free(p_tag->datatag.name);
|
||||
free(p_tag->datatag.address);
|
||||
free(p_tag->datatag.description);
|
||||
|
||||
p_tag++;
|
||||
}
|
||||
|
||||
void * meta_object = neu_json_encode_new();
|
||||
neu_json_elem_t meta_elems[] = {
|
||||
{ .name = "currentPage",
|
||||
.t = NEU_JSON_INT,
|
||||
.v.val_int = resp->meta.current_page },
|
||||
{ .name = "pageSize",
|
||||
.t = NEU_JSON_INT,
|
||||
.v.val_int = resp->meta.page_size },
|
||||
{ .name = "total", .t = NEU_JSON_INT, .v.val_int = resp->meta.total }
|
||||
};
|
||||
neu_json_encode_field(meta_object, meta_elems, 3);
|
||||
|
||||
neu_json_elem_t resp_elems[] = {
|
||||
{ .name = "meta", .t = NEU_JSON_OBJECT, .v.val_object = meta_object },
|
||||
{ .name = "items", .t = NEU_JSON_OBJECT, .v.val_object = tag_array },
|
||||
};
|
||||
ret = neu_json_encode_field(json_object, resp_elems, 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int neu_json_encode_test_read_tag_resp(void *json_object, void *param)
|
||||
{
|
||||
int ret = 0;
|
||||
neu_resp_test_read_tag_t *resp = (neu_resp_test_read_tag_t *) param;
|
||||
neu_json_elem_t resp_elem = { 0 };
|
||||
|
||||
if (resp->type == NEU_TYPE_ERROR) {
|
||||
resp_elem.name = "error";
|
||||
resp_elem.t = NEU_JSON_INT;
|
||||
resp_elem.v.val_int = resp->error;
|
||||
} else {
|
||||
resp_elem.name = "value";
|
||||
resp_elem.t = resp->t;
|
||||
resp_elem.v = resp->value;
|
||||
}
|
||||
|
||||
ret = neu_json_encode_field(json_object, &resp_elem, 1);
|
||||
|
||||
if (resp->t == NEU_JSON_STR) {
|
||||
free(resp->value.val_str);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int neu_json_encode_read_resp1(void *json_object, void *param)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -500,6 +627,220 @@ void neu_json_decode_read_req_free(neu_json_read_req_t *req)
|
||||
free(req);
|
||||
}
|
||||
|
||||
int neu_json_decode_read_paginate_req(char * buf,
|
||||
neu_json_read_paginate_req_t **result)
|
||||
{
|
||||
int ret = 0;
|
||||
void *json_obj = NULL;
|
||||
|
||||
json_obj = neu_json_decode_new(buf);
|
||||
if (NULL == json_obj) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
neu_json_read_paginate_req_t *req =
|
||||
calloc(1, sizeof(neu_json_read_paginate_req_t));
|
||||
if (req == NULL) {
|
||||
neu_json_decode_free(json_obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
neu_json_elem_t req_elems[] = {
|
||||
{
|
||||
.name = "node",
|
||||
.t = NEU_JSON_STR,
|
||||
},
|
||||
{
|
||||
.name = "group",
|
||||
.t = NEU_JSON_STR,
|
||||
},
|
||||
{
|
||||
.name = "sync",
|
||||
.t = NEU_JSON_BOOL,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
{
|
||||
.name = "query",
|
||||
.t = NEU_JSON_OBJECT,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
};
|
||||
|
||||
neu_json_elem_t query_elems[] = {
|
||||
{
|
||||
.name = "name",
|
||||
.t = NEU_JSON_STR,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
{
|
||||
.name = "description",
|
||||
.t = NEU_JSON_STR,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
{
|
||||
.name = "currentPage",
|
||||
.t = NEU_JSON_INT,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
{
|
||||
.name = "pageSize",
|
||||
.t = NEU_JSON_INT,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
{
|
||||
.name = "isError",
|
||||
.t = NEU_JSON_BOOL,
|
||||
.attribute = NEU_JSON_ATTRIBUTE_OPTIONAL,
|
||||
},
|
||||
};
|
||||
|
||||
ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
|
||||
req_elems);
|
||||
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
req->node = req_elems[0].v.val_str;
|
||||
req->group = req_elems[1].v.val_str;
|
||||
req->sync = req_elems[2].v.val_bool;
|
||||
|
||||
if (req_elems[3].v.val_object) {
|
||||
ret = neu_json_decode_by_json(req_elems[3].v.val_object,
|
||||
NEU_JSON_ELEM_SIZE(query_elems),
|
||||
query_elems);
|
||||
|
||||
if (ret != 0) {
|
||||
goto error;
|
||||
}
|
||||
req->name = query_elems[0].v.val_str;
|
||||
req->desc = query_elems[1].v.val_str;
|
||||
req->current_page = query_elems[2].v.val_int;
|
||||
req->page_size = query_elems[3].v.val_int;
|
||||
req->is_error = query_elems[4].v.val_bool;
|
||||
}
|
||||
|
||||
*result = req;
|
||||
neu_json_decode_free(json_obj);
|
||||
return ret;
|
||||
|
||||
error:
|
||||
free(query_elems[0].v.val_str);
|
||||
free(query_elems[1].v.val_str);
|
||||
free(req_elems[0].v.val_str);
|
||||
free(req_elems[1].v.val_str);
|
||||
free(req);
|
||||
if (json_obj != NULL) {
|
||||
neu_json_decode_free(json_obj);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void neu_json_decode_read_paginate_req_free(neu_json_read_paginate_req_t *req)
|
||||
{
|
||||
free(req->group);
|
||||
free(req->node);
|
||||
|
||||
free(req);
|
||||
}
|
||||
|
||||
int neu_json_decode_test_read_tag_req(char * buf,
|
||||
neu_json_test_read_tag_req_t **result)
|
||||
{
|
||||
int ret = 0;
|
||||
void * json_obj = NULL;
|
||||
neu_json_test_read_tag_req_t *req =
|
||||
calloc(1, sizeof(neu_json_test_read_tag_req_t));
|
||||
if (req == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_obj = neu_json_decode_new(buf);
|
||||
if (NULL == json_obj) {
|
||||
free(req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
neu_json_elem_t req_elems[] = {
|
||||
{
|
||||
.name = "driver",
|
||||
.t = NEU_JSON_STR,
|
||||
},
|
||||
{
|
||||
.name = "group",
|
||||
.t = NEU_JSON_STR,
|
||||
},
|
||||
{
|
||||
.name = "tag",
|
||||
.t = NEU_JSON_STR,
|
||||
},
|
||||
{
|
||||
.name = "address",
|
||||
.t = NEU_JSON_STR,
|
||||
},
|
||||
{
|
||||
.name = "attribute",
|
||||
.t = NEU_JSON_INT,
|
||||
},
|
||||
{
|
||||
.name = "type",
|
||||
.t = NEU_JSON_INT,
|
||||
},
|
||||
{
|
||||
.name = "precision",
|
||||
.t = NEU_JSON_INT,
|
||||
},
|
||||
{
|
||||
.name = "decimal",
|
||||
.t = NEU_JSON_DOUBLE,
|
||||
},
|
||||
{
|
||||
.name = "bias",
|
||||
.t = NEU_JSON_DOUBLE,
|
||||
},
|
||||
};
|
||||
ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
|
||||
req_elems);
|
||||
if (ret != 0) {
|
||||
goto decode_fail;
|
||||
}
|
||||
|
||||
req->driver = req_elems[0].v.val_str;
|
||||
req->group = req_elems[1].v.val_str;
|
||||
req->tag = req_elems[2].v.val_str;
|
||||
req->address = req_elems[3].v.val_str;
|
||||
req->attribute = req_elems[4].v.val_int;
|
||||
req->type = req_elems[5].v.val_int;
|
||||
req->precision = req_elems[6].v.val_int;
|
||||
req->decimal = req_elems[7].v.val_double;
|
||||
req->bias = req_elems[8].v.val_double;
|
||||
*result = req;
|
||||
goto decode_exit;
|
||||
|
||||
decode_fail:
|
||||
free(req);
|
||||
free(req_elems[0].v.val_str);
|
||||
free(req_elems[1].v.val_str);
|
||||
free(req_elems[2].v.val_str);
|
||||
free(req_elems[3].v.val_str);
|
||||
ret = -1;
|
||||
|
||||
decode_exit:
|
||||
if (json_obj != NULL) {
|
||||
neu_json_decode_free(json_obj);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void neu_json_decode_test_read_tag_req_free(neu_json_test_read_tag_req_t *req)
|
||||
{
|
||||
free(req->driver);
|
||||
free(req->group);
|
||||
free(req->tag);
|
||||
free(req->address);
|
||||
free(req);
|
||||
}
|
||||
|
||||
int neu_json_encode_read_periodic_resp(void *json_object, void *param)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -600,6 +941,81 @@ void neu_json_metas_to_json(neu_tag_meta_t *metas, int n_meta,
|
||||
}
|
||||
}
|
||||
|
||||
void neu_json_metas_to_json_paginate(
|
||||
neu_tag_meta_t *metas, int n_meta,
|
||||
neu_json_read_paginate_resp_tag_t *json_tag)
|
||||
{
|
||||
for (int k = 0; k < n_meta; k++) {
|
||||
if (strlen(metas[k].name) > 0) {
|
||||
json_tag->metas[k].name = metas[k].name;
|
||||
switch (metas[k].value.type) {
|
||||
case NEU_TYPE_UINT8:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.u8;
|
||||
break;
|
||||
case NEU_TYPE_INT8:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.i8;
|
||||
break;
|
||||
case NEU_TYPE_INT16:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.i16;
|
||||
break;
|
||||
case NEU_TYPE_INT32:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.i32;
|
||||
break;
|
||||
case NEU_TYPE_INT64:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.i64;
|
||||
break;
|
||||
case NEU_TYPE_WORD:
|
||||
case NEU_TYPE_UINT16:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.u16;
|
||||
break;
|
||||
case NEU_TYPE_DWORD:
|
||||
case NEU_TYPE_UINT32:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.u32;
|
||||
break;
|
||||
case NEU_TYPE_LWORD:
|
||||
case NEU_TYPE_UINT64:
|
||||
json_tag->metas[k].t = NEU_JSON_INT;
|
||||
json_tag->metas[k].value.val_int = metas[k].value.value.u64;
|
||||
break;
|
||||
case NEU_TYPE_FLOAT:
|
||||
json_tag->metas[k].t = NEU_JSON_FLOAT;
|
||||
json_tag->metas[k].value.val_float = metas[k].value.value.f32;
|
||||
break;
|
||||
case NEU_TYPE_DOUBLE:
|
||||
json_tag->metas[k].t = NEU_JSON_DOUBLE;
|
||||
json_tag->metas[k].value.val_double = metas[k].value.value.d64;
|
||||
break;
|
||||
case NEU_TYPE_BOOL:
|
||||
json_tag->metas[k].t = NEU_JSON_BOOL;
|
||||
json_tag->metas[k].value.val_bool =
|
||||
metas[k].value.value.boolean;
|
||||
break;
|
||||
case NEU_TYPE_BIT:
|
||||
json_tag->metas[k].t = NEU_JSON_BIT;
|
||||
json_tag->metas[k].value.val_bit = metas[k].value.value.u8;
|
||||
break;
|
||||
case NEU_TYPE_STRING:
|
||||
case NEU_TYPE_TIME:
|
||||
case NEU_TYPE_DATA_AND_TIME:
|
||||
json_tag->metas[k].t = NEU_JSON_STR;
|
||||
json_tag->metas[k].value.val_str = metas[k].value.value.str;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int neu_json_decode_write_gtags_req(char * buf,
|
||||
neu_json_write_gtags_req_t **result)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* NEURON IIoT System for Industry 4.0
|
||||
* Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
|
||||
/*
|
||||
* DO NOT EDIT THIS FILE MANUALLY!
|
||||
* It was automatically generated by `json-autotype`.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#include "define.h"
|
||||
#include "msg.h"
|
||||
#include "json/json.h"
|
||||
|
||||
#include "json/neu_json_scan.h"
|
||||
|
||||
int neu_json_decode_scan_tags_req(char *buf, neu_json_scan_tags_req_t **result)
|
||||
{
|
||||
void *json_obj = neu_json_decode_new(buf);
|
||||
if (NULL == json_obj) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
neu_json_scan_tags_req_t *req = calloc(1, sizeof(neu_json_scan_tags_req_t));
|
||||
if (req == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
neu_json_elem_t req_node_elems[] = { {
|
||||
.name = "node",
|
||||
.t = NEU_JSON_STR,
|
||||
} };
|
||||
|
||||
neu_json_elem_t req_id_elems[] = {
|
||||
{
|
||||
.name = "id",
|
||||
.t = NEU_JSON_STR,
|
||||
},
|
||||
};
|
||||
|
||||
if (0 !=
|
||||
neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_node_elems),
|
||||
req_node_elems)) {
|
||||
neu_json_decode_free(json_obj);
|
||||
free(req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_id_elems),
|
||||
req_id_elems);
|
||||
req->node = req_node_elems[0].v.val_str;
|
||||
req->id = req_id_elems[0].v.val_str;
|
||||
*result = req;
|
||||
|
||||
neu_json_decode_free(json_obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void neu_json_decode_scan_tags_req_free(neu_json_scan_tags_req_t *req)
|
||||
{
|
||||
free(req->node);
|
||||
free(req->id);
|
||||
free(req);
|
||||
}
|
||||
|
||||
int neu_json_encode_scan_tags_resp(void *json_object, void *param)
|
||||
{
|
||||
int ret = 0;
|
||||
neu_resp_scan_tags_t *resp = (neu_resp_scan_tags_t *) param;
|
||||
void * tag_array = neu_json_array();
|
||||
int len = 0;
|
||||
|
||||
if (NULL != resp->scan_tags) {
|
||||
len = utarray_len(resp->scan_tags);
|
||||
utarray_foreach(resp->scan_tags, neu_scan_tag_t *, p_tag)
|
||||
{
|
||||
if (NULL != p_tag) {
|
||||
neu_json_elem_t tag_elems[] = {
|
||||
{
|
||||
.name = "name",
|
||||
.t = NEU_JSON_STR,
|
||||
.v.val_str = p_tag->name,
|
||||
},
|
||||
{
|
||||
.name = "id",
|
||||
.t = NEU_JSON_STR,
|
||||
.v.val_str = p_tag->id,
|
||||
},
|
||||
{
|
||||
.name = "tag",
|
||||
.t = NEU_JSON_INT,
|
||||
.v.val_int = p_tag->type,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
neu_json_encode_array(tag_array, tag_elems,
|
||||
NEU_JSON_ELEM_SIZE(tag_elems));
|
||||
}
|
||||
}
|
||||
|
||||
utarray_free(resp->scan_tags);
|
||||
}
|
||||
|
||||
neu_json_elem_t resp_elems[] = { {
|
||||
.name = "error",
|
||||
.t = NEU_JSON_INT,
|
||||
.v.val_int = resp->error,
|
||||
},
|
||||
{
|
||||
.name = "total",
|
||||
.t = NEU_JSON_INT,
|
||||
.v.val_int = len,
|
||||
},
|
||||
{
|
||||
.name = "type",
|
||||
.t = NEU_JSON_INT,
|
||||
.v.val_int = resp->type,
|
||||
},
|
||||
{
|
||||
.name = "is_array",
|
||||
.t = NEU_JSON_BOOL,
|
||||
.v.val_bool = resp->is_array,
|
||||
},
|
||||
{
|
||||
.name = "tags",
|
||||
.t = NEU_JSON_OBJECT,
|
||||
.v.val_object = tag_array,
|
||||
} };
|
||||
|
||||
ret = neu_json_encode_field(json_object, resp_elems,
|
||||
NEU_JSON_ELEM_SIZE(resp_elems));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -159,4 +159,16 @@ void neu_async_queue_clean(neu_async_queue_t *q)
|
||||
free(el);
|
||||
}
|
||||
pthread_mutex_unlock(&q->mtx);
|
||||
}
|
||||
|
||||
int neu_async_queue_len(neu_async_queue_t *q)
|
||||
{
|
||||
int count = 0;
|
||||
element *elt = NULL;
|
||||
|
||||
pthread_mutex_lock(&q->mtx);
|
||||
DL_COUNT(q->list, elt, count);
|
||||
pthread_mutex_unlock(&q->mtx);
|
||||
|
||||
return count;
|
||||
}
|
||||
+47
-5
@@ -17,6 +17,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -25,6 +26,38 @@
|
||||
#include "utils/log.h"
|
||||
#include "json/json.h"
|
||||
|
||||
static double format_tag_value(float ele_value)
|
||||
{
|
||||
double scale = pow(10, 5);
|
||||
double value = ele_value;
|
||||
|
||||
int64_t integer_part = (int64_t)(value);
|
||||
double decimal_part = value - integer_part;
|
||||
decimal_part *= scale;
|
||||
decimal_part = round(decimal_part);
|
||||
|
||||
char str[6] = { 0 };
|
||||
snprintf(str, sizeof(str), "%05" PRId64 "", (int64_t) decimal_part);
|
||||
int i = 0, flag = 0;
|
||||
for (; i < 4; i++) {
|
||||
if (str[i] == '0' && str[i + 1] == '0') {
|
||||
flag = 1;
|
||||
break;
|
||||
} else if (str[i] == '9' && str[i + 1] == '9') {
|
||||
flag = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag != 0 && i != 0) {
|
||||
decimal_part = round(decimal_part / pow(10, 5 - i));
|
||||
value = (double) integer_part + decimal_part / pow(10, i);
|
||||
} else {
|
||||
value = (double) integer_part + decimal_part / scale;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static json_t *encode_object_value(neu_json_elem_t *ele)
|
||||
{
|
||||
json_t *ob = NULL;
|
||||
@@ -42,9 +75,14 @@ static json_t *encode_object_value(neu_json_elem_t *ele)
|
||||
case NEU_JSON_DOUBLE:
|
||||
ob = json_realp(ele->v.val_double, ele->precision);
|
||||
break;
|
||||
case NEU_JSON_FLOAT:
|
||||
ob = json_realp(ele->v.val_float, ele->precision);
|
||||
case NEU_JSON_FLOAT: {
|
||||
double t = ele->v.val_float;
|
||||
if (ele->precision == 0) {
|
||||
t = format_tag_value(ele->v.val_float);
|
||||
}
|
||||
ob = json_realp(t, ele->precision);
|
||||
break;
|
||||
}
|
||||
case NEU_JSON_BOOL:
|
||||
ob = json_boolean(ele->v.val_bool);
|
||||
break;
|
||||
@@ -69,10 +107,14 @@ static json_t *encode_object(json_t *object, neu_json_elem_t ele)
|
||||
case NEU_JSON_STR:
|
||||
json_object_set_new(ob, ele.name, json_string(ele.v.val_str));
|
||||
break;
|
||||
case NEU_JSON_FLOAT:
|
||||
json_object_set_new(ob, ele.name,
|
||||
json_realp(ele.v.val_float, ele.precision));
|
||||
case NEU_JSON_FLOAT: {
|
||||
double t = ele.v.val_float;
|
||||
if (ele.precision == 0) {
|
||||
t = format_tag_value(ele.v.val_float);
|
||||
}
|
||||
json_object_set_new(ob, ele.name, json_realp(t, ele.precision));
|
||||
break;
|
||||
}
|
||||
case NEU_JSON_DOUBLE:
|
||||
json_object_set_new(ob, ele.name,
|
||||
json_realp(ele.v.val_double, ele.precision));
|
||||
|
||||
@@ -744,6 +744,27 @@ class TestModbus:
|
||||
assert 0 == api.read_tag(
|
||||
node=param[0], group='group', tag=input_bit_5[0]['name'])
|
||||
|
||||
@description(given="created modbus node", when="test read tag", then="read tcp success and read rtu failed")
|
||||
def test_modbus_test_read_tag(self, param):
|
||||
body = {
|
||||
"driver": param[0],
|
||||
"group": "group",
|
||||
"tag": "tag",
|
||||
"address": "1!400001",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW,
|
||||
"type": config.NEU_TYPE_INT16,
|
||||
"precision": 0,
|
||||
"decimal": 0,
|
||||
"bias": 0.0
|
||||
}
|
||||
if param[0] == 'modbus-tcp':
|
||||
time.sleep(1)
|
||||
response = api.test_read_tag(json=body)
|
||||
assert response.json()["value"] == -123
|
||||
else:
|
||||
response = api.test_read_tag(json=body)
|
||||
assert response.json()["error"] == 3022
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags fuzz", then="should return correct result")
|
||||
def test_read_tags_fuzz(self, param):
|
||||
response = api.read_tags(
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
import neuron.api as api
|
||||
import neuron.error as error
|
||||
import neuron.config as config
|
||||
from neuron.common import *
|
||||
|
||||
tcp_port = random_port()
|
||||
|
||||
|
||||
@pytest.fixture(params=[('modbus-tcp', config.PLUGIN_MODBUS_TCP)], scope='class')
|
||||
def param(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope='class')
|
||||
def simulator_setup_teardown(param):
|
||||
p = process.start_simulator(
|
||||
['./modbus_simulator', 'tcp', f'{tcp_port}', 'ip_v4'])
|
||||
|
||||
response = api.add_node(node=param[0], plugin=param[1])
|
||||
assert 200 == response.status_code
|
||||
|
||||
response = api.add_group(node=param[0], group='group')
|
||||
assert 200 == response.status_code
|
||||
|
||||
response = api.modbus_tcp_node_setting(
|
||||
node=param[0], interval=1, port=tcp_port)
|
||||
|
||||
yield
|
||||
process.stop_simulator(p)
|
||||
|
||||
|
||||
hold_bit = [{"name": "hold_bit", "address": "1!400001.15",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_READ_SUBSCRIBE, "type": config.NEU_TYPE_BIT, "description": "123"}]
|
||||
hold_int16 = [{"name": "hold_int16", "address": "1!400001",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_INT16, "description": "123"}]
|
||||
hold_uint16 = [{"name": "hold_uint16", "address": "1!400002",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_UINT16, "description": "456"}]
|
||||
hold_int32 = [{"name": "hold_int32", "address": "1!400003",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_INT32, "description": "456"}]
|
||||
hold_uint32 = [{"name": "hold_uint32", "address": "1!400015",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_UINT32}]
|
||||
hold_float = [{"name": "hold_float", "address": "1!400017",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_FLOAT}]
|
||||
hold_string = [{"name": "hold_string", "address": "1!400020.10",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_STRING}]
|
||||
hold_bytes = [{"name": "hold_bytes", "address": "1!400040.10",
|
||||
"attribute": config.NEU_TAG_ATTRIBUTE_RW_SUBSCRIBE, "type": config.NEU_TYPE_BYTES}]
|
||||
|
||||
|
||||
class TestReadPaginate:
|
||||
|
||||
@description(given="created modbus node", when="add multiple tags", then="add success")
|
||||
def test_add_tags(self, param):
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_bit)
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_int16)
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_uint16)
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_int32)
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_uint32)
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_float)
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_string)
|
||||
api.add_tags_check(node=param[0], group='group', tags=hold_bytes)
|
||||
|
||||
|
||||
@description(given="created modbus node and tags", when="write/read tags without filter", then="write/read success")
|
||||
def test_write_read_tags(self, param):
|
||||
api.write_tag_check(
|
||||
node=param[0], group='group', tag=hold_int16[0]['name'], value=-123)
|
||||
api.write_tag_check(
|
||||
node=param[0], group='group', tag=hold_uint16[0]['name'], value=123)
|
||||
api.write_tag_check(
|
||||
node=param[0], group='group', tag=hold_int32[0]['name'], value=-1234)
|
||||
api.write_tag_check(
|
||||
node=param[0], group='group', tag=hold_uint32[0]['name'], value=1234)
|
||||
api.write_tag_check(
|
||||
node=param[0], group='group', tag=hold_float[0]['name'], value=13.4121)
|
||||
api.write_tag_check(
|
||||
node=param[0], group='group', tag=hold_string[0]['name'], value='hello')
|
||||
api.write_tag_check(
|
||||
node=param[0], group='group', tag=hold_bytes[0]['name'], value=[0x1, 0x2, 0x3, 0x4])
|
||||
|
||||
time.sleep(0.3)
|
||||
response = api.read_tags_paginate(node=param[0], group='group')
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
|
||||
assert 8 == len(response.json()["items"])
|
||||
|
||||
assert "hold_bit" == response.json()["items"][0]["name"]
|
||||
assert 1 == response.json()["items"][0]["value"]
|
||||
|
||||
assert "hold_int16" == response.json()["items"][1]["name"]
|
||||
assert -123 == response.json()["items"][1]["value"]
|
||||
|
||||
assert "hold_uint16" == response.json()["items"][2]["name"]
|
||||
assert 123 == response.json()["items"][2]["value"]
|
||||
|
||||
assert "hold_int32" == response.json()["items"][3]["name"]
|
||||
assert -1234 == response.json()["items"][3]["value"]
|
||||
|
||||
assert "hold_uint32" == response.json()["items"][4]["name"]
|
||||
assert 1234 == response.json()["items"][4]["value"]
|
||||
|
||||
assert "hold_float" == response.json()["items"][5]["name"]
|
||||
assert compare_float(13.4121, response.json()["items"][5]["value"])
|
||||
|
||||
assert "hold_string" == response.json()["items"][6]["name"]
|
||||
assert 'hello' == response.json()["items"][6]["value"]
|
||||
|
||||
assert "hold_bytes" == response.json()["items"][7]["name"]
|
||||
assert [0x1, 0x2, 0x3, 0x4, 0, 0, 0, 0, 0, 0] == response.json()["items"][7]["value"]
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with filter(name)", then="read success")
|
||||
def test_read_tags_filter_name(self, param):
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"name": "int16"})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 2 == response.json()["meta"]["total"]
|
||||
|
||||
assert 2 == len(response.json()["items"])
|
||||
|
||||
assert "hold_int16" == response.json()["items"][0]["name"]
|
||||
assert -123 == response.json()["items"][0]["value"]
|
||||
assert "hold_uint16" == response.json()["items"][1]["name"]
|
||||
assert 123 == response.json()["items"][1]["value"]
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with filter(desc)", then="read success")
|
||||
def test_read_tags_filter_desc(self, param):
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"description": "12"})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 2 == response.json()["meta"]["total"]
|
||||
|
||||
assert 2 == len(response.json()["items"])
|
||||
|
||||
assert "hold_bit" == response.json()["items"][0]["name"]
|
||||
assert 1 == response.json()["items"][0]["value"]
|
||||
assert "hold_int16" == response.json()["items"][1]["name"]
|
||||
assert -123 == response.json()["items"][1]["value"]
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with paginate", then="read success")
|
||||
def test_read_tags_paginate(self, param):
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 1, "pageSize": 5})
|
||||
assert 1 == response.json()["meta"]["currentPage"]
|
||||
assert 5 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 5 == len(response.json()["items"])
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 2, "pageSize": 5})
|
||||
assert 2 == response.json()["meta"]["currentPage"]
|
||||
assert 5 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 3 == len(response.json()["items"])
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 3, "pageSize": 5})
|
||||
assert 3 == response.json()["meta"]["currentPage"]
|
||||
assert 5 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 0 == len(response.json()["items"])
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 6, "pageSize": 5})
|
||||
assert 6 == response.json()["meta"]["currentPage"]
|
||||
assert 5 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 0 == len(response.json()["items"])
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 0, "pageSize": 5})
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 5 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 8 == len(response.json()["items"])
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with filter(isError)", then="read success")
|
||||
def test_read_tags_filter_isError(self, param):
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 0 == response.json()["meta"]["total"]
|
||||
assert 0 == len(response.json()["items"])
|
||||
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 8 == len(response.json()["items"])
|
||||
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
|
||||
time.sleep(0.3)
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with filter(name&desc)", then="read success")
|
||||
def test_read_tags_filter_name_desc(self, param):
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"name": "16", "description": "123"})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 1 == response.json()["meta"]["total"]
|
||||
assert 1 == len(response.json()["items"])
|
||||
assert "hold_int16" == response.json()["items"][0]["name"]
|
||||
assert -123 == response.json()["items"][0]["value"]
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with filter(isError&name)", then="read success")
|
||||
def test_read_tags_filter_isError_name(self, param):
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True, "name": "16"})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 2 == response.json()["meta"]["total"]
|
||||
assert 2 == len(response.json()["items"])
|
||||
assert "hold_int16" == response.json()["items"][0]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
|
||||
assert "hold_uint16" == response.json()["items"][1]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
|
||||
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
|
||||
time.sleep(0.3)
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with filter(isError&desc)", then="read success")
|
||||
def test_read_tags_filter_isError_desc(self, param):
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True, "description": "12"})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 2 == response.json()["meta"]["total"]
|
||||
assert 2 == len(response.json()["items"])
|
||||
assert "hold_bit" == response.json()["items"][0]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
|
||||
assert "hold_int16" == response.json()["items"][1]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
|
||||
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
|
||||
time.sleep(0.3)
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with filter(isError&name&desc)", then="read success")
|
||||
def test_read_tags_filter_isError_name_desc(self, param):
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"isError": True, "name":"16", "description": "12"})
|
||||
|
||||
assert 0 == response.json()["meta"]["currentPage"]
|
||||
assert 0 == response.json()["meta"]["pageSize"]
|
||||
assert 1 == response.json()["meta"]["total"]
|
||||
assert 1 == len(response.json()["items"])
|
||||
assert "hold_int16" == response.json()["items"][0]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
|
||||
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
|
||||
time.sleep(0.3)
|
||||
|
||||
@description(given="created modbus node and tags", when="read tags with paginate & filter(isError)", then="read success")
|
||||
def test_read_tags_paginate_filter_isError(self, param):
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_STOP)
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 1, "pageSize": 5, "isError": True})
|
||||
assert 1 == response.json()["meta"]["currentPage"]
|
||||
assert 5 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 5 == len(response.json()["items"])
|
||||
assert "hold_bit" == response.json()["items"][0]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
|
||||
assert "hold_int16" == response.json()["items"][1]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
|
||||
assert "hold_uint16" == response.json()["items"][2]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][2]["error"]
|
||||
assert "hold_int32" == response.json()["items"][3]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][3]["error"]
|
||||
assert "hold_uint32" == response.json()["items"][4]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][4]["error"]
|
||||
|
||||
response = api.read_tags_paginate(node=param[0], group='group', query= {"currentPage": 2, "pageSize": 5, "isError": True})
|
||||
assert 2 == response.json()["meta"]["currentPage"]
|
||||
assert 5 == response.json()["meta"]["pageSize"]
|
||||
assert 8 == response.json()["meta"]["total"]
|
||||
assert 3 == len(response.json()["items"])
|
||||
assert "hold_float" == response.json()["items"][0]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][0]["error"]
|
||||
assert "hold_string" == response.json()["items"][1]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][1]["error"]
|
||||
assert "hold_bytes" == response.json()["items"][2]["name"]
|
||||
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()["items"][2]["error"]
|
||||
|
||||
api.node_ctl_check(node='modbus-tcp', ctl=config.NEU_CTL_START)
|
||||
time.sleep(0.3)
|
||||
+14
-1
@@ -157,6 +157,14 @@ def read_tags(node, group, sync=False, query=None):
|
||||
body["query"] = query
|
||||
return requests.post(url=config.BASE_URL + "/api/v2/read", headers={"Authorization": config.default_jwt}, json=body)
|
||||
|
||||
def read_tags_paginate(node, group, sync=False, query=None):
|
||||
body = {"node": node, "group": group, "sync": sync}
|
||||
if query:
|
||||
body["query"] = query
|
||||
return requests.post(url=config.BASE_URL + "/api/v2/read/paginate", headers={"Authorization": config.default_jwt}, json=body)
|
||||
|
||||
def test_read_tag(json):
|
||||
return requests.post(url=config.BASE_URL + '/api/v2/read/test', headers={"Authorization": config.default_jwt}, json=json)
|
||||
|
||||
def read_tag(node, group, tag, sync=False):
|
||||
response = read_tags(node, group, sync, query={"name": tag})
|
||||
@@ -349,4 +357,9 @@ def mqtt_node_setting(node):
|
||||
"offline-cache": False, "cache-sync-interval": 100, "host": "broker.emqx.io", "port": 1883, "username": "", "password": "", "ssl": False})
|
||||
|
||||
def get_nodes_disable_auth(type):
|
||||
return requests.get(url=config.BASE_URL + '/api/v2/node', params={"type": type})
|
||||
return requests.get(url=config.BASE_URL + '/api/v2/node', params={"type": type})
|
||||
|
||||
|
||||
@gen_check
|
||||
def scan_tags(node, id):
|
||||
return requests.post(url=config.BASE_URL + "/api/v2/scan/tags", headers={"Authorization": config.default_jwt}, json={"node": node, "id": id})
|
||||
|
||||
@@ -107,5 +107,6 @@ NEU_ERR_PLUGIN_NOT_SUPPORT_WRITE_TAGS = 3017
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_READ_SYNC = 3018
|
||||
NEU_ERR_PLUGIN_TYPE_NOT_SUPPORT = 3019
|
||||
NEU_ERR_PLUGIN_TAG_VALUE_OUT_OF_RANGE = 3020
|
||||
NEU_ERR_PLUGIN_NOT_SUPPORT_SCAN_TAGS = 3021
|
||||
|
||||
NEU_ERR_MQTT_SUBSCRIBE_FAILURE = 4010
|
||||
@@ -244,7 +244,7 @@ class TestPlugin:
|
||||
assert 200 == response.status_code
|
||||
for plugin in response.json().get("plugins"):
|
||||
if plugin['name'] == 'c1':
|
||||
assert plugin['version'] == '2.7.99'
|
||||
assert plugin['version'] == '2.9.99'
|
||||
|
||||
@description(given="incorrect configuration", when="update plugin", then="fail")
|
||||
def test_10_update_plugin_fail3(self):
|
||||
|
||||
@@ -63,7 +63,7 @@ static const neu_plugin_intf_funs_t plugin_intf_funs = {
|
||||
};
|
||||
|
||||
const neu_plugin_module_t neu_plugin_module = {
|
||||
.version = NEU_VERSION(2, 7, 99),
|
||||
.version = NEU_VERSION(2, 9, 99),
|
||||
.schema = "c1",
|
||||
.module_name = "c1",
|
||||
.module_descr = "c1 v2",
|
||||
|
||||
Reference in New Issue
Block a user