[添加]opcua exporter
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
**/.idea
|
**/.idea
|
||||||
**/vendor
|
**/vendor
|
||||||
**/.env
|
**/.env
|
||||||
**/node_modules
|
**/node_modules
|
||||||
|
**/cmake-build-*
|
||||||
159
.idea/workspace.xml
generated
159
.idea/workspace.xml
generated
@@ -4,18 +4,32 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="596fb1a0-d6fb-4db8-a922-13b01593ce79" name="更改" comment="[增添]增添了datasource中的配置参数及对应页面">
|
<list default="true" id="596fb1a0-d6fb-4db8-a922-13b01593ce79" name="更改" comment="[更新]confd映射本地目录">
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/.gitignore" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/CMakeLists.txt" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/include/algorithm.hpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/periodic_interference/CMakeLists.txt" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/periodic_interference/main.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/periodic_interference/periodic_interference.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/periodic_interference/periodic_interference.h" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/simulation-manager/CMakeLists.txt" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/simulation-manager/algorithm_wrap.hpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/simulation-manager/main.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/simulation-manager/simulation_manager.hpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/step/CMakeLists.txt" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/step/main.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/step/step.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/step/step.h" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/temperature-drift/CMakeLists.txt" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/temperature-drift/main.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/temperature-drift/temperature_drift.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/temperature-drift/temperature_drift.h" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/white_noise/CMakeLists.txt" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/white_noise/main.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/white_noise/white_noise.cpp" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/opcua-expoter/fault-simulation-algorithm/white_noise/white_noise.h" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Filament/Pages/ManageDataSource.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Filament/Pages/ManageDataSource.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Filament/Pages/ManageExporter.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Filament/Pages/ManageExporter.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Filament/Pages/UpdateToEtcd.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Filament/Pages/UpdateToEtcd.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource/Pages/CreateMetric.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource/Pages/CreateMetric.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource/Pages/EditMetric.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource/Pages/EditMetric.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource/Pages/ListMetrics.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Filament/Resources/MetricResource/Pages/ListMetrics.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Services/EtcdService.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Services/EtcdService.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/app/Settings/DataSourceSettings.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/app/Settings/DataSourceSettings.php" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/management-panel/database/settings/2024_08_27_015013_data_source_settings.php" beforeDir="false" afterPath="$PROJECT_DIR$/management-panel/database/settings/2024_08_27_015013_data_source_settings.php" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -36,10 +50,17 @@
|
|||||||
<option name="RESET_MODE" value="HARD" />
|
<option name="RESET_MODE" value="HARD" />
|
||||||
<option name="UPDATE_TYPE" value="REBASE" />
|
<option name="UPDATE_TYPE" value="REBASE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PerforceDirect.Settings">
|
<component name="GitRewordedCommitMessages">
|
||||||
<option name="CHARSET" value="无" />
|
<option name="commitMessagesMapping">
|
||||||
|
<RewordedCommitMessageMapping>
|
||||||
|
<option name="originalMessage" value="[添加]自动创建用户" />
|
||||||
|
<option name="rewordedMessage" value="[添加]自动创建用户" />
|
||||||
|
</RewordedCommitMessageMapping>
|
||||||
|
</option>
|
||||||
|
<option name="currentCommit" value="1" />
|
||||||
|
<option name="onto" value="45f1ded555618a3e1d211baf5f38d047ba08e265" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpWorkspaceProjectConfiguration" interpreter_name="C:\Users\gmch2\scoop\shims\php.exe">
|
<component name="PhpWorkspaceProjectConfiguration" interpreter_name="C:\Users\fly\scoop\shims\php.exe">
|
||||||
<include_path>
|
<include_path>
|
||||||
<path value="$PROJECT_DIR$/vendor/filament/support" />
|
<path value="$PROJECT_DIR$/vendor/filament/support" />
|
||||||
<path value="$PROJECT_DIR$/vendor/filament/spatie-laravel-settings-plugin" />
|
<path value="$PROJECT_DIR$/vendor/filament/spatie-laravel-settings-plugin" />
|
||||||
@@ -307,26 +328,31 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">{
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"git-widget-placeholder": "master",
|
"git-widget-placeholder": "master",
|
||||||
"last_opened_file_path": "E:/data-collection-terminal",
|
"last_opened_file_path": "D:/WorkSpace/FDCP/data-collection-terminal",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}</component>
|
}]]></component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyFile.RECENT_KEYS">
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="D:\WorkSpace\FDCP\data-collection-terminal" />
|
||||||
<recent name="E:\data-collection-terminal\management-panel\app" />
|
<recent name="E:\data-collection-terminal\management-panel\app" />
|
||||||
<recent name="E:\data-collection-terminal\management-panel" />
|
<recent name="E:\data-collection-terminal\management-panel" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Pest.主">
|
<component name="RunManager" selected="Pest.主">
|
||||||
|
<configuration default="true" type="ComposerRunConfigurationType" factoryName="Composer Script">
|
||||||
|
<option name="pathToComposerJson" value="$PROJECT_DIR$/composer.json" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
<configuration name="主" type="PHPUnitRunConfigurationType" factoryName="PHPUnit">
|
<configuration name="主" type="PHPUnitRunConfigurationType" factoryName="PHPUnit">
|
||||||
<TestRunner configuration_file="$PROJECT_DIR$/management-panel/phpunit.xml" scope="XML" use_alternative_configuration_file="true" />
|
<TestRunner configuration_file="$PROJECT_DIR$/management-panel/phpunit.xml" scope="XML" use_alternative_configuration_file="true" />
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
@@ -339,9 +365,6 @@
|
|||||||
<option name="pestRunnerSettings">
|
<option name="pestRunnerSettings">
|
||||||
<PestRunner configuration_file="$PROJECT_DIR$/management-panel/phpunit.xml" scope="ConfigurationFile" use_alternative_configuration_file="true" />
|
<PestRunner configuration_file="$PROJECT_DIR$/management-panel/phpunit.xml" scope="ConfigurationFile" use_alternative_configuration_file="true" />
|
||||||
</option>
|
</option>
|
||||||
<option name="runnerSettings">
|
|
||||||
<PhpTestRunnerSettings configuration_file="$PROJECT_DIR$/management-panel/phpunit.xml" scope="ConfigurationFile" use_alternative_configuration_file="true" />
|
|
||||||
</option>
|
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
@@ -365,9 +388,7 @@
|
|||||||
<workItem from="1724721535300" duration="1534000" />
|
<workItem from="1724721535300" duration="1534000" />
|
||||||
<workItem from="1724723119931" duration="37000" />
|
<workItem from="1724723119931" duration="37000" />
|
||||||
<workItem from="1724723165774" duration="1511000" />
|
<workItem from="1724723165774" duration="1511000" />
|
||||||
<workItem from="1724724784154" duration="12793000" />
|
<workItem from="1724724784154" duration="6338000" />
|
||||||
<workItem from="1724743649380" duration="22000" />
|
|
||||||
<workItem from="1724743707590" duration="5557000" />
|
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="[增添]添加注册">
|
<task id="LOCAL-00001" summary="[增添]添加注册">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -433,75 +454,53 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1724736926763</updated>
|
<updated>1724736926763</updated>
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00009" summary="[增添]在初始仪表盘添加了用于导出etcd配置的widget">
|
<task id="LOCAL-00009" summary="[更新]gitignore">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
<created>1724737302338</created>
|
<created>1724741136342</created>
|
||||||
<option name="number" value="00009" />
|
<option name="number" value="00009" />
|
||||||
<option name="presentableId" value="LOCAL-00009" />
|
<option name="presentableId" value="LOCAL-00009" />
|
||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1724737302338</updated>
|
<updated>1724741136342</updated>
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00010" summary="[修改]修改了Exporter变量名称及页面配置">
|
<task id="LOCAL-00010" summary="[添加]自动创建用户">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
<created>1724743562419</created>
|
<created>1724742151638</created>
|
||||||
<option name="number" value="00010" />
|
<option name="number" value="00010" />
|
||||||
<option name="presentableId" value="LOCAL-00010" />
|
<option name="presentableId" value="LOCAL-00010" />
|
||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1724743562420</updated>
|
<updated>1724742151638</updated>
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00011" summary="[修改]修改了Exporter变量名称及页面配置">
|
<task id="LOCAL-00011" summary="[添加]自动创建用户">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
<created>1724743728810</created>
|
<created>1724742216453</created>
|
||||||
<option name="number" value="00011" />
|
<option name="number" value="00011" />
|
||||||
<option name="presentableId" value="LOCAL-00011" />
|
<option name="presentableId" value="LOCAL-00011" />
|
||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1724743728810</updated>
|
<updated>1724742216453</updated>
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00012" summary="[增添]增添了datasource中的配置参数及对应页面">
|
<task id="LOCAL-00012" summary="[修复]etcd服务地址">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
<created>1724745600949</created>
|
<created>1724742239281</created>
|
||||||
<option name="number" value="00012" />
|
<option name="number" value="00012" />
|
||||||
<option name="presentableId" value="LOCAL-00012" />
|
<option name="presentableId" value="LOCAL-00012" />
|
||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1724745600949</updated>
|
<updated>1724742239281</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="13" />
|
<task id="LOCAL-00013" summary="[更新]confd映射本地目录">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1724742322416</created>
|
||||||
|
<option name="number" value="00013" />
|
||||||
|
<option name="presentableId" value="LOCAL-00013" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1724742322416</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="14" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
<option name="version" value="3" />
|
<option name="version" value="3" />
|
||||||
</component>
|
</component>
|
||||||
<component name="Vcs.Log.Tabs.Properties">
|
<component name="Vcs.Log.Tabs.Properties">
|
||||||
<option name="RECENT_FILTERS">
|
|
||||||
<map>
|
|
||||||
<entry key="Branch">
|
|
||||||
<value>
|
|
||||||
<list>
|
|
||||||
<RecentGroup>
|
|
||||||
<option name="FILTER_VALUES">
|
|
||||||
<option value="HEAD" />
|
|
||||||
</option>
|
|
||||||
</RecentGroup>
|
|
||||||
<RecentGroup>
|
|
||||||
<option name="FILTER_VALUES">
|
|
||||||
<option value="origin/feature/panel" />
|
|
||||||
</option>
|
|
||||||
</RecentGroup>
|
|
||||||
<RecentGroup>
|
|
||||||
<option name="FILTER_VALUES">
|
|
||||||
<option value="origin/master" />
|
|
||||||
</option>
|
|
||||||
</RecentGroup>
|
|
||||||
<RecentGroup>
|
|
||||||
<option name="FILTER_VALUES">
|
|
||||||
<option value="master" />
|
|
||||||
</option>
|
|
||||||
</RecentGroup>
|
|
||||||
</list>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
<option name="TAB_STATES">
|
<option name="TAB_STATES">
|
||||||
<map>
|
<map>
|
||||||
<entry key="MAIN">
|
<entry key="MAIN">
|
||||||
@@ -520,9 +519,11 @@
|
|||||||
<MESSAGE value="[增添]添加了MetricResource的数据库以及页面元素" />
|
<MESSAGE value="[增添]添加了MetricResource的数据库以及页面元素" />
|
||||||
<MESSAGE value="[增添]添加了MetricResource的数据库以及页面元素" />
|
<MESSAGE value="[增添]添加了MetricResource的数据库以及页面元素" />
|
||||||
<MESSAGE value="[增添]添加了etcd服务与对应页面" />
|
<MESSAGE value="[增添]添加了etcd服务与对应页面" />
|
||||||
<MESSAGE value="[增添]在初始仪表盘添加了用于导出etcd配置的widget" />
|
<MESSAGE value="[Add]添加filament-settings插件" />
|
||||||
<MESSAGE value="[修改]修改了Exporter变量名称及页面配置" />
|
<MESSAGE value="[更新]gitignore" />
|
||||||
<MESSAGE value="[增添]增添了datasource中的配置参数及对应页面" />
|
<MESSAGE value="[添加]自动创建用户" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="[增添]增添了datasource中的配置参数及对应页面" />
|
<MESSAGE value="[修复]etcd服务地址" />
|
||||||
|
<MESSAGE value="[更新]confd映射本地目录" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="[更新]confd映射本地目录" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
37
opcua-expoter/.gitignore
vendored
Normal file
37
opcua-expoter/.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
### C++ template
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
#Clion
|
||||||
|
.idea
|
||||||
|
cmake-build-*
|
||||||
57
opcua-expoter/CMakeLists.txt
Normal file
57
opcua-expoter/CMakeLists.txt
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.18)
|
||||||
|
project(opcua_exporter)
|
||||||
|
|
||||||
|
cmake_policy(SET CMP0148 OLD)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
option(ENABLE_METRICS_SIMULATE "开启测点故障仿真功能" ON)
|
||||||
|
|
||||||
|
find_package(civetweb CONFIG REQUIRED)
|
||||||
|
find_package(spdlog CONFIG REQUIRED)
|
||||||
|
find_package(prometheus-cpp CONFIG REQUIRED)
|
||||||
|
find_package(open62541 CONFIG REQUIRED)
|
||||||
|
find_package(yaml-cpp CONFIG REQUIRED)
|
||||||
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
|
|
||||||
|
add_subdirectory(fault-simulation-algorithm)
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
set(
|
||||||
|
OPC_UA_EXPORTER_SRCS
|
||||||
|
main.cpp
|
||||||
|
client/client.cpp
|
||||||
|
client/client.h
|
||||||
|
collector/collector.cpp
|
||||||
|
collector/collector.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
opcua_exporter
|
||||||
|
${OPC_UA_EXPORTER_SRCS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(
|
||||||
|
opcua_exporter
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_BUILD_TYPE}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (${ENABLE_METRICS_SIMULATE})
|
||||||
|
target_compile_definitions(
|
||||||
|
opcua_exporter
|
||||||
|
PRIVATE
|
||||||
|
METRICS_SIMULATE
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
opcua_exporter
|
||||||
|
simulation-manager
|
||||||
|
spdlog::spdlog
|
||||||
|
yaml-cpp::yaml-cpp
|
||||||
|
nlohmann_json::nlohmann_json
|
||||||
|
open62541::open62541
|
||||||
|
civetweb::civetweb
|
||||||
|
prometheus-cpp::core prometheus-cpp::pull
|
||||||
|
)
|
||||||
399
opcua-expoter/client/client.cpp
Normal file
399
opcua-expoter/client/client.cpp
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
//
|
||||||
|
// Created by 闫鹏宇 on 2022/7/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "client.h"
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <open62541/client_config_default.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <open62541/client_highlevel_async.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<>
|
||||||
|
struct hash <std::vector<std::string>>{
|
||||||
|
size_t operator()(const std::vector<std::string> &rhs) const noexcept {
|
||||||
|
size_t res = 0;
|
||||||
|
for (auto const &str: rhs) {
|
||||||
|
res ^= std::hash<std::string>()(str);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline static spdlog::level::level_enum get_spd_level(UA_LogLevel level) {
|
||||||
|
switch (level) {
|
||||||
|
case UA_LogLevel::UA_LOGLEVEL_TRACE:
|
||||||
|
return spdlog::level::trace;
|
||||||
|
case UA_LogLevel::UA_LOGLEVEL_DEBUG:
|
||||||
|
return spdlog::level::debug;
|
||||||
|
case UA_LogLevel::UA_LOGLEVEL_INFO:
|
||||||
|
return spdlog::level::info;
|
||||||
|
case UA_LogLevel::UA_LOGLEVEL_WARNING:
|
||||||
|
return spdlog::level::warn;
|
||||||
|
case UA_LogLevel::UA_LOGLEVEL_ERROR:
|
||||||
|
return spdlog::level::err;
|
||||||
|
case UA_LogLevel::UA_LOGLEVEL_FATAL:
|
||||||
|
return spdlog::level::critical;
|
||||||
|
default:
|
||||||
|
return spdlog::level::trace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void opc_ua_log(void *logContext, UA_LogLevel level, UA_LogCategory category,
|
||||||
|
const char *msg, va_list args) {
|
||||||
|
(void) args;
|
||||||
|
thread_local static char const *last_log_msg = nullptr;
|
||||||
|
|
||||||
|
auto c = static_cast<client *>(logContext);
|
||||||
|
if (!c) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg != last_log_msg) {
|
||||||
|
char buff[256] = {0};
|
||||||
|
vsprintf(buff, msg, args);
|
||||||
|
spdlog::log(get_spd_level(level), buff);
|
||||||
|
}
|
||||||
|
last_log_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OPC_UA_Client_DeleteSubscriptionCallback(
|
||||||
|
UA_Client *client,
|
||||||
|
UA_UInt32 subId,
|
||||||
|
void *subContext
|
||||||
|
) {
|
||||||
|
spdlog::trace(
|
||||||
|
"OPC_UA_Client_DeleteSubscriptionCallback subId{}",
|
||||||
|
subId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OPC_UA_Client_StatusChangeNotificationCallback(
|
||||||
|
UA_Client *client,
|
||||||
|
UA_UInt32 subId,
|
||||||
|
void *subContext,
|
||||||
|
UA_StatusChangeNotification *notification
|
||||||
|
) {
|
||||||
|
spdlog::trace(
|
||||||
|
"OPC_UA_Client_StatusChangeNotificationCallback subId{}",
|
||||||
|
subId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OPC_UA_Client_DataChangeNotificationCallback(
|
||||||
|
UA_Client *client,
|
||||||
|
UA_UInt32 subId,
|
||||||
|
void *subContext,
|
||||||
|
UA_UInt32 monId,
|
||||||
|
void *monContext,
|
||||||
|
UA_DataValue *value
|
||||||
|
) {
|
||||||
|
spdlog::trace(
|
||||||
|
"OPC_UA_Client_DataChangeNotificationCallback subId{} monId",
|
||||||
|
subId,
|
||||||
|
monId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OPC_UA_Client_DeleteMonitoredItemCallback(
|
||||||
|
UA_Client *client,
|
||||||
|
UA_UInt32 subId,
|
||||||
|
void *subContext,
|
||||||
|
UA_UInt32 monId,
|
||||||
|
void *monContext) {
|
||||||
|
spdlog::trace(
|
||||||
|
"OPC_UA_Client_DeleteMonitoredItemCallback subId{} monId",
|
||||||
|
subId,
|
||||||
|
monId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OPC_UA_ClientAsyncReadCallback(
|
||||||
|
UA_Client *c, void *userdata,
|
||||||
|
UA_UInt32 requestId,
|
||||||
|
UA_ReadResponse *rr
|
||||||
|
) {
|
||||||
|
auto cc = static_cast<client *>(userdata);
|
||||||
|
auto hash_key = cc->getAsyncReadRequestHashKey(requestId);
|
||||||
|
cc->updateReadValueCache(hash_key, *rr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
client::client(std::string endpoint) :
|
||||||
|
ua_endpoint(std::move(endpoint)) {
|
||||||
|
ua_config.logger.context = this;
|
||||||
|
ua_config.logger.log = &opc_ua_log;
|
||||||
|
UA_ClientConfig_setDefault(&ua_config);
|
||||||
|
ua_client = UA_Client_newWithConfig(&ua_config);
|
||||||
|
for (int i = 0; i < async_read_request_ids.size(); ++i) {
|
||||||
|
async_read_request_ids[i].first = i;
|
||||||
|
async_read_request_ids[i].second = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client::~client() {
|
||||||
|
stop();
|
||||||
|
UA_Client_delete(ua_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::createSubscription() {
|
||||||
|
if (create_subscription_response) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto request = UA_CreateSubscriptionRequest_default();
|
||||||
|
create_subscription_response = UA_Client_Subscriptions_create(
|
||||||
|
ua_client,
|
||||||
|
request,
|
||||||
|
this,
|
||||||
|
&OPC_UA_Client_StatusChangeNotificationCallback,
|
||||||
|
&OPC_UA_Client_DeleteSubscriptionCallback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::stop() {
|
||||||
|
running = false;
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::run() {
|
||||||
|
UA_StatusCode retval = UA_STATUSCODE_GOOD;
|
||||||
|
int error_time = 0;
|
||||||
|
while (running) {
|
||||||
|
if (!connect()) {
|
||||||
|
//disconnect();
|
||||||
|
spdlog::error("OPC-UA Server({}) not connected({}). Retrying to connect in 1 second.", ua_endpoint,
|
||||||
|
retval);
|
||||||
|
UA_sleep_ms(1000);
|
||||||
|
continue;
|
||||||
|
} else if (MONITOR == read_mode) {
|
||||||
|
createSubscription();
|
||||||
|
}
|
||||||
|
while (running && UA_STATUSCODE_GOOD == retval) {
|
||||||
|
std::unique_lock lock(ua_mutex);
|
||||||
|
retval = UA_Client_run_iterate(ua_client, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool client::connect() {
|
||||||
|
std::unique_lock lock(ua_mutex);
|
||||||
|
return UA_STATUSCODE_GOOD == UA_Client_connect(ua_client, ua_endpoint.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::disconnect() {
|
||||||
|
std::unique_lock lock(ua_mutex);
|
||||||
|
UA_Client_disconnect(ua_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<UA_ReadValueId> client::makeReadValueIds(std::vector<std::string> const &node_ids) {
|
||||||
|
std::vector<UA_ReadValueId> ids;
|
||||||
|
if (!node_ids.empty()) {
|
||||||
|
for (auto const &node_id: node_ids) {
|
||||||
|
ids.emplace_back(
|
||||||
|
UA_ReadValueId{
|
||||||
|
UA_NODEID(node_id.c_str()),
|
||||||
|
UA_ATTRIBUTEID_VALUE,
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
UA_ReadRequest &client::makeReadRequest(size_t hash_key) {
|
||||||
|
|
||||||
|
std::vector<UA_ReadValueId> &read_value_ids = ua_read_value_request_cache_[hash_key].read_value_ids;
|
||||||
|
auto &request = ua_read_value_request_cache_[hash_key].read_request;
|
||||||
|
request.nodesToRead = const_cast<UA_ReadValueId *>(read_value_ids.data());
|
||||||
|
request.nodesToReadSize = read_value_ids.size();
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::cachePreCheckAndInit(size_t hash_key, std::vector<std::string> const &node_ids) {
|
||||||
|
auto ua_read_value_ids_iter = ua_read_value_request_cache_.find(hash_key);
|
||||||
|
if (ua_read_value_ids_iter == ua_read_value_request_cache_.end()) {
|
||||||
|
auto ids = makeReadValueIds(node_ids);
|
||||||
|
if (ids.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ua_read_value_request_cache_[hash_key].read_value_ids = std::move(ids);
|
||||||
|
ua_read_value_request_cache_[hash_key].node_ids = node_ids;
|
||||||
|
UA_ReadRequest_init(&ua_read_value_request_cache_[hash_key].read_request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t *client::getAsyncReadRequestId(size_t hash_key) {
|
||||||
|
auto &ids = async_read_request_ids[(current_async_read_request_pos++) % async_read_request_ids.size()];
|
||||||
|
ids.second = hash_key;
|
||||||
|
return &ids.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t client::getAsyncReadRequestHashKey(uint32_t req_id) {
|
||||||
|
for (auto const &iter: async_read_request_ids) {
|
||||||
|
if (iter.first == req_id) {
|
||||||
|
return iter.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::sendReadRequest(size_t hash_key, bool force_sync) {
|
||||||
|
ua_read_value_request_cache_[hash_key].last_read_request_time = std::chrono::system_clock::now();
|
||||||
|
if (SYNC == read_mode || force_sync) {
|
||||||
|
UA_ReadResponse response;
|
||||||
|
{
|
||||||
|
std::shared_lock lock(ua_mutex);
|
||||||
|
response = UA_Client_Service_read(
|
||||||
|
ua_client,
|
||||||
|
makeReadRequest(
|
||||||
|
hash_key
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (UA_STATUSCODE_GOOD == response.responseHeader.serviceResult) {
|
||||||
|
updateReadValueCache(hash_key, response);
|
||||||
|
}
|
||||||
|
UA_ReadResponse_clear(&response);
|
||||||
|
}
|
||||||
|
switch (read_mode) {
|
||||||
|
case ASYNC: {
|
||||||
|
UA_Client_sendAsyncReadRequest(
|
||||||
|
ua_client,
|
||||||
|
&makeReadRequest(hash_key),
|
||||||
|
&OPC_UA_ClientAsyncReadCallback,
|
||||||
|
this,
|
||||||
|
getAsyncReadRequestId(hash_key)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MONITOR: {
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::system_clock::duration client::getReadRequestDuration(size_t hash_key) {
|
||||||
|
return std::chrono::system_clock::now() -
|
||||||
|
ua_read_value_request_cache_[hash_key].last_read_request_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::system_clock::duration client::getCacheUpdateDuration(size_t hash_key) {
|
||||||
|
return std::chrono::system_clock::now() -
|
||||||
|
ua_read_value_request_cache_[hash_key].last_read_response_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, double> client::readValue(std::vector<std::string> const &node_ids) {
|
||||||
|
if (!node_ids.empty()) {
|
||||||
|
auto node_ids_hash_value = std::hash<std::vector<std::string>>()(node_ids);
|
||||||
|
cachePreCheckAndInit(node_ids_hash_value, node_ids);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(ua_read_mutex);
|
||||||
|
|
||||||
|
auto duration = getCacheUpdateDuration(node_ids_hash_value);
|
||||||
|
if (duration > cache_timeout) {
|
||||||
|
sendReadRequest(node_ids_hash_value, true);
|
||||||
|
} else if (duration > cache_update_time) {
|
||||||
|
sendReadRequest(node_ids_hash_value);
|
||||||
|
}
|
||||||
|
if (getCacheUpdateDuration(node_ids_hash_value) < cache_timeout) {
|
||||||
|
return getCacheValue(node_ids_hash_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, double> client::getCacheValue(size_t hash_key) {
|
||||||
|
std::map<std::string, double> values;
|
||||||
|
|
||||||
|
auto iter = ua_read_value_request_cache_.find(hash_key);
|
||||||
|
if (iter != ua_read_value_request_cache_.end()) {
|
||||||
|
for (auto const &node_id: iter->second.node_ids) {
|
||||||
|
values[node_id] = ua_read_value_cache[node_id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::updateReadValueCache(size_t hash_key, UA_ReadResponse const &response) {
|
||||||
|
auto iter = ua_read_value_request_cache_.find(hash_key);
|
||||||
|
if (iter == ua_read_value_request_cache_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (response.resultsSize != iter->second.read_value_ids.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
iter->second.last_read_response_time = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
for (int i = 0; i < response.resultsSize; ++i) {
|
||||||
|
auto &data_value = response.results[i];
|
||||||
|
setValueCache(iter->second.node_ids[i], getValueAsDouble(data_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::setValueCache(std::string const &node_id, double value) {
|
||||||
|
ua_read_value_cache[node_id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
double client::getValueAsDouble(UA_DataValue const &ua_value) {
|
||||||
|
if (ua_value.hasValue) {
|
||||||
|
switch (ua_value.value.type->typeKind) {
|
||||||
|
case UA_DATATYPEKIND_BOOLEAN: {
|
||||||
|
return static_cast<double>(*static_cast<UA_Boolean *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_SBYTE: {
|
||||||
|
return static_cast<double>(*static_cast<UA_SByte *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_BYTE: {
|
||||||
|
return static_cast<double>(*static_cast<UA_Byte *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_INT16: {
|
||||||
|
return static_cast<double>(*static_cast<UA_Int16 *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_UINT16: {
|
||||||
|
return static_cast<double>(*static_cast<UA_UInt16 *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_INT32: {
|
||||||
|
return static_cast<double>(*static_cast<UA_Int32 *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_UINT32: {
|
||||||
|
return static_cast<double>(*static_cast<UA_UInt32 *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_INT64: {
|
||||||
|
return static_cast<double>(*static_cast<UA_Int64 *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_UINT64: {
|
||||||
|
return static_cast<double>(*static_cast<UA_UInt64 *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_FLOAT: {
|
||||||
|
return static_cast<double>(*static_cast<UA_Float *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
case UA_DATATYPEKIND_DOUBLE: {
|
||||||
|
return static_cast<double>(*static_cast<UA_Double *>(ua_value.value.data));
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::nan(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client::readTest() {
|
||||||
|
auto read_request = UA_ReadRequest_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UA_Client *client::getClient() {
|
||||||
|
return ua_client;
|
||||||
|
}
|
||||||
83
opcua-expoter/client/client.h
Normal file
83
opcua-expoter/client/client.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// Created by 闫鹏宇 on 2022/7/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OPCUA_EXPORTER_CLIENT_H
|
||||||
|
#define OPCUA_EXPORTER_CLIENT_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <open62541/client.h>
|
||||||
|
#include <shared_mutex>
|
||||||
|
#include <chrono>
|
||||||
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
|
#include <open62541/client_subscriptions.h>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
class client final {
|
||||||
|
public:
|
||||||
|
explicit client(std::string endpoint);
|
||||||
|
~client();
|
||||||
|
void stop();
|
||||||
|
void run();
|
||||||
|
bool connect();
|
||||||
|
void disconnect();
|
||||||
|
std::map<std::string, double> readValue(std::vector<std::string> const &node_ids);
|
||||||
|
void readTest();
|
||||||
|
UA_Client *getClient();
|
||||||
|
size_t getAsyncReadRequestHashKey(uint32_t req_id);
|
||||||
|
void updateReadValueCache(size_t hash_key, UA_ReadResponse const &response);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<UA_ReadValueId> makeReadValueIds(std::vector<std::string> const &node_ids);
|
||||||
|
UA_ReadRequest &makeReadRequest(size_t hash_key);
|
||||||
|
std::map<std::string, double> getCacheValue(size_t hash_key);
|
||||||
|
double getValueAsDouble(UA_DataValue const &ua_value);
|
||||||
|
void cachePreCheckAndInit(size_t hash_key, std::vector<std::string> const &node_ids);
|
||||||
|
void sendReadRequest(size_t hash_key, bool force_sync = false);
|
||||||
|
std::chrono::system_clock::duration getCacheUpdateDuration(size_t hash_key);
|
||||||
|
std::chrono::system_clock::duration getReadRequestDuration(size_t hash_key);
|
||||||
|
void setValueCache(std::string const &node_id, double value);
|
||||||
|
uint32_t *getAsyncReadRequestId(size_t hash_key);
|
||||||
|
void createSubscription();
|
||||||
|
protected:
|
||||||
|
enum enum_read_mode {
|
||||||
|
SYNC,
|
||||||
|
ASYNC,
|
||||||
|
MONITOR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_read_value_request_cache {
|
||||||
|
std::chrono::system_clock::time_point last_read_response_time;
|
||||||
|
std::chrono::system_clock::time_point last_read_request_time;
|
||||||
|
std::vector<UA_ReadValueId> read_value_ids;
|
||||||
|
UA_ReadRequest read_request;
|
||||||
|
std::vector<std::string> node_ids;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
UA_Client *ua_client{nullptr};
|
||||||
|
UA_ClientConfig ua_config{};
|
||||||
|
std::string ua_endpoint;
|
||||||
|
std::shared_mutex ua_mutex;
|
||||||
|
std::mutex ua_read_mutex;
|
||||||
|
std::chrono::system_clock::duration cache_timeout{std::chrono::milliseconds(1000)};
|
||||||
|
std::chrono::system_clock::duration cache_update_time{std::chrono::milliseconds(400)};
|
||||||
|
|
||||||
|
enum_read_mode read_mode{ASYNC};
|
||||||
|
|
||||||
|
std::unordered_map<std::size_t, st_read_value_request_cache> ua_read_value_request_cache_;
|
||||||
|
std::map<std::string, double> ua_read_value_cache;
|
||||||
|
|
||||||
|
bool running{true};
|
||||||
|
|
||||||
|
std::array<std::pair<uint32_t, size_t>, 1024> async_read_request_ids;
|
||||||
|
std::atomic_int64_t current_async_read_request_pos{0};
|
||||||
|
|
||||||
|
std::optional<UA_CreateSubscriptionResponse> create_subscription_response;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OPCUA_EXPORTER_CLIENT_H
|
||||||
1
opcua-expoter/cmake/civetweb-config.cmake
Normal file
1
opcua-expoter/cmake/civetweb-config.cmake
Normal file
@@ -0,0 +1 @@
|
|||||||
|
add_library(civetweb::civetweb-cpp ALIAS civetweb-cpp)
|
||||||
127
opcua-expoter/collector/collector.cpp
Normal file
127
opcua-expoter/collector/collector.cpp
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// Created by 闫鹏宇 on 2022/7/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "collector.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include "../client/client.h"
|
||||||
|
|
||||||
|
|
||||||
|
collector::collector(YAML::Node const &config, std::shared_ptr<client> ua_client) :
|
||||||
|
registry_(std::make_shared<prometheus::Registry>()),
|
||||||
|
ua_client_(ua_client) {
|
||||||
|
buildMetrics(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void collector::clearMetrics() {
|
||||||
|
ua_read_node_ids.clear();
|
||||||
|
for (auto &node: nodes) {
|
||||||
|
if (nullptr != node.second.family) {
|
||||||
|
if (nullptr != node.second.real) {
|
||||||
|
node.second.family->Remove(node.second.real);
|
||||||
|
}
|
||||||
|
if (nullptr != node.second.simulation) {
|
||||||
|
node.second.family->Remove(node.second.simulation);
|
||||||
|
}
|
||||||
|
registry_->Remove(*node.second.family);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes.clear();
|
||||||
|
metrics_json_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
prometheus::Labels collector::getNodeLabels(YAML::Node const &labels) {
|
||||||
|
return prometheus::Labels();
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json const &collector::getMetricsJson() {
|
||||||
|
|
||||||
|
return metrics_json_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void collector::buildMetrics(YAML::Node const &config) {
|
||||||
|
clearMetrics();
|
||||||
|
for (auto item: config) {
|
||||||
|
if (item.IsNull() || item["name"].IsNull() || item["nodeid"].IsNull() || item["type"].IsNull()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto node_id = item["nodeid"].as<std::string>();
|
||||||
|
auto name = item["name"].as<std::string>();
|
||||||
|
auto help = item["help"].as<std::string>(std::string());
|
||||||
|
metrics_json_.push_back({
|
||||||
|
{"node_id", node_id},
|
||||||
|
{"name", name},
|
||||||
|
{"help", help}
|
||||||
|
});
|
||||||
|
ua_read_node_ids.emplace_back(node_id);
|
||||||
|
spdlog::info("load metrics {}({}).", name, node_id);
|
||||||
|
auto &node_family = prometheus::BuildGauge()
|
||||||
|
.Name(name)
|
||||||
|
.Help(help)
|
||||||
|
.Labels(getNodeLabels(item["labels"]))
|
||||||
|
.Register(*registry_);
|
||||||
|
simulation_manager_[name] = new simulation_manager();
|
||||||
|
nodes[node_id] = {
|
||||||
|
name,
|
||||||
|
&node_family,
|
||||||
|
&(node_family.Add({{"data", "real"}})),
|
||||||
|
&(node_family.Add({{"data", "simulate"}})),
|
||||||
|
simulation_manager_[name]
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool collector::updateMetrics() {
|
||||||
|
do {
|
||||||
|
if (ua_read_node_ids.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto values = ua_client_->readValue(ua_read_node_ids);
|
||||||
|
if (values.empty()) { // none value return
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (auto const &value: values) {
|
||||||
|
auto node_iter = nodes.find(value.first);
|
||||||
|
if (node_iter != nodes.end()) {
|
||||||
|
node_iter->second.setValue(value.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} while (false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<prometheus::MetricFamily> collector::Collect() const {
|
||||||
|
if (const_cast<collector *>(this)->updateMetrics()) {
|
||||||
|
return registry_->Collect();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void collector::st_node::setValue(double val) {
|
||||||
|
if (nullptr != real) {
|
||||||
|
real->Set(val);
|
||||||
|
}
|
||||||
|
if (nullptr != simulation && manager) {
|
||||||
|
simulation->Set(manager->eval(val));
|
||||||
|
// simulation->Set(val + 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json collector::simulationConfig(std::string const &name) {
|
||||||
|
if (simulation_manager_.contains(name)) {
|
||||||
|
return simulation_manager_[name]->config();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void collector::setSimulationConfig(std::string const &name, nlohmann::json const &config) {
|
||||||
|
if (simulation_manager_.contains(name)) {
|
||||||
|
return simulation_manager_[name]->set_config(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
opcua-expoter/collector/collector.h
Normal file
57
opcua-expoter/collector/collector.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// Created by 闫鹏宇 on 2022/7/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OPCUA_EXPORTER_COLLECTOR_H
|
||||||
|
#define OPCUA_EXPORTER_COLLECTOR_H
|
||||||
|
|
||||||
|
#include <client/client.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <open62541/client.h>
|
||||||
|
#include <prometheus/collectable.h>
|
||||||
|
#include <prometheus/family.h>
|
||||||
|
#include <prometheus/gauge.h>
|
||||||
|
#include <prometheus/labels.h>
|
||||||
|
#include <prometheus/metric_family.h>
|
||||||
|
#include <prometheus/registry.h>
|
||||||
|
#include <simulation_manager.hpp>
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
|
class collector : public prometheus::Collectable {
|
||||||
|
public:
|
||||||
|
explicit collector(YAML::Node const &config,
|
||||||
|
std::shared_ptr<client> ua_client);
|
||||||
|
~collector() override = default;
|
||||||
|
std::vector<prometheus::MetricFamily> Collect() const override;
|
||||||
|
|
||||||
|
nlohmann::json const &getMetricsJson();
|
||||||
|
nlohmann::json simulationConfig(std::string const &name);
|
||||||
|
void setSimulationConfig(std::string const &name,
|
||||||
|
nlohmann::json const &config);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void buildMetrics(YAML::Node const &config);
|
||||||
|
bool updateMetrics();
|
||||||
|
void clearMetrics();
|
||||||
|
prometheus::Labels getNodeLabels(YAML::Node const &labels);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<prometheus::Registry> registry_;
|
||||||
|
std::shared_ptr<client> ua_client_;
|
||||||
|
std::vector<std::string> ua_read_node_ids;
|
||||||
|
|
||||||
|
struct st_node {
|
||||||
|
std::string name;
|
||||||
|
prometheus::Family<prometheus::Gauge> *family{nullptr};
|
||||||
|
prometheus::Gauge *real{nullptr};
|
||||||
|
prometheus::Gauge *simulation{nullptr};
|
||||||
|
simulation_manager *manager;
|
||||||
|
void setValue(double val);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, st_node> nodes;
|
||||||
|
std::map<std::string, simulation_manager *> simulation_manager_;
|
||||||
|
nlohmann::json metrics_json_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OPCUA_EXPORTER_COLLECTOR_H
|
||||||
2
opcua-expoter/fault-simulation-algorithm/.gitignore
vendored
Normal file
2
opcua-expoter/fault-simulation-algorithm/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.idea/
|
||||||
|
cmake-build-*/
|
||||||
14
opcua-expoter/fault-simulation-algorithm/CMakeLists.txt
Normal file
14
opcua-expoter/fault-simulation-algorithm/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.18)
|
||||||
|
project(fault_simulation_algorithm)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
|
|
||||||
|
include_directories(include)
|
||||||
|
add_subdirectory(periodic_interference)
|
||||||
|
add_subdirectory(temperature-drift)
|
||||||
|
add_subdirectory(step)
|
||||||
|
add_subdirectory(white_noise)
|
||||||
|
|
||||||
|
add_subdirectory(simulation-manager)
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// Created by fly on 2022/4/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FAULT_SIMULATION_ALGORITHM_ALGORITHM_HPP
|
||||||
|
#define FAULT_SIMULATION_ALGORITHM_ALGORITHM_HPP
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
class algorithm {
|
||||||
|
public:
|
||||||
|
virtual void set_config(nlohmann::json const &config) = 0;
|
||||||
|
|
||||||
|
virtual nlohmann::json config() = 0;
|
||||||
|
|
||||||
|
virtual double eval(double value) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double jsonValue(nlohmann::json const &j, std::string const &key) {
|
||||||
|
if (j.contains(key)) {
|
||||||
|
if (j[key].is_string()) {
|
||||||
|
return std::atof(j[key].get<std::string>().c_str());
|
||||||
|
}
|
||||||
|
if (j[key].is_number()) {
|
||||||
|
return j[key].get<double>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nan("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FAULT_SIMULATION_ALGORITHM_ALGORITHM_HPP
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
add_library(
|
||||||
|
periodic-interference
|
||||||
|
INTERFACE
|
||||||
|
)
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
periodic-interference
|
||||||
|
INTERFACE
|
||||||
|
periodic_interference.cpp
|
||||||
|
periodic_interference.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
periodic-interference
|
||||||
|
INTERFACE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
periodic-interference
|
||||||
|
INTERFACE
|
||||||
|
nlohmann_json::nlohmann_json
|
||||||
|
)
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/23.
|
||||||
|
//
|
||||||
|
#include <iostream>
|
||||||
|
#include "periodic_interference.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
periodic_interference algorithm;
|
||||||
|
|
||||||
|
algorithm.set_config(
|
||||||
|
{
|
||||||
|
{"PERIODIC_INTERFERENCE_AMPLITUDE", 20},
|
||||||
|
{"PERIODIC_INTERFERENCE_AMPLITUDE_BASE", 1},
|
||||||
|
{"CYCLE_", 20}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
std::vector <std::vector<double>> user_arr;
|
||||||
|
std::ifstream fp("C:/data/user_data.csv");
|
||||||
|
std::string line;
|
||||||
|
getline(fp,line);
|
||||||
|
while (getline(fp,line)){
|
||||||
|
std::vector <double> data_line;
|
||||||
|
std::string number;
|
||||||
|
std::istringstream readstr(line);
|
||||||
|
for(int j = 0;j < 2814;j++){
|
||||||
|
getline(readstr,number,',');
|
||||||
|
data_line.push_back(atof(number.c_str()));
|
||||||
|
}
|
||||||
|
user_arr.push_back(data_line);
|
||||||
|
}
|
||||||
|
std::ofstream outfile;
|
||||||
|
outfile.open("C:/data/user_data5.csv", std::ios::out);
|
||||||
|
outfile<<"origin"<<','<<"periodic_interference"<<std::endl;
|
||||||
|
for (int i = 0; i <2814; ++i) {
|
||||||
|
user_arr[i][1]=algorithm.eval(user_arr[i][0]);
|
||||||
|
std::cout << i << "\t" << user_arr[i][1] << std::endl;
|
||||||
|
outfile<<user_arr[i][0]<<','<<user_arr[i][1]<<std::endl;
|
||||||
|
}
|
||||||
|
outfile.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/23.
|
||||||
|
//
|
||||||
|
#include "periodic_interference.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <numbers>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
void periodic_interference::set_config(const nlohmann::json &config) {
|
||||||
|
try {
|
||||||
|
eval_time_ = 0;
|
||||||
|
amplitude_ = jsonValue(config, "PERIODIC_INTERFERENCE_AMPLITUDE");
|
||||||
|
amplitude_base_ = jsonValue(config, "PERIODIC_INTERFERENCE_AMPLITUDE_BASE");
|
||||||
|
cycle_ = jsonValue(config, "CYCLE_");
|
||||||
|
config_ = config;
|
||||||
|
} catch (...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json periodic_interference::config() {
|
||||||
|
return config_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double periodic_interference::eval(double value) {
|
||||||
|
return value + amplitude_base_ * sin((2 * std::numbers::pi / cycle_) * eval_time_++) + amplitude_;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FAULT_SIMULATION_ALGORITHM_PERIODIC_INTERFERENCE_H
|
||||||
|
#define FAULT_SIMULATION_ALGORITHM_PERIODIC_INTERFERENCE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm.hpp>
|
||||||
|
|
||||||
|
class periodic_interference : public algorithm {
|
||||||
|
public:
|
||||||
|
void set_config(const nlohmann::json &config) override;
|
||||||
|
|
||||||
|
nlohmann::json config() override;
|
||||||
|
|
||||||
|
double eval(double value) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nlohmann::json config_{};
|
||||||
|
double amplitude_{0};
|
||||||
|
double amplitude_base_{0};
|
||||||
|
double cycle_{0};
|
||||||
|
uint64_t eval_time_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //FAULT_SIMULATION_ALGORITHM_PERIODIC_INTERFERENCE_H
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
|
||||||
|
add_library(simulation-manager INTERFACE)
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
simulation-manager
|
||||||
|
INTERFACE
|
||||||
|
simulation_manager.hpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
simulation-manager
|
||||||
|
INTERFACE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../include
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
simulation-manager
|
||||||
|
INTERFACE
|
||||||
|
periodic-interference
|
||||||
|
step
|
||||||
|
temperature-drift
|
||||||
|
white-noise
|
||||||
|
)
|
||||||
|
|
||||||
|
#add_executable(simulation-manager main.cpp simulation_manager.hpp algorithm_wrap.hpp)
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// Created by fly on 2022/4/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FAULT_SIMULATION_ALGORITHM_ALGORITHM_WRAP_HPP
|
||||||
|
#define FAULT_SIMULATION_ALGORITHM_ALGORITHM_WRAP_HPP
|
||||||
|
|
||||||
|
#include <algorithm.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
class algorithm_wrap : public algorithm {
|
||||||
|
public:
|
||||||
|
explicit algorithm_wrap(std::shared_ptr<algorithm> algo) {
|
||||||
|
algorithm_ = std::move(algo);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enable() const {
|
||||||
|
return enable_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_enable(bool flag) {
|
||||||
|
enable_ = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
int duration_period() const {
|
||||||
|
return duration_period_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_duration_period(int durationPeriod) {
|
||||||
|
duration_period_ = durationPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_config(nlohmann::json const &config) override {
|
||||||
|
if (algorithm_) {
|
||||||
|
algorithm_->set_config(config);
|
||||||
|
if (config.contains("enable") && config["enable"].is_boolean()) {
|
||||||
|
set_enable(config["enable"].get<bool>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json config() override {
|
||||||
|
nlohmann::json config;
|
||||||
|
config["enable"] = enable();
|
||||||
|
if (algorithm_) {
|
||||||
|
return algorithm_->config();
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
double eval(double value) override {
|
||||||
|
if (algorithm_ && enable_ && duration_period_) {
|
||||||
|
if (duration_period_ > 0) {
|
||||||
|
--duration_period_;
|
||||||
|
}
|
||||||
|
return algorithm_->eval(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<algorithm> algorithm_;
|
||||||
|
|
||||||
|
bool enable_ = false;
|
||||||
|
int duration_period_ = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FAULT_SIMULATION_ALGORITHM_ALGORITHM_WRAP_HPP
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by fly on 2022/4/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "simulation_manager.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char *argv) {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
//
|
||||||
|
// Created by fly on 2022/4/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FAULT_SIMULATION_ALGORITHM_SIMULATION_MANAGER_HPP
|
||||||
|
#define FAULT_SIMULATION_ALGORITHM_SIMULATION_MANAGER_HPP
|
||||||
|
|
||||||
|
#include "algorithm_wrap.hpp"
|
||||||
|
#include <periodic_interference.h>
|
||||||
|
#include <step.h>
|
||||||
|
#include <white_noise.h>
|
||||||
|
#include <temperature_drift.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
class simulation_manager {
|
||||||
|
public:
|
||||||
|
void add_algorithm(std::string const &name, std::shared_ptr<algorithm> algo) {
|
||||||
|
if (!algorithms_.contains(name)) {
|
||||||
|
algorithms_.emplace(name, std::make_shared<algorithm_wrap>(algo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_algorithm(std::string const &name) {
|
||||||
|
algorithms_.erase(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_algorithm_enable(std::string const &name, bool flag) {
|
||||||
|
if (algorithms_.contains(name)) {
|
||||||
|
algorithms_[name]->set_enable(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool algorithm_enable(std::string const &name) {
|
||||||
|
if (algorithms_.contains(name)) {
|
||||||
|
return algorithms_[name]->enable();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_algorithm_duration_period(std::string const &name, int duration_period) {
|
||||||
|
if (algorithms_.contains(name)) {
|
||||||
|
algorithms_[name]->set_duration_period(duration_period);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int algorithm_duration_period(std::string const &name) {
|
||||||
|
if (algorithms_.contains(name)) {
|
||||||
|
return algorithms_[name]->duration_period();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_algorithm_config(std::string const &name, nlohmann::json const &config) {
|
||||||
|
if (!algorithms_.contains(name)) {
|
||||||
|
spdlog::debug("Create {} Algorithm Object", name);
|
||||||
|
if ("periodic_interference" == name) {
|
||||||
|
algorithms_[name] = std::make_shared<algorithm_wrap>(std::make_shared<periodic_interference>());
|
||||||
|
} else if ("step" == name) {
|
||||||
|
algorithms_[name] = std::make_shared<algorithm_wrap>(std::make_shared<step>());
|
||||||
|
} else if ("white_noise" == name) {
|
||||||
|
algorithms_[name] = std::make_shared<algorithm_wrap>(std::make_shared<white_noise>());
|
||||||
|
} else if ("temperature_drift" == name) {
|
||||||
|
algorithms_[name] = std::make_shared<algorithm_wrap>(std::make_shared<temperature_drift>());
|
||||||
|
} else if ("pulse" == name) {
|
||||||
|
algorithms_[name] = std::make_shared<algorithm_wrap>(std::make_shared<step>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (algorithms_.contains(name)) {
|
||||||
|
algorithms_[name]->set_config(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json algorithm_config(std::string const &name) {
|
||||||
|
if (algorithms_.contains(name)) {
|
||||||
|
return algorithms_[name]->config();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json config() {
|
||||||
|
nlohmann::json j;
|
||||||
|
for (auto iter = algorithms_.begin(); iter != algorithms_.end(); ++iter) {
|
||||||
|
j[iter->first] = iter->second->config();
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_config(nlohmann::json const &c) {
|
||||||
|
for (auto iter = c.begin(); iter != c.end(); ++iter) {
|
||||||
|
set_algorithm_config(iter.key(), iter.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double eval(double value) {
|
||||||
|
for (auto &iter: algorithms_) {
|
||||||
|
value = iter.second->eval(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::shared_ptr<algorithm_wrap>> algorithms_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FAULT_SIMULATION_ALGORITHM_SIMULATION_MANAGER_HPP
|
||||||
23
opcua-expoter/fault-simulation-algorithm/step/CMakeLists.txt
Normal file
23
opcua-expoter/fault-simulation-algorithm/step/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
add_library(
|
||||||
|
step
|
||||||
|
INTERFACE
|
||||||
|
)
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
step
|
||||||
|
INTERFACE
|
||||||
|
step.cpp
|
||||||
|
step.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
step
|
||||||
|
INTERFACE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
step
|
||||||
|
INTERFACE
|
||||||
|
nlohmann_json::nlohmann_json
|
||||||
|
)
|
||||||
44
opcua-expoter/fault-simulation-algorithm/step/main.cpp
Normal file
44
opcua-expoter/fault-simulation-algorithm/step/main.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/20.
|
||||||
|
//
|
||||||
|
#include <iostream>
|
||||||
|
#include "step.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
step algorithm;
|
||||||
|
|
||||||
|
algorithm.set_config(
|
||||||
|
{
|
||||||
|
{"STEP_AMPLITUDE_BASE", 10}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
std::vector <std::vector<double>> user_arr;
|
||||||
|
std::ifstream fp("C:/data/user_data.csv");
|
||||||
|
std::string line;
|
||||||
|
getline(fp,line);
|
||||||
|
while (getline(fp,line)){
|
||||||
|
std::vector <double> data_line;
|
||||||
|
std::string number;
|
||||||
|
std::istringstream readstr(line);
|
||||||
|
for(int j = 0;j < 2814;j++){
|
||||||
|
getline(readstr,number,',');
|
||||||
|
data_line.push_back(atof(number.c_str()));
|
||||||
|
}
|
||||||
|
user_arr.push_back(data_line);
|
||||||
|
}
|
||||||
|
std::ofstream outfile;
|
||||||
|
outfile.open("C:/data/user_data6.csv", std::ios::out);
|
||||||
|
outfile<<"origin"<<','<<"step"<<std::endl;
|
||||||
|
for (int i = 0; i <2814; ++i) {
|
||||||
|
user_arr[i][1]=algorithm.eval(user_arr[i][0]);
|
||||||
|
std::cout << i << "\t" << user_arr[i][1] << std::endl;
|
||||||
|
outfile<<user_arr[i][0]<<','<<user_arr[i][1]<<std::endl;
|
||||||
|
}
|
||||||
|
outfile.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
23
opcua-expoter/fault-simulation-algorithm/step/step.cpp
Normal file
23
opcua-expoter/fault-simulation-algorithm/step/step.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/20.
|
||||||
|
//
|
||||||
|
#include "step.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void step::set_config(const nlohmann::json &config) {
|
||||||
|
try {
|
||||||
|
amplitude_base_ = jsonValue(config, "STEP_AMPLITUDE_BASE");
|
||||||
|
config_ = config;
|
||||||
|
} catch (...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json step::config() {
|
||||||
|
return config_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double step::eval(double value) {
|
||||||
|
return value + amplitude_base_;
|
||||||
|
}
|
||||||
21
opcua-expoter/fault-simulation-algorithm/step/step.h
Normal file
21
opcua-expoter/fault-simulation-algorithm/step/step.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FAULT_SIMULATION_ALGORITHM_MAIN_STEP_H
|
||||||
|
#define FAULT_SIMULATION_ALGORITHM_MAIN_STEP_H
|
||||||
|
#include <algorithm.hpp>
|
||||||
|
|
||||||
|
class step : public algorithm {
|
||||||
|
public:
|
||||||
|
void set_config(const nlohmann::json &config) override;
|
||||||
|
|
||||||
|
nlohmann::json config() override;
|
||||||
|
|
||||||
|
double eval(double value) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nlohmann::json config_{};
|
||||||
|
double amplitude_base_{0};
|
||||||
|
};
|
||||||
|
#endif //FAULT_SIMULATION_ALGORITHM_MAIN_STEP_H
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
add_library(
|
||||||
|
temperature-drift
|
||||||
|
INTERFACE
|
||||||
|
)
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
temperature-drift
|
||||||
|
INTERFACE
|
||||||
|
temperature_drift.cpp
|
||||||
|
temperature_drift.h
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
temperature-drift
|
||||||
|
INTERFACE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
temperature-drift
|
||||||
|
INTERFACE
|
||||||
|
nlohmann_json::nlohmann_json
|
||||||
|
)
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "temperature_drift.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
temperature_drift algorithm;
|
||||||
|
|
||||||
|
algorithm.set_config(
|
||||||
|
{
|
||||||
|
{"TEMPERATURE_DRIFT_AMPLITUDE", 0.01},
|
||||||
|
{"TEMPERATURE_DRIFT_AMPLITUDE_BASE", 10}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
std::vector <std::vector<double>> user_arr;
|
||||||
|
std::ifstream fp("C:/data/user_data.csv");
|
||||||
|
std::string line;
|
||||||
|
getline(fp,line);
|
||||||
|
while (getline(fp,line)){
|
||||||
|
std::vector <double> data_line;
|
||||||
|
std::string number;
|
||||||
|
std::istringstream readstr(line);
|
||||||
|
for(int j = 0;j < 2814;j++){
|
||||||
|
getline(readstr,number,',');
|
||||||
|
data_line.push_back(atof(number.c_str()));
|
||||||
|
}
|
||||||
|
user_arr.push_back(data_line);
|
||||||
|
}
|
||||||
|
std::ofstream outfile;
|
||||||
|
outfile.open("C:/data/user_data7.csv", std::ios::out);
|
||||||
|
outfile<<"origin"<<','<<"temperature_drift"<<std::endl;
|
||||||
|
for (int i = 0; i <2814; ++i) {
|
||||||
|
user_arr[i][1]=algorithm.eval(user_arr[i][0]);
|
||||||
|
std::cout << i << "\t" << user_arr[i][1] << std::endl;
|
||||||
|
outfile<<user_arr[i][0]<<','<<user_arr[i][1]<<std::endl;
|
||||||
|
}
|
||||||
|
outfile.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// std::vector<int> x(100);
|
||||||
|
// std::generate(x.begin(), x.end(), []() {
|
||||||
|
// static int i = 0;
|
||||||
|
// return i++;
|
||||||
|
// });
|
||||||
|
// std::vector<double> virtual_data(100, 100.0);
|
||||||
|
// std::vector<double> temperature_drift_data;
|
||||||
|
// sciplot::Plot plot;
|
||||||
|
//
|
||||||
|
// for (auto iter: virtual_data) {
|
||||||
|
// temperature_drift_data.push_back(algorithm.eval(iter));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// plot.drawCurve(x, virtual_data).label("org");
|
||||||
|
// plot.drawCurve(x, temperature_drift_data).label("td");
|
||||||
|
// plot.show();
|
||||||
|
//
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//#include <sciplot/sciplot.hpp>
|
||||||
|
//using namespace sciplot;
|
||||||
|
//
|
||||||
|
//int main(int argc, char** argv)
|
||||||
|
//{
|
||||||
|
// // Create values for your x-axis
|
||||||
|
// Vec x = linspace(0.0, 5.0, 100);
|
||||||
|
//
|
||||||
|
// // Create a Plot object
|
||||||
|
// Plot plot;
|
||||||
|
//
|
||||||
|
// // Set color palette
|
||||||
|
// plot.palette("set2");
|
||||||
|
//
|
||||||
|
// // Draw a sine graph putting x on the x-axis and sin(x) on the y-axis
|
||||||
|
// plot.drawCurve(x, std::sin(x)).label("sin(x)").lineWidth(4);
|
||||||
|
//
|
||||||
|
// // Draw a cosine graph putting x on the x-axis and cos(x) on the y-axis
|
||||||
|
// plot.drawCurve(x, std::cos(x)).label("cos(x)").lineWidth(4);
|
||||||
|
//
|
||||||
|
// // Show the plot in a pop-up window
|
||||||
|
// plot.show();
|
||||||
|
//
|
||||||
|
// // Save the plot to a PDF file
|
||||||
|
// plot.save("plot.pdf");
|
||||||
|
//}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by fly on 2022/4/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "temperature_drift.h"
|
||||||
|
|
||||||
|
void temperature_drift::set_config(nlohmann::json const &config) {
|
||||||
|
try {
|
||||||
|
eval_time_ = 0;
|
||||||
|
amplitude_ = jsonValue(config, "TEMPERATURE_DRIFT_AMPLITUDE");
|
||||||
|
amplitude_base_ = jsonValue(config, "TEMPERATURE_DRIFT_AMPLITUDE_BASE");
|
||||||
|
config_ = config;
|
||||||
|
} catch (...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json temperature_drift::config() {
|
||||||
|
return config_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double temperature_drift::eval(double value) {
|
||||||
|
return value + amplitude_base_ + (amplitude_ * ++eval_time_);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by fly on 2022/4/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FAULT_SIMULATION_ALGORITHM_TEMPERATURE_DRIFT_H
|
||||||
|
#define FAULT_SIMULATION_ALGORITHM_TEMPERATURE_DRIFT_H
|
||||||
|
|
||||||
|
#include <algorithm.hpp>
|
||||||
|
|
||||||
|
class temperature_drift : public algorithm {
|
||||||
|
public:
|
||||||
|
void set_config(nlohmann::json const &config) override;
|
||||||
|
|
||||||
|
nlohmann::json config() override;
|
||||||
|
|
||||||
|
double eval(double value) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nlohmann::json config_{};
|
||||||
|
double amplitude_{0};
|
||||||
|
double amplitude_base_{0};
|
||||||
|
uint64_t eval_time_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //FAULT_SIMULATION_ALGORITHM_TEMPERATURE_DRIFT_H
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
add_library(
|
||||||
|
white-noise
|
||||||
|
INTERFACE
|
||||||
|
)
|
||||||
|
|
||||||
|
target_sources(
|
||||||
|
white-noise
|
||||||
|
INTERFACE
|
||||||
|
white_noise.cpp
|
||||||
|
white_noise.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
white-noise
|
||||||
|
INTERFACE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
white-noise
|
||||||
|
INTERFACE
|
||||||
|
nlohmann_json::nlohmann_json
|
||||||
|
)
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/24.
|
||||||
|
//
|
||||||
|
#include <iostream>
|
||||||
|
#include "white_noise.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
//#include <sciplot/sciplot.hpp>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
white_noise algorithm;
|
||||||
|
double white_noise_stddev=2;
|
||||||
|
double white_noise_mean=0;
|
||||||
|
|
||||||
|
algorithm.set_config(
|
||||||
|
{
|
||||||
|
{"WHITE_NOISE_MEAN", white_noise_mean},
|
||||||
|
{"WHITE_NOISE_STDDEV", white_noise_stddev},
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
std::vector <std::vector<double>> user_arr;
|
||||||
|
std::ifstream fp("C:/data/user_data.csv");
|
||||||
|
std::string line;
|
||||||
|
getline(fp,line);
|
||||||
|
while (getline(fp,line)){
|
||||||
|
std::vector <double> data_line;
|
||||||
|
std::string number;
|
||||||
|
std::istringstream readstr(line);
|
||||||
|
for(int j = 0;j < 2814;j++){
|
||||||
|
getline(readstr,number,',');
|
||||||
|
data_line.push_back(atof(number.c_str()));
|
||||||
|
}
|
||||||
|
user_arr.push_back(data_line);
|
||||||
|
}
|
||||||
|
std::ofstream outfile;
|
||||||
|
outfile.open("C:/data/user_data8.csv", std::ios::out);
|
||||||
|
outfile<<"origin"<<','<<"white_noise"<<std::endl;
|
||||||
|
for (int i = 0; i <2814; ++i) {
|
||||||
|
user_arr[i][1]=algorithm.eval(user_arr[i][0]);
|
||||||
|
std::cout << i << "\t" << user_arr[i][1] << std::endl;
|
||||||
|
outfile<<user_arr[i][0]<<','<<user_arr[i][1]<<std::endl;
|
||||||
|
}
|
||||||
|
outfile.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// int length=round(white_noise_stddev)*6;
|
||||||
|
// std::vector<int> x(length+1,0);
|
||||||
|
//for(int i=0;i<length+1;i++){
|
||||||
|
// x[i]=100-length/2+round(white_noise_mean)+i;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
// std::vector<double> virtual_data(10000, 100.0);
|
||||||
|
// std::vector<double> white_noise_data;
|
||||||
|
// std::vector<int> white_noise_data_number(length+1,0);
|
||||||
|
// sciplot::Plot plot;
|
||||||
|
//
|
||||||
|
// for (auto iter: virtual_data) {
|
||||||
|
// double a=algorithm.eval(iter);
|
||||||
|
// white_noise_data.push_back (round(a));
|
||||||
|
// std::cout << iter << "\t" << a << std::endl;
|
||||||
|
// }
|
||||||
|
// for(int k=0;k<virtual_data.size();k++){
|
||||||
|
// for(int l=0;l<length+1;l++){
|
||||||
|
// if(white_noise_data[k]==x[l])
|
||||||
|
// white_noise_data_number[l]++;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// plot.drawCurve(x, white_noise_data_number).label("td");
|
||||||
|
// plot.show();
|
||||||
|
//
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/24.
|
||||||
|
//
|
||||||
|
#include "white_noise.h"
|
||||||
|
|
||||||
|
void white_noise::set_config(const nlohmann::json &config) {
|
||||||
|
try {
|
||||||
|
mean_ = jsonValue(config, "WHITE_NOISE_MEAN");
|
||||||
|
standard_deviation_ = jsonValue(config, "WHITE_NOISE_STDDEV");
|
||||||
|
normal_distribution_.reset(new std::normal_distribution<>(mean_, standard_deviation_));
|
||||||
|
config_ = config;
|
||||||
|
} catch (...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json white_noise::config() {
|
||||||
|
return config_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double white_noise::eval(double value) {
|
||||||
|
if (normal_distribution_) {
|
||||||
|
value = value + normal_distribution_->operator()(mt19937_);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by baiguwen on 2022/4/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FAULT_SIMULATION_ALGORITHM_WHITE_NOISE_H
|
||||||
|
#define FAULT_SIMULATION_ALGORITHM_WHITE_NOISE_H
|
||||||
|
#include <algorithm.hpp>
|
||||||
|
#include <math.h>
|
||||||
|
#include <random>
|
||||||
|
class white_noise : public algorithm {
|
||||||
|
public:
|
||||||
|
void set_config(const nlohmann::json &config) override;
|
||||||
|
|
||||||
|
nlohmann::json config() override;
|
||||||
|
|
||||||
|
double eval(double value) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nlohmann::json config_{};
|
||||||
|
std::mt19937 mt19937_{std::random_device()()};
|
||||||
|
std::shared_ptr <std::normal_distribution<>> normal_distribution_;
|
||||||
|
double mean_{0};
|
||||||
|
double standard_deviation_{0};
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif //FAULT_SIMULATION_ALGORITHM_WHITE_NOISE_H
|
||||||
144
opcua-expoter/main.cpp
Normal file
144
opcua-expoter/main.cpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <open62541/client.h>
|
||||||
|
#include <prometheus/exposer.h>
|
||||||
|
#include <prometheus/registry.h>
|
||||||
|
#include <prometheus/counter.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
#include <CivetServer.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "client/client.h"
|
||||||
|
#include "collector/collector.h"
|
||||||
|
|
||||||
|
class MetricsHandle : public CivetHandler {
|
||||||
|
public:
|
||||||
|
explicit MetricsHandle(std::shared_ptr<collector> coll) : coll_(coll) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleGet(CivetServer *server, struct mg_connection *conn) override {
|
||||||
|
std::string json = to_string(coll_->getMetricsJson());
|
||||||
|
mg_send_http_ok(conn, "application/json", json.size());
|
||||||
|
mg_write(conn, json.c_str(), json.size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<collector> coll_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SimulationHandle : public CivetHandler {
|
||||||
|
public:
|
||||||
|
explicit SimulationHandle(std::shared_ptr<collector> coll) : coll_(coll) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleGet(CivetServer *server, struct mg_connection *conn) override {
|
||||||
|
auto name = getMetric(conn);
|
||||||
|
auto context = to_string(coll_->simulationConfig(name));
|
||||||
|
mg_send_http_ok(conn, "application/json", context.size());
|
||||||
|
mg_write(conn, context.c_str(), context.size());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handlePost(CivetServer *server, struct mg_connection *conn) override {
|
||||||
|
auto name = getMetric(conn);
|
||||||
|
auto json = getPostJson(conn);
|
||||||
|
|
||||||
|
coll_->setSimulationConfig(name, json);
|
||||||
|
|
||||||
|
mg_send_http_ok(conn, "application/json", 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string getMetric(mg_connection *conn) {
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
if (nullptr != req_info->query_string) {
|
||||||
|
return req_info->query_string;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json getPostJson(mg_connection *conn) {
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
auto size = req_info->content_length + 1;
|
||||||
|
char *buff = new char[size];
|
||||||
|
mg_read(conn, buff, size);
|
||||||
|
auto ret = nlohmann::json::parse(buff, buff + size - 1, nullptr, false);
|
||||||
|
delete[] buff;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<collector> coll_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
mg_init_library(0);
|
||||||
|
spdlog::info("OPC-UA Exporter");
|
||||||
|
std::string config_file_name = "./opcua.yml";
|
||||||
|
|
||||||
|
#ifdef Debug
|
||||||
|
spdlog::set_level(spdlog::level::trace);
|
||||||
|
#endif
|
||||||
|
if (2 == argc) {
|
||||||
|
config_file_name = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(config_file_name)) {
|
||||||
|
spdlog::error("the config file({}) not exists.", config_file_name);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
YAML::Node config = YAML::LoadFile(config_file_name);
|
||||||
|
|
||||||
|
auto exposer_bind_addr = config["exposer"]["bind"].as<std::string>("0.0.0.0:8090");
|
||||||
|
auto exposer_thread_num = config["exposer"]["thread"].as<std::size_t>(2);
|
||||||
|
spdlog::info("exposer bind addr : {}", exposer_bind_addr);
|
||||||
|
spdlog::info("exposer thread number : {}", exposer_thread_num);
|
||||||
|
prometheus::Exposer exposer{exposer_bind_addr, exposer_thread_num};
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string> civetOptions = {
|
||||||
|
{"listening_ports"},
|
||||||
|
{config["api"]["port"].as<std::string>("8080")}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CivetServer webServer(civetOptions);
|
||||||
|
|
||||||
|
auto ua_edp = config["opcua"]["endpoint"].as<std::string>();
|
||||||
|
if (ua_edp.empty()) {
|
||||||
|
spdlog::error("the opc ua endpoint not exists.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto ua_client = std::make_shared<client>(ua_edp);
|
||||||
|
|
||||||
|
auto opc_collector = std::make_shared<collector>(config["metrics"], ua_client);
|
||||||
|
|
||||||
|
exposer.RegisterCollectable(opc_collector);
|
||||||
|
|
||||||
|
auto metricsHandle = MetricsHandle(opc_collector);
|
||||||
|
auto simulationHandle = SimulationHandle(opc_collector);
|
||||||
|
|
||||||
|
webServer.addHandler(
|
||||||
|
"/api/metrics",
|
||||||
|
metricsHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
webServer.addHandler(
|
||||||
|
"/api/simulate",
|
||||||
|
simulationHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
ua_client->run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
11608
opcua-expoter/new_opcua.yaml
Normal file
11608
opcua-expoter/new_opcua.yaml
Normal file
File diff suppressed because it is too large
Load Diff
11623
opcua-expoter/opcua.yaml
Normal file
11623
opcua-expoter/opcua.yaml
Normal file
File diff suppressed because it is too large
Load Diff
11623
opcua-expoter/opcua.yml
Normal file
11623
opcua-expoter/opcua.yml
Normal file
File diff suppressed because it is too large
Load Diff
23440
opcua-expoter/opcua_fake.yaml
Normal file
23440
opcua-expoter/opcua_fake.yaml
Normal file
File diff suppressed because it is too large
Load Diff
12
opcua-expoter/vcpkg.json
Normal file
12
opcua-expoter/vcpkg.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "opcua-exporter",
|
||||||
|
"version": "1.0",
|
||||||
|
"dependencies": [
|
||||||
|
"civetweb",
|
||||||
|
"prometheus-cpp",
|
||||||
|
"spdlog",
|
||||||
|
"nlohmann-json",
|
||||||
|
"yaml-cpp",
|
||||||
|
"open62541"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user