Compare commits

..
52 Commits
Author SHA1 Message Date
fengzeroz 8e62bc1b22 Merge pull request #824 from fengzeroz/v2.2
version: 2.2.4
2022-09-30 15:16:40 +08:00
fengzero 896eb3a52e version: 2.2.4 2022-09-30 07:15:56 +00:00
fengzeroz 1539dd065a Merge pull request #823 from eeff/eeff/2.2
Pick to v2.2: fix license expiry time parsing overflow
2022-09-30 11:08:48 +08:00
eeff 574c34a085 fix: license expiry time parsing overflow 2022-09-30 00:21:03 +08:00
fengzeroz ba8d56fdd0 Merge pull request #817 from fengzeroz/v2.2
version: 2.2.3
2022-09-23 16:39:03 +08:00
fengzero 8795028313 version: 2.2.3 2022-09-23 08:37:51 +00:00
fengzeroz 05d83878db Merge pull request #816 from eeff/eeff/2.2
Pick to v2.2: upload license to persistence directory
2022-09-23 16:33:52 +08:00
eeff d031a0ee71 chore: copy license file for backward compatiblity 2022-09-23 16:21:39 +08:00
eeff 969a302b58 chore: upload license to persistence directory 2022-09-23 16:21:27 +08:00
fengzeroz 57d5a51aad Merge pull request #815 from fengzeroz/v2.2
fix(modbus): bit operation
2022-09-23 11:07:29 +08:00
fengzero c46795ce30 fix(modbus): bit operation 2022-09-23 03:06:21 +00:00
fengzeroz ef9e505517 Merge pull request #812 from eeff/eeff/2.2
Pick optimize persistence speed when adding tags to v2.2
2022-09-22 18:04:22 +08:00
eeff 24d3ce2667 perf: optimize persistence speed when adding tags 2022-09-22 14:11:50 +08:00
fengzeroz 3c71082121 Merge pull request #810 from lixiumei123/v2.2
add(modbus tcp):add the address regularity of modbus tcp
2022-09-22 13:36:33 +08:00
lixiumei123 0d1c2b93c0 add(modbus tcp):add the address regularity of modbus tcp 2022-09-22 03:38:28 +00:00
fengzeroz 0ae76e1c5f Merge pull request #799 from fengzeroz/v2.2
version: 2.2.2
2022-09-16 16:26:30 +08:00
fengzero 5f41286600 version: 2.2.2 2022-09-16 08:24:45 +00:00
fengzeroz 9c48d6bcaa Merge pull request #797 from gc87/mqtt-fix-nonuser-login-v2.2
[v2.2]fix(mqtt): non-user login to rabbitmq auth failed
2022-09-16 14:58:49 +08:00
gc87 83eb1ecf61 fix(mqtt): non-user login to rabbitmq auth failed
- empty user name login to rqbbitmq login failed for user ''
2022-09-16 14:09:42 +08:00
fengzeroz 4059c22de1 Merge pull request #795 from fengzeroz/v2.2
fix(queue): modify the type of key to uint64_t
2022-09-15 15:24:10 +08:00
fengzero 179dc71408 fix(queue): modify the type of key to uint64_t 2022-09-15 07:06:43 +00:00
fengzeroz 43fc2a7080 Merge pull request #793 from fengzeroz/v2.2
async_queue FIFO
2022-09-15 09:41:45 +08:00
fengzero a95ecfe7c5 async_queue FIFO 2022-09-15 01:31:07 +00:00
fengzeroz 07b9d077b1 Merge pull request #790 from fengzeroz/v2.2
chore(rest): log unhandle msg
2022-09-14 15:40:40 +08:00
fengzero 6119023896 chore(rest): log unhandle msg 2022-09-14 06:48:39 +00:00
fengzeroz b3b9e69b7a Merge pull request #788 from fengzeroz/v2.2
fix(main): manager destory when receive sigabrt
2022-09-14 10:44:00 +08:00
fengzeroz 05aa6ea141 Merge pull request #785 from gc87/mqtt-schema-improved-v2.2
[v2.2]refactor(mqtt): improved mqtt schema description
2022-09-14 10:29:59 +08:00
fengzero 74415465ff fix(main): manager destory when receive sigabrt 2022-09-14 02:01:28 +00:00
gc87 658779c28f refactor(mqtt): improved mqtt schema description 2022-09-14 09:53:07 +08:00
fengzeroz edee7007b3 Merge pull request #784 from fengzeroz/v2.2
update tag & negative multiplication
2022-09-13 16:41:43 +08:00
fengzero 012c7b756c fix(ft): update tag 2022-09-13 08:31:13 +00:00
fengzero 3b0bdefd1a fix(driver): negative multiplication 2022-09-13 08:21:06 +00:00
fengzero 380bae660c chore(driver): update tags in group table 2022-09-13 07:39:58 +00:00
fengzeroz 32e49e0386 Merge pull request #782 from fengzeroz/v2.2
chore(driver): log timer spend time
2022-09-13 09:52:00 +08:00
fengzero 24111cacac chore(driver): log timer spend time 2022-09-13 01:43:45 +00:00
fengzeroz 978e0d3d8f Merge pull request #780 from fengzeroz/v2.2
version: 2.2.1
2022-09-09 16:42:05 +08:00
fengzero 549fe9ed7c version: 2.2.1 2022-09-09 08:41:32 +00:00
fengzeroz 4e4491eda2 Merge pull request #779 from fengzeroz/v2.2
fix(connection): multithreaded connection status exception
2022-09-09 11:27:17 +08:00
fengzero a9f4089979 fix(connection): multithreaded connection status exception 2022-09-09 03:21:21 +00:00
fengzeroz 02d14ea096 Merge pull request #777 from fengzeroz/v2.2
chore(log): log version
2022-09-08 16:59:39 +08:00
fengzero 33dbdd9eca chore(log): log version 2022-09-08 08:49:30 +00:00
fengzeroz 52dfb55007 Merge pull request #773 from fengzeroz/v2.2
fix(driver): persistence failed when updating group
2022-09-08 10:57:55 +08:00
fengzero 9b4dfef460 fix(driver): persistence failed when updating group 2022-09-08 02:41:29 +00:00
fengzeroz 31316c9363 Merge pull request #769 from eeff/eeff/2.2
Pick error code NEU_ERR_LICENSE_BAD_CLOCK to v2.2
2022-09-07 15:49:59 +08:00
eeff 58ca53f07d chore: add new error code NEU_ERR_LICENSE_BAD_CLOCK 2022-09-07 15:36:07 +08:00
fengzeroz f65d734285 Merge pull request #766 from fengzeroz/v2.2
fix(api): fix double type precision
2022-09-06 17:21:03 +08:00
fengzero bdaba2c339 fix(api): fix double type precision 2022-09-06 09:13:04 +00:00
fengzeroz 1c3cb0f9a3 Merge pull request #764 from fengzeroz/v2.2
fix(json): decode int as float/double
2022-09-06 16:33:24 +08:00
fengzero d6a040515e fix(json): decode int as float/double 2022-09-06 08:23:19 +00:00
fengzeroz fd22dc29d2 Merge pull request #755 from gc87/mqtt-mem-cache
[v2.2]Changed MQTT memory cache from per connection to per node
2022-09-06 13:42:15 +08:00
fengzeroz 865a9fc364 Merge pull request #759 from fengzeroz/v2.2
fix(driver): write 1 or 1.0 fail
2022-09-05 15:35:06 +08:00
fengzero 86f17aaf90 fix(driver): write 1 or 1.0 fail 2022-09-05 07:17:41 +00:00
315 changed files with 12756 additions and 38313 deletions
+1
View File
@@ -12,3 +12,4 @@ PointerAlignment: Right
SpaceAfterCStyleCast: true
AllowShortFunctionsOnASingleLine: Inline
BreakBeforeBinaryOperators: None
+28
View File
@@ -0,0 +1,28 @@
name: Check helm version
on:
push:
paths:
- deploy/charts/neuron/templates/**
pull_request:
paths:
- deploy/charts/neuron/templates/**
jobs:
check-helm-version:
runs-on: ubuntu-latest
steps:
- run: minikube start
- uses: actions/checkout@v2
- name: Update helm
run: |
helm repo add emqx https://repos.emqx.io/charts
helm repo update
- name: Check helm version
run: |
old=$(helm show chart emqx/neuron |egrep "^version" | sed -r 's|^version:[[:space:]]([0-9]+.[0-9]+.[0-9]+)$|\1|g')
now=$(egrep "^version" deploy/charts/neuron/Chart.yaml | sed -r 's|^version:[[:space:]]([0-9]+.[0-9]+.[0-9]+)$|\1|g')
if [ "$old" = "$now" ];then
echo "Need update version for Chart.yaml"
exit 1
fi
+21 -60
View File
@@ -9,16 +9,16 @@ on:
jobs:
clang_format_check:
runs-on: ubuntu-24.04
runs-on: ubuntu-20.04
steps:
# checkout
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Run clang-format style check for C/C++ programs.
uses: DoozyX/clang-format-lint-action@v0.18
uses: DoozyX/clang-format-lint-action@v0.12
with:
source: 'src plugins include tests'
exclude: 'include/neuron/utils/uthash.h include/neuron/utils/utarray.h include/neuron/utils/utlist.h include/neuron/utils/zlog.h'
@@ -29,30 +29,31 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: recursive
- name: cppcheck
run: |
sudo apt install cppcheck
cppcheck --enable=all --error-exitcode=2 --inline-suppr --suppress=missingInclude --suppress=unusedFunction ./plugins ./src
cppcheck --enable=all --error-exitcode=2 --inline-suppr --suppress=missingInclude --suppress=variableScope ./simulator
cppcheck --enable=all --error-exitcode=2 --suppress=missingInclude --suppress=unusedFunction ./plugins ./simulator ./src
ut:
runs-on: ubuntu-20.04
container: ghcr.io/neugates/build:x86_64-v2.8
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: recursive
- name: install dep
run: |
./install.sh -d /usr/local -a x86_64 -c x86_64-linux-gnu
- name: compile
run: |
git config --global --add safe.directory $(pwd)
mkdir -p build && cd build
cmake -DUSE_GCOV=1 .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-linux-gnu.cmake
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-linux-gnu.cmake
make -j4
- name: unit test
@@ -62,18 +63,20 @@ jobs:
ft:
runs-on: ubuntu-20.04
container: ghcr.io/neugates/build:x86_64-v2.8
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: recursive
- name: install dep
run: |
./install.sh -d /usr/local -a x86_64 -c x86_64-linux-gnu
- name: compile
run: |
git config --global --add safe.directory $(pwd)
mkdir -p build && cd build
cmake -DUSE_GCOV=1 .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-linux-gnu.cmake
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-linux-gnu.cmake
make -j4
- name: function test
@@ -88,49 +91,7 @@ jobs:
with:
name: ft_result
path: |
build/neuron.log
pft:
runs-on: ubuntu-20.04
container: ghcr.io/neugates/build:x86_64-v2.8
strategy:
matrix:
plugin: [core, ekuiper, modbus, mqtt, metrics]
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: setup dependencies
run: |
if [ "${{ matrix.plugin }}" = "mqtt" ]; then
sudo apt-get install -y mosquitto
fi
pip install -U pytest requests prometheus-client gmqtt pynng sniffio
sudo apt-get install -y socat
- name: compile
run: |
git config --global --add safe.directory $(pwd)
mkdir -p build && cd build
cmake -DUSE_GCOV=1 .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-linux-gnu.cmake
make -j4
- name: function test
run: |
if [ "${{ matrix.plugin }}" = "core" ]; then
pytest -s -v tests/ft \
--ignore=tests/ft/app/test_ekuiper.py \
--ignore=tests/ft/app/test_mqtt.py \
--ignore=tests/ft/driver/test_modbus.py \
--ignore=tests/ft/metrics/test_metrics.py
elif [ "${{ matrix.plugin }}" = "ekuiper" ]; then
pytest -s -v tests/ft/app/"test_ekuiper.py"
elif [ "${{ matrix.plugin }}" = "modbus" ]; then
pytest -s -v tests/ft/driver/"test_modbus.py"
elif [ "${{ matrix.plugin }}" = "mqtt" ]; then
pytest -s -v tests/ft/app/"test_mqtt.py"
else
pytest -s -v tests/ft/metrics/"test_metrics.py"
fi
ft/reports/log.html
ft/reports/output.xml
ft/reports/report.html
build/neuron.log
+215 -38
View File
@@ -7,40 +7,48 @@ on:
types:
- published
env:
VERSION: 2.8.3
UI_VERSION: 2.6.1
BRANCH: v2.8
jobs:
cross-build:
runs-on: ubuntu-24.04
runs-on: ubuntu-18.04
strategy:
matrix:
arch:
- [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] }}-v2.8
- [aarch64-linux-gnu, aarch64, gcc-aarch64-linux-gnu, g++-aarch64-linux-gnu, /opt/externs/libs, arm64]
- [arm-linux-gnueabihf, armv4, gcc-arm-linux-gnueabihf, g++-arm-linux-gnueabihf, /opt/externs/libs, armhf]
- [x86_64-linux-gnu, x86_64, gcc, g++, /usr/local, amd64]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: recursive
- name: install
run: sudo apt-get update && sudo apt-get install -y ${{ matrix.arch[2] }} ${{ matrix.arch[3] }} pkg-config alien
- name: install dep
run: |
./install.sh -d ${{ matrix.arch[4] }} -c ${{ matrix.arch[0] }} -a ${{ matrix.arch[1] }}
- name: get version
id: get_version
run: echo "::set-output name=version::$(cat version)"
- name: compile
run: |
git config --global --add safe.directory $(pwd)
mkdir -p build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/${{ matrix.arch[0] }}.cmake \
-DCMAKE_BUILD_TYPE=Release -DDISABLE_UT=ON
make -j4
- name: get ui version
id: get_ui_version
run: echo "::set-output name=version::$(cat ui_version)"
- name: fetch dashboard
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: "emqx/neuron-dashboard-src"
version: "tags/${{ env.UI_VERSION }}"
version: "tags/${{ steps.get_ui_version.outputs.version }}"
file: "neuron-dashboard.zip"
target: "neuron-dashboard.zip"
@@ -50,30 +58,39 @@ jobs:
- name: Create neuron sdk package
run: |
./package-sdk.sh -p ${{ matrix.arch[2] }} -n neuron-sdk-$VERSION
./package-sdk.sh -p ${{ matrix.arch[5] }} -n neuron-sdk-${{ steps.get_version.outputs.version }}
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: neuron-sdk-${{ matrix.arch[2] }}
name: neuron-sdk-${{ matrix.arch[5] }}
path: |
neuron-sdk-*.tar.gz
build-debug-sdk:
runs-on: ubuntu-24.04
runs-on: ubuntu-20.04
strategy:
matrix:
arch:
- [x86_64-linux-gnu, x86_64, amd64]
container: ghcr.io/neugates/build:${{ matrix.arch[1] }}-v2.8
- [x86_64-linux-gnu, x86_64, gcc, g++, /usr/local, amd64]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
submodules: recursive
- name: install
run: sudo apt-get update && sudo apt-get install -y ${{ matrix.arch[2] }} ${{ matrix.arch[3] }} pkg-config alien
- name: install dep
run: |
./install.sh -d ${{ matrix.arch[4] }} -c ${{ matrix.arch[0] }} -a ${{ matrix.arch[1] }}
- name: get version
id: get_version
run: echo "::set-output name=version::$(cat version)"
- name: compile
run: |
git config --global --add safe.directory $(pwd)
mkdir -p build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/${{ matrix.arch[0] }}.cmake \
-DDISABLE_UT=ON
@@ -81,38 +98,198 @@ jobs:
- name: Create neuron sdk package
run: |
./package-sdk.sh -p ${{ matrix.arch[2] }} -n neuron-sdk-debug-$VERSION
./package-sdk.sh -p ${{ matrix.arch[5] }} -n neuron-sdk-debug-${{ steps.get_version.outputs.version }}
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: neuron-sdk
name: neuron-sdk-debug-${{ matrix.arch[5] }}
path: |
neuron-sdk-debug-*.tar.gz
create_update_daily_release:
runs-on: ubuntu-latest
create_daily_release:
runs-on: ubuntu-20.04
if: github.event_name == 'push'
needs: [cross-build, build-debug-sdk]
steps:
- name: Extract branch name
shell: bash
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
id: extract_branch
- name: delete old daily-pre-release
uses: dev-drprasad/delete-tag-and-release@v0.2.1
uses: dev-drprasad/delete-tag-and-release@v0.2.0
with:
delete_release: true
tag_name: ${{ env.BRANCH }}-daily
tag_name: ${{ steps.extract_branch.outputs.branch }}-daily
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/download-artifact@v4
with:
name: neuron-sdk
- uses: softprops/action-gh-release@v1
- name: create daily-pre-release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
name: Daily Release(${{ env.BRANCH }})
tag_name: ${{ env.BRANCH }}-daily
tag_name: ${{ steps.extract_branch.outputs.branch }}-daily
release_name: Daily Release(${{ steps.extract_branch.outputs.branch }})
draft: false
prerelease: true
files: |
neuron-sdk-*
- shell: bash
run: |
echo "${{ steps.create_release.outputs.upload_url }}" > release_url.txt
- uses: actions/upload-artifact@v3
with:
name: release_url
path: release_url.txt
upload_daily_release_asset:
runs-on: ubuntu-20.04
if: github.event_name == 'push'
needs: create_daily_release
strategy:
matrix:
arch: [arm64, armhf, amd64]
type: [neuron-sdk]
package: [tar.gz]
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: get version
id: get_version
run: echo "::set-output name=version::$(cat version)"
- uses: actions/download-artifact@v2
with:
name: release_url
- id: release_url
run: |
value=`cat release_url.txt`
echo "::set-output name=name::$value"
- uses: actions/download-artifact@v2
with:
name: ${{ matrix.type }}-${{ matrix.arch }}
- id: package
run: echo "::set-output name=name::${{ matrix.type }}-${{ steps.get_version.outputs.version }}-${{ matrix.arch }}.${{ matrix.package }}"
- name: upload daily release asset
id: upload-release-asset
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.release_url.outputs.name }}
asset_path: ./${{ steps.package.outputs.name }}
asset_name: ${{ matrix.type }}-${{ steps.get_version.outputs.version }}-daily-linux-${{ matrix.arch }}.${{ matrix.package }}
asset_content_type: application/octet-stream
upload_daily_release_debug_asset:
runs-on: ubuntu-20.04
if: github.event_name == 'push'
needs: create_daily_release
strategy:
matrix:
arch: [amd64]
type: [neuron-sdk-debug]
package: [tar.gz]
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: get version
id: get_version
run: echo "::set-output name=version::$(cat version)"
- uses: actions/download-artifact@v2
with:
name: release_url
- id: release_url
run: |
value=`cat release_url.txt`
echo "::set-output name=name::$value"
- uses: actions/download-artifact@v2
with:
name: ${{ matrix.type }}-${{ matrix.arch }}
- id: package
run: echo "::set-output name=name::${{ matrix.type }}-${{ steps.get_version.outputs.version }}-${{ matrix.arch }}.${{ matrix.package }}"
- name: upload daily release asset
id: upload-release-asset
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.release_url.outputs.name }}
asset_path: ./${{ steps.package.outputs.name }}
asset_name: ${{ matrix.type }}-${{ steps.get_version.outputs.version }}-daily-linux-${{ matrix.arch }}.${{ matrix.package }}
asset_content_type: application/octet-stream
clean:
runs-on: ubuntu-20.04
needs: [upload_daily_release_asset, upload_daily_release_debug_asset]
steps:
- uses: geekyeggo/delete-artifact@v1
with:
name: release_url
release:
runs-on: ubuntu-20.04
if: github.event_name == 'release'
needs: cross-build
strategy:
matrix:
arch: [arm64, armhf, amd64]
type: [neuron-sdk]
package: [tar.gz]
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: get version
id: get_version
run: echo "::set-output name=version::$(cat version)"
- uses: actions/download-artifact@v2
with:
name: ${{ matrix.type }}-${{ matrix.arch }}
- id: package
run: echo "::set-output name=name::${{ matrix.type }}-${{ steps.get_version.outputs.version }}-${{ matrix.arch }}.${{ matrix.package }}"
- name: gen packages sha256
run: sudo bash -c "echo $(sha256sum ./${{ steps.package.outputs.name }} | awk '{print $1}') > ./${{ steps.package.outputs.name }}.sha256"
- uses: actions/upload-release-asset@v1
if: github.event_name == 'release'
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./${{ steps.package.outputs.name}}.sha256
asset_name: ${{ matrix.type }}-${{ steps.get_version.outputs.version }}-linux-${{ matrix.arch }}.${{ matrix.package }}.sha256
asset_content_type: application/octet-stream
- uses: actions/upload-release-asset@v1
if: github.event_name == 'release'
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./${{ steps.package.outputs.name}}
asset_name: ${{ matrix.type }}-${{ steps.get_version.outputs.version }}-linux-${{ matrix.arch }}.${{ matrix.package }}
asset_content_type: application/octet-stream
+42
View File
@@ -0,0 +1,42 @@
name: Release neuron
on:
push:
tags:
- "*"
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Check appVersion for helm
run: |
appVersion=$(egrep "^appVersion" deploy/charts/neuron/Chart.yaml | sed -r 's|^appVersion:[[:space:]]([0-9]+.[0-9]+.[0-9]+)$|\1|g')
if [ "$appVersion" != "${GITHUB_REF##*/}" ]; then
echo "Need update appVersion for Chart.yaml"
exit 1
fi
helm:
runs-on: self-hosted
if: github.repository_owner == 'emqx'
needs:
- release
steps:
- uses: actions/checkout@v2
- name: Check appVersion for helm
working-directory: deploy/charts/neuron
run: |
appVersion=$(egrep "^appVersion" Chart.yaml | sed -r 's|^appVersion:[[:space:]]([0-9]+.[0-9]+.[0-9]+)$|\1|g')
if [ "$appVersion" != "${GITHUB_REF##*/}" ]; then
echo "Need update appVersion for Chart.yaml"
exit 1
fi
- name: Create helm package
working-directory: deploy/charts/neuron
run: helm package .
- name: Update helm repo
run: |
sudo mv $(find deploy/charts/neuron -name "*.tgz") /repos/charts
sudo helm repo index /repos/charts
+33
View File
@@ -0,0 +1,33 @@
name: Test helm
on:
push:
tags:
- "*"
pull_request:
jobs:
deployment:
runs-on: ubuntu-latest
steps:
- run: minikube start --kubernetes-version="v1.23.0"
- uses: actions/checkout@v2
- name: Deploy neuron by helm
shell: bash
run: |
helm install neuron deploy/charts/neuron\
--set image.repository="emqx/neuron"\
--set image.tag="2.0.1"
- name: Check deployment
timeout-minutes: 5
run: |
set -euo pipefail
while [ "$(kubectl get pods -o json | jq '.items[0].status.containerStatuses[] | select(.ready==true) | .containerID')" = "" ]; do
echo "=============================="
kubectl get pods
echo "=============================="
echo "waiting neuron started"
sleep 10
done
+1 -4
View File
@@ -16,7 +16,4 @@ tmp
*.deb
*.rpm
neuron-sdk
.vscode
log.html
output.xml
report.html
.vscode
+3
View File
@@ -0,0 +1,3 @@
[submodule "extern/uthash"]
path = extern/uthash
url = https://github.com/troydhanson/uthash.git
+22 -58
View File
@@ -31,17 +31,8 @@ if(NOT DISABLE_WERROR)
set(CMAKE_C_FLAGS "$ENV{CFLAGS} -Werror")
endif()
if(USE_GCOV)
message(STATUS "using gcov")
SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage -O0")
SET(GCC_COVERAGE_LINK_FLAGS "-lgcov")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
endif(USE_GCOV)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -g")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O0")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O1")
if(NOT DISABLE_ASAN)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -fsanitize=address")
@@ -53,6 +44,10 @@ add_custom_target(neuron-version
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_SOURCE_DIR}/cmake/neuron-version.cmake)
configure_file(extern/uthash/include/uthash.h ${CMAKE_SOURCE_DIR}/include/neuron/utils/uthash.h)
configure_file(extern/uthash/include/utarray.h ${CMAKE_SOURCE_DIR}/include/neuron/utils/utarray.h)
configure_file(extern/uthash/include/utlist.h ${CMAKE_SOURCE_DIR}/include/neuron/utils/utlist.h)
find_package(nng CONFIG REQUIRED)
find_package(Threads)
@@ -64,63 +59,36 @@ else()
link_directories(/usr/local/lib)
endif()
set(PERSIST_SOURCES
src/persist/persist.c
src/persist/sqlite.c
src/persist/json/persist_json_plugin.c)
aux_source_directory(src/parser NEURON_SRC_PARSE)
set(NEURON_BASE_SOURCES
src/base/tag.c
src/base/neu_plugin_common.c
src/base/tag_sort.c
src/base/group.c
src/base/metrics.c
src/base/msg.c
src/connection/connection.c
src/connection/connection_eth.c
src/connection/mqtt_client.c
src/connection/mqtt_c_client.c
src/connection/mqtt_client_intf.c
src/event/event_linux.c
src/event/event_unix.c
src/utils/asprintf.c
src/utils/json.c
src/utils/http.c
src/utils/http_handler.c
src/utils/neu_jwt.c
src/utils/base64.c
src/utils/async_queue.c
src/utils/log.c
${PERSIST_SOURCES})
if (SMART_LINK)
message(STATUS "using smart link")
add_definitions(-DNEU_SMART_LINK)
set(NEURON_BASE_SOURCES ${NEURON_BASE_SOURCES} src/connection/smart_link.c)
endif()
if (CLIB)
message(STATUS "set clib")
add_definitions(-DNEU_CLIB=${CLIB})
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release")
message(STATUS "build release")
add_definitions(-DNEU_RELEASE)
endif()
src/utils/mem_cache.c)
add_library(neuron-base SHARED)
target_sources(neuron-base PRIVATE ${NEURON_BASE_SOURCES} ${NEURON_SRC_PARSE})
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} -lm)
target_compile_definitions(neuron-base PRIVATE MQTT_USE_BIO)
target_link_libraries(neuron-base nng libzlog.so jansson crypto ssl mqttc jwt
${CMAKE_THREAD_LIBS_INIT})
add_dependencies(neuron-base neuron-version)
# dependency imposed by nng
#find_package(MbedTLS)
target_link_libraries(neuron-base mbedtls mbedx509 mbedcrypto)
set(PERSIST_SOURCES
src/persist/persist.c
src/persist/json/persist_json_plugin.c)
set(NEURON_SOURCES
src/main.c
src/argparse.c
@@ -128,41 +96,41 @@ set(NEURON_SOURCES
src/core/manager_internal.c
src/core/manager.c
src/core/subscribe.c
src/core/sub_msg.c
src/core/plugin_manager.c
src/core/node_manager.c
src/core/storage.c
src/adapter/msg_q.c
src/adapter/storage.c
src/adapter/adapter.c
src/adapter/driver/cache.c
src/adapter/driver/driver.c
plugins/restful/handle.c
plugins/restful/license.c
plugins/restful/license_handle.c
plugins/restful/log_handle.c
plugins/restful/metric_handle.c
plugins/restful/normal_handle.c
plugins/restful/rw_handle.c
plugins/restful/adapter_handle.c
plugins/restful/datatag_handle.c
plugins/restful/global_config_handle.c
plugins/restful/group_config_handle.c
plugins/restful/plugin_handle.c
plugins/restful/version_handle.c
plugins/restful/rest.c
plugins/restful/user.c)
plugins/restful/http.c
plugins/restful/proxy.c
plugins/restful/websocket.c
${PERSIST_SOURCES})
set(CMAKE_BUILD_RPATH ./)
add_executable(neuron)
target_sources(neuron PRIVATE ${NEURON_SOURCES})
target_include_directories(neuron PRIVATE include/neuron src plugins)
target_link_libraries(neuron dl neuron-base sqlite3 -lm)
target_link_options(neuron PRIVATE "LINKER:--dynamic-list-data")
#copy file for run
file(COPY ${CMAKE_SOURCE_DIR}/zlog.conf DESTINATION ${CMAKE_BINARY_DIR}/config)
file(COPY ${CMAKE_SOURCE_DIR}/dev.conf DESTINATION ${CMAKE_BINARY_DIR}/config)
file(COPY ${CMAKE_SOURCE_DIR}/neuron.json DESTINATION ${CMAKE_BINARY_DIR}/config)
file(COPY ${CMAKE_SOURCE_DIR}/.gitkeep DESTINATION ${CMAKE_BINARY_DIR}/logs)
file(COPY ${CMAKE_SOURCE_DIR}/.gitkeep DESTINATION ${CMAKE_BINARY_DIR}/persistence)
file(COPY ${CMAKE_SOURCE_DIR}/neuron.key DESTINATION ${CMAKE_BINARY_DIR}/config)
file(COPY ${CMAKE_SOURCE_DIR}/neuron.pem DESTINATION ${CMAKE_BINARY_DIR}/config)
file(GLOB SQL_SCHEMAS ${CMAKE_SOURCE_DIR}/persistence/*.sql)
@@ -176,13 +144,9 @@ add_subdirectory(plugins/ekuiper)
add_subdirectory(simulator)
if(NOT DISABLE_UT)
add_subdirectory(tests/ut)
add_subdirectory(tests)
endif()
add_subdirectory(tests/plugins/c1)
add_subdirectory(tests/plugins/s1)
add_subdirectory(tests/plugins/sc1)
# Set sane defaults for multi-lib linux systems
include(GNUInstallDirs)
if(UNIX)
+12 -12
View File
@@ -19,18 +19,11 @@ $ cd jansson && mkdir build && cd build
$ cmake -DJANSSON_BUILD_DOCS=OFF -DJANSSON_EXAMPLES=OFF ..&& make && sudo make install
```
[mbedtls](https://github.com/ARMmbed/mbedtls.git)
[nng](https://github.com/neugates/nng.git)
```shell
$ git clone -b v2.16.12 https://github.com/Mbed-TLS/mbedtls.git
$ cd mbedtls && mkdir build && cd build
$ cmake -DUSE_SHARED_MBEDTLS_LIBRARY=OFF -DENABLE_TESTING=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. && make && sudo make install
```
[NanoSDK](https://github.com/neugates/NanoSDK.git)
```shell
$ git clone -b neuron https://github.com/neugates/NanoSDK.git
$ cd NanoSDK && mkdir build && cd build
$ cmake -DBUILD_SHARED_LIBS=OFF -DNNG_TESTS=OFF -DNNG_ENABLE_SQLITE=ON -DNNG_ENABLE_TLS=ON .. && make && sudo make install
$ git clone https://github.com/neugates/nng.git
$ cd nng && mkdir build && cd build
$ cmake -DBUILD_SHARED_LIBS=OFF -DNNG_TESTS=OFF .. && make && sudo make install
```
[jwt](https://github.com/benmcollins/libjwt.git)
@@ -40,6 +33,13 @@ $ cd libjwt && mkdir build && cd build
$ cmake -DENABLE_PIC=ON -DBUILD_SHARED_LIBS=OFF .. && make && sudo make install
```
[MQTT-C](https://github.com/neugates/MQTT-C.git)
```shell
$ git clone https://github.com/neugates/MQTT-C.git
$ cd MQTT-C && mkdir build && cd build
$ cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DMQTT_C_OpenSSL_SUPPORT=ON -DMQTT_C_EXAMPLES=OFF .. && make && sudo make install
```
[googletest](https://github.com/google/googletest.git)
```shell
$ git clone -b release-1.11.0 https://github.com/google/googletest.git
@@ -53,5 +53,5 @@ $ curl -o sqlite3.tar.gz https://www.sqlite.org/2022/sqlite-autoconf-3390000.tar
$ mkdir sqlite3
$ tar xzf sqlite3.tar.gz --strip-components=1 -C sqlite3
$ cd sqlite3
$ ./configure CFLAGS=-fPIC && make && sudo make install
$ ./configure && make && sudo make install
```
+12 -13
View File
@@ -18,17 +18,17 @@ Neuron 是一款开源的、轻量级工业协议网关软件,支持数十种
以下是 Neuron 的一些重要特性:
- 具有实时能力的边缘原生应用程序可以利用边缘端的低延迟网络。
- 松耦合模块化 [架构设计](https://neugates.io/docs/zh/latest/introduction/architecture/architecture.html) 通过可插拔模块扩展更多功能服务。
- 松耦合模块化 [架构设计](https://neugates.io/docs/en/latest/architecture.html) 通过可插拔模块扩展更多功能服务。
- 支持可以在运行时更新设备和应用程序模块的热插件。
- 支持多种工业设备协议,包括 Modbus、OPCUA、Ethernet/IP、IEC104、BACnet 等 [更多协议](https://neugates.io/docs/zh/latest/configuration/south-devices/south-devices.html)。
- 支持多种工业设备协议,包括 Modbus、OPCUA、Ethernet/IP、IEC104、BACnet 等 [更多协议](https://neugates.io/docs/en/latest/module-plugins/module-list.html)。
- 支持同时连接大量不同协议的工业设备。
- 结合[eKuiper](https://www.lfedge.org/projects/ekuiper)提供的规则引擎功能,快速实现基于规则的设备控制或 AI/ML 分析。
- 通过 [SparkplugB](https://neugates.io/docs/zh/latest/use-cases/use_cases.html#mqtt-sparkplugb-%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88) 解决方案支持对工业应用程序的数据访问,例如 MES 或 ERP、SCADA、historian 和数据分析软件。
- 通过 [SparkplugB](https://neugates.io/docs/en/latest/use_cases.html) 解决方案支持对工业应用程序的数据访问,例如 MES 或 ERP、SCADA、historian 和数据分析软件。
- 具有非常低的内存占用,小于 10M 的内存占用和 CPU 使用率,可以在 ARM、x86 和 RISC-V 等资源有限的硬件上运行。
- 支持在本地安装可执行文件或部署在容器化环境中。
- 控制工业设备,通过[HTTP API](https://neugates.io/docs/zh/latest/http-api/http-api.html)和[MQTT API](https://neugates.io/docs/en/latest/north-apps/mqtt/api.html) 服务更改参数和数据标签。
- 控制工业设备,通过[API](https://neugates.io/docs/en/latest/api.html)和[MQTT](https://neugates.io/docs/en/latest/mqtt.html) 服务更改参数和数据标签。
- 与其他 EMQ 产品高度集成,包括 [EMQX](https://www.emqx.com/zh/products/emqx)、[NanoMQ](https://nanomq.io/zh)、[eKuiper](https://ekuiper.org/zh)。
- 核心框架和 Modbus、MQTT 和 eKuiper 的代码在 LGPLv3 的许可下开源。商业模块需要 [EMQ 许可证](https://neugates.io/docs/zh/latest/introduction/license-describe.html) 才能运行。
- 核心框架和 Modbus、MQTT 和 eKuiper 的代码在 LGPLv3 的许可下开源。商业模块需要 [EMQ 许可证](https://neugates.io/docs/en/latest/getting-started/license_policy.html) 才能运行。
获取更多信息,请访问 [Neuron 官网](https://neugates.io/zh)。
@@ -40,7 +40,7 @@ Neuron 是一款开源的、轻量级工业协议网关软件,支持数十种
docker run -d --name neuron -p 7000:7000 -p 7001:7001 -p 9081:9081 --privileged=true --restart=always emqx/neuron:latest
```
接下来请参考 [快速入门](https://neugates.io/docs/zh/latest/quick-start/hardware-specifications.html) 开启您的 Neuron 之旅。
接下来请参考 [入门指南](https://neugates.io/docs/zh/latest/getting-started/quick_start.html#运行和使用) 开启您的 Neuron 之旅。
> **提示**
>
@@ -52,7 +52,7 @@ docker run -d --name neuron -p 7000:7000 -p 7001:7001 -p 9081:9081 --privileged=
您可以从 [neugates.io/zh/downloads?os=Linux](https://neugates.io/zh/downloads?os=Linux) 下载不同格式的 Neuron 安装包进行手动安装。
也可以直接访问 [Neuron 安装文档](https://neugates.io/docs/zh/latest/installation/installation.html) 查看不同安装方式的操作步骤。
也可以直接访问 [Neuron 安装文档](https://neugates.io/docs/zh/latest/getting-started/installation.html) 查看不同安装方式的操作步骤。
## 文档
@@ -70,20 +70,21 @@ Neuron 文档地址:[https://neugates.io/docs/zh/latest/](https://neugates.io/
**安装依赖**
请参考 [Install-dependencies](https://github.com/emqx/neuron/blob/main/Install-dependencies.md)
请参考 [github.com/neugates/neuron/blob/main/Install-dependencies.md](https://github.com/neugates/neuron/blob/main/Install-dependencies.md)
**编译**
```
$ git clone https://github.com/emqx/neuron
$ cd neuron
$ git submodule update --init
$ mkdir build && cd build
$ cmake .. && make
```
**安装 Dashboard**
在 [neuron-dashboard](https://github.com/emqx/neuron-dashboard/releases) 页面下载最新的 `neuron-dashboard.zip`,解压后放到 Neuron 可执行目录下的 dist 目录中。
在 [github.com/emqx/neuron-dashboard/releases](https://github.com/emqx/neuron-dashboard/releases) 页面下载最新的 `neuron-dashboard.zip`,解压后放到 Neuron 可执行目录下的 dist 目录中。
**运行**
@@ -112,11 +113,9 @@ $ ctest --output-on-failure
运行所有的功能测试
```shell
$ sudo apt-get install -y mosquitto
$ mosquitto -v &
$ python3 -m pip install -U pip
$ python3 -m pip install -r ft/requirements.txt
$ python3 -m robot --maxerroelines=600 -P ft/ -d ft/reports ft
$ pip3 install -r ft/requirements.txt
$ python3 -m robot -P ft/ --variable neuron_api:http -d ft/http_reports ft
```
### 压力测试
+53 -10
View File
@@ -2,12 +2,13 @@
[![GitHub Release](https://img.shields.io/github/release/emqx/neuron?color=brightgreen&label=Release)](https://github.com/emqx/neuron/releases)
[![Docker Pulls](https://img.shields.io/docker/pulls/emqx/neuron?label=Docker%20Pulls)](https://hub.docker.com/r/emqx/neuron)
[![codecov](https://codecov.io/gh/emqx/neuron/graph/badge.svg?token=X95RD0NUT0)](https://codecov.io/gh/emqx/neuron)
[![Slack](https://img.shields.io/badge/Slack-Neuron-39AE85?logo=slack)](https://slack-invite.emqx.io/)
[![Discord](https://img.shields.io/discord/931086341838622751?label=Discord&logo=discord)](https://discord.gg/xYGf3fQnES)
[![Twitter](https://img.shields.io/badge/Follow-EMQ-1DA1F2?logo=twitter)](https://twitter.com/EMQTech)
[![YouTube](https://img.shields.io/badge/Subscribe-EMQ-FF0000?logo=youtube)](https://www.youtube.com/channel/UC5FjR77ErAxvZENEWzQaO5Q)
English | [简体中文](https://github.com/neugates/neuron/blob/main/README-CN.md)
Neuron is an Industrial IoT (IIoT) connectivity server for modern big data and AI/ML technology to leverage the power of Industrial 4.0. It supports one-stop access to dozens of industrial protocols and converts them into MQTT protocol and realize the interconnection between IIoT platforms and various industrial devices.
![neuron-overview](docs/pictures/neuron-final.png)
@@ -15,17 +16,17 @@ Neuron is an Industrial IoT (IIoT) connectivity server for modern big data and A
The following are some important features of Neuron:
- Edge native application with real-time capability to leverage the low latency network of edge side.
- Loosely-coupled modularity [architecture design](https://neugates.io/docs/en/latest/introduction/architecture/architecture.html) for extending more functional services by pluggable modules.
- Loosely-coupled modularity [architecture design](https://neugates.io/docs/en/latest/architecture.html) for extending more functional services by pluggable modules.
- Support hot plugins that can update device and application modules during runtime.
- Support numerous protocols for industrial devices, including Modbus, OPCUA, Ethernet/IP, IEC104, BACnet and [more](https://neugates.io/docs/en/latest/configuration/south-devices/south-devices.html).
- Support numerous protocols for industrial devices, including Modbus, OPCUA, Ethernet/IP, IEC104, BACnet and [more](https://neugates.io/docs/en/latest/module-plugins/module-list.html).
- Support simultaneous connection of a large number of industrial devices with different protocols.
- Combine with the rule engine function provided by [eKuiper](https://www.lfedge.org/projects/ekuiper) to quickly implement rule-based device control or AI/ML analytics.
- Support data access to industrial applications, such as MES or ERP, SCADA, historian and data analytics software via [SparkplugB](https://neugates.io/docs/en/latest/use-cases/sparkplug/sparkplug.html) solution.
- Support data access to industrial applications, such as MES or ERP, SCADA, historian and data analytics software via [SparkplugB](https://neugates.io/docs/en/latest/use_cases.html) solution.
- Has very low memory footprint, less than 10M, and CPU usage, can run on limited resource hardware like ARM, x86 and RISC-V.
- Support installation of native executable or deployed in containerized enviornment.
- Control industrial devices, and make changes to the parameters and data tags through [HTTP API](https://neugates.io/docs/en/latest/api/configuration.html) and [MQTT API](https://neugates.io/docs/en/latest/configuration/north-apps/mqtt/api.html) services.
- Control industrial devices, and make changes to the parameters and data tags through [API](https://neugates.io/docs/en/latest/api.html) and [MQTT](https://neugates.io/docs/en/latest/mqtt.html) services.
- Highly integrated with other EMQ products, including [EMQX](https://www.emqx.com/en/products/emqx), [NanoMQ](https://nanomq.io/), [eKuiper](https://ekuiper.org/).
- The code of the core framework and Modbus, MQTT and eKuiper are licensed under open source LGPLv3. Commercial modules require a [EMQ License](https://neugates.io/docs/en/latest/installation/license-install/license-install.html) to run.
- The code of the core framework and Modbus, MQTT and eKuiper are licensed under open source LGPLv3. Commercial modules require a [EMQ License](https://neugates.io/docs/en/latest/getting-started/license_policy.html) to run.
For more information, please visit [Neuron homepage](https://neugates.io/).
@@ -37,7 +38,7 @@ For more information, please visit [Neuron homepage](https://neugates.io/).
docker run -d --name neuron -p 7000:7000 -p 7001:7001 -p 9081:9081 --privileged=true --restart=always emqx/neuron:latest
```
Next, please follow the [getting started guide](https://neugates.io/docs/en/latest/quick-start/hardware-specifications.html) to tour the Neuron features.
Next, please follow the [getting started guide](https://neugates.io/docs/en/latest/getting-started/quick_start.html#run-for-the-first-time) to tour the Neuron features.
> **Limitations**
>
@@ -49,7 +50,7 @@ Next, please follow the [getting started guide](https://neugates.io/docs/en/late
If you prefer to install and manage Neuron yourself, you can download the latest version from [neugates.io/downloads?os=Linux](https://neugates.io/downloads?os=Linux).
For more installation options, see the [Neuron installation documentation](https://neugates.io/docs/en/latest/installation/installation.html).
For more installation options, see the [Neuron installation documentation](https://neugates.io/docs/en/latest/getting-started/installation.html).
## Documentation
@@ -66,20 +67,21 @@ The Neuron documentation is available at [neugates.io/docs/en/latest/](https://n
**Install required dependencies**
[Install-dependencies](https://github.com/emqx/neuron/blob/main/Install-dependencies.md)
[github.com/neugates/neuron/blob/main/Install-dependencies.md](https://github.com/neugates/neuron/blob/main/Install-dependencies.md)
**Build**
```
$ git clone https://github.com/emqx/neuron
$ cd neuron
$ git submodule update --init
$ mkdir build && cd build
$ cmake .. && make
```
**Install Dashboard**
Download the latest `neuron-dashboard.zip` from the [neuron-dashboard](https://github.com/emqx/neuron-dashboard/releases) page, unzip it and put it to the `dist` directory under the Neuron executable directory.
Download the latest `neuron-dashboard.zip` from the [github.com/emqx/neuron-dashboard/releases](https://github.com/emqx/neuron-dashboard/releases) page, unzip it and put it to the `dist` directory under the Neuron executable directory.
**Run**
@@ -93,6 +95,47 @@ $ ./neuron
>Change the log level in the rules in the zlog.conf file. Available levels include INFO, DEBUG, NOTICE, WARN, ERROR and FATAL.
>
## Test
To run all unit testers
```shell
$ cd build
$ ctest --output-on-failure
```
### Functional test
To run all functional testers
```shell
$ mosquitto -v &
$ pip3 install -r ft/requirements.txt
$ python3 -m robot -P ft/ --variable neuron_api:http -d ft/http_reports ft
```
### Pressure test
There are datasets for pressure testing in directory `ft/data/persistence/`.
To run pressure tests
```shell
# python dependencies
$ pip3 install -r ft/requirements.txt
# through http api, on dataset total-10k
$ python3 -m robot -P ft/ --variable neuron_api:http --variable dataset:total-10k -d ft/http-total-10k ft/pressure.test
# through http api, on dataset total-50k
$ python3 -m robot -P ft/ --variable neuron_api:http --variable dataset:total-50k -d ft/http-total-50k ft/pressure.test
# A MQTT broker is needed if using the mqtt api, mosquitto in this example
$ mosquitto -v &
# through mqtt api, on dataset simple-1k
$ python3 -m robot -P ft/ --variable neuron_api:mqtt --variable dataset:simple-1k -d ft/mqtt-simple-1k ft/pressure.test
```
## License
See [LICENSE](./LICENSE).
+2 -3
View File
@@ -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/v2.8/libs)
set(LIBRARY_DIR /opt/externs/libs)
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
@@ -19,6 +19,5 @@ set(CMAKE_FIND_ROOT_PATH ${CMAKE_STAGING_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_SYSROOT ${CMAKE_STAGING_PREFIX})
link_directories(${CMAKE_STAGING_PREFIX})
file(COPY ${CMAKE_STAGING_PREFIX}/lib/libzlog.so.1.2 DESTINATION /usr/local/lib)
+2 -3
View File
@@ -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/v2.8/libs)
set(LIBRARY_DIR /opt/externs/libs)
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
@@ -19,6 +19,5 @@ set(CMAKE_FIND_ROOT_PATH ${CMAKE_STAGING_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_SYSROOT ${CMAKE_STAGING_PREFIX})
link_directories(${CMAKE_STAGING_PREFIX})
file(COPY ${CMAKE_STAGING_PREFIX}/lib/libzlog.so.1.2 DESTINATION /usr/local/lib)
+2 -3
View File
@@ -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/v2.8/libs)
set(LIBRARY_DIR /opt/externs/libs)
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
@@ -19,6 +19,5 @@ set(CMAKE_FIND_ROOT_PATH ${CMAKE_STAGING_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_SYSROOT ${CMAKE_STAGING_PREFIX})
link_directories(${CMAKE_STAGING_PREFIX})
file(COPY ${CMAKE_STAGING_PREFIX}/lib/libzlog.so.1.2 DESTINATION /usr/local/lib)
-30
View File
@@ -1,30 +0,0 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER ${TOOL_DIR}/${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOL_DIR}/${COMPILER_PREFIX}-g++)
set(CMAKE_AR ${TOOL_DIR}/${COMPILER_PREFIX}-ar)
set(CMAKE_LINKER ${TOOL_DIR}/${COMPILER_PREFIX}-ld)
set(CMAKE_NM ${TOOL_DIR}/${COMPILER_PREFIX}-nm)
set(CMAKE_OBJDUMP ${TOOL_DIR}/${COMPILER_PREFIX}-objdump)
set(CMAKE_RANLIB ${TOOL_DIR}/${COMPILER_PREFIX}-ranlib)
set(CMAKE_STAGING_PREFIX ${LIBRARY_DIR}/${COMPILER_PREFIX})
set(CMAKE_PREFIX_PATH ${CMAKE_STAGING_PREFIX})
include_directories(SYSTEM ${CMAKE_STAGING_PREFIX}/include)
include_directories(SYSTEM ${CMAKE_STAGING_PREFIX}/openssl/include)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_STAGING_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
link_directories(${CMAKE_STAGING_PREFIX})
if(CMAKE_SYSTEM_PROCESSOR MATCHES "mips32")
link_libraries(atomic)
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "riscv64")
link_libraries(atomic)
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "loongarch64")
link_libraries(atomic)
endif()
+2 -19
View File
@@ -1,24 +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/v2.8/libs)
set(LIBRARY_DIR /usr/local)
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
set(CMAKE_AR ${COMPILER_PREFIX}-ar)
set(CMAKE_LINKER ${COMPILER_PREFIX}-ld)
set(CMAKE_NM ${COMPILER_PREFIX}-nm)
set(CMAKE_OBJDUMP ${COMPILER_PREFIX}-objdump)
set(CMAKE_RANLIB ${COMPILER_PREFIX}-ranlib)
set(CMAKE_STAGING_PREFIX ${LIBRARY_DIR}/${COMPILER_PREFIX})
set(CMAKE_PREFIX_PATH ${CMAKE_STAGING_PREFIX})
include_directories(SYSTEM ${CMAKE_STAGING_PREFIX}/include)
include_directories(SYSTEM ${CMAKE_STAGING_PREFIX}/openssl/include)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_STAGING_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
link_directories(${CMAKE_STAGING_PREFIX})
file(COPY ${CMAKE_STAGING_PREFIX}/lib/libzlog.so.1.2 DESTINATION /usr/local/lib)
set(CMAKE_PREFIX_PATH ${CMAKE_STAGING_PREFIX})
-50
View File
@@ -1,50 +0,0 @@
#!/bin/bash
# core trace
lcov -c -d build/CMakeFiles/neuron-base.dir/src -o cov_report/cov-neuron-base.info
lcov -c -d build/CMakeFiles/neuron.dir/src -o cov_report/cov-neuron.info
lcov -c -d build/CMakeFiles/neuron.dir/plugins/restful -o cov_report/cov-restful.info
# always with core trace
function gen_trace () {
lcov -a cov-neuron-base.info -a cov-neuron.info -a cov-restful.info $@;
}
case $1 in
(ut)
rm -f cov_report/cov-neuron.info cov_report/cov-restful.info
for dir in build/tests/ut/CMakeFiles/*_test.dir; do
test_name=$(basename ${dir} "_test.dir")
lcov -c -d ${dir} -o "cov_report/cov-${test_name}_test.info"
done
cd cov_report
lcov $(for file in cov-*.info; do echo "-a $file "; done) -a cov-neuron-base.info -o cov-ut.info;;
(ft)
lcov -c -d build/plugins/mqtt/CMakeFiles/plugin-mqtt.dir -o cov_report/cov-mqtt.info
lcov -c -d build/plugins/modbus/CMakeFiles/plugin-modbus-rtu.dir -o cov_report/cov-modbus-rtu.info
lcov -c -d build/plugins/modbus/CMakeFiles/plugin-modbus-tcp.dir -o cov_report/cov-modbus-tcp.info
cd cov_report
gen_trace -a cov-mqtt.info -a cov-modbus-rtu.info -a cov-modbus-tcp.info -o cov-ft.info;;
(ekuiper)
lcov -c -d build/plugins/ekuiper/CMakeFiles/plugin-ekuiper.dir -o cov_report/cov-ekuiper.info
cd cov_report
gen_trace -a cov-ekuiper.info -o cov-ekuiper.info;;
(modbus)
lcov -c -d build/plugins/modbus/CMakeFiles/plugin-modbus-rtu.dir -o cov_report/cov-modbus-rtu.info
lcov -c -d build/plugins/modbus/CMakeFiles/plugin-modbus-tcp.dir -o cov_report/cov-modbus-tcp.info
lcov -c -d build/simulator/CMakeFiles/modbus_simulator.dir -o cov_report/cov-simulator-modbus.info
cd cov_report
gen_trace -a cov-simulator-modbus.info -a cov-modbus-rtu.info -a cov-modbus-tcp.info -o cov-modbus.info;;
(mqtt)
lcov -c -d build/plugins/mqtt/CMakeFiles/plugin-mqtt.dir -o cov_report/cov-mqtt.info
cd cov_report
gen_trace -a cov-mqtt.info -o cov-mqtt.info;;
(core)
cd cov_report
gen_trace -o cov-core.info;;
(metrics)
cd cov_report
gen_trace -o cov-metrics.info;;
(*)
lcov -c -d build/plugins/$1/CMakeFiles/plugin-$1.dir -o cov_report/cov-$1.info;;
esac
+3 -4
View File
@@ -1,8 +1,7 @@
{
"plugins": [
"libplugin-mqtt.so",
"libplugin-ekuiper.so",
"libplugin-modbus-tcp.so",
"libplugin-modbus-rtu.so"
"libplugin-mqtt.so",
"libplugin-modbus-tcp.so"
]
}
}
+2 -2
View File
@@ -15,10 +15,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.0.6
version: 1.0.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: 2.2.8
appVersion: "2.0.1"
+24 -19
View File
@@ -1,10 +1,9 @@
# neuron
![Version: 1.0.6](https://img.shields.io/badge/Version-1.0.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.2.8](https://img.shields.io/badge/AppVersion-2.2.8-informational?style=flat-square)
![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.0.1](https://img.shields.io/badge/AppVersion-2.0.1-informational?style=flat-square)
A Helm chart for Kubernetes
## Install the Chart
- From Github
@@ -24,27 +23,37 @@ helm uninstall my-neuron
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | |
| autoscaling.enabled | bool | `false` | |
| autoscaling.maxReplicas | int | `100` | |
| autoscaling.minReplicas | int | `1` | |
| autoscaling.targetCPUUtilizationPercentage | int | `80` | |
| clusterDomain | string | `"cluster.local"` | Kubernetes Cluster Domain |
| containerPorts | object | `{"api":7001,"web":7000}` | Container Ports |
| containerPorts.api | int | `7001` | containerPorts.api |
| containerPorts.web | int | `7000` | containerPorts.web |
| fullnameOverride | string | `""` | |
| hostPorts | object | `{"api":30371,"enabled":false,"web":30370}` | only for kubeedge deployment |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.repository | string | `"emqx/neuron"` | |
| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
| imagePullSecrets | list | `[]` | |
| ingress.annotations | object | `{}` | |
| ingress.className | string | `""` | |
| ingress.enabled | bool | `false` | |
| ingress.hosts[0].host | string | `"chart-example.local"` | |
| ingress.hosts[0].paths[0].path | string | `"/"` | |
| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | |
| ingress.tls | list | `[]` | |
| nameOverride | string | `""` | |
| neuronEnv.enabled | bool | `true` | |
| neuronEnv.keys.disableAuth | string | `"DISABLE_AUTH"` | |
| neuronEnv.values.disableAuth | bool | `true` | |
| neuronMounts[0].capacity | string | `"100Mi"` | |
| neuronMounts[0].mountPath | string | `"/opt/neuron/persistence"` | |
| neuronMounts[0].name | string | `"pvc-neuron-data"` | |
| nodeSelector | object | `{}` | |
| persistence.accessMode | string | `"ReadWriteOnce"` | |
| persistence.enabled | bool | `false` | |
| persistence.storageClass | string | `"standard"` | |
| persistence.existingClaim | string | `""` | Existing PersistentVolumeClaims The value is evaluated as a template So, for example, the name can depend on .Release or .Chart |
| podAnnotations | object | `{}` | |
| readinessProbe.enabled | bool | `true` | |
| readinessProbe.initialDelaySeconds | int | `5` | |
| readinessProbe.periodSeconds | int | `5` | |
| resources | object | `{}` | |
| service.annotations | object | `{"eip.openelb.kubesphere.io/v1alpha2":"eip-pool","lb.kubesphere.io/v1alpha1":"openelb","protocol.openelb.kubesphere.io/v1alpha1":"layer2"}` | Provide any additional annotations which may be required. Evaluated as a template |
| service.annotations | object | `{}` | Provide any additional annotations which may be required. Evaluated as a template |
| service.enabled | bool | `true` | |
| service.loadBalancerSourceRanges | list | `[]` | loadBalancerSourceRanges: - 10.10.10.0/24 |
| service.nodePorts | object | `{"api":null,"web":null}` | Specify the nodePort(s) value for the LoadBalancer and NodePort service types. ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport |
@@ -54,11 +63,7 @@ helm uninstall my-neuron
| service.ports.web.name | string | `"web"` | Neuron Dashboard port name |
| service.ports.web.port | int | `7000` | Neuron Dashboard port |
| service.type | string | `"ClusterIP"` | |
| tolerations[0].effect | string | `"NoExecute"` | |
| tolerations[0].key | string | `"node.kubernetes.io/not-ready"` | |
| tolerations[0].operator | string | `"Exists"` | |
| tolerations[0].tolerationSeconds | int | `30` | |
| tolerations[1].effect | string | `"NoExecute"` | |
| tolerations[1].key | string | `"node.kubernetes.io/unreachable"` | |
| tolerations[1].operator | string | `"Exists"` | |
| tolerations[1].tolerationSeconds | int | `30` | |
| serviceAccount.annotations | object | `{}` | Annotations to add to the service account |
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template |
| tolerations | list | `[]` | |
@@ -50,6 +50,16 @@ app.kubernetes.io/name: {{ include "neuron.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "neuron.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "neuron.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Get the TLS secret.
+10 -17
View File
@@ -15,17 +15,15 @@ spec:
labels:
{{- include "neuron.selectorLabels" . | nindent 8 }}
spec:
serviceAccountName: {{ include "neuron.serviceAccountName" . }}
volumes:
{{- range $mount := .Values.neuronMounts }}
- name: {{ $mount.name }}
{{- if $.Values.persistence.enabled }}
- name: neuron-persistence
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ printf "%s-%s" $.Release.Name (tpl $mount.name $) }}
claimName: {{ (tpl .Values.persistence.existingClaim $) | default (include "neuron.fullname" .) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}
{{- if .Values.tls.enabled }}
- name: certs
secret:
@@ -40,32 +38,27 @@ spec:
- name: neuron
image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if .Values.neuronEnv.enabled }}
env:
- name: {{ .Values.neuronEnv.keys.disableAuth }}
value: "{{ .Values.neuronEnv.values.disableAuth }}"
{{- end }}
{{- if .Values.readinessProbe.enabled }}
readinessProbe:
httpGet:
port: {{ .Values.service.web | default 7000 }}
initialDelaySeconds: 5
periodSeconds: 5
{{- end }}
ports:
- name: web
containerPort: {{ .Values.service.ports.web.port | default 7000 }}
containerPort: {{ .Values.containerPorts.web | default 7000 }}
{{- if .Values.hostPorts.enabled }}
hostPort: {{ .Values.hostPorts.web | default 7000 }}
{{- end}}
- name: api
containerPort: {{ .Values.service.ports.api.port | default 7001 }}
containerPort: {{ .Values.containerPorts.api | default 7001 }}
{{- if .Values.hostPorts.enabled }}
hostPort: {{ .Values.hostPorts.api | default 7001 }}
{{- end}}
volumeMounts:
{{- range $mount := .Values.neuronMounts }}
- name: {{ $mount.name }}
mountPath: {{ $mount.mountPath }}
{{- end }}
- name: neuron-persistence
mountPath: "/opt/neuron/persistence"
{{- if .Values.tls.enabled }}
- name: certs
mountPath: "/opt/neuron/config/neuron.pem"
@@ -0,0 +1,61 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "neuron.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "neuron.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
-41
View File
@@ -1,41 +0,0 @@
{{- if $.Values.persistence.enabled }}
{{- $top := . -}}
{{- range $mount := .Values.ekuiperMounts }}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ printf "%s-%s" $.Release.Name (tpl $mount.name $) }}
namespace: {{ $.Release.Namespace }}
annotations:
kubesphere.io/creator: admin
finalizers:
- kubernetes.io/pvc-protection
spec:
accessModes:
- {{ $.Values.persistence.accessMode }}
resources:
requests:
storage: {{ $mount.capacity }}
storageClassName: {{ $.Values.persistence.storageClass }}
{{- end }}
{{- range $mount := .Values.neuronMounts }}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ printf "%s-%s" $.Release.Name (tpl $mount.name $) }}
namespace: {{ $.Release.Namespace }}
annotations:
kubesphere.io/creator: admin
finalizers:
- kubernetes.io/pvc-protection
spec:
accessModes:
- {{ $.Values.persistence.accessMode }}
resources:
requests:
storage: {{ $mount.capacity }}
storageClassName: {{ $.Values.persistence.storageClass }}
{{- end }}
{{- end }}
@@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "neuron.serviceAccountName" . }}
labels:
{{- include "neuron.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
-6
View File
@@ -6,12 +6,6 @@ metadata:
namespace: {{ .Release.Namespace }}
labels:
{{- include "neuron.labels" . | nindent 4 }}
{{- if eq .Values.service.type "LoadBalancer" }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if eq .Values.service.type "LoadBalancer" }}
+48 -28
View File
@@ -13,6 +13,15 @@ imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# -- Specifies whether a service account should be created
create: true
# -- Annotations to add to the service account
annotations: {}
# -- The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
# @ignored
@@ -62,24 +71,32 @@ service:
# - 10.10.10.0/24
#
loadBalancerSourceRanges: []
## TODO: it's just for OpenELB
# -- Provide any additional annotations which may be required. Evaluated as a template
annotations:
lb.kubesphere.io/v1alpha1: openelb
eip.openelb.kubesphere.io/v1alpha2: eip-pool
protocol.openelb.kubesphere.io/v1alpha1: layer2
annotations: {}
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
persistence:
enabled: false
accessMode: ReadWriteOnce
## TODO: not all storage class can work well, it depends on the specific storage
storageClass: standard
# storageClass: huawei-nfs
neuronMounts:
- name: pvc-neuron-data
capacity: 100Mi
mountPath: "/opt/neuron/persistence"
# -- Existing PersistentVolumeClaims
# The value is evaluated as a template
# So, for example, the name can depend on .Release or .Chart
existingClaim: ""
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
@@ -93,17 +110,16 @@ resources: {}
# cpu: 100m
# memory: 128Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations:
- key: "node.kubernetes.io/not-ready"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 30
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 30
tolerations: []
affinity: {}
@@ -155,13 +171,17 @@ tls:
-----END RSA PRIVATE KEY-----
neuronEnv:
readinessProbe:
enabled: true
keys:
disableAuth: DISABLE_AUTH
initialDelaySeconds: 5
periodSeconds: 5
values:
disableAuth: true
# -- Container Ports
containerPorts:
# -- containerPorts.web
web: 7000
# -- containerPorts.api
api: 7001
# -- only for kubeedge deployment
hostPorts:
+3 -10
View File
@@ -1,15 +1,8 @@
[global]
file perms = 666
[formats]
stdout_format = "%d:%ms [%V] [%c] %f:%L %m%n"
file_format = "%d:%ms [%V] %f:%L %m%n"
syslog = "<P>%d(%Y-%m-%dT%T%z) %H neuron[%p]: level=%v msg="[%c] %m" file="%f:%L"%n"
simple = "%d [%V] [%c] %f:%L %m%n"
[rules]
*.* "./logs/%c.log", 25MB * 1 ~ "./logs/%c.#2r.log"; file_format
*.* >stdout; stdout_format
*.* $remote_syslog,"%V"; syslog
*.DEBUG >stdout; simple
*.DEBUG $ws, "%V,%c"; simple
Vendored Submodule
+1
Submodule extern/uthash added at 44a66fe8e0
-35
View File
@@ -1,35 +0,0 @@
# Functional test
Functional testing uses the robotframework automated testing framework, providing templates for each test case of the northbound APP and southbound DRIVER types.
Testing is divided into the following categories.
|Test case|Description|
|-----|----------|
|Core interface test|Mainly including the addition, deletion, modification, query, subscription, and other operations of the HTTP API interface for core data(PLUGIN, NODE, GROUP, TAG)|
|Southbound DRIVER test||
|Northbound APP test||
|Plugin specific test case|Such as OPC UA specific device discovery, can different devices be connected normally|
To run all functional testers
Enter the neuron/build directory.
Install Mosquito software.
```shell
$ sudo apt-get install -y mosquitto
```
Start the mosquitto server.
```shell
$ mosquitto -v &
```
Install requirements.
```shell
$ python3 -m pip install -U pip
$ python3 -m pip install -r ft/requirements.txt
```
Run functional tests and generate test reports.
```shell
$ python3 -m robot --maxerroelines=600 -P ft/ -d ft/reports ft
```
-153
View File
@@ -5,8 +5,6 @@ Resource resource/error.resource
Suite Setup Start Neuronx
Suite Teardown Stop Neuronx
*** Variables ***
${g_long_str} ${{'a'*200}}
*** Test Cases ***
Add group under non-existent node, it should return failure
@@ -67,154 +65,3 @@ Add group under app node, it should return failure
Check Error Code ${res} ${NEU_ERR_GROUP_NOT_ALLOW}
[Teardown] Del Node mqtt
Update group with nonexistent node, it should fail.
${res} = Update Group modbus-node group interval=${1000}
Check Response Status ${res} 404
Check Error Code ${res} ${NEU_ERR_NODE_NOT_EXIST}
[Teardown] Del Node modbus-node
Update group using too long node name, it should fail.
${res} = Update Group ${g_long_str} group interval=${1000}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_NODE_NAME_TOO_LONG}
[Teardown] Del Node modbus-node
Update group with nonexistent group, it should fail.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
${res} = Update Group modbus-node group interval=${1000}
Check Response Status ${res} 404
Check Error Code ${res} ${NEU_ERR_GROUP_NOT_EXIST}
[Teardown] Del Node modbus-node
Update group using to long group name, it should fail.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
${res} = Update Group modbus-node ${g_long_str} interval=${1000}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_GROUP_NAME_TOO_LONG}
[Teardown] Del Node modbus-node
Update group with too small interval, it should fail.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
${res} = Update Group modbus-node group interval=${10}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_GROUP_PARAMETER_INVALID}
[Teardown] Del Node modbus-node
Update group with too large interval, it should fail.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
${res} = Update Group modbus-node group interval=${100000000000}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_GROUP_PARAMETER_INVALID}
[Teardown] Del Node modbus-node
Update group interval, it should success.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
${res} = Update Group modbus-node group interval=${2000}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Get Group modbus-node
Set Local Variable ${groups} ${res}[groups]
Should Match Group ${groups} group ${2000}
[Teardown] Del Node modbus-node
Update group with empty new name, it should fail.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
${res} = Update Group modbus-node group new_name=${EMPTY}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_BODY_IS_WRONG}
[Teardown] Del Node modbus-node
Update group with too long new name, it should fail.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
${res} = Update Group modbus-node group new_name=${g_long_str}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_GROUP_NAME_TOO_LONG}
[Teardown] Del Node modbus-node
Update group name to conflicting group name, it should fail.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
Add Group modbus-node grp 1000
${res} = Update Group modbus-node group new_name=grp
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_GROUP_EXIST}
[Teardown] Del Node modbus-node
Update group name, it should success.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
${res} = Update Group modbus-node group new_name=grp
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Get Group modbus-node
Set Local Variable ${groups} ${res}[groups]
Should Match Group ${groups} grp ${1000}
[Teardown] Del Node modbus-node
Update group name and interval, it should success.
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
${res} = Update Group modbus-node group new_name=grp interval=${2000}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Get Group modbus-node
Set Local Variable ${groups} ${res}[groups]
Should Match Group ${groups} grp ${2000}
[Teardown] Del Node modbus-node
Update group name, subscriptions should be updated.
Add Node mqtt-node ${PLUGIN-MQTT}
Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Add Group modbus-node group 1000
Subscribe Group mqtt-node modbus-node group
${res} = Update Group modbus-node group new_name=grp
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Get Subscribe Group mqtt-node
Check Response Status ${res} 200
Set Local Variable ${groups} ${res}[groups]
List Length Should Be ${groups} 1
Should Be Equal As Strings ${groups}[0][driver] modbus-node
Should Be Equal As Strings ${groups}[0][group] grp
[Teardown] Del Node modbus-node
*** Keywords ***
Should Match Group
[Arguments] ${groups} ${name} ${interval}
List Length Should Be ${groups} 1
Should Be Equal As Strings ${name} ${groups}[0][name]
Should Be Equal As Integers ${interval} ${groups}[0][interval]
-43
View File
@@ -1,43 +0,0 @@
*** Settings ***
Library String
Library Collections
Resource resource/api.resource
Resource resource/common.resource
Resource resource/error.resource
Suite Setup Metrics Test Setup
Suite Teardown Metrics Test Teardown
*** Test Cases ***
Get all metrics, it should return success
${res}= Get all metrics
Check Response Status ${res} 200
Get single node metrics, it should return success
${res}= Get single node metrics mqtt app
Check Response Status ${res} 200
Check Prometheus format, it should return success
${nlines}= Get metrics lines
${parameter_lines}= Get parameter lines ${nlines}
Check endswith isdigit ${parameter_lines}
Check node state, it should return success
${nlines}= Get metrics lines
${parameter_lines}= Get parameter lines ${nlines}
Check node state ${parameter_lines} mqtt
*** Keywords ***
Metrics Test Setup
Start Neuronx
${res}= Add Node mqtt ${PLUGIN_MQTT}
Check Response Status ${res} 200
Metrics Test Teardown
Del Node mqtt
Stop Neuronx
+184
View File
@@ -0,0 +1,184 @@
*** Settings ***
Resource resource/api.resource
Resource resource/common.resource
Resource resource/error.resource
Resource resource/driver.resource
Suite Setup Modbus Test Setup
Suite Teardown Modbus Test Teardown
*** Variables ***
${modbus_node} modbus_node
${MODBUS_TCP_CONFIG_WRONG} {"host": "127.0.0.1", "port": 60502}
${hold_bit} {"name": "hold_bit", "address": "1!400001.15", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${hold_int16} {"name": "hold_int16", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_uint16} {"name": "hold_uint16", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT16}}
${hold_int32} {"name": "hold_int32", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}}
${hold_uint32} {"name": "hold_uint32", "address": "1!400015", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT32}}
${hold_float} {"name": "hold_float", "address": "1!400017", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_FLOAT}}
${hold_string} {"name": "hold_string", "address": "1!400020.10", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
${coil_bit_1} {"name": "coil_bit_1", "address": "1!000001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_2} {"name": "coil_bit_2", "address": "1!000002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_3} {"name": "coil_bit_3", "address": "1!000003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_4} {"name": "coil_bit_4", "address": "1!000005", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_5} {"name": "coil_bit_5", "address": "1!000010", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${input_bit_1} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_2} {"name": "input_bit_2", "address": "1!100002", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_3} {"name": "input_bit_3", "address": "1!100003", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_4} {"name": "input_bit_4", "address": "1!100005", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_5} {"name": "input_bit_5", "address": "1!100010", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_register_bit} {"name": "input_register_bit", "address": "1!30101.15", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_register_int16} {"name": "input_register_int16", "address": "1!30101", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
${input_register_uint16} {"name": "input_register_uint16", "address": "1!30102", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_UINT16}}
${input_register_int32} {"name": "input_register_int32", "address": "1!30103", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT32}}
${input_register_uint32} {"name": "input_register_uint32", "address": "1!30115", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_UINT32}}
${input_register_float} {"name": "input_register_float", "address": "1!30117", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_FLOAT}}
${input_register_string} {"name": "input_register_string", "address": "1!30120.10", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_STRING}}
${hold_int16_address_update} {"name": "hold_int16", "address": "1!400100", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_int16_type_update} {"name": "hold_int16", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}}
${input_bit_1_name_wrong} {"name": "input_bit", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_1_attribute_unmatch} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${input_bit_1_type_unmatch} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
*** Test Cases ***
Set a node with right settings, it should be success.
[Template] Set a ${node} with right ${node_settings}, it will be success.
${modbus_node} ${MODBUS_TCP_CONFIG}
Set a node with wrong settings, it should be failure.
[Template] Set a ${node} with wrong ${node_settings}, it will be failure.
${modbus_node} ${MODBUS_TCP_CONFIG_WRONG}
Set tags with multiple address and types and attribute, it should be success.
[Template] Add a ${tag} with right address and type and attribute from ${node}, it will be success.
${hold_int16} ${modbus_node}
${hold_uint16} ${modbus_node}
${hold_int32} ${modbus_node}
${hold_uint32} ${modbus_node}
${hold_float} ${modbus_node}
${hold_string} ${modbus_node}
${coil_bit_1} ${modbus_node}
${coil_bit_2} ${modbus_node}
${coil_bit_3} ${modbus_node}
${coil_bit_4} ${modbus_node}
${coil_bit_5} ${modbus_node}
${input_register_int16} ${modbus_node}
${input_register_uint16} ${modbus_node}
${input_register_int32} ${modbus_node}
${input_register_uint32} ${modbus_node}
${input_register_float} ${modbus_node}
${input_register_string} ${modbus_node}
${input_bit_1} ${modbus_node}
${input_bit_2} ${modbus_node}
${input_bit_3} ${modbus_node}
${input_bit_4} ${modbus_node}
${input_bit_5} ${modbus_node}
Set tags with unmatch address, type or attribute, it should be failure.
[Template] Set a ${tag} with unmatch address, type or attribute from ${node}, it will be failure and return ${resp_status} and ${error_code}.
${input_bit_1_type_unmatch} ${modbus_node} 200 ${NEU_ERR_TAG_TYPE_NOT_SUPPORT}
${input_bit_1_attribute_unmatch} ${modbus_node} 200 ${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT}
Write and Read all type tag with same slave id in hold register and coil, it should be success.
[Template] Write and Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${hold_int16} hold_int16 ${modbus_node} Compare Tag Value As Int 120
${hold_uint16} hold_uint16 ${modbus_node} Compare Tag Value As Int 65535
${hold_int32} hold_int32 ${modbus_node} Compare Tag Value As Int 77889912
${hold_uint32} hold_uint32 ${modbus_node} Compare Tag Value As Int 88991232
${hold_float} hold_float ${modbus_node} Compare Tag Value As Float 12.34
${hold_string} hold_string ${modbus_node} Compare Tag Value As Strings "abc123"
${coil_bit_1} coil_bit_1 ${modbus_node} Compare Tag Value As Int 1
${coil_bit_2} coil_bit_2 ${modbus_node} Compare Tag Value As Int 0
${coil_bit_3} coil_bit_3 ${modbus_node} Compare Tag Value As Int 0
${coil_bit_4} coil_bit_4 ${modbus_node} Compare Tag Value As Int 1
${coil_bit_5} coil_bit_5 ${modbus_node} Compare Tag Value As Int 1
Read all type tag with same slave id in input register and input, it should be success.
[Template] Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${input_register_int16} input_register_int16 ${modbus_node} Compare Tag Value As Int 0
${input_register_uint16} input_register_uint16 ${modbus_node} Compare Tag Value As Int 0
${input_register_int32} input_register_int32 ${modbus_node} Compare Tag Value As Int 0
${input_register_uint32} input_register_uint32 ${modbus_node} Compare Tag Value As Int 0
${input_register_float} input_register_float ${modbus_node} Compare Tag Value As Float 0
${input_register_string} input_register_string ${modbus_node} Compare Tag Value As Strings ""
${input_bit_1} input_bit_1 ${modbus_node} Compare Tag Value As Int 0
${input_bit_2} input_bit_2 ${modbus_node} Compare Tag Value As Int 0
${input_bit_3} input_bit_3 ${modbus_node} Compare Tag Value As Int 0
${input_bit_4} input_bit_4 ${modbus_node} Compare Tag Value As Int 0
${input_bit_5} input_bit_5 ${modbus_node} Compare Tag Value As Int 0
Read some tags at time, it will be success.
${input_register_tags}= Create List ${input_register_int16} ${input_register_uint16} ${input_register_int32} ${input_register_uint32} ${input_register_float} ${input_register_string} ${input_register_bit}
Read some ${input_register_tags} from ${modbus_node}, it will be success.
${hold_tags}= Create List ${hold_int16} ${hold_uint16} ${hold_int32} ${hold_uint32} ${hold_float} ${hold_string} ${hold_bit}
Read some ${hold_tags} from ${modbus_node}, it will be success.
${coil_tags}= Create List ${coil_bit_1} ${coil_bit_2} ${coil_bit_3} ${coil_bit_4} ${coil_bit_5}
Read some ${coil_tags} from ${modbus_node}, it will be success.
${input_tags}= Create List ${input_bit_1} ${input_bit_2} ${input_bit_3} ${input_bit_4} ${input_bit_5}
Read some ${input_tags} from ${modbus_node}, it will be success.
Write and read a tag with same name and same address that in different groups, it should be success.
${groups}= Create List group-1 group-2 group-3
Write and read a ${hold_int16} with same hold_int16 and same address in different ${groups} that from ${modbus_node}, using Compare Tag Value As Int to check the 2, it will be success.
Write and read a tag with same name but different address that in different groups, it should be success.
${groups}= Create List group-1 group-2 group-3
Write and read ${hold_int16} ${hold_int16_address_update} with same hold_int16 but different address in different ${groups} that from ${modbus_node}, using Compare Tag Value As Int to check the 2, it will be success.
Update a tag with right address and types and attribute, it will be success
[Template] Update a ${tag} by a ${tag_update} named ${tag_name} from ${node} , it can read and write, using ${check} to check the ${value}, it will be success.
${hold_int16} ${hold_int16_address_update} hold_int16 ${modbus_node} Compare Tag Value As Int 120
${hold_int16} ${hold_int16_type_update} hold_int16 ${modbus_node} Compare Tag Value As Int 120
Update a tag with unmatch address and types and attribute, it should be failure.
[Template] Update a ${tag} by a ${tag_update} with the unmatch settings from ${node} , it will be failure and return ${resp_status} and ${error_code}.
${input_bit_1} ${input_bit_1_attribute_unmatch} ${modbus_node} 200 ${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT}
${input_bit_1} ${input_bit_1_type_unmatch} ${modbus_node} 200 ${NEU_ERR_TAG_TYPE_NOT_SUPPORT}
${input_bit_1} ${input_bit_1_name_wrong} ${modbus_node} 200 ${NEU_ERR_TAG_NOT_EXIST}
Write a value to a tag that don't exit in plc or neuron, it will be failure.
[Template] Write a ${value} to a ${tag} with named ${tag_name} that don't exist in neuron or plc from ${node}, it will be failure.
12 ${input_bit_1} input ${modbus_node}
Write value to a tag without write attribute, it will be failure.
[Template] Write a ${value} to a ${tag} named ${tag_name} that without write attribute from ${node}, it will be failure.
1 ${input_bit_1} input_bit_1 ${modbus_node}
Write and read a value to a tag when the node is stoped, it will be failure.
[Template] Write and read a ${value} to a ${tag} named ${tag_name} when the ${node} is stoped, it will be failure.
1 ${hold_int16} hold_int16 ${modbus_node}
*** Keywords ***
Modbus Test Setup
Start Modbus Simulator
Start Neuronx
${res}= Add Node ${modbus_node} ${PLUGIN-MODBUS-TCP}
Check Response Status ${res} 200
${res}= Node Setting ${modbus_node} ${MODBUS_TCP_CONFIG}
Check Response Status ${res} 200
${state}= Get Node State ${modbus_node}
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
Modbus Test Teardown
Del Node ${modbus_node}
Stop Neuronx
Terminate All Processes kill=false
+86
View File
@@ -0,0 +1,86 @@
*** Settings ***
Resource resource/api.resource
Resource resource/common.resource
Resource resource/error.resource
Suite Setup Start Neuronx
Suite Teardown Stop Neuronx
*** Test Cases ***
Start an unconfigured node, it should return failure
${res}= Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Sleep 1s
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_INIT}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
${res} = Node Ctl modbus-node ${NODE_CTL_START}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_NOT_READY}
Stop node that is ready(init/idle), it should return failure
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_NOT_RUNNING}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_INIT}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
[Teardown] Del Node modbus-node
Start the configured node, it should return success
${res}= Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Sleep 1s
Node Setting modbus-node ${MODBUS_TCP_CONFIG}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_STOP}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
Stop node that is stopped, it should return failure
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_IS_STOPED}
Start the stopped node, it should return success
${res} = Node Ctl modbus-node ${NODE_CTL_START}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
Start the running node, it should return failure
${res} = Node Ctl modbus-node ${NODE_CTL_START}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_IS_RUNNING}
When setting up a READY/RUNNING/STOPED node, the node status will not change
${res} = Node Setting modbus-node ${MODBUS_TCP_CONFIG}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Node Setting modbus-node ${MODBUS_TCP_CONFIG}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_STOP}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
[Teardown] Del Node modbus-node
-52
View File
@@ -59,58 +59,6 @@ Get APP node, it should be success.
Check Response Status ${res} 200
Node Should Exist ${res}[nodes] mqtt-node
Update node name to empty string, it should fail.
${res} = Update Node modbus-node ${EMPTY}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_NODE_NAME_EMPTY}
Update node name to excessive long string, it should fail.
${name} = Evaluate 'a'*200
${res} = Update Node modbus-node ${name}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_NODE_NAME_TOO_LONG}
Update driver node name, it should fail if the node does not exist
${res} = Update Node modbus-node-nonexistent mqtt-node
Check Response Status ${res} 404
Check Error Code ${res} ${NEU_ERR_NODE_NOT_EXIST}
Update driver node name, it should fail if node name conflicts
${res} = Update Node modbus-node mqtt-node
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_EXIST}
Update node name to the same, it should fail as name conflicts
${res} = Update Node modbus-node modbus-node
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_EXIST}
${res} = Update Node mqtt-node mqtt-node
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_EXIST}
Update driver node name, it should success
${res} = Update Node modbus-node modbus-node-new
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Update Node modbus-node-new modbus-node
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Update app node name, it should success
${res} = Update Node mqtt-node mqtt-node-new
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Update Node mqtt-node-new mqtt-node
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Delete a APP node with an existing name, it should be success.
${res}= Del Node mqtt-node
+17
View File
@@ -0,0 +1,17 @@
*** Settings ***
Resource resource/api.resource
Resource resource/common.resource
Resource resource/error.resource
Suite Setup Start Neuronx
Suite Teardown Stop Neuronx
*** Test Cases ***
login with invalid username and password, it should return failure
POST /api/v2/login {"name":"admin1", "pass": "0000"}
Integer response status 401
Integer $.error ${NEU_ERR_INVALID_USER_OR_PASSWORD}
login with username and password, it should return success
POST /api/v2/login {"name":"admin", "pass": "0000"}
Integer response status 200
output $.token
+12 -102
View File
@@ -6,16 +6,14 @@ Suite Setup Neuron Context Ready
Suite Teardown Neuron Context Stop
*** Variables ***
${test_gconfig1} test_gconfig1
${test_gconfig2} test_gconfig2
${test_gconfig3} test_gconfig3
${modbus-tcp-1} modbus-tcp-1
${modbus-tcp-2} modbus-tcp-2
${modbus-tcp-3} modbus-tcp-3
${modbus-tcp-4} modbus-tcp-4
${modbus-tcp-1-new} modbus-tcp-1-new
${mqtt-1} mqtt-1
${mqtt-1-new} mqtt-1-new
${test_gconfig1} test_gconfig1
${test_gconfig2} test_gconfig2
${test_gconfig3} test_gconfig3
${modbus-tcp-1} modbus-tcp-1
${modbus-tcp-2} modbus-tcp-2
${modbus-tcp-3} modbus-tcp-3
${modbus-tcp-4} modbus-tcp-4
${mqtt-1} mqtt-1
${tag1} {"name": "tag1", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
${tag2} {"name": "tag2", "address": "1!00001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${tag3} {"name": "tag3", "address": "2!400003", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT32}}
@@ -74,9 +72,9 @@ Get the deleted adapter after stopping and restarting Neuron, it should return f
Get the setted adapters information after stopping and restarting Neuron, it should return the correct information
${process} = Neuron Start Running
Node Setting ${modbus-tcp-1} {"host": "127.0.0.1", "port": 502, "timeout": 3000, "connection_mode": 0, "transport_mode": 0, "interval": 20}
Node Setting ${modbus-tcp-2} {"host": "127.0.0.1", "port": 502, "timeout": 3000, "connection_mode": 0, "transport_mode": 0, "interval": 20}
Node Setting ${mqtt-1} {"client-id":"123456", "upload-topic":"/neuron/mqtt-1/upload", "heartbeat-topic": "/neuron/mqtt-1/heartbeat","format": 0,"cache-mem-size": 10,"cache-disk-size": 10,"ssl":false,"host":"127.0.0.1","port":1883,"username":"admin","password":"0000","ca":"", "cert":"", "key":"", "keypass":""}
Node Setting ${modbus-tcp-1} {"host": "127.0.0.1", "port": 502, "timeout": 3000}
Node Setting ${modbus-tcp-2} {"host": "127.0.0.1", "port": 502, "timeout": 3000}
Node Setting ${mqtt-1} {"upload-topic":"/neuron/mqtt-1/upload", "heartbeat-topic": "/neuron/mqtt-1/heartbeat", "format": 0, "ssl":false,"host":"127.0.0.1","port":1883,"username":"admin","password":"0000","ca":"", "cert":"", "key":"", "keypass":""}
Neuron Stop Running ${process}
${process} = Neuron Start Running
@@ -119,7 +117,7 @@ Get the setted adapters information after stopping and restarting Neuron, it sho
Get the updated adapters settings information after stopping and restarting Neuron, it should return the correct information
${process} = Neuron Start Running
Node Setting ${modbus-tcp-2} {"host": "127.0.0.1", "port": 502, "timeout": 3000, "connection_mode": 0, "transport_mode": 0, "interval": 20}
Node Setting ${modbus-tcp-2} {"host": "127.0.0.1", "port": 502, "timeout": 3000}
Neuron Stop Running ${process}
${process} = Neuron Start Running
@@ -282,94 +280,6 @@ Get the subscribed groups after stopping and restarting Neuron, it should return
[Teardown] Neuron Stop Running ${process}
Update driver name, it should keep the setting, groups, tags and subscription
${process} = Neuron Start Running
${res} = Update Node ${modbus-tcp-1} ${modbus-tcp-1-new}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Neuron Stop Running ${process}
${process} = Neuron Start Running
${res} = Get Node Setting ${modbus-tcp-1-new}
${params} = Set Variable ${res}[params]
Check Response Status ${res} 200
Should Be Equal As Strings ${res}[node] ${modbus-tcp-1-new}
Should Be Equal As Integers ${params}[port] 502
Should Be Equal As Integers ${params}[timeout] 3000
Should Be Equal As Strings ${params}[host] 127.0.0.1
${res} = Get Tags ${modbus-tcp-1-new} ${test_gconfig1}
Check Response Status ${res} 200
${len} = Get Length ${res}[tags]
Should Be Equal As Integers ${len} 2
${tag1} = Tag Find By Name ${res}[tags] tag1
Should Be Equal As Strings ${tag1}[name] tag1
Should Be Equal As Strings ${tag1}[address] 1!400002
Should Be Equal As Strings ${tag1}[attribute] ${TAG_ATTRIBUTE_READ}
Should Be Equal As Strings ${tag1}[type] ${TAG_TYPE_INT16}
${tag2} = Tag Find By Name ${res}[tags] tag2
Should Be Equal As Strings ${tag2}[name] tag2
Should Be Equal As Strings ${tag2}[address] 1!00001
Should Be Equal As Strings ${tag2}[attribute] ${TAG_ATTRIBUTE_RW}
Should Be Equal As Strings ${tag2}[type] ${TAG_TYPE_BIT}
${res} = Get Subscribe Group ${mqtt-1}
${len} = Get Length ${res}[groups]
Should Be Equal As Integers ${len} 2
Should Be Equal As Strings ${res}[groups][0][driver] ${modbus-tcp-1-new}
Should Be Equal As Strings ${res}[groups][0][group] ${test_gconfig1}
Should Be Equal As Strings ${res}[groups][1][driver] ${modbus-tcp-1-new}
Should Be Equal As Strings ${res}[groups][1][group] ${test_gconfig2}
${res} = Update Node ${modbus-tcp-1-new} ${modbus-tcp-1}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
[Teardown] Neuron Stop Running ${process}
Update app name, it should keep the setting and subscription
${process} = Neuron Start Running
${res} = Update Node ${mqtt-1} ${mqtt-1-new}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Neuron Stop Running ${process}
${process} = Neuron Start Running
${res} = Get Node Setting ${mqtt-1-new}
${params} = Set Variable ${res}[params]
Check Response Status ${res} 200
Should Be Equal As Strings ${res}[node] ${mqtt-1-new}
Should Be Equal As Strings ${params}[upload-topic] /neuron/mqtt-1/upload
Should Be Equal As Strings ${params}[heartbeat-topic] /neuron/mqtt-1/heartbeat
Should Be Equal As Integers ${params}[format] 0
Should Not Be True ${params}[ssl]
Should Be Equal As Strings ${params}[host] 127.0.0.1
Should Be Equal As Integers ${params}[port] 1883
Should Be Equal As Strings ${params}[username] admin
Should Be Equal As Strings ${params}[password] 0000
Should Be Empty ${params}[ca]
Should Be Empty ${params}[cert]
Should Be Empty ${params}[key]
Should Be Empty ${params}[keypass]
${res} = Get Subscribe Group ${mqtt-1-new}
${len} = Get Length ${res}[groups]
Should Be Equal As Integers ${len} 2
Should Be Equal As Strings ${res}[groups][0][driver] ${modbus-tcp-1}
Should Be Equal As Strings ${res}[groups][0][group] ${test_gconfig1}
Should Be Equal As Strings ${res}[groups][1][driver] ${modbus-tcp-1}
Should Be Equal As Strings ${res}[groups][1][group] ${test_gconfig2}
${res} = Update Node ${mqtt-1-new} ${mqtt-1}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
[Teardown] Neuron Stop Running ${process}
Get the unsubscribed groups after stopping ande restarting Neuron, it should return failure
${process} = Neuron Start Running
+4 -200
View File
@@ -1,11 +1,11 @@
*** Settings ***
Library REST http://127.0.0.1:7000
Library REST http://127.0.0.1:7001
Resource common.resource
*** Variables ***
${PLUGIN-MODBUS-TCP} Modbus TCP
${PLUGIN-MQTT} MQTT
${PLUGIN-EKUIPER} eKuiper
${PLUGIN-MODBUS-TCP} modbus-tcp
${PLUGIN-MQTT} mqtt
${PLUGIN-EKUIPER} ekuiper
${NODE_DRIVER} 1
${NODE_APP} 2
@@ -24,9 +24,7 @@ ${NODE_CTL_STOP} 1
${TAG_ATTRIBUTE_READ} 1
${TAG_ATTRIBUTE_WRITE} 2
${TAG_ATTRIBUTE_SUBSCRIBE} 4
${TAG_ATTRIBUTE_STATIC} 8
${TAG_ATTRIBUTE_RW} 3
${TAG_ATTRIBUTE_STATIC_RW} 11
${TAG_TYPE_INT8} 1
${TAG_TYPE_UINT8} 2
@@ -69,12 +67,6 @@ Add Node
${res} Object response body
[RETURN] ${res}[0]
Update Node
[Arguments] ${name} ${new_name}
PUT /api/v2/node {"name": "${name}", "new_name": "${new_name}"}
${res} Object response body
[RETURN] ${res}[0]
Del Node
[Arguments] ${name}
DELETE /api/v2/node {"name": "${name}"}
@@ -117,14 +109,6 @@ Add Group
${res} = Object response body
[RETURN] ${res}[0]
Update Group
[Arguments] ${node} ${group} &{updates}
${dict} = Evaluate {"node":$node, "group":$group, **$updates}
${data} = Evaluate json.dumps(${dict}) json
PUT /api/v2/group ${data}
${res} = Object response body
[RETURN] ${res}[0]
Del Group
[Arguments] ${node} ${group}
DELETE /api/v2/group {"node": "${node}", "group": "${group}"}
@@ -149,20 +133,6 @@ Unsubscribe Group
${res} = Object response body
[RETURN] ${res}[0]
Update Subscribe
[Arguments] ${app} ${driver} ${group} &{params}
${data} = Evaluate json.dumps(${params}) json
PUT /api/v2/subscribe {"app": "${app}", "driver": "${driver}", "group": "${group}", "params": ${data}}
${res} = Object response body
[RETURN] ${res}[0]
Subscribe Groups
[Arguments] ${app} @{groups}
${data} = Evaluate json.dumps(${groups}) json
POST /api/v2/subscribes {"app": "${app}", "groups": ${data}}
${res} = Object response body
[RETURN] ${res}[0]
Get Subscribe Group
[Arguments] ${app}
GET /api/v2/subscribe?app=${app}
@@ -207,169 +177,3 @@ Write Tags
POST /api/v2/write {"node": "${node}", "group": "${group}", "tag": "${tag}", "value": ${value}}
${res} = Object response body
[RETURN] ${res}[0]
Write 3 Tags 1 Time
[Arguments] ${node} ${group} ${tag1} ${value1} ${tag2} ${value2} ${tag3} ${value3}
POST /api/v2/write/tags {"node": "${node}", "group": "${group}", "tags": [{"tag": "${tag1}", "value": ${value1}}, {"tag": "${tag2}", "value": ${value2}}, {"tag": "${tag3}", "value": ${value3}}]}
${res} = Object response body
[RETURN] ${res}[0]
Add Template
[Arguments] ${name} ${plugin} ${groups}
${data} = Evaluate json.dumps(${groups}) json
POST /api/v2/template {"name": "${name}", "plugin": "${plugin}", "groups": ${data} }
${res} Object response body
[RETURN] ${res}[0]
Del Template
[Arguments] ${name}
DELETE /api/v2/template?name=${name}
${res} Object response body
[RETURN] ${res}[0]
Inst Template
[Arguments] ${name} ${node}
POST /api/v2/template/inst {"name": "${name}", "node": "${node}" }
${res} Object response body
[RETURN] ${res}[0]
Inst Templates
[Arguments] @{insts}
${data} = Evaluate json.dumps(${insts}) json
POST /api/v2/template/instances {"nodes": ${data}}
${res} Object response body
[RETURN] ${res}[0]
Get Template
[Arguments] ${name}
GET /api/v2/template?name=${name}
${res} Object response body
[RETURN] ${res}[0]
Get Templates
GET /api/v2/template
${res} Object response body
[RETURN] ${res}[0]
Add Template Group
[Arguments] ${tmpl} ${group} ${interval}
POST /api/v2/template/group {"template": "${tmpl}", "group": "${group}", "interval": ${interval}}
${res} = Object response body
[RETURN] ${res}[0]
Put Template Group
[Arguments] ${tmpl} ${group} &{updates}
${data} = Evaluate json.dumps({"template": "${tmpl}", "group": "${group}", **$updates}) json
PUT /api/v2/template/group ${data}
${res} = Object response body
[RETURN] ${res}[0]
Del Template Group
[Arguments] ${tmpl} ${group}
DELETE /api/v2/template/group {"template": "${tmpl}", "group": "${group}"}
${res} = Object response body
[RETURN] ${res}[0]
Get Template Groups
[Arguments] ${tmpl}
GET /api/v2/template/group?name=${tmpl}
${res} = Object response body
[RETURN] ${res}[0]
Add Template Tags
[Arguments] ${tmpl} ${group} @{tags}
${data} = Evaluate json.dumps(${tags}) json
POST /api/v2/template/tag {"template": "${tmpl}", "group": "${group}", "tags": ${data}}
${res} = Object response body
[RETURN] ${res}[0]
Get Template Tags
[Arguments] ${tmpl} ${group}
GET /api/v2/template/tag?template=${tmpl}&group=${group}
${res} = Object response body
[RETURN] ${res}[0]
Grep Template Tags
[Arguments] ${tmpl} ${group} ${pattern}
GET /api/v2/template/tag?template=${tmpl}&group=${group}&name=${pattern}
${res} = Object response body
[RETURN] ${res}[0]
Put Template Tags
[Arguments] ${tmpl} ${group} @{tags}
${data} = Evaluate json.dumps(${tags}) json
PUT /api/v2/template/tag {"template": "${tmpl}", "group": "${group}", "tags": ${data}}
${res} = Object response body
[RETURN] ${res}[0]
Del Template Tags
[Arguments] ${tmpl} ${group} @{tags}
${data} = Evaluate json.dumps(${tags}) json
DELETE /api/v2/template/tag {"template": "${tmpl}", "group": "${group}", "tags": ${data}}
${res} = Object response body
[RETURN] ${res}[0]
Get all metrics
GET /api/v2/metrics
${res} = String response body
[RETURN] ${res}
Get single node metrics
[Arguments] ${node_name} ${category}
GET /api/v2/metrics?node=${node_name}&category=${category}
${res} = String response body
[RETURN] ${res}
Get metrics lines
${lines}= Get all metrics
${lines_str}= Convert To String ${lines}
${lines_str} Evaluate str(${lines_str}).strip('[]')
${lines_str} Evaluate str(${lines_str}).strip(\"'\")
${nlines}= Split String ${lines_str} \n
Remove From List ${nlines} -1
[RETURN] ${nlines}
Get parameter lines
[Arguments] ${nlines}
${description_lines} Create List
${parameter_lines} Create List
FOR ${line} IN @{nlines}
${first_char}= Get Substring ${line} 0 1
IF "${first_char}"=="#"
Append To List ${description_lines} ${line}
ELSE
Append To List ${parameter_lines} ${line}
END
END
[RETURN] ${parameter_lines}
Check endswith isdigit
[Arguments] ${parameter_lines}
FOR ${line} IN @{parameter_lines}
${last_char}= Get Substring ${line} -1
Should Be True '${last_char}'.isdigit()
END
Check node state
[Arguments] ${parameter_lines} ${node}
${link_state} Create List
${running_state} Create List
${node_state}= Get Node State ${node}
FOR ${line} IN @{parameter_lines}
${param}= Get Substring ${line} 0 10
IF "${param}"=="link_state"
Append To List ${link_state} ${line}
END
IF "${param}"=="running_st"
Append To List ${running_state} ${line}
END
END
${metrics_link}= Get Substring ${link_state}[0] -1
${metrics_link}= Convert To Integer ${metrics_link}
Should Be Equal As Integers ${metrics_link} ${node_state}[link]
${metrics_running}= Get Substring ${running_state}[0] -1
${metrics_running}= Convert To Integer ${metrics_running}
Should Be Equal As Integers ${metrics_running} ${node_state}[running]
+1 -1
View File
@@ -1,7 +1,7 @@
*** Settings ***
Library Collections
Library Keyword.MQTT.Client reconnect_retries=5 reconnect_delay=0
Library REST http://127.0.0.1:7000
Library REST http://127.0.0.1:7001
Resource common.resource
*** Keywords ***
+4 -10
View File
@@ -17,9 +17,8 @@ Resource simulator.resource
${test_data_dir} ft/data
${PLUGIN_MODBUS_TCP} Modbus TCP
${PLUGIN_MONITOR} Monitor
${PLUGIN_MQTT} MQTT
${PLUGIN_MODBUS_TCP} modbus-tcp
${PLUGIN_MQTT} mqtt
${MQTT_CMD_NONE}
@@ -40,12 +39,12 @@ ${MQTT_CONFIG} {"client-id": "${MQTT_CLIENTID}", "u
... "ssl": false, "host": "${MQTT_CONFIG_HOST}", "port": ${MQTT_CONFIG_PORT},
... "username": "", "password": "", "ca":"", "cert":"", "key":"", "keypass":""}
${MODBUS_TCP_CONFIG} {"host": "127.0.0.1", "port": 60502, "connection_mode": 0, "transport_mode": 0, "timeout": 3000, "interval": 20}
${MODBUS_TCP_CONFIG} {"host": "127.0.0.1", "port": 60502, "timeout": 3000}
*** Variables ***
${neuron_process}
${MODBUS_PLUS_TCP_CONFIG} {"host": "127.0.0.1", "port": 60502, "connection_mode": 0, "transport_mode": 0, "timeout": 3000}
${MODBUS_PLUS_TCP_CONFIG} {"host": "127.0.0.1", "port": 60502, "connection_mode": 0, "timeout": 3000}
*** Keywords ***
Start Neuronx
@@ -71,11 +70,6 @@ Neuron Ready
Start Neuron
Sleep 3
List Length Should Be
[Arguments] ${data} ${len}
${res} = Get Length ${data}
Should Be Equal As Integers ${len} ${res}
Compare Tag Value As Bool
[Arguments] ${tags} ${name} ${value}
+9 -39
View File
@@ -70,9 +70,13 @@ Read some ${tags} from ${node}, it will be success.
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res}= Add Tags ${node} group ${tags}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Log ${tags}
FOR ${tag} IN @{tags}
${res}= Add Tags ${node} group ${tag}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
END
Sleep 290ms
${res}= Read Tags ${node} group
@@ -234,7 +238,7 @@ Write a ${value} to a ${tag} with named ${tag_name} that don't exist in neuron o
[Teardown] Del Group ${node} group
Read a ${tag} with named ${tag_name} that don't exist in plc form ${node}, it will be failure ${error}.
Read a ${tag} with named ${tag_name} that don't exist in plc form ${node}, it will be failure.
[Tags] Driver 15
${res}= Add Group ${node} group 100
@@ -248,7 +252,7 @@ Read a ${tag} with named ${tag_name} that don't exist in plc form ${node}, it wi
Sleep 290ms
${res}= Read Tags ${node} group
Check Response Status ${res} 200
Check Tag Error As Int ${res}[tags] ${tag_name} ${error}
Check Tag Error As Int ${res} ${tag_name} ${NEU_ERR_TAG_NOT_EXIST}
[Teardown] Del Group ${node} group
@@ -293,37 +297,3 @@ Write and read a ${value} to a ${tag} named ${tag_name} when the ${node} is stop
Check Tag Error As Int ${res}[tags] ${tag_name} ${NEU_ERR_PLUGIN_NOT_RUNNING}
[Teardown] Del Group ${node} group
Write and Read ${tag_data1}, ${tag_data2} and ${tag_data3} named ${tag1}, ${tag2} and ${tag3} from ${node}, using ${check} to check the ${value1}, ${value2} and ${value3}, it will be success.
[Tags] Driver 18
${res}= Add Group ${node} group 100
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res}= Add Tags ${node} group ${tag_data1}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res}= Add Tags ${node} group ${tag_data2}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res}= Add Tags ${node} group ${tag_data3}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Sleep 290ms
${res}= Write 3 Tags 1 Time ${node} group ${tag1} ${value1} ${tag2} ${value2} ${tag3} ${value3}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Sleep 100ms
${res}= Read Tags ${node} group
Check Response Status ${res} 200
Run Keyword ${check} ${res}[tags] ${tag1} ${value1}
Run Keyword ${check} ${res}[tags] ${tag2} ${value2}
Run Keyword ${check} ${res}[tags] ${tag3} ${value3}
[Teardown] Del Group ${node} group
+63 -91
View File
@@ -1,99 +1,71 @@
*** Variables ***
${NEU_ERR_SUCCESS} 0
${NEU_ERR_SUCCESS} 0
${NEU_ERR_FAILURE} 1000
${NEU_ERR_EINTERNAL} 1001
${NEU_ERR_BODY_IS_WRONG} 1002
${NEU_ERR_PARAM_IS_WRONG} 1003
${NEU_ERR_NEED_TOKEN} 1004
${NEU_ERR_DECODE_TOKEN} 1005
${NEU_ERR_EXPIRED_TOKEN} 1006
${NEU_ERR_VALIDATE_TOKEN} 1007
${NEU_ERR_INVALID_TOKEN} 1008
${NEU_ERR_INVALID_USER_OR_PASSWORD} 1009
${NEU_ERR_IS_BUSY} 1010
${NEU_ERR_FILE_NOT_EXIST} 1011
${NEU_ERR_INVALID_PASSWORD_LEN} 1012
${NEU_ERR_DUPLICATE_PASSWORD} 1013
${NEU_ERR_COMMAND_EXECUTION_FAILED} 1014
${NEU_ERR_IP_ADDRESS_INVALID} 1015
${NEU_ERR_IP_ADDRESS_IN_USE} 1016
${NEU_ERR_INVALID_USER} 1017
${NEU_ERR_INVALID_PASSWORD} 1018
${NEU_ERR_FAILURE} 1000
${NEU_ERR_EINTERNAL} 1001
${NEU_ERR_BODY_IS_WRONG} 1002
${NEU_ERR_PARAM_IS_WRONG} 1003
${NEU_ERR_NEED_TOKEN} 1004
${NEU_ERR_DECODE_TOKEN} 1005
${NEU_ERR_EXPIRED_TOKEN} 1006
${NEU_ERR_VALIDATE_TOKEN} 1007
${NEU_ERR_INVALID_TOKEN} 1008
${NEU_ERR_INVALID_USER_OR_PASSWORD} 1009
${NEU_ERR_IS_BUSY} 1010
${NEU_ERR_NODE_EXIST} 2002
${NEU_ERR_NODE_NOT_EXIST} 2003
${NEU_ERR_NODE_SETTING_INVALID} 2004
${NEU_ERR_NODE_SETTING_NOT_FOUND} 2005
${NEU_ERR_NODE_NOT_READY} 2006
${NEU_ERR_NODE_IS_RUNNING} 2007
${NEU_ERR_NODE_NOT_RUNNING} 2008
${NEU_ERR_NODE_IS_STOPED} 2009
${NEU_ERR_NODE_NAME_TOO_LONG} 2010
${NEU_ERR_NODE_NOT_ALLOW_DELETE} 2011
${NEU_ERR_NODE_EXIST} 2002
${NEU_ERR_NODE_NOT_EXIST} 2003
${NEU_ERR_NODE_SETTING_INVALID} 2004
${NEU_ERR_NODE_SETTING_NOT_FOUND} 2005
${NEU_ERR_NODE_NOT_READY} 2006
${NEU_ERR_NODE_IS_RUNNING} 2007
${NEU_ERR_NODE_NOT_RUNNING} 2008
${NEU_ERR_NODE_IS_STOPED} 2009
${NEU_ERR_NODE_NAME_TOO_LONG} 2010
${NEU_ERR_NODE_NOT_ALLOW_DELETE} 2011
${NEU_ERR_NODE_NOT_ALLOW_SUBSCRIBE} 2012
${NEU_ERR_NODE_NOT_ALLOW_UPDATE} 2013
${NEU_ERR_NODE_NOT_ALLOW_MAP} 2014
${NEU_ERR_NODE_NAME_EMPTY} 2015
${NEU_ERR_GROUP_ALREADY_SUBSCRIBED} 2101
${NEU_ERR_GROUP_NOT_SUBSCRIBE} 2102
${NEU_ERR_GROUP_NOT_ALLOW} 2103
${NEU_ERR_GROUP_EXIST} 2104
${NEU_ERR_GROUP_PARAMETER_INVALID} 2105
${NEU_ERR_GROUP_NOT_EXIST} 2106
${NEU_ERR_GROUP_NAME_TOO_LONG} 2107
${NEU_ERR_GROUP_ALREADY_SUBSCRIBED} 2101
${NEU_ERR_GROUP_NOT_SUBSCRIBE} 2102
${NEU_ERR_GROUP_NOT_ALLOW} 2103
${NEU_ERR_GROUP_EXIST} 2104
${NEU_ERR_GROUP_PARAMETER_INVALID} 2105
${NEU_ERR_GROUP_NOT_EXIST} 2106
${NEU_ERR_GROUP_NAME_TOO_LONG} 2107
${NEU_ERR_TAG_NOT_EXIST} 2201
${NEU_ERR_TAG_NAME_CONFLICT} 2202
${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT} 2203
${NEU_ERR_TAG_TYPE_NOT_SUPPORT} 2204
${NEU_ERR_TAG_ADDRESS_FORMAT_INVALID} 2205
${NEU_ERR_TAG_NAME_TOO_LONG} 2206
${NEU_ERR_TAG_ADDRESS_TOO_LONG} 2207
${NEU_ERR_TAG_DESCRIPTION_TOO_LONG} 2208
${NEU_ERR_TAG_PRECISION_INVALID} 2209
${NEU_ERR_TAG_NOT_EXIST} 2201
${NEU_ERR_TAG_NAME_CONFLICT} 2202
${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT} 2203
${NEU_ERR_TAG_TYPE_NOT_SUPPORT} 2204
${NEU_ERR_TAG_ADDRESS_FORMAT_INVALID} 2205
${NEU_ERR_TAG_NAME_TOO_LONG} 2206
${NEU_ERR_TAG_ADDRESS_TOO_LONG} 2207
${NEU_ERR_TAG_DESCRIPTION_TOO_LONG} 2208
${NEU_ERR_TAG_PRECISION_INVALID} 2209
${NEU_ERR_TAG_EXIST} 2210
${NEU_ERR_LIBRARY_NOT_FOUND} 2301
${NEU_ERR_LIBRARY_INFO_INVALID} 2302
${NEU_ERR_LIBRARY_NAME_CONFLICT} 2303
${NEU_ERR_LIBRARY_FAILED_TO_OPEN} 2304
${NEU_ERR_LIBRARY_MODULE_INVALID} 2305
${NEU_ERR_LIBRARY_SYSTEM_NOT_ALLOW_DEL} 2306
${NEU_ERR_LIBRARY_NOT_ALLOW_CREATE_INSTANCE} 2307
${NEU_ERR_LIBRARY_NOT_FOUND} 2301
${NEU_ERR_LIBRARY_INFO_INVALID} 2302
${NEU_ERR_LIBRARY_NAME_CONFLICT} 2303
${NEU_ERR_LIBRARY_FAILED_TO_OPEN} 2304
${NEU_ERR_LIBRARY_MODULE_INVALID} 2305
${NEU_ERR_LIBRARY_SYSTEM_NOT_ALLOW_DEL} 2306
${NEU_ERR_LIBRARY_NOT_ALLOW_CREATE_INSTANCE} 2307
${NEU_ERR_LIBRARY_ARCH_NOT_SUPPORT} 2308
${NEU_ERR_LICENSE_NOT_FOUND} 2400
${NEU_ERR_LICENSE_INVALID} 2401
${NEU_ERR_LICENSE_EXPIRED} 2402
${NEU_ERR_LICENSE_DISABLED} 2403
${NEU_ERR_LICENSE_MAX_NODES} 2404
${NEU_ERR_LICENSE_MAX_TAGS} 2405
${NEU_ERR_LICENSE_TOKEN_NOT_MATCH} 2406
${NEU_ERR_LICENSE_NOT_FOUND} 2400
${NEU_ERR_LICENSE_INVALID} 2401
${NEU_ERR_LICENSE_EXPIRED} 2402
${NEU_ERR_LICENSE_DISABLED} 2403
${NEU_ERR_LICENSE_MAX_NODES} 2404
${NEU_ERR_LICENSE_MAX_TAGS} 2405
${NEU_ERR_LICENSE_TOKEN_NOT_MATCH} 2406
${NEU_ERR_LICENSE_BAD_CLOCK} 2407
${NEU_ERR_LICENSE_MODULE_INVALID} 2408
${NEU_ERR_TEMPLATE_EXIST} 2500
${NEU_ERR_TEMPLATE_NOT_FOUND} 2501
${NEU_ERR_TEMPLATE_NAME_TOO_LONG} 2502
${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_MQTT_SUBSCRIBE_FAILURE} 4010
${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
+1 -1
View File
@@ -8,7 +8,7 @@ ${OPCUA_SERVER_SIMULATOR} ./opcua_simulator
*** Keywords ***
Start Modbus Simulator
${handle} = Start Process ${MODBUS_TCP_SERVER_SIMULATOR} tcp 60502 ip_v4 cwd=build/simulator
${handle} = Start Process ${MODBUS_TCP_SERVER_SIMULATOR} tcp 60502 cwd=build/simulator
[Return] ${handle}
Start Simulator Arg
-44
View File
@@ -24,49 +24,6 @@ North APP subscribe existent group, it should return success
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
North APP update subscribe nonexistent group, it should return success
${res}= Update Subscribe mqtt modbus-node group1 topic=/neuron
Check Response Status ${res} 404
Check Error Code ${res} ${NEU_ERR_GROUP_NOT_SUBSCRIBE}
North APP update subscribe existent group, it should return success
${res}= Update Subscribe mqtt modbus-node group topic=/neuron
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
North APP subscribe multiple nonexistent groups, it should fail.
${g1} = Evaluate {"driver":"modbus-node", "group": "group1"}
${g2} = Evaluate {"driver": "modbus-node", "group": "group2", "params":{"topic":"/neuron"}}
${res}= Subscribe Groups mqtt ${g1} ${g2}
Check Response Status ${res} 404
Check Error Code ${res} ${NEU_ERR_GROUP_NOT_EXIST}
North MQTT APP subscribe with empty topic, it should fail.
${g1} = Evaluate {"driver": "modbus-node", "group": "group1", "params":{"topic":""}}
${res}= Subscribe Groups mqtt ${g1}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_MQTT_SUBSCRIBE_FAILURE}
North APP subscribe multiple groups, it should return success
Add Group modbus-node group1 1000
Add Group modbus-node group2 1000
${g1} = Evaluate {"driver":"modbus-node", "group": "group1"}
${g2} = Evaluate {"driver": "modbus-node", "group": "group2", "params":{"topic":"/neuron"}}
${res}= Subscribe Groups mqtt ${g1} ${g2}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
[Teardown] Run Keywords Del Group modbus-node group1
... AND Del Group modbus-node group2
Query the subscribers of the group, it should return all nodes subscribed to this group
${res} = Get Subscribe Group mqtt
Check Response Status ${res} 200
@@ -75,7 +32,6 @@ Query the subscribers of the group, it should return all nodes subscribed to thi
Should Be Equal As Integers ${len} 1
Should Be Equal As Strings ${res}[groups][0][driver] modbus-node
Should Be Equal As Strings ${res}[groups][0][group] group
Should Be Equal As Strings ${res}[groups][0][params][topic] /neuron
Add Group modbus-node group1 1000
Subscribe Group mqtt modbus-node group1
+5 -75
View File
@@ -11,11 +11,7 @@ ${tag2} {"name": "tag2", "address": "1!00001", "attribute": ${TAG_AT
${tag3} {"name": "tag3", "address": "1!00001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT16}}
${tag4} {"name": "tag4", "address": "1!00031", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${tag1update} {"name": "tag1", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}}
${tag_desc} {"name": "tag_desc", "description": "description info", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
${tag1_static} {"name": "tag1", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_INT16}, "value": 1}
${tag1_static_no_value} {"name": "tag1", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_INT16}}
${tag_decimal} {"name": "tag_decimal", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}, "decimal": 0.1}
${tag_desc} {"name": "tag_desc", "description": "description info", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
*** Test Cases ***
Add tags to non-existent node, it should return failure
@@ -32,22 +28,6 @@ Add tags to the non-existent group, it should return success
Check Error Code ${res} ${NEU_ERR_SUCCESS}
[Teardown] Del Tags modbus-node group "tag1","tag2"
Add static tag, it should return success.
${res}= Add Tags modbus-node group ${tag1_static}
Check Response Status ${res} 200
Check Error Code ${res} 0
[Teardown] Del Tags modbus-node group "tag1"
Add static tag without value, it should fail.
${res}= Add Tags modbus-node group ${tag1_static_no_value}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_BODY_IS_WRONG}
[Teardown] Del Tags modbus-node group "tag1"
Add different types of tags to the group, it should return success
Add Group modbus-node group 5000
${res}= Add Tags modbus-node group ${tag1},${tag2}
@@ -59,7 +39,7 @@ Add different types of tags to the group, it should return success
Add a list of tags with errors, it should return the number of successful additions.
${res}= Add Tags modbus-node group ${tag1},${tag2},${tag3},${tag4}
Check Response Status ${res} 409
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_TAG_NAME_CONFLICT}
Should Be Equal As Integers ${res}[index] 0
@@ -80,34 +60,6 @@ Get tag list from modbus-node, it should return success.
Should Be Equal As Strings ${res}[tags][1][attribute] ${TAG_ATTRIBUTE_RW}
Should Be Equal As Strings ${res}[tags][1][type] ${TAG_TYPE_BIT}
Update tag to be static, it should return success.
${res}= Update Tags modbus-node group ${tag1_static}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res}= Get Tags modbus-node group
Check Response Status ${res} 200
${len} = Get Length ${res}[tags]
Should Be Equal As Integers ${len} 2
Should Be Equal As Strings ${res}[tags][0][name] tag1
Should Be Equal As Strings ${res}[tags][0][address] 1!400001
Should Be Equal As Strings ${res}[tags][0][attribute] ${TAG_ATTRIBUTE_STATIC_RW}
Should Be Equal As Strings ${res}[tags][0][type] ${TAG_TYPE_INT16}
Should Be Equal As Strings ${res}[tags][1][name] tag2
Should Be Equal As Strings ${res}[tags][1][address] 1!00001
Should Be Equal As Strings ${res}[tags][1][attribute] ${TAG_ATTRIBUTE_RW}
Should Be Equal As Strings ${res}[tags][1][type] ${TAG_TYPE_BIT}
Update static tag without value, it should fail.
${res}= Update Tags modbus-node group ${tag1_static_no_value}
Check Response Status ${res} 400
Check Error Code ${res} ${NEU_ERR_BODY_IS_WRONG}
Update tag, it should return success.
${res}= Update Tags modbus-node group ${tag1update}
@@ -133,13 +85,13 @@ Update tag, it should return success.
Delete tag from non-existent group, it should return success
${res}= Del Tags modbus-node group1 "tag1"
Check Response Status ${res} 404
Check Error Code ${res} ${NEU_ERR_GROUP_NOT_EXIST}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Update non-existent tag, it should return failure.
${res}= Update Tags modbus-node group ${tag4}
Check Response Status ${res} 404
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_TAG_NOT_EXIST}
${res}= Get Tags modbus-node group
@@ -185,25 +137,3 @@ Add a tag with description, it should return success
Should Be Equal As Strings ${res}[tags][0][description] description info
Should Be Equal As Strings ${res}[tags][0][attribute] ${TAG_ATTRIBUTE_READ}
Should Be Equal As Strings ${res}[tags][0][type] ${TAG_TYPE_INT16}
[Teardown] Del Tags modbus-node group "tag_desc"
Add a tag with decimal, it should return success
${res}= Add Tags modbus-node group ${tag_decimal}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
Should Be Equal As Integers ${res}[index] 1
${res}= Get Tags modbus-node group
Check Response Status ${res} 200
${len} = Get Length ${res}[tags]
Should Be Equal As Integers ${len} 1
Should Be Equal As Strings ${res}[tags][0][name] tag_decimal
Should Be Equal As Strings ${res}[tags][0][address] 1!400003
Should Be Equal As Strings ${res}[tags][0][decimal] 0.1
Should Be Equal As Strings ${res}[tags][0][attribute] ${TAG_ATTRIBUTE_RW}
Should Be Equal As Strings ${res}[tags][0][type] ${TAG_TYPE_INT16}
+399 -23
View File
@@ -26,45 +26,421 @@ extern "C" {
#include <stdint.h>
#include <sys/un.h>
#include "define.h"
#include "metrics.h"
#include "msg.h"
#include "tag.h"
#include "type.h"
typedef struct {
neu_node_running_state_e running;
neu_node_link_state_e link;
} neu_node_state_t;
typedef enum neu_reqresp_type {
NEU_RESP_ERROR,
NEU_REQ_UPDATE_LICENSE,
NEU_REQ_READ_GROUP,
NEU_RESP_READ_GROUP,
NEU_REQ_WRITE_TAG,
NEU_REQ_SUBSCRIBE_GROUP,
NEU_REQ_UNSUBSCRIBE_GROUP,
NEU_REQ_GET_SUBSCRIBE_GROUP,
NEU_RESP_GET_SUBSCRIBE_GROUP,
NEU_REQ_GET_SUB_DRIVER_TAGS,
NEU_RESP_GET_SUB_DRIVER_TAGS,
NEU_REQ_NODE_INIT,
NEU_REQ_NODE_UNINIT,
NEU_RESP_NODE_UNINIT,
NEU_REQ_ADD_NODE,
NEU_REQ_DEL_NODE,
NEU_REQ_GET_NODE,
NEU_RESP_GET_NODE,
NEU_REQ_NODE_SETTING,
NEU_REQ_GET_NODE_SETTING,
NEU_RESP_GET_NODE_SETTING,
NEU_REQ_GET_NODE_STATE,
NEU_RESP_GET_NODE_STATE,
NEU_REQ_GET_NODES_STATE,
NEU_RESP_GET_NODES_STATE,
NEU_REQ_NODE_CTL,
NEU_REQ_ADD_GROUP,
NEU_REQ_DEL_GROUP,
NEU_REQ_UPDATE_GROUP,
NEU_REQ_GET_GROUP,
NEU_RESP_GET_GROUP,
NEU_REQ_GET_DRIVER_GROUP,
NEU_RESP_GET_DRIVER_GROUP,
NEU_REQ_ADD_TAG,
NEU_RESP_ADD_TAG,
NEU_REQ_DEL_TAG,
NEU_REQ_UPDATE_TAG,
NEU_RESP_UPDATE_TAG,
NEU_REQ_GET_TAG,
NEU_RESP_GET_TAG,
NEU_REQ_ADD_PLUGIN,
NEU_REQ_DEL_PLUGIN,
NEU_REQ_GET_PLUGIN,
NEU_RESP_GET_PLUGIN,
NEU_REQRESP_TRANS_DATA,
NEU_REQRESP_NODES_STATE,
NEU_REQRESP_NODE_DELETED,
} neu_reqresp_type_e;
typedef enum {
NEU_SUBSCRIBE_NODES_STATE = NEU_REQRESP_NODES_STATE,
} neu_subscribe_type_e;
static const char *neu_reqresp_type_string_t[] = {
[NEU_RESP_ERROR] = "NEU_RESP_ERROR",
[NEU_REQ_UPDATE_LICENSE] = "NEU_REQ_UPDATE_LICENSE",
[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_SUBSCRIBE_GROUP] = "NEU_REQ_SUBSCRIBE_GROUP",
[NEU_REQ_UNSUBSCRIBE_GROUP] = "NEU_REQ_UNSUBSCRIBE_GROUP",
[NEU_REQ_GET_SUBSCRIBE_GROUP] = "NEU_REQ_GET_SUBSCRIBE_GROUP",
[NEU_RESP_GET_SUBSCRIBE_GROUP] = "NEU_RESP_GET_SUBSCRIBE_GROUP",
[NEU_REQ_GET_SUB_DRIVER_TAGS] = "NEU_REQ_GET_SUB_DRIVER_TAGS",
[NEU_RESP_GET_SUB_DRIVER_TAGS] = "NEU_RESP_GET_SUB_DRIVER_TAGS",
[NEU_REQ_NODE_INIT] = "NEU_REQ_NODE_INIT",
[NEU_REQ_NODE_UNINIT] = "NEU_REQ_NODE_UNINIT",
[NEU_RESP_NODE_UNINIT] = "NEU_RESP_NODE_UNINIT",
[NEU_REQ_ADD_NODE] = "NEU_REQ_ADD_NODE",
[NEU_REQ_DEL_NODE] = "NEU_REQ_DEL_NODE",
[NEU_REQ_GET_NODE] = "NEU_REQ_GET_NODE",
[NEU_RESP_GET_NODE] = "NEU_RESP_GET_NODE",
[NEU_REQ_NODE_SETTING] = "NEU_REQ_NODE_SETTING",
[NEU_REQ_GET_NODE_SETTING] = "NEU_REQ_GET_NODE_SETTING",
[NEU_RESP_GET_NODE_SETTING] = "NEU_RESP_GET_NODE_SETTING",
[NEU_REQ_GET_NODE_STATE] = "NEU_REQ_GET_NODE_STATE",
[NEU_RESP_GET_NODE_STATE] = "NEU_RESP_GET_NODE_STATE",
[NEU_REQ_GET_NODES_STATE] = "NEU_REQ_GET_NODES_STATE",
[NEU_RESP_GET_NODES_STATE] = "NEU_RESP_GET_NODES_STATE",
[NEU_REQ_NODE_CTL] = "NEU_REQ_NODE_CTL",
[NEU_REQ_ADD_GROUP] = "NEU_REQ_ADD_GROUP",
[NEU_REQ_DEL_GROUP] = "NEU_REQ_DEL_GROUP",
[NEU_REQ_UPDATE_GROUP] = "NEU_REQ_UPDATE_GROUP",
[NEU_REQ_GET_GROUP] = "NEU_REQ_GET_GROUP",
[NEU_RESP_GET_GROUP] = "NEU_RESP_GET_GROUP",
[NEU_REQ_GET_DRIVER_GROUP] = "NEU_REQ_GET_DRIVER_GROUP",
[NEU_RESP_GET_DRIVER_GROUP] = "NEU_RESP_GET_DRIVER_GROUP",
[NEU_REQ_ADD_TAG] = "NEU_REQ_ADD_TAG",
[NEU_RESP_ADD_TAG] = "NEU_RESP_ADD_TAG",
[NEU_REQ_DEL_TAG] = "NEU_REQ_DEL_TAG",
[NEU_REQ_UPDATE_TAG] = "NEU_REQ_UPDATE_TAG",
[NEU_RESP_UPDATE_TAG] = "NEU_RESP_UPDATE_TAG",
[NEU_REQ_GET_TAG] = "NEU_REQ_GET_TAG",
[NEU_RESP_GET_TAG] = "NEU_RESP_GET_TAG",
[NEU_REQ_ADD_PLUGIN] = "NEU_REQ_ADD_PLUGIN",
[NEU_REQ_DEL_PLUGIN] = "NEU_REQ_DEL_PLUGIN",
[NEU_REQ_GET_PLUGIN] = "NEU_REQ_GET_PLUGIN",
[NEU_RESP_GET_PLUGIN] = "NEU_RESP_GET_PLUGIN",
[NEU_REQRESP_TRANS_DATA] = "NEU_REQRESP_TRANS_DATA",
[NEU_REQRESP_NODES_STATE] = "NEU_REQRESP_NODES_STATE",
[NEU_REQRESP_NODE_DELETED] = "NEU_REQRESP_NODE_DELETED",
};
inline static const char *neu_reqresp_type_string(neu_reqresp_type_e type)
{
return neu_reqresp_type_string_t[type];
}
typedef struct neu_reqresp_head {
neu_reqresp_type_e type;
void * ctx;
char sender[NEU_NODE_NAME_LEN];
char receiver[NEU_NODE_NAME_LEN];
} neu_reqresp_head_t;
typedef struct neu_resp_error {
int error;
} neu_resp_error_t;
typedef struct {
char node[NEU_NODE_NAME_LEN];
bool auto_start;
} neu_req_node_init_t, neu_req_node_uninit_t, neu_resp_node_uninit_t;
typedef struct neu_req_add_plugin {
char library[NEU_PLUGIN_LIBRARY_LEN];
} neu_req_add_plugin_t;
typedef struct neu_req_del_plugin {
char plugin[NEU_PLUGIN_NAME_LEN];
} neu_req_del_plugin_t;
typedef struct neu_req_get_plugin {
} neu_req_get_plugin_t;
typedef struct neu_resp_plugin_info {
char name[NEU_PLUGIN_NAME_LEN];
char description[NEU_PLUGIN_DESCRIPTION_LEN];
char library[NEU_PLUGIN_LIBRARY_LEN];
neu_plugin_kind_e kind;
neu_node_type_e type;
bool single;
bool display;
char single_name[NEU_NODE_NAME_LEN];
} neu_resp_plugin_info_t;
typedef struct neu_resp_get_plugin {
UT_array *plugins; // array neu_resp_plugin_info_t
} neu_resp_get_plugin_t;
typedef struct neu_req_add_node {
char node[NEU_NODE_NAME_LEN];
char plugin[NEU_PLUGIN_NAME_LEN];
} neu_req_add_node_t;
typedef struct neu_req_del_node {
char node[NEU_NODE_NAME_LEN];
} neu_req_del_node_t;
typedef struct neu_req_get_node {
neu_node_type_e type;
} neu_req_get_node_t;
typedef struct neu_resp_node_info {
char node[NEU_NODE_NAME_LEN];
char plugin[NEU_PLUGIN_NAME_LEN];
} neu_resp_node_info_t;
typedef struct neu_resp_get_node {
UT_array *nodes; // array neu_resp_node_info_t
} neu_resp_get_node_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
uint32_t interval;
} neu_req_add_group_t, neu_req_update_group_t;
typedef struct neu_req_del_group {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
} neu_req_del_group_t;
typedef struct neu_req_get_group {
char driver[NEU_NODE_NAME_LEN];
} neu_req_get_group_t;
typedef struct neu_resp_group_info {
char name[NEU_GROUP_NAME_LEN];
uint16_t tag_count;
uint32_t interval;
} neu_resp_group_info_t;
typedef struct neu_resp_get_group {
UT_array *groups; // array neu_resp_group_info_t
} neu_resp_get_group_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
uint16_t tag_count;
uint32_t interval;
} neu_resp_driver_group_info_t;
typedef struct {
UT_array *groups; // array neu_resp_driver_group_info_t
} neu_resp_get_driver_group_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
uint16_t n_tag;
neu_datatag_t *tags;
} neu_req_add_tag_t, neu_req_update_tag_t;
typedef struct {
uint16_t index;
int error;
} neu_resp_add_tag_t, neu_resp_update_tag_t;
typedef struct neu_req_del_tag {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
uint16_t n_tag;
char ** tags;
} neu_req_del_tag_t;
typedef struct neu_req_get_tag {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
} neu_req_get_tag_t;
typedef struct neu_resp_get_tag {
UT_array *tags; // array neu_datatag_t
} neu_resp_get_tag_t;
typedef struct {
char app[NEU_NODE_NAME_LEN];
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
} neu_req_subscribe_t, neu_req_unsubscribe_t;
typedef struct neu_req_get_subscribe_group {
char app[NEU_NODE_NAME_LEN];
} neu_req_get_subscribe_group_t, neu_req_get_sub_driver_tags_t;
typedef struct neu_resp_subscribe_info {
char app[NEU_NODE_NAME_LEN];
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
} neu_resp_subscribe_info_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
UT_array *tags;
} neu_resp_get_sub_driver_tags_info_t;
inline static UT_icd *neu_resp_get_sub_driver_tags_info_icd()
{
static UT_icd icd = { sizeof(neu_resp_get_sub_driver_tags_info_t), NULL,
NULL, NULL };
return &icd;
}
typedef struct {
UT_array *infos; // array neu_resp_get_sub_driver_tags_info_t
} neu_resp_get_sub_driver_tags_t;
typedef struct neu_resp_get_subscribe_group {
UT_array *groups; // array neu_resp_subscribe_info_t
} neu_resp_get_subscribe_group_t;
typedef struct neu_req_node_setting {
char node[NEU_NODE_NAME_LEN];
char *setting;
} neu_req_node_setting_t;
typedef struct neu_req_get_node_setting {
char ndoe[NEU_NODE_NAME_LEN];
} neu_req_get_node_setting_t;
typedef struct neu_resp_get_node_setting {
char *setting;
} neu_resp_get_node_setting_t;
typedef enum neu_adapter_ctl {
NEU_ADAPTER_CTL_START = 0,
NEU_ADAPTER_CTL_STOP,
} neu_adapter_ctl_e;
typedef struct neu_req_node_ctl {
char node[NEU_NODE_NAME_LEN];
neu_adapter_ctl_e ctl;
} neu_req_node_ctl_t;
typedef struct neu_req_get_node_state {
char node[NEU_NODE_NAME_LEN];
} neu_req_get_node_state_t;
typedef struct neu_resp_get_node_state {
neu_node_state_t state;
} neu_resp_get_node_state_t;
typedef struct neu_req_get_nodes_state {
} neu_req_get_nodes_state_t;
typedef struct {
char node[NEU_NODE_NAME_LEN];
neu_node_state_t state;
} neu_nodes_state_t;
inline static UT_icd neu_nodes_state_t_icd()
{
UT_icd icd = { sizeof(neu_nodes_state_t), NULL, NULL, NULL };
return icd;
}
typedef struct {
UT_array *states; // array of neu_nodes_state_t
} neu_resp_get_nodes_state_t, neu_reqresp_nodes_state_t;
typedef struct neu_req_update_license {
} neu_req_update_license_t;
typedef struct neu_req_read_group {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
} neu_req_read_group_t;
typedef struct neu_req_write_tag {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
char tag[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
} neu_req_write_tag_t;
typedef struct neu_resp_tag_value {
char tag[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
} neu_resp_tag_value_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
uint16_t n_tag;
neu_resp_tag_value_t *tags;
} neu_resp_read_group_t;
typedef struct {
char driver[NEU_NODE_NAME_LEN];
char group[NEU_GROUP_NAME_LEN];
uint16_t n_tag;
neu_resp_tag_value_t tags[];
} neu_reqresp_trans_data_t;
typedef struct {
char node[NEU_NODE_NAME_LEN];
} neu_reqresp_node_deleted_t;
void *neu_msg_gen(neu_reqresp_head_t *header, void *data);
inline static void neu_msg_exchange(neu_reqresp_head_t *header)
{
char tmp[NEU_NODE_NAME_LEN] = { 0 };
strcpy(tmp, header->sender);
memset(header->sender, 0, sizeof(header->sender));
strcpy(header->sender, header->receiver);
memset(header->receiver, 0, sizeof(header->receiver));
strcpy(header->receiver, tmp);
}
typedef struct neu_adapter neu_adapter_t;
typedef struct neu_adapter_driver neu_adapter_driver_t;
typedef struct neu_adapter_app neu_adapter_app_t;
typedef int (*neu_adapter_update_metric_cb_t)(neu_adapter_t *adapter,
const char * metric_name,
uint64_t n, const char *group);
typedef int (*neu_adapter_register_metric_cb_t)(neu_adapter_t * adapter,
const char * name,
const char * help,
neu_metric_type_e type,
uint64_t init);
typedef struct adapter_callbacks {
int (*command)(neu_adapter_t *adapter, neu_reqresp_head_t head, void *data);
int (*response)(neu_adapter_t *adapter, neu_reqresp_head_t *head,
void *data);
int (*responseto)(neu_adapter_t *adapter, neu_reqresp_head_t *head,
void *data, struct sockaddr_un dst);
neu_adapter_register_metric_cb_t register_metric;
neu_adapter_update_metric_cb_t update_metric;
union {
struct {
void (*update)(neu_adapter_t *adapter, const char *group,
const char *tag, neu_dvalue_t value);
void (*update_with_meta)(neu_adapter_t *adapter, const char *group,
const char *tag, neu_dvalue_t value,
neu_tag_meta_t *metas, int n_meta);
void (*write_response)(neu_adapter_t *adapter, void *req,
int error);
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);
} driver;
};
} adapter_callbacks_t;
-147
View File
@@ -1,147 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef NEURON_CONNECTION_MQTT_CLIENT_H
#define NEURON_CONNECTION_MQTT_CLIENT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "utils/zlog.h"
// number of messages cached
#define NEU_METRIC_CACHED_MSGS_NUM "cached_msgs"
#define NEU_METRIC_CACHED_MSGS_NUM_TYPE NEU_METRIC_TYPE_GAUAGE
#define NEU_METRIC_CACHED_MSGS_NUM_HELP "Number of messages cached"
#define NEU_MQTT_CACHE_SYNC_INTERVAL_MIN 10
#define NEU_MQTT_CACHE_SYNC_INTERVAL_MAX 12000
#define NEU_MQTT_CACHE_SYNC_INTERVAL_DEFAULT 100
typedef enum {
NEU_MQTT_VERSION_V31 = 3,
NEU_MQTT_VERSION_V311 = 4,
NEU_MQTT_VERSION_V5 = 5,
} neu_mqtt_version_e;
typedef enum {
NEU_MQTT_QOS0,
NEU_MQTT_QOS1,
NEU_MQTT_QOS2,
} neu_mqtt_qos_e;
typedef struct neu_mqtt_client_s neu_mqtt_client_t;
/**
* Check that `topic_filter` is a valid MQTT topic filter.
*/
bool neu_mqtt_topic_filter_is_valid(const char *topic_filter);
/**
* Check the given `topic_filter` matches the given `topic_name`.
*
* @Precondition `topic_filter` must be a valid MQTT topic filter.
* @Precondition `topic_name` must be a valid MQTT topic name.
*/
bool neu_mqtt_topic_filter_is_match(const char *topic_filter,
const char *topic_name);
typedef void (*neu_mqtt_client_connection_cb_t)(void *data);
typedef void (*neu_mqtt_client_publish_cb_t)(int errcode, neu_mqtt_qos_e qos,
char *topic, uint8_t *payload,
uint32_t len, void *data);
typedef void (*neu_mqtt_client_subscribe_cb_t)(neu_mqtt_qos_e qos,
const char * topic,
const uint8_t *payload,
uint32_t len, void *data);
neu_mqtt_client_t *neu_mqtt_client_new(neu_mqtt_version_e version);
neu_mqtt_client_t *neu_mqtt_client_from_addr(const char *host, uint16_t port,
neu_mqtt_version_e version);
void neu_mqtt_client_free(neu_mqtt_client_t *client);
bool neu_mqtt_client_is_open(neu_mqtt_client_t *client);
bool neu_mqtt_client_is_connected(neu_mqtt_client_t *client);
size_t neu_mqtt_client_get_cached_msgs_num(neu_mqtt_client_t *client);
int neu_mqtt_client_set_addr(neu_mqtt_client_t *client, const char *host,
uint16_t port);
int neu_mqtt_client_set_id(neu_mqtt_client_t *client, const char *id);
int neu_mqtt_client_set_will_msg(neu_mqtt_client_t *client, const char *topic,
uint8_t *msg, uint32_t len, bool retain,
uint8_t qos);
int neu_mqtt_client_set_user(neu_mqtt_client_t *client, const char *username,
const char *password);
int neu_mqtt_client_set_connect_cb(neu_mqtt_client_t * client,
neu_mqtt_client_connection_cb_t cb,
void * data);
int neu_mqtt_client_set_disconnect_cb(neu_mqtt_client_t * client,
neu_mqtt_client_connection_cb_t cb,
void * data);
int neu_mqtt_client_set_tls(neu_mqtt_client_t *client, bool enabled,
const char *ca, const char *cert, const char *key,
const char *keypass);
int neu_mqtt_client_set_cache_size(neu_mqtt_client_t *client,
size_t mem_size_bytes, size_t db_size_bytes);
// default to NEU_MQTT_CACHE_SYNC_INTERVAL_DEFAULT if not set
int neu_mqtt_client_set_cache_sync_interval(neu_mqtt_client_t *client,
uint32_t interval);
int neu_mqtt_client_set_zlog_category(neu_mqtt_client_t *client,
zlog_category_t * cat);
int neu_mqtt_client_open(neu_mqtt_client_t *client);
int neu_mqtt_client_close(neu_mqtt_client_t *client);
/** Publish a `qos` message with `len` bytes `payload` on `topic`.
*
* This function initiates sending a `PUBLISH` packet, and if successful
* returns zero and the callback `cb` will be called once on completion of
* message delivery, otherwise returns a nonzero value. Callback invocation
* will be of the form `cb(errcode, qos, topic, payload, len, data)`, where
* `errcode` is zero if delivery was successful and nonzero otherwise, and
* the other arguments are exactly the same what you pass into this function.
* You may set `cb` to NULL if you do not care about the result.
*/
int neu_mqtt_client_publish(neu_mqtt_client_t *client, neu_mqtt_qos_e qos,
char *topic, uint8_t *payload, uint32_t len,
void *data, neu_mqtt_client_publish_cb_t cb);
/** Subscribe to `topic` with service quality `qos`.
*
* This function tries to send a `SUBSCRIBE` packet with the given `qos` and
* `topic`. If this was successful returns zero and the callback `cb` will be
* called on each received message with the matching topic, otherwise a nonzero
* value is returned.
*/
int neu_mqtt_client_subscribe(neu_mqtt_client_t *client, neu_mqtt_qos_e qos,
const char *topic, void *data,
neu_mqtt_client_subscribe_cb_t cb);
int neu_mqtt_client_unsubscribe(neu_mqtt_client_t *client, const char *topic);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,102 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef NEURON_NEU_MQTT_INTERFACE
#define NEURON_NEU_MQTT_INTERFACE
#ifdef __cplusplus
extern "C" {
#endif
#include "neuron.h"
#include <stddef.h>
#include <stdint.h>
typedef void (*state_update)(void *context, int state);
typedef struct {
/* debug app options */
int verbose;
/* MQTT options */
int MQTT_version; // 3-3_1, 4-3_3_1, 5-5
char *clientid;
int qos;
int retained;
char *username;
char *password;
char *host;
char *port;
char *connection; // tcp://, ssl://, ws://, wss://
int keepalive;
int keepalive_interval;
int clean_session;
/* will options */
char *will_topic;
char *will_payload;
int will_qos;
int will_retain;
/* TLS options */
char *ca;
char *cert;
char *key;
char *keypass;
/*application*/
int format;
char * upload_topic;
char * heartbeat_topic;
size_t cache;
char * group_id;
state_update state_update_func;
zlog_category_t *log;
} neu_mqtt_option_t;
typedef void *neu_mqtt_client_t;
typedef void (*neu_subscribe_handle)(const char *topic_name, size_t topic_len,
void *payload, const size_t len,
void *context);
neu_err_code_e neu_mqtt_client_open(neu_mqtt_client_t * p_client,
const neu_mqtt_option_t *option,
void * context);
neu_err_code_e neu_mqtt_client_is_connected(neu_mqtt_client_t client);
neu_err_code_e neu_mqtt_client_subscribe(neu_mqtt_client_t client,
const char *topic, const int qos,
neu_subscribe_handle handle);
neu_err_code_e neu_mqtt_client_unsubscribe(neu_mqtt_client_t client,
const char * topic);
neu_err_code_e neu_mqtt_client_publish(neu_mqtt_client_t client,
const char *topic, int qos,
unsigned char *payload, size_t len);
neu_err_code_e neu_mqtt_client_suspend(neu_mqtt_client_t client);
neu_err_code_e neu_mqtt_client_continue(neu_mqtt_client_t client);
neu_err_code_e neu_mqtt_client_close(neu_mqtt_client_t client);
#ifdef __cplusplus
}
#endif
#endif
+4 -57
View File
@@ -30,7 +30,6 @@ typedef enum neu_conn_type {
NEU_CONN_TCP_CLIENT,
NEU_CONN_UDP,
NEU_CONN_TTY_CLIENT,
NEU_CONN_UDP_TO,
} neu_conn_type_e;
typedef enum neu_conn_tty_baud {
@@ -41,12 +40,6 @@ typedef enum neu_conn_tty_baud {
NEU_CONN_TTY_BAUD_9600,
NEU_CONN_TTY_BAUD_4800,
NEU_CONN_TTY_BAUD_2400,
NEU_CONN_TTY_BAUD_1800,
NEU_CONN_TTY_BAUD_1200,
NEU_CONN_TTY_BAUD_600,
NEU_CONN_TTY_BAUD_300,
NEU_CONN_TTY_BAUD_200,
NEU_CONN_TTY_BAUD_150,
} neu_conn_tty_baud_e;
typedef enum neu_conn_tty_parity {
@@ -104,12 +97,6 @@ typedef struct neu_conn_param {
uint16_t timeout; // millisecond
} udp;
struct {
char * src_ip;
uint16_t src_port;
uint16_t timeout; // millisecond
} udpto;
struct {
char * device;
neu_conn_tty_data_e data;
@@ -124,11 +111,6 @@ typedef struct neu_conn_param {
typedef struct neu_conn neu_conn_t;
typedef struct neu_conn_state {
uint64_t send_bytes;
uint64_t recv_bytes;
} neu_conn_state_t;
/**
* @brief create a new connection.
*
@@ -160,24 +142,6 @@ neu_conn_t *neu_conn_reconfig(neu_conn_t *conn, neu_conn_param_t *param);
*/
void neu_conn_destory(neu_conn_t *conn);
/**
* @brief Connect
*
*
* @param[in] conn
*/
void neu_conn_connect(neu_conn_t *conn);
/**
* @brief Get connection fd
*
*
* @param[in] conn
* @return Successfully returns a number greater than 0, -1 or 0 on
* failure.
*/
int neu_conn_fd(neu_conn_t *conn);
/**
* @brief Disconnect
*
@@ -202,14 +166,6 @@ void neu_conn_stop(neu_conn_t *conn);
*/
void neu_conn_start(neu_conn_t *conn);
/**
* @brief get state of connection
*
*
* @param[in] conn
* @return returns state.
*/
neu_conn_state_t neu_conn_state(neu_conn_t *conn);
/**
* @brief Receive connection requests from clients.
*
@@ -238,8 +194,6 @@ int neu_conn_tcp_server_close_client(neu_conn_t *conn, int fd);
* less than or equal to 0 fails.
*/
ssize_t neu_conn_send(neu_conn_t *conn, uint8_t *buf, ssize_t len);
ssize_t neu_conn_udp_sendto(neu_conn_t *conn, uint8_t *buf, ssize_t len,
void *dst);
/**
* @brief Receive data via connection read.
@@ -251,10 +205,6 @@ ssize_t neu_conn_udp_sendto(neu_conn_t *conn, uint8_t *buf, ssize_t len,
* received, less than or equal to 0 fails.
*/
ssize_t neu_conn_recv(neu_conn_t *conn, uint8_t *buf, ssize_t len);
ssize_t neu_conn_udp_recvfrom(neu_conn_t *conn, uint8_t *buf, ssize_t len,
void *src);
void neu_conn_clear_recv_buffer(neu_conn_t *conn);
/**
* @brief Specify the client to send data.
@@ -285,11 +235,11 @@ ssize_t neu_conn_tcp_server_recv(neu_conn_t *conn, int fd, uint8_t *buf,
typedef int (*neu_conn_stream_consume_fn)(
void *context, neu_protocol_unpack_buf_t *protocol_buf);
int neu_conn_stream_consume(neu_conn_t *conn, void *context,
neu_conn_stream_consume_fn fn);
void neu_conn_stream_consume(neu_conn_t *conn, void *context,
neu_conn_stream_consume_fn fn);
int neu_conn_stream_tcp_server_consume(neu_conn_t *conn, int fd, void *context,
neu_conn_stream_consume_fn fn);
void neu_conn_stream_tcp_server_consume(neu_conn_t *conn, int fd, void *context,
neu_conn_stream_consume_fn fn);
typedef neu_buf_result_t (*neu_conn_process_msg)(
void *context, neu_protocol_unpack_buf_t *protocol_buf);
@@ -300,7 +250,4 @@ int neu_conn_wait_msg(neu_conn_t *conn, void *context, uint16_t n_byte,
int neu_conn_tcp_server_wait_msg(neu_conn_t *conn, int fd, void *context,
uint16_t n_byte, neu_conn_process_msg fn);
int is_ipv4(const char *ip);
int is_ipv6(const char *ip);
#endif
@@ -1,50 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef NEURON_CONNECTION_ETH_H
#define NEURON_CONNECTION_ETH_H
#include <stdint.h>
#include "define.h"
// profinet
typedef struct neu_conn_eth neu_conn_eth_t;
neu_conn_eth_t *neu_conn_eth_init(const char *interface, void *ctx);
int neu_conn_eth_uninit(neu_conn_eth_t *conn);
int neu_conn_eth_check_interface(const char *interface);
void neu_conn_eth_get_mac(neu_conn_eth_t *conn, uint8_t *mac);
int neu_conn_eth_size();
typedef void (*neu_conn_eth_msg_callback)(neu_conn_eth_t *conn, void *ctx,
uint16_t protocol, uint16_t n_byte,
uint8_t *bytes, uint8_t src_mac[6]);
typedef struct neu_conn_eth_sub neu_conn_eth_sub_t;
neu_conn_eth_sub_t *neu_conn_eth_register(neu_conn_eth_t *conn, uint8_t mac[6],
neu_conn_eth_msg_callback callback);
int neu_conn_eth_unregister(neu_conn_eth_t *conn, neu_conn_eth_sub_t *sub);
int neu_conn_eth_send(neu_conn_eth_t *conn, uint16_t protocol, uint16_t n_byte,
uint8_t *bytes);
#endif
@@ -1,25 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef NEURON_CONNECTION_SMART_LINK_H
#define NEURON_CONNECTION_SMART_LINK_H
int neu_conn_smart_link_auto_set(const char *dev_path);
#endif
+6 -77
View File
@@ -20,81 +20,18 @@
#ifndef _NEU_DEFINE_H_
#define _NEU_DEFINE_H_
#include <stdbool.h>
#define NEU_VERSION_MAJOR 2
#define NEU_VERSION_MINOR 8
#define NEU_VERSION_FIX 3
#define NEU_GET_VERSION_MAJOR(V) ((0xffff0000 & V) >> 16)
#define NEU_GET_VERSION_MINOR(V) ((0x0000ff00 & V) >> 8)
#define NEU_GET_VERSION_FIX(V) ((0x000000ff & V))
#define NEU_VERSION(MAJOR, MINOR, FIX) ((MAJOR << 16) | (MINOR << 8) | FIX)
#define NEU_TAG_NAME_LEN 128
#define NEU_TAG_ADDRESS_LEN 128
#define NEU_TAG_NAME_LEN 32
#define NEU_TAG_ADDRESS_LEN 64
#define NEU_TAG_DESCRIPTION_LEN 128
#define NEU_GROUP_MAX_PER_NODE 512
#define NEU_GROUP_NAME_LEN 128
#define NEU_GROUP_NAME_LEN 32
#define NEU_GROUP_INTERVAL_LIMIT 100
#define NEU_DEFAULT_GROUP_INTERVAL 100
#define NEU_NODE_NAME_LEN 128
#define NEU_NODE_NAME_LEN 32
#define NEU_PLUGIN_NAME_LEN 32
#define NEU_PLUGIN_LIBRARY_LEN 64
#define NEU_PLUGIN_LIBRARY_LEN 32
#define NEU_PLUGIN_DESCRIPTION_LEN 512
#define NEU_TEMPLATE_NAME_LEN 128
#define NEU_DRIVER_TAG_CACHE_EXPIRE_TIME 60
#define NEU_DRIVER_TAG_CACHE_EXPIRE_TIME 30
#define NEU_APP_SUBSCRIBE_MSG_SIZE 4
#define NEU_TAG_FLOAG_PRECISION_MAX 17
#define NEU_USER_PASSWORD_MIN_LEN 4
#define NEU_USER_PASSWORD_MAX_LEN 16
#define NEU_LOG_LEVEL_LEN 9
#define NEU_FILE_PATH_LEN 128
#define NEU_MSG_MAX_SIZE 2048
#define NEU_TAG_META_LENGTH 20
#define NEU_TAG_META_SIZE 3
#define NEU_LOG_LEVEL_DEBUG "debug"
#define NEU_LOG_LEVEL_INFO "info"
#define NEU_LOG_LEVEL_NOTICE "notice"
#define NEU_LOG_LEVEL_WARN "warn"
#define NEU_LOG_LEVEL_ERROR "error"
#define NEU_LOG_LEVEL_FATAL "fatal"
#define CHECK_NODE_NAME_LENGTH_ERR \
do { \
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_NAME_TOO_LONG, { \
neu_http_response(aio, NEU_ERR_NODE_NAME_TOO_LONG, result_error); \
}); \
} while (0)
#define CHECK_GROUP_NAME_LENGTH_ERR \
do { \
NEU_JSON_RESPONSE_ERROR(NEU_ERR_GROUP_NAME_TOO_LONG, { \
neu_http_response(aio, NEU_ERR_GROUP_NAME_TOO_LONG, result_error); \
}); \
} while (0)
#define CHECK_TAG_NAME_LENGTH_ERR \
do { \
NEU_JSON_RESPONSE_ERROR(NEU_ERR_TAG_NAME_TOO_LONG, { \
neu_http_response(aio, NEU_ERR_TAG_NAME_TOO_LONG, result_error); \
}); \
} while (0)
#define CHECK_GROUP_INTERVAL_ERR \
do { \
NEU_JSON_RESPONSE_ERROR(NEU_ERR_GROUP_PARAMETER_INVALID, { \
neu_http_response(aio, NEU_ERR_GROUP_PARAMETER_INVALID, \
result_error); \
}); \
} while (0)
extern int default_log_level;
extern bool disable_jwt;
extern char host_port[32];
extern char g_status[32];
typedef enum neu_plugin_kind {
NEU_PLUGIN_KIND_STATIC = 0,
@@ -120,12 +57,4 @@ typedef enum {
NEU_NODE_RUNNING_STATE_STOPPED = 4,
} neu_node_running_state_e;
typedef enum {
NEU_TAG_CACHE_TYPE_INTERVAL = 0,
NEU_TAG_CACHE_TYPE_NEVER,
} neu_tag_cache_type_e;
// forward declaration for neu_adapter_t
typedef struct neu_adapter neu_adapter_t;
#endif
+10 -50
View File
@@ -42,27 +42,17 @@ typedef enum {
NEU_ERR_INVALID_USER_OR_PASSWORD = 1009,
NEU_ERR_IS_BUSY = 1010,
NEU_ERR_FILE_NOT_EXIST = 1011,
NEU_ERR_INVALID_PASSWORD_LEN = 1012,
NEU_ERR_DUPLICATE_PASSWORD = 1013,
NEU_ERR_COMMAND_EXECUTION_FAILED = 1014,
NEU_ERR_IP_ADDRESS_INVALID = 1015,
NEU_ERR_IP_ADDRESS_IN_USE = 1016,
NEU_ERR_BODY_TOO_BIG = 1017,
NEU_ERR_NODE_EXIST = 2002,
NEU_ERR_NODE_NOT_EXIST = 2003,
NEU_ERR_NODE_SETTING_INVALID = 2004,
NEU_ERR_NODE_SETTING_NOT_FOUND = 2005,
NEU_ERR_NODE_NOT_READY = 2006,
NEU_ERR_NODE_IS_RUNNING = 2007,
NEU_ERR_NODE_NOT_RUNNING = 2008,
NEU_ERR_NODE_IS_STOPED = 2009,
NEU_ERR_NODE_NAME_TOO_LONG = 2010,
NEU_ERR_NODE_NOT_ALLOW_DELETE = 2011,
NEU_ERR_NODE_NOT_ALLOW_SUBSCRIBE = 2012,
NEU_ERR_NODE_NOT_ALLOW_UPDATE = 2013,
NEU_ERR_NODE_NOT_ALLOW_MAP = 2014,
NEU_ERR_NODE_NAME_EMPTY = 2015,
NEU_ERR_NODE_EXIST = 2002,
NEU_ERR_NODE_NOT_EXIST = 2003,
NEU_ERR_NODE_SETTING_INVALID = 2004,
NEU_ERR_NODE_SETTING_NOT_FOUND = 2005,
NEU_ERR_NODE_NOT_READY = 2006,
NEU_ERR_NODE_IS_RUNNING = 2007,
NEU_ERR_NODE_NOT_RUNNING = 2008,
NEU_ERR_NODE_IS_STOPED = 2009,
NEU_ERR_NODE_NAME_TOO_LONG = 2010,
NEU_ERR_NODE_NOT_ALLOW_DELETE = 2011,
NEU_ERR_GROUP_ALREADY_SUBSCRIBED = 2101,
NEU_ERR_GROUP_NOT_SUBSCRIBE = 2102,
@@ -71,7 +61,6 @@ typedef enum {
NEU_ERR_GROUP_PARAMETER_INVALID = 2105,
NEU_ERR_GROUP_NOT_EXIST = 2106,
NEU_ERR_GROUP_NAME_TOO_LONG = 2107,
NEU_ERR_GROUP_MAX_GROUPS = 2108,
NEU_ERR_TAG_NOT_EXIST = 2201,
NEU_ERR_TAG_NAME_CONFLICT = 2202,
@@ -82,7 +71,6 @@ typedef enum {
NEU_ERR_TAG_ADDRESS_TOO_LONG = 2207,
NEU_ERR_TAG_DESCRIPTION_TOO_LONG = 2208,
NEU_ERR_TAG_PRECISION_INVALID = 2209,
NEU_ERR_TAG_EXIST = 2210,
NEU_ERR_LIBRARY_NOT_FOUND = 2301,
NEU_ERR_LIBRARY_INFO_INVALID = 2302,
@@ -91,16 +79,6 @@ typedef enum {
NEU_ERR_LIBRARY_MODULE_INVALID = 2305,
NEU_ERR_LIBRARY_SYSTEM_NOT_ALLOW_DEL = 2306,
NEU_ERR_LIBRARY_NOT_ALLOW_CREATE_INSTANCE = 2307,
NEU_ERR_LIBRARY_ARCH_NOT_SUPPORT = 2308,
NEU_ERR_LIBRARY_IN_USE = 2309,
NEU_ERR_LIBRARY_ADD_FAIL = 2310,
NEU_ERR_LIBRARY_MODULE_ALREADY_EXIST = 2311,
NEU_ERR_LIBRARY_MODULE_NOT_EXISTS = 2312,
NEU_ERR_LIBRARY_MODULE_KIND_NOT_SUPPORT = 2313,
NEU_ERR_LIBRARY_MODULE_VERSION_NOT_MATCH = 2314,
NEU_ERR_LIBRARY_NAME_NOT_CONFORM = 2315,
NEU_ERR_LIBRARY_CLIB_NOT_MATCH = 2316,
NEU_ERR_LIBRARY_UPDATE_FAIL = 2317,
NEU_ERR_LICENSE_NOT_FOUND = 2400,
NEU_ERR_LICENSE_INVALID = 2401,
@@ -110,12 +88,6 @@ typedef enum {
NEU_ERR_LICENSE_MAX_TAGS = 2405,
NEU_ERR_LICENSE_TOKEN_NOT_MATCH = 2406,
NEU_ERR_LICENSE_BAD_CLOCK = 2407,
NEU_ERR_LICENSE_MODULE_INVALID = 2408,
NEU_ERR_LICENSE_TOKEN_NOT_FOUND = 2409,
NEU_ERR_TEMPLATE_EXIST = 2500,
NEU_ERR_TEMPLATE_NOT_FOUND = 2501,
NEU_ERR_TEMPLATE_NAME_TOO_LONG = 2502,
// common error codes for plugins
NEU_ERR_PLUGIN_READ_FAILURE = 3000,
@@ -129,13 +101,6 @@ typedef enum {
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_MQTT_FAILURE = 4000,
NEU_ERR_MQTT_NO_CERTFILESET = 4001,
@@ -155,11 +120,6 @@ typedef enum {
NEU_ERR_MQTT_SUSPENDED = 4015,
NEU_ERR_MQTT_PUBLISH_OVER_LENGTH = 4016,
NEU_ERR_STRING_TOO_LONG = 4100,
NEU_ERR_FILE_OPEN_FAILURE = 4101,
NEU_ERR_FILE_READ_FAILURE = 4102,
NEU_ERR_FILE_WRITE_FAILURE = 4103,
NEU_ERR_PLUGIN_ERROR_START = 10000,
NEU_ERR_PLUGIN_ERROR_END = 20000,
} neu_err_code_e;
-6
View File
@@ -48,11 +48,6 @@ int neu_event_close(neu_events_t *events);
typedef struct neu_event_timer neu_event_timer_t;
typedef int (*neu_event_timer_callback)(void *usr_data);
typedef enum neu_event_timer_type {
NEU_EVENT_TIMER_BLOCK = 0,
NEU_EVENT_TIMER_NOBLOCK = 1,
} neu_event_timer_type_e;
typedef struct neu_event_timer_param {
// timer trigger period
int64_t second;
@@ -61,7 +56,6 @@ typedef struct neu_event_timer_param {
void *usr_data;
// Callback function that fires every time the timer fires
neu_event_timer_callback cb;
neu_event_timer_type_e type;
} neu_event_timer_param_t;
/**
+8 -22
View File
@@ -37,24 +37,17 @@ typedef enum neu_json_type {
NEU_JSON_FLOAT,
NEU_JSON_BOOL,
NEU_JSON_OBJECT,
NEU_JSON_BYTES,
NEU_JSON_VALUE = NEU_JSON_UNDEFINE
} neu_json_type_e;
typedef struct {
uint8_t *bytes;
uint8_t length;
} neu_json_value_bytes_t;
typedef union neu_json_value {
int64_t val_int;
uint8_t val_bit;
float val_float;
double val_double;
bool val_bool;
char * val_str;
void * val_object;
neu_json_value_bytes_t val_bytes;
int64_t val_int;
uint8_t val_bit;
float val_float;
double val_double;
bool val_bool;
char * val_str;
void * val_object;
} neu_json_value_u;
typedef enum neu_json_attribute {
@@ -78,14 +71,12 @@ void *neu_json_array();
int neu_json_decode_by_json(void *json, int size, neu_json_elem_t *ele);
int neu_json_decode(char *buf, int size, neu_json_elem_t *ele);
int neu_json_decode_array_size_by_json(void *json, char *child);
int neu_json_decode_array_elem(void *json, int index, int size,
neu_json_elem_t *ele);
int neu_json_decode_array_by_json(void *json, char *name, int index, int size,
neu_json_elem_t *ele);
int neu_json_decode_array_size(char *buf, char *child);
int neu_json_decode_array(char *buf, char *name, int index, int size,
neu_json_elem_t *ele);
void *neu_json_decode_new(const char *buf);
void *neu_json_decode_new(char *buf);
void *neu_json_decode_newb(char *buf, size_t len);
void neu_json_decode_free(void *ob);
int neu_json_decode_value(void *object, neu_json_elem_t *ele);
@@ -97,11 +88,6 @@ void *neu_json_encode_array_value(void *array, neu_json_elem_t *t, int n);
int neu_json_encode_field(void *json_object, neu_json_elem_t *elem, int n);
int neu_json_encode(void *json_object, char **str);
int neu_json_dump_key(void *object, const char *key, char **const result,
bool must_exist);
int neu_json_load_key(void *object, const char *key, const char *input,
bool must_exist);
#ifdef __cplusplus
}
#endif
+3
View File
@@ -56,6 +56,9 @@ void neu_json_decode_mqtt_req_free(neu_json_mqtt_t *req);
int neu_json_encode_mqtt_resp(void *json_object, void *param);
int neu_json_encode_state_header_resp(void *json_object, void *param);
int neu_json_encode_states_resp(void *json_object, void *param);
#ifdef __cplusplus
}
#endif
+2 -2
View File
@@ -26,8 +26,8 @@ extern "C" {
#include "json/json.h"
int neu_parse_param(const char *buf, char **err_param, int n,
neu_json_elem_t *ele, ...);
int neu_parse_param(char *buf, char **err_param, int n, neu_json_elem_t *ele,
...);
#ifdef __cplusplus
}
-108
View File
@@ -27,8 +27,6 @@
#include "json/json.h"
#include "tag.h"
#ifdef __cplusplus
extern "C" {
#endif
@@ -39,20 +37,12 @@ typedef struct {
uint64_t timestamp;
} neu_json_read_periodic_t;
typedef struct {
char * name;
enum neu_json_type t;
union neu_json_value value;
} neu_json_tag_meta_t;
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_json_read_resp_tag_t;
typedef struct {
@@ -62,31 +52,6 @@ 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_resp2(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;
@@ -97,91 +62,18 @@ typedef struct {
} neu_json_write_req_t;
int neu_json_decode_write_req(char *buf, neu_json_write_req_t **result);
int neu_json_decode_write_req_json(void * json_obj,
neu_json_write_req_t **result);
void neu_json_decode_write_req_free(neu_json_write_req_t *req);
typedef struct {
char * tag;
enum neu_json_type t;
union neu_json_value value;
} neu_json_write_tags_elem_t;
typedef struct {
char * group;
char * node;
int n_tag;
neu_json_write_tags_elem_t *tags;
} neu_json_write_tags_req_t;
int neu_json_decode_write_tags_req(char * buf,
neu_json_write_tags_req_t **result);
int neu_json_decode_write_tags_req_json(void * json_obj,
neu_json_write_tags_req_t **result);
void neu_json_decode_write_tags_req_free(neu_json_write_tags_req_t *req);
typedef struct {
char * group;
int n_tag;
neu_json_write_tags_elem_t *tags;
} neu_json_write_gtags_elem_t;
typedef struct {
char *node;
int n_group;
neu_json_write_gtags_elem_t *groups;
} neu_json_write_gtags_req_t;
int neu_json_decode_write_gtags_req(char * buf,
neu_json_write_gtags_req_t **result);
int neu_json_decode_write_gtags_req_json(void * json_obj,
neu_json_write_gtags_req_t **result);
void neu_json_decode_write_gtags_req_free(neu_json_write_gtags_req_t *req);
typedef struct {
union {
neu_json_write_req_t single;
neu_json_write_tags_req_t plural;
};
bool singular;
} neu_json_write_t;
int neu_json_decode_write(char *buf, neu_json_write_t **result);
void neu_json_decode_write_free(neu_json_write_t *req);
typedef struct {
char *group;
char *node;
char *name;
char *desc;
bool sync;
} neu_json_read_req_t;
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);
#ifdef __cplusplus
}
#endif
-558
View File
@@ -1,558 +0,0 @@
/**
* 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_METRICS_H
#define NEU_METRICS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <pthread.h>
#include "define.h"
#include "type.h"
#include "utils/rolling_counter.h"
#include "utils/utextend.h"
#include "utils/uthash.h"
extern int64_t global_timestamp;
typedef enum {
NEU_METRIC_TYPE_COUNTER,
NEU_METRIC_TYPE_GAUAGE,
NEU_METRIC_TYPE_COUNTER_SET,
NEU_METRIC_TYPE_ROLLING_COUNTER,
NEU_METRIC_TYPE_FLAG_NO_RESET = 0x80,
} neu_metric_type_e;
#define NEU_METRIC_TYPE_MASK 0x0F
// node running state
#define NEU_METRIC_RUNNING_STATE "running_state"
#define NEU_METRIC_RUNNING_STATE_TYPE \
(NEU_METRIC_TYPE_GAUAGE | NEU_METRIC_TYPE_FLAG_NO_RESET)
#define NEU_METRIC_RUNNING_STATE_HELP "Node running state"
// node link state
#define NEU_METRIC_LINK_STATE "link_state"
#define NEU_METRIC_LINK_STATE_TYPE \
(NEU_METRIC_TYPE_GAUAGE | NEU_METRIC_TYPE_FLAG_NO_RESET)
#define NEU_METRIC_LINK_STATE_HELP "Node link state"
// last round trip time in millisends
#define NEU_METRIC_LAST_RTT_MS "last_rtt_ms"
#define NEU_METRIC_LAST_RTT_MS_TYPE NEU_METRIC_TYPE_GAUAGE
#define NEU_METRIC_LAST_RTT_MS_HELP \
"Last request round trip time in milliseconds"
#define NEU_METRIC_LAST_RTT_MS_MAX 9999
// number of bytes sent
#define NEU_METRIC_SEND_BYTES "send_bytes"
#define NEU_METRIC_SEND_BYTES_TYPE NEU_METRIC_TYPE_COUNTER_SET
#define NEU_METRIC_SEND_BYTES_HELP "Total number of bytes sent"
// number of bytes received
#define NEU_METRIC_RECV_BYTES "recv_bytes"
#define NEU_METRIC_RECV_BYTES_TYPE NEU_METRIC_TYPE_COUNTER_SET
#define NEU_METRIC_RECV_BYTES_HELP "Total number of bytes received"
// maintained by neuron core
// number of tag read including errors
#define NEU_METRIC_TAG_READS_TOTAL "tag_reads_total"
#define NEU_METRIC_TAG_READS_TOTAL_TYPE NEU_METRIC_TYPE_COUNTER
#define NEU_METRIC_TAG_READS_TOTAL_HELP \
"Total number of tag reads including errors"
// maintained by neuron core
// number of tag read errors
#define NEU_METRIC_TAG_READ_ERRORS_TOTAL "tag_read_errors_total"
#define NEU_METRIC_TAG_READ_ERRORS_TOTAL_TYPE NEU_METRIC_TYPE_COUNTER
#define NEU_METRIC_TAG_READ_ERRORS_TOTAL_HELP "Total number of tag read errors"
// maintained by neuron core
// number of tags in group
#define NEU_METRIC_TAGS_TOTAL "tags_total"
#define NEU_METRIC_TAGS_TOTAL_TYPE \
(NEU_METRIC_TYPE_GAUAGE | NEU_METRIC_TYPE_FLAG_NO_RESET)
#define NEU_METRIC_TAGS_TOTAL_HELP "Total number of tags in the node"
// maintained by neuron core
// number of tags in group
#define NEU_METRIC_GROUP_TAGS_TOTAL "group_tags_total"
#define NEU_METRIC_GROUP_TAGS_TOTAL_TYPE \
(NEU_METRIC_TYPE_GAUAGE | NEU_METRIC_TYPE_FLAG_NO_RESET)
#define NEU_METRIC_GROUP_TAGS_TOTAL_HELP "Total number of tags in the group"
// number of messages sent in last group timer
#define NEU_METRIC_GROUP_LAST_SEND_MSGS "group_last_send_msgs"
#define NEU_METRIC_GROUP_LAST_SEND_MSGS_TYPE NEU_METRIC_TYPE_GAUAGE
#define NEU_METRIC_GROUP_LAST_SEND_MSGS_HELP \
"Number of messages sent on last group timer invocation"
// maintained by neuron core
// milliseconds consumed in last group timer invocation
#define NEU_METRIC_GROUP_LAST_TIMER_MS "group_last_timer_ms"
#define NEU_METRIC_GROUP_LAST_TIMER_MS_TYPE NEU_METRIC_TYPE_GAUAGE
#define NEU_METRIC_GROUP_LAST_TIMER_MS_HELP \
"Time in milliseconds consumed on last group timer invocation"
// maintained by neuron core
// group last error code
#define NEU_METRIC_GROUP_LAST_ERROR_CODE "group_last_error_code"
#define NEU_METRIC_GROUP_LAST_ERROR_CODE_TYPE NEU_METRIC_TYPE_GAUAGE
#define NEU_METRIC_GROUP_LAST_ERROR_CODE_HELP \
"Last encountered error code in group data acquisition"
// maintained by neuron core
// group last error timestamp
#define NEU_METRIC_GROUP_LAST_ERROR_TS "group_last_error_timestamp_ms"
#define NEU_METRIC_GROUP_LAST_ERROR_TS_TYPE NEU_METRIC_TYPE_GAUAGE
#define NEU_METRIC_GROUP_LAST_ERROR_TS_HELP \
"Timestamp (ms) of the last encountered error in group data acquisition"
// number of messages sent
#define NEU_METRIC_SEND_MSGS_TOTAL "send_msgs_total"
#define NEU_METRIC_SEND_MSGS_TOTAL_TYPE NEU_METRIC_TYPE_COUNTER
#define NEU_METRIC_SEND_MSGS_TOTAL_HELP "Total number of messages sent"
// number of errors encounter while sending messages
#define NEU_METRIC_SEND_MSG_ERRORS_TOTAL "send_msg_errors_total"
#define NEU_METRIC_SEND_MSG_ERRORS_TOTAL_TYPE NEU_METRIC_TYPE_COUNTER
#define NEU_METRIC_SEND_MSG_ERRORS_TOTAL_HELP \
"Total number of errors sending messages"
// number of messages received
#define NEU_METRIC_RECV_MSGS_TOTAL "recv_msgs_total"
#define NEU_METRIC_RECV_MSGS_TOTAL_TYPE NEU_METRIC_TYPE_COUNTER
#define NEU_METRIC_RECV_MSGS_TOTAL_HELP "Total number of messages received"
// number of trans data message within the last 5 seconds
#define NEU_METRIC_TRANS_DATA_5S "last_5s_trans_data_msgs"
#define NEU_METRIC_TRANS_DATA_5S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_TRANS_DATA_5S_HELP \
"Number of internal trans data message within the last 5 seconds"
// number of trans data message within the last 30 seconds
#define NEU_METRIC_TRANS_DATA_30S "last_30s_trans_data_msgs"
#define NEU_METRIC_TRANS_DATA_30S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_TRANS_DATA_30S_HELP \
"Number of internal trans data message within the last 30 seconds"
// number of trans data message within the last 60 seconds
#define NEU_METRIC_TRANS_DATA_60S "last_60s_trans_data_msgs"
#define NEU_METRIC_TRANS_DATA_60S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_TRANS_DATA_60S_HELP \
"Number of internal trans data message within the last 60 seconds"
// number of bytes sent within the last 5 seconds
#define NEU_METRIC_SEND_BYTES_5S "last_5s_send_bytes"
#define NEU_METRIC_SEND_BYTES_5S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_SEND_BYTES_5S_HELP \
"Number of bytes sent within the last 5 seconds"
// number of bytes sent within the last 30 seconds
#define NEU_METRIC_SEND_BYTES_30S "last_30s_send_bytes"
#define NEU_METRIC_SEND_BYTES_30S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_SEND_BYTES_30S_HELP \
"Number of bytes sent within the last 30 seconds"
// number of bytes sent within the last 60 seconds
#define NEU_METRIC_SEND_BYTES_60S "last_60s_send_bytes"
#define NEU_METRIC_SEND_BYTES_60S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_SEND_BYTES_60S_HELP \
"Number of bytes sent within the last 60 seconds"
// number of bytes received within the last 5 seconds
#define NEU_METRIC_RECV_BYTES_5S "last_5s_recv_bytes"
#define NEU_METRIC_RECV_BYTES_5S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_RECV_BYTES_5S_HELP \
"Number of bytes received within the last 5 seconds"
// number of bytes received within the last 30 seconds
#define NEU_METRIC_RECV_BYTES_30S "last_30s_recv_bytes"
#define NEU_METRIC_RECV_BYTES_30S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_RECV_BYTES_30S_HELP \
"Number of bytes received within the last 30 seconds"
// number of bytes received within the last 60 seconds
#define NEU_METRIC_RECV_BYTES_60S "last_60s_recv_bytes"
#define NEU_METRIC_RECV_BYTES_60S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_RECV_BYTES_60S_HELP \
"Number of bytes received within the last 60 seconds"
// number of messages received within the last 5 seconds
#define NEU_METRIC_RECV_MSGS_5S "last_5s_recv_msgs"
#define NEU_METRIC_RECV_MSGS_5S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_RECV_MSGS_5S_HELP \
"Number of messages received within the last 5 seconds"
// number of messages received within the last 30 seconds
#define NEU_METRIC_RECV_MSGS_30S "last_30s_recv_msgs"
#define NEU_METRIC_RECV_MSGS_30S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_RECV_MSGS_30S_HELP \
"Number of messages received within the last 30 seconds"
// number of messages received within the last 60 seconds
#define NEU_METRIC_RECV_MSGS_60S "last_60s_recv_msgs"
#define NEU_METRIC_RECV_MSGS_60S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_RECV_MSGS_60S_HELP \
"Number of messages received within the last 60 seconds"
// number of disconnection within the last 60 seconds
#define NEU_METRIC_DISCONNECTION_60S "last_60s_disconnections"
#define NEU_METRIC_DISCONNECTION_60S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_DISCONNECTION_60S_HELP \
"Number of disconnection within the last 60 seconds"
// number of disconnection within the last 600 seconds
#define NEU_METRIC_DISCONNECTION_600S "last_600s_disconnections"
#define NEU_METRIC_DISCONNECTION_600S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_DISCONNECTION_600S_HELP \
"Number of disconnection within the last 600 seconds"
// number of disconnection within the last 1800 seconds
#define NEU_METRIC_DISCONNECTION_1800S "last_1800s_disconnections"
#define NEU_METRIC_DISCONNECTION_1800S_TYPE NEU_METRIC_TYPE_ROLLING_COUNTER
#define NEU_METRIC_DISCONNECTION_1800S_HELP \
"Number of disconnection within the last 1800 seconds"
typedef enum {
NEU_METRICS_CATEGORY_GLOBAL,
NEU_METRICS_CATEGORY_DRIVER,
NEU_METRICS_CATEGORY_APP,
NEU_METRICS_CATEGORY_ALL,
} neu_metrics_category_e;
// metric entry
typedef struct {
const char * name; // NOTE: should points to string literal
const char * help; // NOTE: should points to string literal
neu_metric_type_e type; //
uint64_t init; //
uint64_t value; //
neu_rolling_counter_t *rcnt; //
UT_hash_handle hh; // ordered by name
} neu_metric_entry_t;
// group metrics
typedef struct {
char * name; // group name
neu_metric_entry_t *entries; // group metric entries
UT_hash_handle hh; // ordered by name
} neu_group_metrics_t;
// node metrics
typedef struct {
pthread_mutex_t lock; // spin lock
neu_node_type_e type; // node type
char * name; // node name
neu_metric_entry_t * entries; // node metric entries
neu_group_metrics_t *group_metrics; // group metrics
neu_adapter_t * adapter; //
UT_hash_handle hh; // ordered by name
} neu_node_metrics_t;
typedef struct {
char distro[32];
char kernel[32];
char machine[32];
char clib[32];
char clib_version[32];
unsigned cpu_percent;
unsigned cpu_cores;
size_t mem_total_bytes;
size_t mem_used_bytes;
size_t mem_cache_bytes;
size_t disk_size_gibibytes;
size_t disk_used_gibibytes;
size_t disk_avail_gibibytes;
bool core_dumped;
uint64_t license_max_tags;
uint64_t license_used_tags;
uint64_t uptime_seconds;
size_t north_nodes;
size_t north_running_nodes;
size_t north_disconnected_nodes;
size_t south_nodes;
size_t south_running_nodes;
size_t south_disconnected_nodes;
neu_node_metrics_t *node_metrics;
neu_metric_entry_t *registered_metrics;
} neu_metrics_t;
void neu_metrics_init();
void neu_metrics_add_node(const neu_adapter_t *adapter);
void neu_metrics_del_node(const neu_adapter_t *adapter);
int neu_metrics_register_entry(const char *name, const char *help,
neu_metric_type_e type);
void neu_metrics_unregister_entry(const char *name);
typedef void (*neu_metrics_cb_t)(const neu_metrics_t *metrics, void *data);
void neu_metrics_visist(neu_metrics_cb_t cb, void *data);
static inline bool neu_metric_type_is_counter(neu_metric_type_e type)
{
return NEU_METRIC_TYPE_COUNTER == (type & NEU_METRIC_TYPE_MASK);
}
static inline bool neu_metric_type_is_rolling_counter(neu_metric_type_e type)
{
return NEU_METRIC_TYPE_ROLLING_COUNTER == (type & NEU_METRIC_TYPE_MASK);
}
static inline bool neu_metric_type_no_reset(neu_metric_type_e type)
{
return NEU_METRIC_TYPE_FLAG_NO_RESET & type;
}
static inline const char *neu_metric_type_str(neu_metric_type_e type)
{
if (neu_metric_type_is_counter(type)) {
return "counter";
} else {
return "gauge";
}
}
int neu_metric_entries_add(neu_metric_entry_t **entries, const char *name,
const char *help, neu_metric_type_e type,
uint64_t init);
static inline void neu_metric_entry_free(neu_metric_entry_t *entry)
{
if (neu_metric_type_is_rolling_counter(entry->type)) {
neu_rolling_counter_free(entry->rcnt);
}
free(entry);
}
static inline void neu_group_metrics_free(neu_group_metrics_t *group_metrics)
{
if (NULL == group_metrics) {
return;
}
neu_metric_entry_t *e = NULL, *tmp = NULL;
HASH_ITER(hh, group_metrics->entries, e, tmp)
{
HASH_DEL(group_metrics->entries, e);
neu_metrics_unregister_entry(e->name);
neu_metric_entry_free(e);
}
free(group_metrics->name);
free(group_metrics);
}
static inline neu_node_metrics_t *
neu_node_metrics_new(neu_adapter_t *adapter, neu_node_type_e type, char *name)
{
neu_node_metrics_t *node_metrics =
(neu_node_metrics_t *) calloc(1, sizeof(*node_metrics));
if (NULL != node_metrics) {
pthread_mutex_init(&node_metrics->lock, NULL);
node_metrics->type = type;
node_metrics->name = name;
node_metrics->adapter = adapter;
// neu_metrics_add_node(adapter);
}
return node_metrics;
}
static inline void neu_node_metrics_free(neu_node_metrics_t *node_metrics)
{
if (NULL == node_metrics) {
return;
}
pthread_mutex_destroy(&node_metrics->lock);
neu_metric_entry_t *e = NULL, *etmp = NULL;
HASH_ITER(hh, node_metrics->entries, e, etmp)
{
HASH_DEL(node_metrics->entries, e);
neu_metrics_unregister_entry(e->name);
neu_metric_entry_free(e);
}
neu_group_metrics_t *g = NULL, *gtmp = NULL;
HASH_ITER(hh, node_metrics->group_metrics, g, gtmp)
{
HASH_DEL(node_metrics->group_metrics, g);
neu_group_metrics_free(g);
}
free(node_metrics);
}
static inline int neu_node_metrics_add(neu_node_metrics_t *node_metrics,
const char *group_name, const char *name,
const char *help, neu_metric_type_e type,
uint64_t init)
{
int rv = 0;
if (0 > neu_metrics_register_entry(name, help, type)) {
return -1;
}
pthread_mutex_lock(&node_metrics->lock);
if (NULL == group_name) {
rv = neu_metric_entries_add(&node_metrics->entries, name, help, type,
init);
} else {
neu_group_metrics_t *group_metrics = NULL;
HASH_FIND_STR(node_metrics->group_metrics, group_name, group_metrics);
if (NULL != group_metrics) {
rv = neu_metric_entries_add(&group_metrics->entries, name, help,
type, init);
} else {
group_metrics =
(neu_group_metrics_t *) calloc(1, sizeof(*group_metrics));
if (NULL != group_metrics &&
NULL != (group_metrics->name = strdup(group_name))) {
HASH_ADD_STR(node_metrics->group_metrics, name, group_metrics);
rv = neu_metric_entries_add(&group_metrics->entries, name, help,
type, init);
} else {
free(group_metrics);
rv = -1;
}
}
}
pthread_mutex_unlock(&node_metrics->lock);
if (0 != rv) {
neu_metrics_unregister_entry(name);
}
return rv;
}
static inline int neu_node_metrics_update(neu_node_metrics_t *node_metrics,
const char * group,
const char *metric_name, uint64_t n)
{
neu_metric_entry_t *entry = NULL;
pthread_mutex_lock(&node_metrics->lock);
if (NULL == group) {
HASH_FIND_STR(node_metrics->entries, metric_name, entry);
} else if (NULL != node_metrics->group_metrics) {
neu_group_metrics_t *g = NULL;
HASH_FIND_STR(node_metrics->group_metrics, group, g);
if (NULL != g) {
HASH_FIND_STR(g->entries, metric_name, entry);
}
}
if (NULL == entry) {
pthread_mutex_unlock(&node_metrics->lock);
return -1;
}
if (neu_metric_type_is_counter(entry->type)) {
entry->value += n;
} else if (neu_metric_type_is_rolling_counter(entry->type)) {
entry->value =
neu_rolling_counter_inc(entry->rcnt, global_timestamp, n);
} else {
entry->value = n;
}
pthread_mutex_unlock(&node_metrics->lock);
return 0;
}
static inline void neu_node_metrics_reset(neu_node_metrics_t *node_metrics)
{
neu_metric_entry_t *entry = NULL;
pthread_mutex_lock(&node_metrics->lock);
HASH_LOOP(hh, node_metrics->entries, entry)
{
if (!neu_metric_type_no_reset(entry->type)) {
entry->value = entry->init;
if (neu_metric_type_is_rolling_counter(entry->type)) {
neu_rolling_counter_reset(entry->rcnt);
}
}
}
neu_group_metrics_t *g = NULL;
HASH_LOOP(hh, node_metrics->group_metrics, g)
{
HASH_LOOP(hh, g->entries, entry)
{
if (!neu_metric_type_no_reset(entry->type)) {
entry->value = entry->init;
if (neu_metric_type_is_rolling_counter(entry->type)) {
neu_rolling_counter_reset(entry->rcnt);
}
}
}
}
pthread_mutex_unlock(&node_metrics->lock);
}
static inline int
neu_node_metrics_update_group(neu_node_metrics_t *node_metrics,
const char * group_name,
const char * new_group_name)
{
int rv = -1;
neu_group_metrics_t *group_metrics = NULL;
pthread_mutex_lock(&node_metrics->lock);
HASH_FIND_STR(node_metrics->group_metrics, group_name, group_metrics);
if (NULL != group_metrics) {
char *name = strdup(new_group_name);
if (NULL != name) {
HASH_DEL(node_metrics->group_metrics, group_metrics);
free(group_metrics->name);
group_metrics->name = name;
HASH_ADD_STR(node_metrics->group_metrics, name, group_metrics);
rv = 0;
}
}
pthread_mutex_unlock(&node_metrics->lock);
return rv;
}
static inline void neu_node_metrics_del_group(neu_node_metrics_t *node_metrics,
const char * group_name)
{
neu_group_metrics_t *gm = NULL;
pthread_mutex_lock(&node_metrics->lock);
HASH_FIND_STR(node_metrics->group_metrics, group_name, gm);
if (NULL != gm) {
HASH_DEL(node_metrics->group_metrics, gm);
neu_group_metrics_free(gm);
}
pthread_mutex_unlock(&node_metrics->lock);
}
#ifdef __cplusplus
}
#endif
#endif
-1130
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -35,17 +35,17 @@ extern "C" {
#include "utils/base64.h"
#include "utils/log.h"
#include "utils/mem_cache.h"
#include "utils/zlog.h"
#include "utils/neu_jwt.h"
#include "utils/time.h"
#include "utils/utarray.h"
#include "utils/utextend.h"
#include "utils/uthash.h"
#include "utils/utlist.h"
#include "connection/mqtt_client_intf.h"
#include "connection/neu_connection.h"
#include "connection/neu_connection_eth.h"
#include "event/event.h"
#include "json/json.h"
+7 -41
View File
@@ -27,24 +27,12 @@ extern "C" {
#include "utils/utextend.h"
#include "utils/zlog.h"
#include "event/event.h"
#include "adapter.h"
#include "define.h"
#include "type.h"
#define NEURON_PLUGIN_VER_1_0 \
NEU_VERSION(NEU_VERSION_MAJOR, NEU_VERSION_MINOR, NEU_VERSION_FIX)
#define NEU_PLUGIN_REGISTER_METRIC(plugin, name, init) \
plugin->common.adapter_callbacks->register_metric( \
plugin->common.adapter, name, name##_HELP, name##_TYPE, init)
#define NEU_PLUGIN_UPDATE_METRIC(plugin, name, val, grp) \
plugin->common.adapter_callbacks->update_metric(plugin->common.adapter, \
name, val, grp)
extern int64_t global_timestamp;
#define NEURON_PLUGIN_VER_1_0 100
#define NEURON_PLUGIN_VER_2_0 200
typedef struct neu_plugin_common {
uint32_t magic;
@@ -54,7 +42,9 @@ typedef struct neu_plugin_common {
char name[NEU_NODE_NAME_LEN];
neu_node_link_state_e link_state;
char log_level[NEU_LOG_LEVEL_LEN];
uint16_t tag_size;
uint32_t tag_all_size;
int64_t timestamp;
zlog_category_t *log;
} neu_plugin_common_t;
@@ -69,20 +59,12 @@ struct neu_plugin_group {
void * user_data;
neu_plugin_group_free group_free;
uint32_t interval;
};
typedef int (*neu_plugin_tag_validator_t)(const neu_datatag_t *tag);
typedef struct {
neu_datatag_t *tag;
neu_value_u value;
} neu_plugin_tag_value_t;
typedef struct neu_plugin_intf_funs {
neu_plugin_t *(*open)(void);
int (*close)(neu_plugin_t *plugin);
int (*init)(neu_plugin_t *plugin, bool load);
int (*init)(neu_plugin_t *plugin);
int (*uninit)(neu_plugin_t *plugin);
int (*start)(neu_plugin_t *plugin);
int (*stop)(neu_plugin_t *plugin);
@@ -94,21 +76,8 @@ typedef struct neu_plugin_intf_funs {
struct {
int (*validate_tag)(neu_plugin_t *plugin, neu_datatag_t *tag);
int (*group_timer)(neu_plugin_t *plugin, neu_plugin_group_t *group);
int (*group_sync)(neu_plugin_t *plugin, neu_plugin_group_t *group);
int (*write_tag)(neu_plugin_t *plugin, void *req,
neu_datatag_t *tag, neu_value_u value);
int (*write_tags)(
neu_plugin_t *plugin, void *req,
UT_array *tag_values); // UT_array {neu_datatag_t, neu_value_u}
neu_plugin_tag_validator_t tag_validator;
int (*load_tags)(
neu_plugin_t *plugin, const char *group, neu_datatag_t *tags,
int n_tag); // create tags using data from the database
int (*add_tags)(neu_plugin_t *plugin, const char *group,
neu_datatag_t *tags,
int n_tag); // create tags by API
int (*del_tags)(neu_plugin_t *plugin, int n_tag);
} driver;
};
@@ -116,18 +85,15 @@ typedef struct neu_plugin_intf_funs {
typedef struct neu_plugin_module {
const uint32_t version;
const char * schema;
const char * module_name;
const char * module_descr;
const char * module_descr_zh;
const neu_plugin_intf_funs_t *intf_funs;
neu_node_type_e type;
neu_plugin_kind_e kind;
neu_subscribe_type_e sub_msg[NEU_APP_SUBSCRIBE_MSG_SIZE];
bool display;
bool single;
const char * single_name;
neu_event_timer_type_e timer_type;
neu_tag_cache_type_e cache_type;
} neu_plugin_module_t;
inline static neu_plugin_common_t *
+12 -44
View File
@@ -23,16 +23,16 @@ config_ **/
#include <stdbool.h>
#include <stdint.h>
#include "define.h"
#include "type.h"
#include "utils/utextend.h"
#include "json/json.h"
#include "type.h"
#define NEU_TAG_META_SIZE 20
typedef enum {
NEU_ATTRIBUTE_READ = 1,
NEU_ATTRIBUTE_WRITE = 2,
NEU_ATTRIBUTE_SUBSCRIBE = 4,
NEU_ATTRIBUTE_STATIC = 8,
} neu_attribute_e;
typedef enum {
@@ -44,10 +44,6 @@ typedef enum {
NEU_DATATAG_ENDIAN_BL32 = 5, // #BL 2,1,4,3
NEU_DATATAG_ENDIAN_L64 = 6, // #L 8,7,6,5,4,3,2,1
NEU_DATATAG_ENDIAN_B64 = 7, // #B 1,2,3,4,5,6,7,8
NEU_DATATAG_ENDIAN_LL64 = 8,
NEU_DATATAG_ENDIAN_LB64 = 9,
NEU_DATATAG_ENDIAN_BB64 = 10,
NEU_DATATAG_ENDIAN_BL64 = 11,
} neu_datatag_endian_e;
typedef enum {
@@ -63,22 +59,15 @@ typedef union {
} value16;
struct {
neu_datatag_endian_e endian;
bool is_default;
} value32;
struct {
neu_datatag_endian_e endian;
bool is_default;
} value64;
struct {
uint16_t length;
neu_datatag_string_type_e type;
bool is_default;
} string;
struct {
uint8_t length;
} bytes;
struct {
bool op;
uint8_t bit;
@@ -88,33 +77,23 @@ typedef union {
typedef struct {
char * name;
char * address;
char * description;
neu_attribute_e attribute;
neu_type_e type;
uint8_t precision;
double decimal;
char * description;
neu_datatag_addr_option_u option;
uint8_t meta[NEU_TAG_META_LENGTH];
uint8_t meta[NEU_TAG_META_SIZE];
} neu_datatag_t;
typedef struct neu_tag_meta {
char name[NEU_TAG_NAME_LEN];
neu_dvalue_t value;
} neu_tag_meta_t;
UT_icd *neu_tag_get_icd();
neu_datatag_t *neu_tag_dup(const neu_datatag_t *tag);
void neu_tag_copy(neu_datatag_t *tag, const neu_datatag_t *other);
void neu_tag_fini(neu_datatag_t *tag);
void neu_tag_free(neu_datatag_t *tag);
inline static bool neu_tag_attribute_test(const neu_datatag_t *tag,
neu_attribute_e attribute)
inline static bool neu_tag_attribute_test(neu_datatag_t * tag,
neu_attribute_e attribute)
{
return (tag->attribute & attribute) == attribute;
}
UT_icd *neu_tag_get_icd();
/**
* @brief Special usage of parsing tag address, e.g. setting length of string
* type, setting of endian.
@@ -123,7 +102,7 @@ inline static bool neu_tag_attribute_test(const neu_datatag_t *tag,
* @param[in] option contain actions that the label can perform.
* @return 0 on success, -1 on failure.
*/
int neu_datatag_parse_addr_option(const neu_datatag_t * datatag,
int neu_datatag_parse_addr_option(neu_datatag_t * datatag,
neu_datatag_addr_option_u *option);
bool neu_datatag_string_is_utf8(char *data, int len);
@@ -137,15 +116,4 @@ int neu_datatag_string_dtoh(char *str, int len);
int neu_datatag_string_tod(char *str, int len, int buf_len);
int neu_datatag_string_toe(char *str, int len, int buf_len);
int neu_tag_get_static_value(const neu_datatag_t *tag, neu_value_u *value);
int neu_tag_set_static_value(neu_datatag_t *tag, const neu_value_u *value);
int neu_tag_get_static_value_json(neu_datatag_t *tag, neu_json_type_e *t,
neu_json_value_u *v);
int neu_tag_set_static_value_json(neu_datatag_t *tag, neu_json_type_e t,
const neu_json_value_u *v);
char *neu_tag_dump_static_value(const neu_datatag_t *tag);
int neu_tag_load_static_value(neu_datatag_t *tag, const char *s);
#endif
#endif
+28 -299
View File
@@ -28,30 +28,23 @@ extern "C" {
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
typedef enum {
NEU_TYPE_INT8 = 1,
NEU_TYPE_UINT8 = 2,
NEU_TYPE_INT16 = 3,
NEU_TYPE_UINT16 = 4,
NEU_TYPE_INT32 = 5,
NEU_TYPE_UINT32 = 6,
NEU_TYPE_INT64 = 7,
NEU_TYPE_UINT64 = 8,
NEU_TYPE_FLOAT = 9,
NEU_TYPE_DOUBLE = 10,
NEU_TYPE_BIT = 11,
NEU_TYPE_BOOL = 12,
NEU_TYPE_STRING = 13,
NEU_TYPE_BYTES = 14,
NEU_TYPE_ERROR = 15,
NEU_TYPE_WORD = 16,
NEU_TYPE_DWORD = 17,
NEU_TYPE_LWORD = 18,
NEU_TYPE_PTR = 19,
NEU_TYPE_TIME = 20,
NEU_TYPE_DATA_AND_TIME = 21,
NEU_TYPE_INT8 = 1,
NEU_TYPE_UINT8 = 2,
NEU_TYPE_INT16 = 3,
NEU_TYPE_UINT16 = 4,
NEU_TYPE_INT32 = 5,
NEU_TYPE_UINT32 = 6,
NEU_TYPE_INT64 = 7,
NEU_TYPE_UINT64 = 8,
NEU_TYPE_FLOAT = 9,
NEU_TYPE_DOUBLE = 10,
NEU_TYPE_BIT = 11,
NEU_TYPE_BOOL = 12,
NEU_TYPE_STRING = 13,
NEU_TYPE_BYTES = 14,
NEU_TYPE_ERROR = 15,
} neu_type_e;
inline static const char *neu_type_string(neu_type_e type)
@@ -87,128 +80,28 @@ inline static const char *neu_type_string(neu_type_e type)
return "NEU_TYPE_BYTES";
case NEU_TYPE_ERROR:
return "NEU_TYPE_ERROR";
case NEU_TYPE_WORD:
return "NEU_TYPE_WORD";
case NEU_TYPE_DWORD:
return "NEU_TYPE_DWORD";
case NEU_TYPE_LWORD:
return "NEU_TYPE_LWORD";
case NEU_TYPE_PTR:
return "NEU_TYPE_PTR";
case NEU_TYPE_TIME:
return "NEU_TYPE_TIME";
case NEU_TYPE_DATA_AND_TIME:
return "NEU_TYPE_DATA_AND_TIME";
}
return "";
}
typedef struct {
neu_type_e type; // string or bytes
uint16_t length;
uint8_t * ptr;
} neu_value_ptr_t;
#define NEU_VALUE_SIZE 128
typedef struct {
uint8_t bytes[NEU_VALUE_SIZE];
uint8_t length;
} __attribute__((packed)) neu_value_bytes_t;
typedef union {
bool boolean;
int8_t i8;
uint8_t u8;
int16_t i16;
uint16_t u16;
int32_t i32;
uint32_t u32;
int64_t i64;
uint64_t u64;
float f32;
double d64;
char str[NEU_VALUE_SIZE];
neu_value_bytes_t bytes;
neu_value_ptr_t ptr;
bool boolean;
int8_t i8;
uint8_t u8;
int16_t i16;
uint16_t u16;
int32_t i32;
uint32_t u32;
int64_t i64;
uint64_t u64;
float f32;
double d64;
char str[NEU_VALUE_SIZE];
uint8_t bytes[NEU_VALUE_SIZE];
} neu_value_u;
static inline char *neu_value_str(neu_type_e type, neu_value_u value)
{
static __thread char str[128] = { 0 };
switch (type) {
case NEU_TYPE_INT8:
snprintf(str, sizeof(str), "type: %s, value: %i", neu_type_string(type),
value.i8);
break;
case NEU_TYPE_UINT8:
snprintf(str, sizeof(str), "type: %s, value: %u", neu_type_string(type),
value.u8);
break;
case NEU_TYPE_INT16:
snprintf(str, sizeof(str), "type: %s, value: %i", neu_type_string(type),
value.i16);
break;
case NEU_TYPE_WORD:
case NEU_TYPE_UINT16:
snprintf(str, sizeof(str), "type: %s, value: %u", neu_type_string(type),
value.u16);
break;
case NEU_TYPE_INT32:
snprintf(str, sizeof(str), "type: %s, value: %i", neu_type_string(type),
value.i32);
break;
case NEU_TYPE_DWORD:
case NEU_TYPE_UINT32:
snprintf(str, sizeof(str), "type: %s, value: %u", neu_type_string(type),
value.u32);
break;
case NEU_TYPE_INT64: {
long long int i = value.i64;
snprintf(str, sizeof(str), "type: %s, value: %lld",
neu_type_string(type), i);
break;
}
case NEU_TYPE_LWORD:
case NEU_TYPE_UINT64: {
long long unsigned int i = value.u64;
snprintf(str, sizeof(str), "type: %s, value: %llu",
neu_type_string(type), i);
break;
}
case NEU_TYPE_FLOAT:
snprintf(str, sizeof(str), "type: %s, value: %f", neu_type_string(type),
value.f32);
break;
case NEU_TYPE_DOUBLE:
snprintf(str, sizeof(str), "type: %s, value: %f", neu_type_string(type),
value.d64);
break;
case NEU_TYPE_BIT:
snprintf(str, sizeof(str), "type: %s, value: %u", neu_type_string(type),
value.u8);
break;
case NEU_TYPE_BOOL:
snprintf(str, sizeof(str), "type: %s, value: %u", neu_type_string(type),
value.boolean);
break;
case NEU_TYPE_STRING:
case NEU_TYPE_TIME:
case NEU_TYPE_DATA_AND_TIME: {
snprintf(str, sizeof(str), "type: %s, value: %c%c%c",
neu_type_string(type), value.str[0], value.str[1],
value.str[2]);
break;
}
default:
break;
}
return str;
}
typedef struct {
neu_type_e type;
neu_value_u value;
@@ -506,42 +399,6 @@ static inline uint64_t neu_htonll(uint64_t u)
return ret;
}
static inline uint64_t neu_htonlb(uint64_t u)
{
uint8_t *in = (uint8_t *) &u;
uint64_t out = 0;
uint8_t *out_bytes = (uint8_t *) &out;
out_bytes[0] = in[1];
out_bytes[1] = in[0];
out_bytes[2] = in[3];
out_bytes[3] = in[2];
out_bytes[4] = in[5];
out_bytes[5] = in[4];
out_bytes[6] = in[7];
out_bytes[7] = in[6];
return out;
}
static inline uint64_t neu_htonbl(uint64_t u)
{
uint8_t *in = (uint8_t *) &u;
uint64_t out = 0;
uint8_t *out_bytes = (uint8_t *) &out;
out_bytes[0] = in[6];
out_bytes[1] = in[7];
out_bytes[2] = in[4];
out_bytes[3] = in[5];
out_bytes[4] = in[2];
out_bytes[5] = in[3];
out_bytes[6] = in[0];
out_bytes[7] = in[1];
return out;
}
static inline uint64_t neu_ntohll(uint64_t u)
{
return neu_htonll(u);
@@ -577,134 +434,6 @@ static inline void neu_htons_p(uint16_t *pu)
neu_ntohs_p(pu);
}
static inline uint16_t neu_get_u16(uint8_t *bytes)
{
uint16_t ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
return ret;
}
static inline int16_t neu_get_i16(uint8_t *bytes)
{
int16_t ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
return ret;
}
static inline uint32_t neu_get_u32(uint8_t *bytes)
{
uint32_t ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
t[2] = bytes[2];
t[3] = bytes[3];
return ret;
}
static inline int32_t neu_get_i32(uint8_t *bytes)
{
int32_t ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
t[2] = bytes[2];
t[3] = bytes[3];
return ret;
}
static inline float neu_get_f32(uint8_t *bytes)
{
float ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
t[2] = bytes[2];
t[3] = bytes[3];
return ret;
}
static inline uint64_t neu_get_u64(uint8_t *bytes)
{
uint64_t ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
t[2] = bytes[2];
t[3] = bytes[3];
t[4] = bytes[4];
t[5] = bytes[5];
t[6] = bytes[6];
t[7] = bytes[7];
return ret;
}
static inline int64_t neu_get_i64(uint8_t *bytes)
{
int64_t ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
t[2] = bytes[2];
t[3] = bytes[3];
t[4] = bytes[4];
t[5] = bytes[5];
t[6] = bytes[6];
t[7] = bytes[7];
return ret;
}
static inline double neu_get_f64(uint8_t *bytes)
{
double ret = 0;
uint8_t *t = NULL;
t = (uint8_t *) &ret;
t[0] = bytes[0];
t[1] = bytes[1];
t[2] = bytes[2];
t[3] = bytes[3];
t[4] = bytes[4];
t[5] = bytes[5];
t[6] = bytes[6];
t[7] = bytes[7];
return ret;
}
#ifdef __cplusplus
}
#endif
-2
View File
@@ -87,6 +87,4 @@ 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
-110
View File
@@ -1,110 +0,0 @@
/**
* 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_HTTP_HANDLER_H_
#define _NEU_HTTP_HANDLER_H_
#include <stdlib.h>
#include <nng/nng.h>
#include <nng/supplemental/http/http.h>
#include "utils/neu_jwt.h"
#include "json/neu_json_error.h"
#define NEU_PROCESS_HTTP_REQUEST(aio, req_type, decode_fun, func) \
{ \
char * req_data = NULL; \
size_t req_data_size = 0; \
req_type *req = NULL; \
\
if (neu_http_get_body((aio), (void **) &req_data, &req_data_size) == \
0 && \
decode_fun(req_data, &req) == 0) { \
{ func }; \
decode_fun##_free(req); \
} else { \
neu_http_bad_request(aio, "{\"error\": 1002}"); \
} \
free(req_data); \
}
#define NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(aio, req_type, decode_fun, func) \
{ \
if (!disable_jwt) { \
char *jwt = \
(char *) neu_http_get_header(aio, (char *) "Authorization"); \
\
NEU_JSON_RESPONSE_ERROR(neu_jwt_validate(jwt), { \
if (error_code.error != NEU_ERR_SUCCESS) { \
neu_http_response(aio, error_code.error, result_error); \
free(result_error); \
return; \
} \
}) \
} \
NEU_PROCESS_HTTP_REQUEST(aio, req_type, decode_fun, func); \
}
#define NEU_VALIDATE_JWT(aio) \
{ \
if (!disable_jwt) { \
char *jwt = \
(char *) neu_http_get_header(aio, (char *) "Authorization"); \
\
NEU_JSON_RESPONSE_ERROR(neu_jwt_validate(jwt), { \
if (error_code.error != NEU_ERR_SUCCESS) { \
neu_http_response(aio, error_code.error, result_error); \
free(result_error); \
return; \
} \
}); \
} \
}
enum neu_http_method {
NEU_HTTP_METHOD_UNDEFINE = 0x0,
NEU_HTTP_METHOD_GET,
NEU_HTTP_METHOD_POST,
NEU_HTTP_METHOD_PUT,
NEU_HTTP_METHOD_DELETE,
NEU_HTTP_METHOD_OPTIONS
};
enum neu_http_handler_type {
NEU_HTTP_HANDLER_FUNCTION = 0x0,
NEU_HTTP_HANDLER_DIRECTORY,
NEU_HTTP_HANDLER_REDIRECT,
};
struct neu_http_handler {
enum neu_http_method method;
char * url;
enum neu_http_handler_type type;
union neu_http_handler_value {
void *handler;
char *path;
char *dst_url;
} value;
};
int neu_http_add_handler(nng_http_server * server,
const struct neu_http_handler *http_handler);
void neu_http_handle_cors(nng_aio *aio);
#endif
+42 -72
View File
@@ -21,36 +21,11 @@ config_ **/
#define _NEU_LOG_H_
#include <inttypes.h>
#include <memory.h>
#include "utils/zlog.h"
#include "define.h"
extern zlog_category_t *neuron;
inline static const char *log_level_to_str(int level)
{
switch (level) {
case ZLOG_LEVEL_FATAL:
return NEU_LOG_LEVEL_FATAL;
case ZLOG_LEVEL_ERROR:
return NEU_LOG_LEVEL_ERROR;
case ZLOG_LEVEL_WARN:
return NEU_LOG_LEVEL_WARN;
case ZLOG_LEVEL_NOTICE:
return NEU_LOG_LEVEL_NOTICE;
case ZLOG_LEVEL_INFO:
return NEU_LOG_LEVEL_INFO;
case ZLOG_LEVEL_DEBUG:
return NEU_LOG_LEVEL_DEBUG;
default:
return "UNKNOWN";
}
}
#define nlog_level_change(level) zlog_level_switch(neuron, level)
#define nlog_fatal(...) \
zlog(neuron, __FILE__, sizeof(__FILE__) - 1, __func__, \
sizeof(__func__) - 1, __LINE__, ZLOG_LEVEL_FATAL, __VA_ARGS__)
@@ -89,54 +64,49 @@ inline static const char *log_level_to_str(int level)
zlog((plugin)->common.log, __FILE__, sizeof(__FILE__) - 1, __func__, \
sizeof(__func__) - 1, __LINE__, ZLOG_LEVEL_DEBUG, __VA_ARGS__)
enum neu_protocol_log_type {
NEU_PROTOCOL_SEND,
NEU_PROTOCOL_RECV,
};
#define plog_send_protocol(plugin, bytes, n_byte) \
uint16_t log_protocol_buf_size = n_byte * 5 + 20; \
char * log_protocol_buf = calloc(log_protocol_buf_size, 1); \
int log_offset = 0; \
uint16_t tmp_n_byte = n_byte; \
log_offset = snprintf(log_protocol_buf, log_protocol_buf_size, ">>(%d)", \
tmp_n_byte); \
for (int i = 0; i < n_byte; i++) { \
log_offset += snprintf(log_protocol_buf + log_offset, \
log_protocol_buf_size - log_offset, \
" 0x%02hhX", (bytes)[i]); \
} \
plog_debug(plugin, "%s", log_protocol_buf); \
free(log_protocol_buf);
inline static void zlog_protocol(zlog_category_t *log, uint8_t *bytes,
uint16_t n_byte,
enum neu_protocol_log_type type)
{
static __thread char buf[2048] = { 0 };
int offset = 0;
#define plog_recv_protocol(plugin, bytes, n_byte) \
uint16_t log_protocol_buf_size = n_byte * 5 + 20; \
char * log_protocol_buf = calloc(log_protocol_buf_size, 1); \
int log_offset = 0; \
uint16_t tmp_n_byte = n_byte; \
log_offset = snprintf(log_protocol_buf, log_protocol_buf_size, "<<(%d)", \
tmp_n_byte); \
for (int i = 0; i < n_byte; i++) { \
log_offset += snprintf(log_protocol_buf + log_offset, \
log_protocol_buf_size - log_offset, \
" 0x%02hhX", (bytes)[i]); \
} \
plog_debug(plugin, "%s", log_protocol_buf); \
free(log_protocol_buf);
memset(buf, 0, sizeof(buf));
if (type == NEU_PROTOCOL_SEND) {
offset = snprintf(buf, sizeof(buf) - 1, ">>(%d)", n_byte);
} else {
offset = snprintf(buf, sizeof(buf) - 1, "<<(%d)", n_byte);
}
for (int i = 0; i < n_byte; i++) {
if (sizeof(buf) > (size_t) offset && sizeof(buf) - offset > 10) {
int s_ret = snprintf(buf + offset, sizeof(buf) - offset - 1,
" 0x%02hhX", bytes[i]);
if (s_ret > 0) {
offset += s_ret;
} else {
break;
}
} else {
break;
}
}
zlog_debug(log, "%s", buf);
}
#define zlog_send_protocol(log, bytes, n_byte) \
zlog_protocol(log, (uint8_t *) bytes, n_byte, NEU_PROTOCOL_SEND)
#define zlog_recv_protocol(log, bytes, n_byte) \
zlog_protocol(log, (uint8_t *) bytes, n_byte, NEU_PROTOCOL_RECV)
#define plog_recv_protocol(plugin, bytes, n_byte) \
zlog_recv_protocol((plugin)->common.log, bytes, n_byte)
#define plog_send_protocol(plugin, bytes, n_byte) \
zlog_send_protocol((plugin)->common.log, bytes, n_byte)
void remove_logs(const char *node);
#define zlog_recv_protocol(log, bytes, n_byte) \
uint16_t log_protocol_buf_size = n_byte * 5 + 20; \
char * log_protocol_buf = calloc(log_protocol_buf_size, 1); \
int log_offset = 0; \
uint16_t tmp_n_byte = n_byte; \
log_offset = snprintf(log_protocol_buf, log_protocol_buf_size, "<<(%d)", \
tmp_n_byte); \
for (int i = 0; i < n_byte; i++) { \
log_offset += snprintf(log_protocol_buf + log_offset, \
log_protocol_buf_size - log_offset, \
" 0x%02hhX", (bytes)[i]); \
} \
zlog_debug(log, "%s", log_protocol_buf); \
free(log_protocol_buf);
#endif
+57
View File
@@ -0,0 +1,57 @@
/**
* 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_MEM_CACHE
#define NEU_MEM_CACHE
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
typedef struct neu_mem_cache neu_mem_cache_t;
typedef void (*cache_data_release)(void *data);
typedef struct {
size_t size;
void * data;
cache_data_release release;
uint32_t timestamp;
} cache_item_t;
typedef void (*cache_dump)(cache_item_t *item, void *ctx);
neu_mem_cache_t *neu_mem_cache_create(const size_t max_bytes,
const size_t max_items);
int neu_mem_cache_add(neu_mem_cache_t *cache, cache_item_t *item);
cache_item_t neu_mem_cache_earliest(neu_mem_cache_t *cache);
cache_item_t neu_mem_cache_latest(neu_mem_cache_t *cache);
void neu_mem_cache_used(neu_mem_cache_t *cache, size_t *used_bytes,
size_t *used_items);
void neu_mem_cache_resize(neu_mem_cache_t *cache, size_t new_bytes,
size_t new_items);
int neu_mem_cache_dump(neu_mem_cache_t *cache, cache_dump callback, void *ctx);
int neu_mem_cache_clear(neu_mem_cache_t *cache);
void neu_mem_cache_destroy(neu_mem_cache_t *cache);
#ifdef __cplusplus
}
#endif
#endif
+2
View File
@@ -25,6 +25,8 @@ extern "C" {
#include <stdbool.h>
extern bool disable_jwt;
int neu_jwt_init(const char *dir_path);
int neu_jwt_new(char **token);
int neu_jwt_validate(char *b_token);
-12
View File
@@ -192,16 +192,4 @@ neu_protocol_unpack_buf_used_size(neu_protocol_unpack_buf_t *buf)
return buf->offset;
}
inline static void
neu_protocol_unpack_buf_use_all(neu_protocol_unpack_buf_t *buf)
{
buf->offset = buf->size;
}
inline static uint16_t
neu_protocol_unpack_buf_size(neu_protocol_unpack_buf_t *buf)
{
return buf->size;
}
#endif
-115
View File
@@ -1,115 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2024 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef NEURON_UTILS_ROLLING_COUNTER_H
#define NEURON_UTILS_ROLLING_COUNTER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/** Rolling counter.
*
* This counter is for counting values within some latest time span, like
* network bytes sent within the last 5 seconds etc.
*/
typedef struct {
uint64_t val; // accumulator
uint64_t ts; // head time stamp in milliseconds
uint32_t res : 21; // time resolution in milliseconds
uint32_t hd : 5; // head position
uint32_t n : 6; // number of counters
uint32_t counts[]; // bins of counters
} neu_rolling_counter_t;
/** Create rolling counter.
*
* @param span time span in milliseconds
*/
static inline neu_rolling_counter_t *neu_rolling_counter_new(unsigned span)
{
unsigned n = span <= 6000 ? 4 : span <= 32000 ? 8 : span <= 64000 ? 16 : 32;
assert(span / n < (1 << 22)); // should not overflow ti
neu_rolling_counter_t *counter = (neu_rolling_counter_t *) calloc(
1, sizeof(*counter) + sizeof(counter->counts[0]) * n);
if (counter) {
counter->res = span / n;
counter->n = n;
}
return counter;
}
/** Destructs the rolling counter.
*/
static inline void neu_rolling_counter_free(neu_rolling_counter_t *counter)
{
if (counter) {
free(counter);
}
}
/** Increment the rolling counter and return the value;
*
* @param ts time stamp in milliseconds, should be monotonic
* @param dt delta value to increment by
*/
static inline uint64_t neu_rolling_counter_inc(neu_rolling_counter_t *counter,
uint64_t ts, unsigned dt)
{
uint64_t step = (ts - counter->ts) / counter->res;
for (unsigned i = 0; i < step && i < counter->n; ++i) {
counter->hd = (counter->hd + 1) & (counter->n - 1);
counter->val -= counter->counts[counter->hd];
counter->counts[counter->hd] = 0;
}
counter->val += dt;
counter->counts[counter->hd] += dt;
counter->ts += step * counter->res;
return counter->val;
}
/** Reset the counter.
*/
static inline void neu_rolling_counter_reset(neu_rolling_counter_t *counter)
{
counter->val = 0;
counter->hd = 0;
memset(counter->counts, 0, counter->n * sizeof(counter->counts[0]));
}
/** Return the counter value.
*
* NOTE: may return stale value if the counter is not updated frequent enough.
*/
static inline uint64_t neu_rolling_counter_value(neu_rolling_counter_t *counter)
{
return counter->val;
}
#ifdef __cplusplus
}
#endif
#endif
-92
View File
@@ -1,92 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2024 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef NEURON_UTILS_SET_H
#define NEURON_UTILS_SET_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdlib.h>
#include "uthash.h"
typedef struct {
const char * str;
UT_hash_handle hh;
} neu_strset_node_t;
/** Set of strings.
*/
typedef neu_strset_node_t *neu_strset_t;
/** Destructs the string set.
*/
static inline void neu_strset_free(neu_strset_t *set)
{
neu_strset_node_t *e = NULL, *tmp = NULL;
HASH_ITER(hh, *set, e, tmp)
{
HASH_DEL(*set, e);
free(e);
}
}
/** Return the cardinal of the set.
*/
static inline unsigned neu_strset_count(neu_strset_t *set)
{
return HASH_COUNT(*set);
}
/** Return true if the given string is a member of the set, false otherwise.
*/
static inline bool neu_strset_test(neu_strset_t *set, const char *str)
{
neu_strset_node_t *e = NULL;
HASH_FIND_STR(*set, str, e);
return NULL != e;
}
/** Add the given string to the set.
* NOTE: The given string is referenced, not copied.
* Return 1 if success, 0 if the string is already a member, -1 on error.
*/
static inline int neu_strset_add(neu_strset_t *set, const char *str)
{
neu_strset_node_t *e = NULL;
HASH_FIND_STR(*set, str, e);
if (e) {
return 0;
}
e = calloc(1, sizeof(*e));
if (NULL == e) {
return -1;
}
e->str = str;
HASH_ADD_KEYPTR(hh, *set, e->str, strlen(e->str), e);
return 1;
}
#ifdef __cplusplus
}
#endif
#endif
+3 -36
View File
@@ -33,25 +33,12 @@ static inline UT_array *utarray_clone(UT_array *array)
result->i = array->i;
result->n = array->n;
result->icd = array->icd;
if (array->n > 0) {
result->d = (char *) calloc(1, array->n * array->icd.sz);
memcpy(result->d, array->d, array->n * array->icd.sz);
} else {
result->d = NULL;
}
result->d = (char *) calloc(1, array->n * array->icd.sz);
memcpy(result->d, array->d, array->n * array->icd.sz);
return result;
}
static inline void *utarray_steal(UT_array *array)
{
void *data = array->d;
array->i = 0;
array->n = 0;
array->d = NULL;
return data;
}
#define utarray_foreach(array, type, elem) \
for (type elem = (type) utarray_front(array); elem != NULL; \
elem = (type) utarray_next(array, elem))
@@ -71,24 +58,4 @@ static inline void *utarray_steal(UT_array *array)
#define DL_REVERSE_FOREACH_END(head, tail, el) \
while (((el) = (el)->prev) != (head))
#ifdef NO_DECLTYPE
#define HASH_LOOP(hh, head, el) \
for ((el) = (head); (el) != NULL; \
(*(char **) (&(el))) = (char *) (el)->hh.next)
#else
#define HASH_LOOP(hh, head, el) \
for ((el) = (head); (el) != NULL; (el) = DECLTYPE(el)((el)->hh.next))
#endif
static inline UT_array *utarray_deep_clone(UT_array *array)
{
UT_array *result = NULL;
utarray_new(result, &array->icd);
utarray_foreach(array, void *, elem) { utarray_push_back(result, elem); }
return result;
}
#endif
#endif
Executable
+101
View File
@@ -0,0 +1,101 @@
#!/bin/bash
set -e
compiler_prefix="x86_64-linux-gnu"
dir="/usr/local/"
install_dir=
arch=x86_64
while getopts ":c:d:a:" OPT; do
case ${OPT} in
a)
arch=$OPTARG
;;
c)
compiler_prefix=$OPTARG
;;
d)
dir=$OPTARG
;;
esac
done
install_dir=${dir}/${compiler_prefix}
#$1 rep
#$2 tag
#$3 compile option
function compile_source() {
git clone https://github.com/$1 tmp
cd tmp
git checkout -b br $2
mkdir build && cd build
cmake .. -DCMAKE_C_COMPILER=${compiler_prefix}-gcc \
-DCMAKE_CXX_COMPILER=${compiler_prefix}-g++ \
-DCMAKE_STAGING_PREFIX=${install_dir} \
-DCMAKE_PREFIX_PATH=${install_dir} \
$3
# github-hosted runners has 2 core
make -j4 && sudo make install
cd ../../
rm -rf tmp
}
function build_openssl() {
echo "Installing openssl (1.1.1)"
if [ $compiler_prefix == "x86_64-linux-gnu" ]; then
sudo apt-get install -y openssl libssl-dev
else
git clone -b OpenSSL_1_1_1 https://github.com/openssl/openssl.git
cd openssl
mkdir -p ${install_dir}/openssl/ssl
./Configure linux-${arch} no-asm shared \
--prefix=${install_dir}/ \
--openssldir=${install_dir}/openssl/ssl \
--cross-compile-prefix=${compiler_prefix}-
make clean
make -j4
make install_sw
make clean
cd ../
fi
}
function build_zlog() {
git clone -b 1.2.15 https://github.com/HardySimpson/zlog.git
cd zlog
make CC=${compiler_prefix}-gcc
if [ $compiler_prefix == "x86_64-linux-gnu" ]; then
sudo make install
sudo make PREFIX=${install_dir} install
else
sudo make PREFIX=${install_dir} install
fi
}
function build_sqlite3() {
curl https://www.sqlite.org/2022/sqlite-autoconf-3390000.tar.gz \
--output sqlite3.tar.gz
mkdir -p sqlite3
tar xzf sqlite3.tar.gz --strip-components=1 -C sqlite3
cd sqlite3
./configure --prefix=${install_dir} \
--disable-shared --disable-readline \
--host ${arch} CC=${compiler_prefix}-gcc \
&& make -j4 \
&& sudo make install
cd ../
}
build_zlog
compile_source neugates/jansson.git HEAD "-DJANSSON_BUILD_DOCS=OFF -DJANSSON_EXAMPLES=OFF"
build_openssl
compile_source neugates/nng.git HEAD "-DBUILD_SHARED_LIBS=OFF -DNNG_TESTS=OFF"
compile_source benmcollins/libjwt.git v1.13.1 "-DENABLE_PIC=ON -DBUILD_SHARED_LIBS=OFF"
compile_source neugates/MQTT-C.git HEAD "-DCMAKE_POSITION_INDEPENDENT_CODE=ON -DMQTT_C_OpenSSL_SUPPORT=ON -DMQTT_C_EXAMPLES=OFF"
build_sqlite3
if [ $compiler_prefix == "x86_64-linux-gnu" ]; then
compile_source google/googletest.git release-1.11.0
fi
-20
View File
@@ -1,20 +0,0 @@
import jwt # pip install pyjwt
import time
with open("neuron.key", "r") as f:
private_key = f.read()
current_time = int(time.time())
two_years = 60 * 60 * 24 * 365 * 2
header = {"alg": "RS256", "typ": "JWT"}
payload = {
"aud": "neuron",
"bodyEncode": 0,
"exp": current_time + two_years,
"iat": current_time,
"iss": "neuron",
}
token = jwt.encode(payload, private_key, algorithm="RS256", headers=header).decode(
"utf-8"
)
print(f"Bearer {token}")
Executable
+466
View File
@@ -0,0 +1,466 @@
#!/bin/sh
#
# 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.
#
"""":
if type python3 > /dev/null 2>&1
then
exec python3 "$0" "$@"
elif type python > /dev/null 2>&1
then
exec python "$0" "$@"
else
echo >&2 "Python not installed"
fi
exit 1
""" # """
from __future__ import print_function
import argparse
import os
import re
import sqlite3
import json
VERBOSE = False
def log(message):
if VERBOSE:
print(message)
def parse_args():
"""Parse command line arguments."""
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", action="count", help="verbosity")
parser.add_argument(
"-s",
"--schema_dir",
type=str,
default="config/",
help="schema directory",
)
parser.add_argument(
"-d",
"--data_dir",
type=str,
default="persistence/",
help="data directory",
)
subparsers = parser.add_subparsers(
dest="subcommand", help="supported subcommands"
)
import_parser = subparsers.add_parser(
"import", help="import persistence json data"
)
show_parser = subparsers.add_parser(
"show", help="show database schema version"
)
up_parser = subparsers.add_parser(
"up", help="bring database schema to latest version"
)
up_parser.add_argument(
"--import_once",
action="store_true",
help="import persistence json data if database is empty",
)
return parser.parse_args()
class Migration:
def __init__(self, schema_dir="config", database_dir="persistence", database_name="sqlite.db"):
try:
database_path = os.path.join(database_dir, database_name)
conn = sqlite3.connect(database_path)
except Exception as e:
print("Connecting database `{}` fail, {}".format(database_path, e))
raise e
self.conn_ = conn
self.cursor_ = self.conn_.cursor()
self.schema_dir = schema_dir
self.database_dir_ = database_dir
self.database_name_ = database_name
log("Creating migrations table if not exists")
self.ensure_migrations_table_exists()
def ensure_migrations_table_exists(self):
"""Create migration table if not exists."""
self.cursor_.execute(
"""
CREATE TABLE IF NOT EXISTS migrations (
migration_id INTEGER PRIMARY KEY,
version TEXT NOT NULL UNIQUE,
description TEXT NOT NULL,
dirty INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP)
"""
)
def head(self):
"""Read the current version from the database"""
log("Reading migration head version")
self.cursor_.execute(
"SELECT version, description, dirty, created_at FROM migrations"
" ORDER BY migration_id DESC LIMIT 1"
)
row = self.cursor_.fetchone()
if not row:
return {
"version": None,
"description": None,
"dirty": None,
"created_at": None,
}
return {
"version": row[0],
"description": row[1],
"dirty": row[2],
"created_at": row[3],
}
def print_head(self):
head = self.head()
if not head["version"]:
print("No version.")
return
print(
"Version: {}, ({} {})".format(
head["version"], head["created_at"], head["description"]
)
)
if head["dirty"]:
print("Warning: the migration database is dirty")
def get_migration_info(self, file_name):
"""Extract the migration info from migration file name."""
match = re.search(
"(?P<version>[^_]*)_?(?P<description>.*)\\.sql",
file_name,
re.IGNORECASE,
)
if not match:
return {"version": None, "description": None}
return {
"version": match.group("version"),
"description": match.group("description"),
}
def should_apply(self, migration_filename, target_version=None):
"""Check whether to apply the migration file."""
head = self.head()
current_version = head["version"] or ""
if target_version and target_version == current_version:
# already on the target version, don't apply the migration
return False
# extract the proposed version from the migration filename
proposed_version = self.get_migration_info(migration_filename)[
"version"
]
if not proposed_version:
# does not have a valid version in the name
return False
if proposed_version <= current_version:
return False
if target_version and proposed_version > target_version:
return False
return True
def apply(self, import_once):
"""Migrate to the latest state."""
head = self.head()
if head["dirty"]:
print("Latest version is dirty, please tune manually.")
return
migration_filenames = list(
filter(self.should_apply, os.listdir(self.schema_dir))
)
# Sort the migrations based on the version encoded in the filename
migration_filenames.sort()
for migration_filename in migration_filenames:
print("Applying migration " + migration_filename)
info = self.get_migration_info(migration_filename)
self.cursor_.execute(
"""INSERT INTO migrations (version, description, dirty)
VALUES (?, ?, 1)""",
(
info["version"],
info["description"],
),
)
self.conn_.commit()
with open(
os.path.join(self.schema_dir, migration_filename), "r"
) as f:
sql = f.read()
self.cursor_.executescript(sql)
self.cursor_.execute(
"UPDATE migrations SET dirty = 0 WHERE migration_id = ?",
(self.cursor_.lastrowid,),
)
self.conn_.commit()
if import_once and self.head()["version"] and self.check_no_data():
self.import_json()
def check_no_data(self):
"""Check the database contains no data."""
self.cursor_.execute("SELECT COUNT(*) FROM nodes")
node_count = self.cursor_.fetchone()[0]
return node_count == 0
def import_json(self):
node_group_names = self.find_json_importable_node_and_group_names()
node_names = self.find_json_importable_node_names()
# 1.
# self.import_plugins_json()
# 2.
self.import_nodes_json(node_names)
# 3.
self.import_settings_json(node_names)
# 4.
self.import_groups_json(node_group_names)
# 5.
self.import_tags_json(node_group_names)
# 6.
self.import_subscritions_json(node_names)
def import_plugins_json(self):
"""Import data from persistence JSON files."""
plugin_file = os.path.join(self.database_dir_, "plugins.json")
if not os.path.exists(plugin_file):
return
data = json.load(open(plugin_file, "r"))
for library in data["plugins"]:
log("Import library {}".format(library))
self.cursor_.execute(
"INSERT INTO plugins (library) VALUES (?)", (library,)
)
self.conn_.commit()
def import_nodes_json(self, node_names):
"""Import nodes data from persistence JSON files."""
adapter_file = os.path.join(self.database_dir_, "adapters.json")
if os.path.exists(adapter_file):
data = json.load(open(adapter_file, "r"))
for node in data["nodes"]:
log("Import node {}".format(node))
self.cursor_.execute(
"""INSERT INTO nodes (name, type, state, plugin_name)
VALUES (?, ?, ?, ?)""",
(
node["name"],
1 if node["type"] == 1 else 2,
node["state"],
node["plugin_name"],
),
)
self.conn_.commit()
for node_name in node_names:
adapter_file = os.path.join(
self.database_dir_, "adapters", node_name, "adapter.json"
)
if not os.path.exists(adapter_file):
continue
data = json.load(open(adapter_file, "r"))
log("Import node {}".format(data))
self.cursor_.execute(
"""INSERT INTO nodes (name, type, state, plugin_name)
VALUES (?, ?, ?, ?)""",
(
data["name"],
data["type"],
data["state"],
data["plugin_name"],
),
)
self.conn_.commit()
def import_settings_json(self, node_names):
"""Import node settings from persistence JSON files."""
for node_name in node_names:
settings_file = os.path.join(
self.database_dir_, "adapters", node_name, "settings.json"
)
if not os.path.exists(settings_file):
continue
data = open(settings_file, "r").read()
log("Import setting {}".format(data))
self.cursor_.execute(
"INSERT INTO settings (node_name, setting) VALUES(?, ?)",
(node_name, data),
)
self.conn_.commit()
def import_groups_json(self, node_group_names):
"""Import node groups from persistence JSON files."""
for node_name, group_name in node_group_names:
group_file = os.path.join(
self.database_dir_,
"adapters",
node_name,
"groups",
group_name,
"config.json",
)
if not os.path.exists(group_file):
continue
data = json.load(open(group_file, "r"))
log("Import group {}".format(data))
self.cursor_.execute(
"""INSERT INTO groups (driver_name, name, interval)
VALUES (?, ?, ?)""",
(node_name, group_name, data["read_interval"]),
)
self.conn_.commit()
def import_tags_json(self, node_group_names):
"""Import node tags from persistence JSON files."""
for node_name, group_name in node_group_names:
tags_file = os.path.join(
self.database_dir_,
"adapters",
node_name,
"groups",
group_name,
"datatags.json",
)
if not os.path.exists(tags_file):
continue
data = json.load(open(tags_file, "r"))
for tag in data["tags"]:
log("Import tag {}".format(tag))
self.cursor_.execute(
"""INSERT INTO tags (driver_name, group_name, name, address,
attribute, precision, decimal, type, description)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(
node_name,
group_name,
tag["name"],
tag["address"],
tag["attribute"],
0,
0,
tag["type"],
tag.get("description", ""),
),
)
self.conn_.commit()
def import_subscritions_json(self, node_names):
"""Import subscriptions from persistence JSON files."""
for node_name in node_names:
subscription_file = os.path.join(
self.database_dir_, "adapters", node_name, "subscriptions.json"
)
if not os.path.exists(subscription_file):
continue
data = json.load(open(subscription_file, "r"))
for subscription in data["subscriptions"]:
log("Import subscription {}".format(subscription))
self.cursor_.execute(
"""INSERT INTO subscriptions (
app_name, driver_name, group_name
) VALUES(?, ?, ?)""",
(
subscription["sub_adapter_name"],
subscription["src_adapter_name"],
subscription["group_config_name"],
),
)
self.conn_.commit()
def find_json_importable_node_names(self):
"""Find node names from persistence directory."""
adapters_dir = os.path.join(self.database_dir_, "adapters")
return (
list(os.listdir(adapters_dir))
if os.path.exists(adapters_dir)
else []
)
def find_json_importable_node_and_group_names(self):
"""Find node names and group names from persistence directory."""
res = []
adapters_dir = os.path.join(self.database_dir_, "adapters")
if not os.path.exists(adapters_dir):
return res
for adapter_name in os.listdir(adapters_dir):
groups_dir = os.path.join(adapters_dir, adapter_name, "groups")
if not os.path.exists(groups_dir):
continue
for group_name in os.listdir(groups_dir):
res.append((adapter_name, group_name))
return res
if __name__ == "__main__":
args = parse_args()
VERBOSE = args.verbose
migrations = Migration(schema_dir=args.schema_dir, database_dir=args.data_dir)
if args.subcommand == "import":
migrations.import_json()
elif args.subcommand == "show":
migrations.print_head()
elif args.subcommand == "up":
migrations.apply(args.import_once)
-8
View File
@@ -1,8 +0,0 @@
{
"ip": "0.0.0.0",
"port": 7000,
"disable_auth": 0,
"syslog_host": "",
"syslog_port": 541,
"sub_filter_error": 0
}
+2 -6
View File
@@ -44,9 +44,10 @@ cp -r build/dist ${package_name}/
cp build/neuron ${package_name}
cp build/libneuron-base.so ${package_name}/lib
cp /usr/local/lib/libzlog.so.1.2 ${package_name}/lib
cp zlog/src/libzlog.so.1.2 ${package_name}/lib
cp persistence/*.sql ${package_name}/config/
cp migrate.py ${package_name}/
cp sdk-zlog.conf ${package_name}/config/
cp zlog.conf ${package_name}/config/
@@ -54,20 +55,15 @@ cp dev.conf ${package_name}/config/
cp neuron.key ${package_name}/config/
cp neuron.pem ${package_name}/config/
cp default_plugins.json ${package_name}/config/
cp neuron.json ${package_name}/config/
cp build/plugins/schema/ekuiper.json \
build/plugins/schema/monitor.json \
build/plugins/schema/mqtt.json \
build/plugins/schema/modbus-tcp.json \
build/plugins/schema/file.json \
${package_name}/plugins/schema/
cp build/plugins/libplugin-ekuiper.so \
build/plugins/libplugin-monitor.so \
build/plugins/libplugin-mqtt.so \
build/plugins/libplugin-modbus-tcp.so \
build/plugins/libplugin-file.so \
${package_name}/plugins/
tar czf ${package_name}-${arch}.tar.gz ${package_name}/
-103
View File
@@ -1,103 +0,0 @@
/**
* 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.
**/
--- Add users table ---
CREATE TABLE
IF NOT EXISTS users (
name TEXT PRIMARY KEY check(length(name) <= 32),
password TEXT NOT NULL
);
--- Default admin user ---
INSERT INTO
users (name, password)
VALUES
(
"admin",
"$5$PwFeXpBBIBZuZdZl$fP8fFPWCLoaWcnVXVSR.3Xi8TEqCvX92gjhowNNn6S4"
);
BEGIN TRANSACTION;
ALTER TABLE nodes RENAME TO old_nodes;
CREATE TABLE
nodes (
name TEXT PRIMARY KEY check(length(name) <= 128),
type integer(1) NOT NULL check(type IN (1, 2)),
state integer(1) NOT NULL check(state BETWEEN 1 AND 4),
plugin_name TEXT NOT NULL check(length(plugin_name) <= 32)
);
INSERT INTO nodes SELECT * FROM old_nodes;
ALTER TABLE groups RENAME TO old_groups;
CREATE TABLE IF NOT EXISTS
groups (
driver_name TEXT NOT NULL,
name TEXT NULL check(length(name) <= 128),
interval INTEGER NOT NULL check(interval >= 100),
UNIQUE (driver_name, name),
FOREIGN KEY (driver_name) REFERENCES nodes (name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO groups SELECT * FROM old_groups;
ALTER TABLE tags RENAME TO old_tags;
CREATE TABLE IF NOT EXISTS
tags (
driver_name TEXT NOT NULL,
group_name TEXT NOT NULL,
name TEXT NULL check(length(name) <= 64),
address TEXT NULL check(length(address) <= 128),
attribute INTEGER NOT NULL check(attribute BETWEEN 0 AND 7),
precision INTEGER NOT NULL check(precision BETWEEN 0 AND 17),
decimal REAL NOT NULL,
type INTEGER NOT NULL check(type BETWEEN 0 AND 19),
description TEXT NULL check(length(description) <= 128),
UNIQUE (driver_name, group_name, name),
FOREIGN KEY (driver_name, group_name) REFERENCES groups (driver_name, name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO tags SELECT * FROM old_tags;
ALTER TABLE subscriptions RENAME TO old_subscriptions;
CREATE TABLE IF NOT EXISTS
subscriptions (
app_name TEXT NOT NULL,
driver_name TEXT NOT NULL,
group_name TEXT NOT NULL,
CHECK (app_name != driver_name),
UNIQUE (app_name, driver_name, group_name),
FOREIGN KEY (app_name) REFERENCES nodes (name) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (driver_name, group_name) REFERENCES groups (driver_name, name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO subscriptions SELECT * FROM old_subscriptions;
ALTER TABLE settings RENAME TO old_settings;
CREATE TABLE IF NOT EXISTS
settings (
node_name TEXT NOT NULL,
setting TEXT NOT NULL,
UNIQUE (node_name),
FOREIGN KEY (node_name) REFERENCES nodes (name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO settings SELECT * FROM old_settings;
CREATE TABLE IF NOT EXISTS
node_cache (
node_name TEXT NOT NULL,
cache TEXT NOT NULL
);
COMMIT;
-36
View File
@@ -1,36 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
--- fix primary key ---
BEGIN;
DROP TABLE IF EXISTS old_node_cache;
ALTER TABLE node_cache RENAME TO old_node_cache;
CREATE TABLE IF NOT EXISTS node_cache (
node_name TEXT PRIMARY KEY,
CACHE TEXT NOT NULL,
FOREIGN KEY (node_name) REFERENCES nodes (name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT OR REPLACE INTO node_cache SELECT * FROM old_node_cache;
DROP TABLE old_node_cache;
COMMIT;
@@ -1,53 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
DROP TABLE
IF EXISTS old_subscriptions;
ALTER TABLE
subscriptions RENAME TO old_subscriptions;
-- add column params for subscription parameters
CREATE TABLE
IF NOT EXISTS subscriptions (
app_name TEXT NOT NULL,
driver_name TEXT NOT NULL,
group_name TEXT NOT NULL,
params TEXT DEFAULT NULL,
CHECK (app_name != driver_name),
UNIQUE (app_name, driver_name, group_name),
FOREIGN KEY (app_name) REFERENCES nodes (name) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (driver_name, group_name) REFERENCES groups (driver_name, name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO
subscriptions
SELECT
app_name,
driver_name,
group_name,
NULL
FROM
old_subscriptions;
DROP TABLE
old_subscriptions;
COMMIT;
-64
View File
@@ -1,64 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
DROP TABLE
IF EXISTS old_tags;
ALTER TABLE
tags RENAME TO old_tags;
-- alter attribute column constraint for static tags
-- add value column
CREATE TABLE
IF NOT EXISTS tags (
driver_name TEXT NOT NULL,
group_name TEXT NOT NULL,
name TEXT NULL check(length(name) <= 64),
address TEXT NULL check(length(address) <= 128),
attribute INTEGER NOT NULL check(attribute BETWEEN 0 AND 15),
PRECISION INTEGER NOT NULL check(PRECISION BETWEEN 0 AND 17),
decimal REAL NOT NULL,
TYPE INTEGER NOT NULL check(TYPE BETWEEN 0 AND 19),
description TEXT NULL check(length(description) <= 128),
value TEXT DEFAULT NULL,
UNIQUE (driver_name, group_name, name),
FOREIGN KEY (driver_name, group_name) REFERENCES groups (driver_name, name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO
tags
SELECT
driver_name,
group_name,
name,
address,
attribute,
PRECISION,
decimal,
TYPE,
description,
NULL
FROM
old_tags;
DROP TABLE
old_tags;
COMMIT;
-48
View File
@@ -1,48 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
-- from neuron version 2.4.0, eKuiper plugin is no more singleton
-- remove default data-stream-processing node if not in use
DELETE FROM
nodes
WHERE
name = 'data-stream-processing'
AND name NOT in (
SELECT
node_name
FROM
settings
)
AND name NOT in (
SELECT
app_name
FROM
subscriptions
);
-- fix data-stream-processing node plugin name
UPDATE
nodes
SET
plugin_name = 'eKuiper'
where
name = 'data-stream-processing';
COMMIT;
-110
View File
@@ -1,110 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
UPDATE nodes
SET plugin_name = 'MQTT'
WHERE plugin_name = 'mqtt';
UPDATE nodes
SET plugin_name = 'eKuiper'
WHERE plugin_name = 'ekuiper';
UPDATE nodes
SET plugin_name = 'SparkPlugB'
WHERE plugin_name = 'sparkplugb';
UPDATE nodes
SET plugin_name = 'Beckhoff ADS'
WHERE plugin_name = 'ads';
UPDATE nodes
SET plugin_name = 'Modbus TCP'
WHERE plugin_name = 'modbus-tcp';
UPDATE nodes
SET plugin_name = 'Modbus RTU'
WHERE plugin_name = 'modbus-rtu';
UPDATE nodes
SET plugin_name = 'Modbus TCP'
WHERE plugin_name = 'modbus-plus-tcp';
UPDATE nodes
SET plugin_name = 'Modbus TCP QH'
WHERE plugin_name = 'modbus-qh-tcp';
UPDATE nodes
SET plugin_name = 'Siemens S7 ISOTCP'
WHERE plugin_name = 's7comm';
UPDATE nodes
SET plugin_name = 'Siemens S7 ISOTCP for 300/400'
WHERE plugin_name = 's7comm_for_300';
UPDATE nodes
SET plugin_name = 'OPC UA'
WHERE plugin_name = 'opcua';
UPDATE nodes
SET plugin_name = 'Omron FINS TCP'
WHERE plugin_name = 'fins';
UPDATE nodes
SET plugin_name = 'Mitsubishi 3E'
WHERE plugin_name = 'qna3e';
UPDATE nodes
SET plugin_name = 'Mitsubishi 1E'
WHERE plugin_name = 'a1e';
UPDATE nodes
SET plugin_name = 'IEC60870-5-104'
WHERE plugin_name = 'iec104';
UPDATE nodes
SET plugin_name = 'BACnet/IP'
WHERE plugin_name = 'bacnet';
UPDATE nodes
SET plugin_name = 'KNXnet/IP'
WHERE plugin_name = 'knx';
UPDATE nodes
SET plugin_name = 'DLT645-2007'
WHERE plugin_name = 'dlt645';
UPDATE nodes
SET plugin_name = 'NON A11'
WHERE plugin_name = 'nona11';
UPDATE nodes
SET plugin_name = 'EtherNet/IP(CIP)'
WHERE plugin_name = 'EtherNet-IP';
UPDATE nodes
SET plugin_name = 'Fanuc Focas Ethernet'
WHERE plugin_name = 'focas';
UPDATE nodes
SET plugin_name = 'File'
WHERE plugin_name = 'file';
COMMIT;
@@ -1,59 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
-- for backward compatibility with version 2.3,
-- migrate MQTT plugin upload-topic to subscription parameters.
WITH
topics AS (
SELECT
name AS app,
json_extract(json(setting), '$.params.upload-topic') AS topic
FROM
nodes
JOIN settings
WHERE
name = node_name
AND plugin_name = 'MQTT'
)
UPDATE
subscriptions
SET
params = (
SELECT
json_object('params', json_object('topic', topic)) AS params
FROM
topics
WHERE
topics.app = subscriptions.app_name
AND topics.topic NOT NULL
)
WHERE
EXISTS (
SELECT
topic
FROM
topics
WHERE
topics.app = subscriptions.app_name
AND topics.topic NOT NULL
AND subscriptions.params IS NULL
);
COMMIT;
-52
View File
@@ -1,52 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
CREATE TABLE
IF NOT EXISTS templates (
name TEXT PRIMARY KEY check(length(name) <= 128),
plugin_name TEXT NOT NULL check(length(plugin_name) <= 32)
);
CREATE TABLE
IF NOT EXISTS template_groups (
tmpl_name TEXT NOT NULL,
name TEXT NULL check(length(name) <= 128),
interval INTEGER NOT NULL check(interval >= 100),
UNIQUE (tmpl_name, name),
FOREIGN KEY (tmpl_name) REFERENCES templates (name) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE
IF NOT EXISTS template_tags (
tmpl_name TEXT NOT NULL,
group_name TEXT NOT NULL,
name TEXT NULL check(length(name) <= 64),
address TEXT NULL check(length(address) <= 128),
attribute INTEGER NOT NULL check(attribute BETWEEN 0 AND 15),
PRECISION INTEGER NOT NULL check(PRECISION BETWEEN 0 AND 17),
decimal REAL NOT NULL,
TYPE INTEGER NOT NULL check(TYPE BETWEEN 0 AND 19),
description TEXT NULL check(length(description) <= 128),
value TEXT DEFAULT NULL,
UNIQUE (tmpl_name, group_name, name),
FOREIGN KEY (tmpl_name, group_name) REFERENCES template_groups (tmpl_name, name) ON UPDATE CASCADE ON DELETE CASCADE
);
COMMIT;
-57
View File
@@ -1,57 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
-- For backward compatibility before version 2.5,
-- add parameters to modbus plugin.
UPDATE settings
SET setting = JSON_SET(json(setting), '$.params.transport_mode', 0)
FROM nodes
WHERE
settings.node_name = nodes.name
AND JSON_EXTRACT(json(setting), '$.params.transport_mode') IS NULL
AND (nodes.plugin_name='modbus-qh-tcp' OR nodes.plugin_name='modbus-plus-tcp' OR nodes.plugin_name='modbus-tcp' OR nodes.plugin_name='Modbus TCP' OR nodes.plugin_name='Modbus TCP QH');
UPDATE settings
SET setting = JSON_SET(json(setting), '$.params.connection_mode', 0)
FROM nodes
WHERE
settings.node_name = nodes.name
AND JSON_EXTRACT(json(setting), '$.params.connection_mode') IS NULL
AND (nodes.plugin_name='modbus-qh-tcp' OR nodes.plugin_name='modbus-plus-tcp' OR nodes.plugin_name='modbus-rtu' OR nodes.plugin_name='modbus-tcp' OR nodes.plugin_name='Modbus TCP' OR nodes.plugin_name='Modbus RTU' OR nodes.plugin_name='Modbus TCP QH');
UPDATE settings
SET setting = JSON_SET(json(setting), '$.params.group_interval', 1000)
FROM nodes
WHERE
settings.node_name = nodes.name
AND JSON_EXTRACT(json(setting), '$.params.group_interval') IS NULL
AND (nodes.plugin_name='modbus-qh-tcp' OR nodes.plugin_name='modbus-plus-tcp' OR nodes.plugin_name='modbus-rtu' OR nodes.plugin_name='modbus-tcp' OR nodes.plugin_name='Modbus TCP' OR nodes.plugin_name='Modbus RTU' OR nodes.plugin_name='Modbus TCP QH');
UPDATE settings
SET setting = JSON_SET(json(setting), '$.params.interval', 20)
FROM nodes
WHERE
settings.node_name = nodes.name
AND JSON_EXTRACT(json(setting), '$.params.interval') IS NULL
AND (nodes.plugin_name='modbus-qh-tcp' OR nodes.plugin_name='modbus-plus-tcp' OR nodes.plugin_name='modbus-rtu' OR nodes.plugin_name='modbus-tcp' OR nodes.plugin_name='Modbus TCP' OR nodes.plugin_name='Modbus RTU' OR nodes.plugin_name='Modbus TCP QH');
COMMIT;
-26
View File
@@ -1,26 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
UPDATE nodes
SET plugin_name = 'Mitsubishi FX'
WHERE plugin_name = 'Mitsabishi FX';
COMMIT;
@@ -1,24 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN;
CREATE TABLE
IF NOT EXISTS virtual_license (license TEXT NOT NULL);
COMMIT;
@@ -1,40 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2023 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
ALTER TABLE tags RENAME TO temp_tags;
CREATE TABLE IF NOT EXISTS
tags (
driver_name TEXT NOT NULL,
group_name TEXT NOT NULL,
name TEXT NULL check(length(name) <= 128),
address TEXT NULL check(length(address) <= 128),
attribute INTEGER NOT NULL check(attribute BETWEEN 0 AND 15),
precision INTEGER NOT NULL check(precision BETWEEN 0 AND 17),
decimal REAL NOT NULL,
type INTEGER NOT NULL check(type BETWEEN 0 AND 19),
description TEXT NULL check(length(description) <= 512),
value TEXT,
UNIQUE (driver_name, group_name, name),
FOREIGN KEY (driver_name, group_name) REFERENCES groups (driver_name, name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO tags SELECT * FROM temp_tags;
DROP TABLE temp_tags;
COMMIT;
-43
View File
@@ -1,43 +0,0 @@
/**
* NEURON IIoT System for Industry 4.0
* Copyright (C) 2020-2024 EMQ Technologies Co., Ltd All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
BEGIN TRANSACTION;
ALTER TABLE tags RENAME TO temp_tags;
CREATE TABLE
IF NOT EXISTS tags (
driver_name TEXT NOT NULL,
group_name TEXT NOT NULL,
name TEXT NULL check (length (name) <= 128),
address TEXT NULL check (length (address) <= 128),
attribute INTEGER NOT NULL check (attribute BETWEEN 0 AND 15),
precision INTEGER NOT NULL check (precision BETWEEN 0 AND 17),
decimal REAL NOT NULL,
type INTEGER NOT NULL check (type BETWEEN 0 AND 21),
description TEXT NULL check (length (description) <= 512),
value TEXT,
UNIQUE (driver_name, group_name, name),
FOREIGN KEY (driver_name, group_name) REFERENCES groups (driver_name, name) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT INTO tags SELECT * FROM temp_tags;
DROP TABLE temp_tags;
COMMIT;
+81
View File
@@ -0,0 +1,81 @@
{
"tag_type": [
4,
5,
6,
7,
8,
9,
10,
11,
14
],
"params": [
"host",
"port",
"mode",
"baud_rate",
"real_param"
],
"host": {
"name": "host",
"description": "host",
"type": "string",
"default": "127.0.0.1",
"valid": {
"length": 30
}
},
"port": {
"name": "port",
"description": "port",
"type": "int",
"default": 502,
"valid": {
"min": 1024,
"max": 65535
}
},
"mode": {
"name": "mode",
"description": "mode",
"type": "bool",
"default": false,
"valid": {}
},
"baud_rate": {
"name": "baud rate",
"description": "port",
"type": "int",
"default": 9600,
"valid": {
"value": [
9600,
112800
]
}
},
"real_param": {
"name": "real param",
"description": "real",
"type": "real",
"default": 11.22,
"valid": {
"min": 1.1,
"max": 20.2
}
},
"ca": {
"name": "ca",
"description": "",
"attribute": "optional",
"type": "file",
"condition": {
"field": "mode",
"value": true
},
"valid": {
"length": 1024
}
}
}
+1 -27
View File
@@ -1,27 +1 @@
{
"host": {
"name": "Local IP Address",
"name_zh": "本地IP地址",
"description": "IP address to listen for connections from eKuiper",
"description_zh": "绑定本地IP地址,等待eKuiper连接",
"attribute": "required",
"type": "string",
"default": "0.0.0.0",
"valid": {
"length": 255
}
},
"port": {
"name": "Local Port",
"name_zh": "本地端口",
"description": "TCP port number to listen for connections from eKuiper",
"description_zh": "绑定本地端口,等待eKuiper连接",
"attribute": "required",
"type": "int",
"default": 7081,
"valid": {
"min": 1024,
"max": 65535
}
}
}
{}
+108 -66
View File
@@ -25,6 +25,81 @@
#include "json_rw.h"
#include "plugin_ekuiper.h"
int wrap_tag_data(neu_json_read_resp_tag_t *json_tag,
neu_resp_tag_value_t * tag_value)
{
if (NULL == json_tag || NULL == tag_value) {
return -1;
}
json_tag->name = tag_value->tag;
json_tag->error = NEU_ERR_SUCCESS;
switch (tag_value->value.type) {
case NEU_TYPE_INT8:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.i8;
break;
case NEU_TYPE_UINT8:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.u8;
break;
case NEU_TYPE_INT16:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.i16;
break;
case NEU_TYPE_UINT16:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.u16;
break;
case NEU_TYPE_INT32:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.i32;
break;
case NEU_TYPE_UINT32:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.u32;
break;
case NEU_TYPE_INT64:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.i64;
break;
case NEU_TYPE_UINT64:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.u64;
break;
case NEU_TYPE_FLOAT:
json_tag->t = NEU_JSON_FLOAT;
json_tag->value.val_float = tag_value->value.value.f32;
break;
case NEU_TYPE_DOUBLE:
json_tag->t = NEU_JSON_DOUBLE;
json_tag->value.val_double = tag_value->value.value.d64;
break;
case NEU_TYPE_BIT:
json_tag->t = NEU_JSON_BIT;
json_tag->value.val_bit = tag_value->value.value.u8;
break;
case NEU_TYPE_BOOL:
json_tag->t = NEU_JSON_BOOL;
json_tag->value.val_bool = tag_value->value.value.boolean;
break;
case NEU_TYPE_STRING:
json_tag->t = NEU_JSON_STR;
json_tag->value.val_str = tag_value->value.value.str;
break;
case NEU_TYPE_ERROR:
json_tag->t = NEU_JSON_INT;
json_tag->value.val_int = tag_value->value.value.i32;
json_tag->error = tag_value->value.value.i32;
break;
default:
break;
}
return 0;
}
int json_encode_read_resp_header(void *json_object, void *param)
{
int ret = 0;
@@ -59,90 +134,53 @@ int json_encode_read_resp_tags(void *json_object, void *param)
neu_reqresp_trans_data_t *trans_data = resp->trans_data;
void * values_object = NULL;
void * errors_object = NULL;
void * metas_object = NULL;
metas_object = neu_json_encode_new();
if (NULL == metas_object) {
plog_error(plugin, "ekuiper cannot allocate json object");
return -1;
}
values_object = neu_json_encode_new();
if (NULL == values_object) {
plog_error(plugin, "ekuiper cannot allocate json object");
json_decref(metas_object);
return -1;
}
errors_object = neu_json_encode_new();
if (NULL == errors_object) {
plog_error(plugin, "ekuiper cannot allocate json object");
json_decref(values_object);
json_decref(metas_object);
return -1;
}
utarray_foreach(trans_data->tags, neu_resp_tag_value_meta_t *, tag_value)
{
for (int i = 0; i < trans_data->n_tag; i++) {
neu_json_read_resp_tag_t json_tag = { 0 };
neu_tag_value_to_json(tag_value, &json_tag);
if (0 != wrap_tag_data(&json_tag, &trans_data->tags[i])) {
continue; // ignore
}
neu_json_elem_t tag_elem = {
.name = json_tag.name,
.t = json_tag.t,
.v = json_tag.value,
.precision = tag_value->value.precision,
.name = json_tag.name,
.t = json_tag.t,
.v = json_tag.value,
};
if (json_tag.n_meta > 0) {
void *meta = neu_json_encode_new();
for (int k = 0; k < json_tag.n_meta; k++) {
neu_json_elem_t meta_elem = {
.name = json_tag.metas[k].name,
.t = json_tag.metas[k].t,
.v = json_tag.metas[k].value,
};
neu_json_encode_field(meta, &meta_elem, 1);
}
neu_json_elem_t meta_elem = {
.name = json_tag.name,
.t = NEU_JSON_OBJECT,
.v.val_object = meta,
};
neu_json_encode_field(metas_object, &meta_elem, 1);
free(json_tag.metas);
}
ret = neu_json_encode_field((0 != json_tag.error) ? errors_object
: values_object,
&tag_elem, 1);
if (0 != ret) {
json_decref(errors_object);
json_decref(values_object);
json_decref(metas_object);
return ret;
}
}
neu_json_elem_t resp_elems[] = {
{
.name = "values",
.t = NEU_JSON_OBJECT,
.v.val_object = values_object,
},
{
.name = "errors",
.t = NEU_JSON_OBJECT,
.v.val_object = errors_object,
neu_json_elem_t resp_elems[] = { {
.name = "values",
.t = NEU_JSON_OBJECT,
.v.val_object = values_object,
},
{
.name = "errors",
.t = NEU_JSON_OBJECT,
.v.val_object = errors_object,
},
{
.name = "metas",
.t = NEU_JSON_OBJECT,
.v.val_object = metas_object,
},
};
} };
// steals `values_object` and `errors_object`
ret = neu_json_encode_field(json_object, resp_elems,
NEU_JSON_ELEM_SIZE(resp_elems));
@@ -159,7 +197,7 @@ int json_encode_read_resp(void *json_object, void *param)
json_read_resp_header_t header = { .group_name = trans_data->group,
.node_name = trans_data->driver,
.timestamp = global_timestamp };
.timestamp = plugin->common.timestamp };
ret = json_encode_read_resp_header(json_object, &header);
if (0 != ret) {
@@ -185,8 +223,7 @@ int json_decode_write_req(char *buf, size_t len, json_write_req_t **result)
json_obj = neu_json_decode_newb(buf, len);
if (NULL == json_obj) {
free(req);
return -1;
goto decode_fail;
}
neu_json_elem_t req_elems[] = {
@@ -209,20 +246,27 @@ int json_decode_write_req(char *buf, size_t len, json_write_req_t **result)
};
ret = neu_json_decode_by_json(json_obj, NEU_JSON_ELEM_SIZE(req_elems),
req_elems);
if (ret != 0) {
goto decode_fail;
}
req->node_name = req_elems[0].v.val_str;
req->group_name = req_elems[1].v.val_str;
req->tag_name = req_elems[2].v.val_str;
req->t = req_elems[3].t;
req->value = req_elems[3].v;
if (0 == ret) {
*result = req;
} else {
json_decode_write_req_free(req);
ret = -1;
}
*result = req;
goto decode_exit;
neu_json_decode_free(json_obj);
decode_fail:
free(req);
ret = -1;
decode_exit:
if (json_obj != NULL) {
neu_json_decode_free(json_obj);
}
return ret;
}
@@ -237,8 +281,6 @@ void json_decode_write_req_free(json_write_req_t *req)
free(req->tag_name);
if (req->t == NEU_JSON_STR) {
free(req->value.val_str);
} else if (req->t == NEU_JSON_BYTES) {
free(req->value.val_bytes.bytes);
}
free(req);
+2 -2
View File
@@ -38,8 +38,8 @@ typedef struct {
uint64_t timestamp;
} json_read_resp_header_t;
int wrap_tag_data(neu_json_read_resp_tag_t * json_tag,
neu_resp_tag_value_meta_t *tag_value);
int wrap_tag_data(neu_json_read_resp_tag_t *json_tag,
neu_resp_tag_value_t * tag_value);
typedef struct {
neu_plugin_t * plugin;
+35 -220
View File
@@ -17,18 +17,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "errcodes.h"
#include "neuron.h"
#include "utils/asprintf.h"
#include "plugin_ekuiper.h"
#include "read_write.h"
#define EKUIPER_PLUGIN_URL "tcp://127.0.0.1:7081"
#define EKUIPER_PLUGIN_URL "ipc:///tmp/neuron-ekuiper.ipc"
const neu_plugin_module_t neu_plugin_module;
@@ -38,8 +32,8 @@ static neu_plugin_t *ekuiper_plugin_open(void)
neu_plugin_common_init(&plugin->common);
zlog_notice(neuron, "success to create plugin: %s",
neu_plugin_module.module_name);
zlog_info(neuron, "success to create plugin: %s",
neu_plugin_module.module_name);
return plugin;
}
@@ -48,8 +42,8 @@ static int ekuiper_plugin_close(neu_plugin_t *plugin)
int rv = 0;
free(plugin);
zlog_notice(neuron, "success to free plugin: %s",
neu_plugin_module.module_name);
zlog_info(neuron, "success to free plugin: %s",
neu_plugin_module.module_name);
return rv;
}
@@ -71,15 +65,10 @@ static void pipe_rm_cb(nng_pipe p, nng_pipe_ev ev, void *arg)
nng_mtx_lock(plugin->mtx);
plugin->common.link_state = NEU_NODE_LINK_STATE_DISCONNECTED;
nng_mtx_unlock(plugin->mtx);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_DISCONNECTION_60S, 1, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_DISCONNECTION_600S, 1, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_DISCONNECTION_1800S, 1, NULL);
}
static int ekuiper_plugin_init(neu_plugin_t *plugin, bool load)
static int ekuiper_plugin_init(neu_plugin_t *plugin)
{
(void) load;
int rv = 0;
nng_aio *recv_aio = NULL;
@@ -93,30 +82,12 @@ static int ekuiper_plugin_init(neu_plugin_t *plugin, bool load)
rv = nng_aio_alloc(&recv_aio, recv_data_callback, plugin);
if (rv < 0) {
plog_error(plugin, "cannot allocate recv_aio: %s", nng_strerror(rv));
nng_mtx_free(plugin->mtx);
plugin->mtx = NULL;
return rv;
}
plugin->recv_aio = recv_aio;
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_TRANS_DATA_5S, 5000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_TRANS_DATA_30S, 30000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_TRANS_DATA_60S, 60000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_SEND_BYTES_5S, 5000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_SEND_BYTES_30S, 30000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_SEND_BYTES_60S, 60000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_RECV_BYTES_5S, 5000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_RECV_BYTES_30S, 30000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_RECV_BYTES_60S, 60000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_RECV_MSGS_5S, 5000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_RECV_MSGS_30S, 30000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_RECV_MSGS_60S, 60000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_DISCONNECTION_60S, 60000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_DISCONNECTION_600S, 600000);
NEU_PLUGIN_REGISTER_METRIC(plugin, NEU_METRIC_DISCONNECTION_1800S, 1800000);
plog_notice(plugin, "plugin initialized");
plog_info(plugin, "plugin initialized");
return rv;
}
@@ -124,17 +95,14 @@ static int ekuiper_plugin_uninit(neu_plugin_t *plugin)
{
int rv = 0;
nng_close(plugin->sock);
nng_aio_free(plugin->recv_aio);
nng_mtx_free(plugin->mtx);
free(plugin->host);
free(plugin->url);
plog_notice(plugin, "plugin uninitialized");
plog_info(plugin, "plugin uninitialized");
return rv;
}
static inline int start(neu_plugin_t *plugin, const char *url)
static int ekuiper_plugin_start(neu_plugin_t *plugin)
{
int rv = 0;
@@ -146,158 +114,33 @@ static inline int start(neu_plugin_t *plugin, const char *url)
nng_pipe_notify(plugin->sock, NNG_PIPE_EV_ADD_POST, pipe_add_cb, plugin);
nng_pipe_notify(plugin->sock, NNG_PIPE_EV_REM_POST, pipe_rm_cb, plugin);
nng_socket_set_int(plugin->sock, NNG_OPT_SENDBUF, 2048);
nng_socket_set_int(plugin->sock, NNG_OPT_RECVBUF, 2048);
if ((rv = nng_listen(plugin->sock, url, NULL, 0)) != 0) {
if ((rv = nng_listen(plugin->sock, EKUIPER_PLUGIN_URL, NULL, 0)) != 0) {
plog_error(plugin, "nng_listen: %s", nng_strerror(rv));
nng_close(plugin->sock);
if (NNG_EADDRINVAL == rv) {
rv = NEU_ERR_IP_ADDRESS_INVALID;
} else if (NNG_EADDRINUSE == rv) {
rv = NEU_ERR_IP_ADDRESS_IN_USE;
} else {
rv = NEU_ERR_EINTERNAL;
}
return rv;
return NEU_ERR_EINTERNAL;
}
nng_mtx_lock(plugin->mtx);
while (plugin->receiving) {
nng_mtx_unlock(plugin->mtx);
nng_msleep(10);
nng_mtx_lock(plugin->mtx);
}
plugin->receiving = true;
nng_recv_aio(plugin->sock, plugin->recv_aio);
nng_mtx_unlock(plugin->mtx);
return NEU_ERR_SUCCESS;
}
static int ekuiper_plugin_start(neu_plugin_t *plugin)
{
int rv = 0;
char *url = plugin->url ? plugin->url : EKUIPER_PLUGIN_URL; // default url
rv = start(plugin, url);
if (rv != 0) {
return rv;
}
plugin->started = true;
plog_notice(plugin, "start successfully");
return NEU_ERR_SUCCESS;
}
static inline void stop(neu_plugin_t *plugin)
{
nng_close(plugin->sock);
}
static int ekuiper_plugin_stop(neu_plugin_t *plugin)
{
stop(plugin);
plugin->started = false;
nng_close(plugin->sock);
plog_notice(plugin, "stop successfully");
return NEU_ERR_SUCCESS;
}
static int parse_config(neu_plugin_t *plugin, const char *setting,
char **host_p, uint16_t *port_p)
static int ekuiper_plugin_config(neu_plugin_t *plugin, const char *configs)
{
char * err_param = NULL;
neu_json_elem_t host = { .name = "host", .t = NEU_JSON_STR };
neu_json_elem_t port = { .name = "port", .t = NEU_JSON_INT };
int rv = 0;
if (0 != neu_parse_param(setting, &err_param, 2, &host, &port)) {
plog_error(plugin, "parsing setting fail, key: `%s`", err_param);
goto error;
}
(void) plugin;
(void) configs;
// host, required
if (0 == strlen(host.v.val_str)) {
plog_error(plugin, "setting invalid host: `%s`", host.v.val_str);
goto error;
}
struct in_addr addr;
if (0 == inet_aton(host.v.val_str, &addr)) {
plog_error(plugin, "inet_aton fail: %s", host.v.val_str);
goto error;
}
// port, required
if (0 == port.v.val_int || port.v.val_int > 65535) {
plog_error(plugin, "setting invalid port: %" PRIi64, port.v.val_int);
goto error;
}
*host_p = host.v.val_str;
*port_p = port.v.val_int;
plog_notice(plugin, "config host:%s port:%" PRIu16, *host_p, *port_p);
return 0;
error:
free(err_param);
free(host.v.val_str);
return -1;
}
static int ekuiper_plugin_config(neu_plugin_t *plugin, const char *setting)
{
int rv = 0;
char * url = NULL;
char * host = NULL;
uint16_t port = 0;
if (0 != parse_config(plugin, setting, &host, &port)) {
rv = NEU_ERR_NODE_SETTING_INVALID;
goto error;
}
neu_asprintf(&url, "tcp://%s:%" PRIu16, host, port);
if (NULL == url) {
plog_error(plugin, "create url fail");
rv = NEU_ERR_EINTERNAL;
goto error;
}
if (plugin->started) {
stop(plugin);
}
// check we could start the plugin with the new setting
if (0 != (rv = start(plugin, url))) {
// recover with old setting
if (plugin->started && 0 != start(plugin, plugin->url)) {
plog_warn(plugin, "restart host:%s port:%" PRIu16 " fail",
plugin->host, plugin->port);
}
goto error;
}
if (!plugin->started) {
stop(plugin);
}
plog_notice(plugin, "config success");
free(plugin->host);
free(plugin->url);
plugin->host = host;
plugin->port = port;
plugin->url = url;
return rv;
error:
free(url);
free(host);
plog_error(plugin, "config failure");
plog_info(plugin, "config success");
return rv;
}
@@ -306,58 +149,31 @@ static int ekuiper_plugin_request(neu_plugin_t * plugin,
{
bool disconnected = false;
plog_debug(plugin, "handling request type: %d", header->type);
plog_info(plugin, "handling request type: %d", header->type);
nng_mtx_lock(plugin->mtx);
disconnected =
NEU_NODE_LINK_STATE_DISCONNECTED == plugin->common.link_state;
nng_mtx_unlock(plugin->mtx);
if (disconnected) {
plog_notice(plugin, "not connected");
return -1;
}
switch (header->type) {
case NEU_RESP_ERROR: {
neu_resp_error_t *error = (neu_resp_error_t *) data;
plog_debug(plugin, "receive resp errcode: %d", error->error);
plog_info(plugin, "receive resp errcode: %d", error->error);
break;
}
case NEU_REQRESP_TRANS_DATA: {
neu_reqresp_trans_data_t *trans_data = data;
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");
} else {
send_data(plugin, trans_data);
}
send_data(plugin, trans_data);
break;
}
case NEU_REQRESP_NODE_DELETED: {
break;
}
case NEU_REQ_UPDATE_NODE: {
break;
}
case NEU_REQ_UPDATE_GROUP: {
break;
}
case NEU_REQ_DEL_GROUP:
break;
case NEU_REQ_SUBSCRIBE_GROUP:
case NEU_REQ_UPDATE_SUBSCRIBE_GROUP: {
neu_req_subscribe_t *sub_info = data;
free(sub_info->params);
break;
}
case NEU_REQ_UNSUBSCRIBE_GROUP:
break;
default:
plog_warn(plugin, "unsupported request type: %d", header->type);
plog_notice(plugin, "unsupported request type: %d", header->type);
break;
}
@@ -376,14 +192,13 @@ static const neu_plugin_intf_funs_t plugin_intf_funs = {
};
const neu_plugin_module_t neu_plugin_module = {
.version = NEURON_PLUGIN_VER_1_0,
.schema = "ekuiper",
.module_name = "eKuiper",
.module_descr = "LF Edge eKuiper integration plugin",
.module_descr_zh = "LF Edge eKuiper 一体化插件",
.intf_funs = &plugin_intf_funs,
.kind = NEU_PLUGIN_KIND_SYSTEM,
.type = NEU_NA_TYPE_APP,
.display = true,
.single = false,
.version = NEURON_PLUGIN_VER_1_0,
.module_name = "ekuiper",
.module_descr = "Neuron and LF Edge eKuiper integration plugin",
.intf_funs = &plugin_intf_funs,
.kind = NEU_PLUGIN_KIND_SYSTEM,
.type = NEU_NA_TYPE_APP,
.display = true,
.single = true,
.single_name = "data-stream-processing",
};
-7
View File
@@ -20,8 +20,6 @@
#ifndef NEURON_PLUGIN_EKUIPER_H
#define NEURON_PLUGIN_EKUIPER_H
#include <stdint.h>
#include <nng/nng.h>
#include <nng/protocol/pair0/pair.h>
#include <nng/supplemental/util/platform.h>
@@ -36,12 +34,7 @@ struct neu_plugin {
neu_plugin_common_t common;
nng_socket sock;
nng_mtx * mtx;
bool started;
bool receiving;
nng_aio * recv_aio;
char * host;
uint16_t port;
char * url;
};
#ifdef __cplusplus
+7 -40
View File
@@ -55,19 +55,9 @@ void send_data(neu_plugin_t *plugin, neu_reqresp_trans_data_t *trans_data)
free(json_str);
rv = nng_sendmsg(plugin->sock, msg,
NNG_FLAG_NONBLOCK); // TODO: use aio to send message
if (0 == rv) {
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_SEND_MSGS_TOTAL, 1, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_SEND_BYTES_5S, json_len,
NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_SEND_BYTES_30S, json_len,
NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_SEND_BYTES_60S, json_len,
NULL);
} else {
plog_error(plugin, "nng cannot send msg: %s", nng_strerror(rv));
if (0 != rv) {
plog_error(plugin, "nng cannot send msg");
nng_msg_free(msg);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_SEND_MSG_ERRORS_TOTAL, 1,
NULL);
}
}
@@ -76,31 +66,19 @@ void recv_data_callback(void *arg)
int rv = 0;
neu_plugin_t * plugin = arg;
nng_msg * msg = NULL;
size_t json_len = 0;
char * json_str = NULL;
json_write_req_t *req = NULL;
rv = nng_aio_result(plugin->recv_aio);
if (0 != rv) {
plog_error(plugin, "nng_recv error: %s", nng_strerror(rv));
nng_mtx_lock(plugin->mtx);
plugin->receiving = false;
nng_mtx_unlock(plugin->mtx);
return;
}
msg = nng_aio_get_msg(plugin->recv_aio);
json_str = nng_msg_body(msg);
json_len = nng_msg_len(msg);
plog_debug(plugin, "<< %.*s", (int) json_len, json_str);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_RECV_MSGS_TOTAL, 1, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_RECV_BYTES_5S, json_len, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_RECV_BYTES_30S, json_len, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_RECV_BYTES_60S, json_len, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_RECV_MSGS_5S, 1, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_RECV_MSGS_30S, 1, NULL);
NEU_PLUGIN_UPDATE_METRIC(plugin, NEU_METRIC_RECV_MSGS_60S, 1, NULL);
if (json_decode_write_req(json_str, json_len, &req) < 0) {
plog_debug(plugin, "<< %.*s", (int) nng_msg_len(msg), json_str);
if (json_decode_write_req(json_str, nng_msg_len(msg), &req) < 0) {
plog_error(plugin, "fail decode write request json: %.*s",
(int) nng_msg_len(msg), json_str);
goto recv_data_callback_end;
@@ -127,9 +105,9 @@ int write_data(neu_plugin_t *plugin, json_write_req_t *write_req)
header.ctx = NULL;
header.type = NEU_REQ_WRITE_TAG;
cmd.driver = write_req->node_name;
cmd.group = write_req->group_name;
cmd.tag = write_req->tag_name;
strcpy(cmd.driver, write_req->node_name);
strcpy(cmd.group, write_req->group_name);
strcpy(cmd.tag, write_req->tag_name);
switch (write_req->t) {
case NEU_JSON_INT:
@@ -148,22 +126,11 @@ int write_data(neu_plugin_t *plugin, json_write_req_t *write_req)
cmd.value.type = NEU_TYPE_BOOL;
cmd.value.value.boolean = write_req->value.val_bool;
break;
case NEU_JSON_BYTES:
cmd.value.type = NEU_TYPE_BYTES;
cmd.value.value.bytes.length = write_req->value.val_bytes.length;
memcpy(cmd.value.value.bytes.bytes, write_req->value.val_bytes.bytes,
write_req->value.val_bytes.length);
break;
default:
assert(false);
break;
}
ret = neu_plugin_op(plugin, header, &cmd);
if (0 == ret) {
write_req->node_name = NULL; // ownership moved
write_req->group_name = NULL; // ownership moved
write_req->tag_name = NULL; // ownership moved
}
return ret;
}
+7 -17
View File
@@ -4,22 +4,12 @@ set(MODBUS_SRC modbus.c modbus_point.c modbus_req.c modbus_stack.c)
set(CMAKE_BUILD_RPATH ./)
file(COPY ${CMAKE_SOURCE_DIR}/plugins/modbus/modbus-tcp.json DESTINATION ${CMAKE_BINARY_DIR}/plugins/schema/)
file(COPY ${CMAKE_SOURCE_DIR}/plugins/modbus/modbus-rtu.json DESTINATION ${CMAKE_BINARY_DIR}/plugins/schema/)
# modbus rtu plugin
set(MODBUS_RTU_PLUGIN plugin-modbus-rtu)
set(MODBUS_RTU_PLUGIN_SOURCES modbus_rtu.c
${MODBUS_SRC})
add_library(${MODBUS_RTU_PLUGIN} SHARED)
target_include_directories(${MODBUS_RTU_PLUGIN} PRIVATE ${CMAKE_SOURCE_DIR}/include/neuron)
target_sources(${MODBUS_RTU_PLUGIN} PRIVATE ${MODBUS_RTU_PLUGIN_SOURCES})
target_link_libraries(${MODBUS_RTU_PLUGIN} neuron-base)
# modbus tcp plugin
set(MODBUS_TCP_PLUS_PLUGIN plugin-modbus-tcp)
set(MODBUS_TCP_PLUS_PLUGIN_SOURCES modbus_tcp.c
set(MODBUS_TCP_PLUGIN plugin-modbus-tcp)
set(MODBUS_TCP_PLUGIN_SOURCES modbus_tcp.c
${MODBUS_SRC})
add_library(${MODBUS_TCP_PLUS_PLUGIN} SHARED)
target_include_directories(${MODBUS_TCP_PLUS_PLUGIN} PRIVATE ${CMAKE_SOURCE_DIR}/include/neuron)
target_sources(${MODBUS_TCP_PLUS_PLUGIN} PRIVATE ${MODBUS_TCP_PLUS_PLUGIN_SOURCES})
target_link_libraries(${MODBUS_TCP_PLUS_PLUGIN} neuron-base)
add_library(${MODBUS_TCP_PLUGIN} SHARED)
target_include_directories(${MODBUS_TCP_PLUGIN} PRIVATE ${CMAKE_SOURCE_DIR}/include/neuron)
target_sources(${MODBUS_TCP_PLUGIN} PRIVATE ${MODBUS_TCP_PLUGIN_SOURCES})
target_link_libraries(${MODBUS_TCP_PLUGIN} neuron-base)

Some files were not shown because too many files have changed in this diff Show More