mirror of
https://github.com/emqx/neuron.git
synced 2026-10-30 16:09:02 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e62bc1b22 | ||
|
|
896eb3a52e | ||
|
|
1539dd065a | ||
|
|
574c34a085 | ||
|
|
ba8d56fdd0 | ||
|
|
8795028313 | ||
|
|
05d83878db | ||
|
|
d031a0ee71 | ||
|
|
969a302b58 | ||
|
|
57d5a51aad | ||
|
|
c46795ce30 | ||
|
|
ef9e505517 | ||
|
|
24d3ce2667 | ||
|
|
3c71082121 | ||
|
|
0d1c2b93c0 | ||
|
|
0ae76e1c5f | ||
|
|
5f41286600 | ||
|
|
9c48d6bcaa | ||
|
|
83eb1ecf61 | ||
|
|
4059c22de1 | ||
|
|
179dc71408 | ||
|
|
43fc2a7080 | ||
|
|
a95ecfe7c5 | ||
|
|
07b9d077b1 | ||
|
|
6119023896 | ||
|
|
b3b9e69b7a | ||
|
|
05aa6ea141 | ||
|
|
74415465ff | ||
|
|
658779c28f | ||
|
|
edee7007b3 | ||
|
|
012c7b756c | ||
|
|
3b0bdefd1a | ||
|
|
380bae660c | ||
|
|
32e49e0386 | ||
|
|
24111cacac | ||
|
|
978e0d3d8f | ||
|
|
549fe9ed7c | ||
|
|
4e4491eda2 | ||
|
|
a9f4089979 | ||
|
|
02d14ea096 | ||
|
|
33dbdd9eca | ||
|
|
52dfb55007 | ||
|
|
9b4dfef460 | ||
|
|
31316c9363 | ||
|
|
58ca53f07d | ||
|
|
f65d734285 | ||
|
|
bdaba2c339 | ||
|
|
1c3cb0f9a3 | ||
|
|
d6a040515e | ||
|
|
fd22dc29d2 | ||
|
|
865a9fc364 | ||
|
|
86f17aaf90 |
@@ -12,3 +12,4 @@ PointerAlignment: Right
|
||||
SpaceAfterCStyleCast: true
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
BreakBeforeBinaryOperators: None
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -16,7 +16,4 @@ tmp
|
||||
*.deb
|
||||
*.rpm
|
||||
neuron-sdk
|
||||
.vscode
|
||||
log.html
|
||||
output.xml
|
||||
report.html
|
||||
.vscode
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "extern/uthash"]
|
||||
path = extern/uthash
|
||||
url = https://github.com/troydhanson/uthash.git
|
||||
|
||||
+22
-58
@@ -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
@@ -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
@@ -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
|
||||
```
|
||||
|
||||
### 压力测试
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
[](https://github.com/emqx/neuron/releases)
|
||||
[](https://hub.docker.com/r/emqx/neuron)
|
||||
[](https://codecov.io/gh/emqx/neuron)
|
||||
[](https://slack-invite.emqx.io/)
|
||||
[](https://discord.gg/xYGf3fQnES)
|
||||
[](https://twitter.com/EMQTech)
|
||||
[](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.
|
||||
|
||||

|
||||
@@ -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).
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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})
|
||||
@@ -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
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# neuron
|
||||
|
||||
  
|
||||
  
|
||||
|
||||
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.
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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,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" }}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
Submodule extern/uthash added at 44a66fe8e0
@@ -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
|
||||
```
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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,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 ***
|
||||
|
||||
@@ -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}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
@@ -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
@@ -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}/
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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 +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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user