update
This commit is contained in:
parent
7e4a55c39d
commit
793418f0a2
@ -181,7 +181,7 @@ if(AIMRT_BUILD_WITH_ROS2)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(AIMRT_BUILD_RUNTIME)
|
if(AIMRT_BUILD_RUNTIME)
|
||||||
include(GetBoost)
|
include(GetAsio)
|
||||||
include(GetGFlags)
|
include(GetGFlags)
|
||||||
include(GetYamlCpp)
|
include(GetYamlCpp)
|
||||||
include(GetTBB)
|
include(GetTBB)
|
||||||
@ -207,13 +207,28 @@ if(AIMRT_BUILD_RUNTIME)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(AIMRT_BUILD_NET_PLUGIN)
|
||||||
|
include(GetBoost)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(AIMRT_BUILD_RECORD_PLAYBACK_PLUGIN)
|
if(AIMRT_BUILD_RECORD_PLAYBACK_PLUGIN)
|
||||||
include(GetSqlite)
|
include(GetSqlite)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(AIMRT_BUILD_ICEORYX_PLUGIN)
|
if(AIMRT_BUILD_ICEORYX_PLUGIN)
|
||||||
include(GetCppToml)
|
# try to find libacl
|
||||||
include(GetIceoryx)
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux|QNX")
|
||||||
|
find_library(ACL_LIB acl)
|
||||||
|
if(NOT ACL_LIB)
|
||||||
|
message(WARNING "ICEORYX PLUGIN: libacl1-dev not found, please install the package by: sudo apt install libacl1-dev.")
|
||||||
|
set(AIMRT_BUILD_ICEORYX_PLUGIN OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(AIMRT_BUILD_ICEORYX_PLUGIN)
|
||||||
|
include(GetCppToml)
|
||||||
|
include(GetIceoryx)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(AIMRT_BUILD_MQTT_PLUGIN)
|
if(AIMRT_BUILD_MQTT_PLUGIN)
|
||||||
@ -232,7 +247,9 @@ if(AIMRT_BUILD_RUNTIME)
|
|||||||
message(STATUS "Rust compiler (rustc) found: ${rustc_output}")
|
message(STATUS "Rust compiler (rustc) found: ${rustc_output}")
|
||||||
include(GetZenoh)
|
include(GetZenoh)
|
||||||
else()
|
else()
|
||||||
message(WARNING "Rust compiler (rustc) not found, will not compile zenoh plugin. Please install Rust environment referring to https://www.rust-lang.org/tools/install.")
|
message(
|
||||||
|
WARNING
|
||||||
|
"ZENOH_PLUGIN: Rust compiler (rustc) not found, will not compile zenoh plugin. Please install Rust environment referring to https://www.rust-lang.org/tools/install.")
|
||||||
set(AIMRT_BUILD_ZENOH_PLUGIN OFF)
|
set(AIMRT_BUILD_ZENOH_PLUGIN OFF)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -245,6 +262,7 @@ if(AIMRT_BUILD_RUNTIME)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(AIMRT_BUILD_GRPC_PLUGIN)
|
if(AIMRT_BUILD_GRPC_PLUGIN)
|
||||||
|
include(GetBoost)
|
||||||
include(GetNghttp2)
|
include(GetNghttp2)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -269,3 +287,24 @@ if(AIMRT_INSTALL
|
|||||||
AND AIMRT_BUILD_PYTHON_PACKAGE)
|
AND AIMRT_BUILD_PYTHON_PACKAGE)
|
||||||
install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" --build \"${CMAKE_BINARY_DIR}\" --config ${CMAKE_BUILD_TYPE} --target create_python_pkg)")
|
install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" --build \"${CMAKE_BINARY_DIR}\" --config ${CMAKE_BUILD_TYPE} --target create_python_pkg)")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# print all aimrt options
|
||||||
|
message("\n\n AIMRT CMake Options/Info:")
|
||||||
|
get_cmake_property(all_variables VARIABLES)
|
||||||
|
set(printed_vars)
|
||||||
|
|
||||||
|
foreach(var ${all_variables})
|
||||||
|
if(var MATCHES "^AIMRT_.*")
|
||||||
|
if(NOT "${var}" IN_LIST printed_vars)
|
||||||
|
list(APPEND printed_vars "${var}")
|
||||||
|
string(LENGTH ${var} var_length)
|
||||||
|
math(EXPR padding_length "40 - ${var_length}")
|
||||||
|
if(padding_length GREATER 0)
|
||||||
|
string(REPEAT "-" ${padding_length} padding)
|
||||||
|
else()
|
||||||
|
set(padding "")
|
||||||
|
endif()
|
||||||
|
message(" ${var}${padding}: ${${var}}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
70
cmake/GetAsio.cmake
Normal file
70
cmake/GetAsio.cmake
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Copyright (c) 2023, AgiBot Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
message(STATUS "get asio ...")
|
||||||
|
|
||||||
|
set(asio_DOWNLOAD_URL
|
||||||
|
"https://github.com/chriskohlhoff/asio/archive/asio-1-30-2.tar.gz"
|
||||||
|
CACHE STRING "")
|
||||||
|
|
||||||
|
if(asio_LOCAL_SOURCE)
|
||||||
|
FetchContent_Declare(
|
||||||
|
asio
|
||||||
|
SOURCE_DIR ${asio_LOCAL_SOURCE}
|
||||||
|
OVERRIDE_FIND_PACKAGE)
|
||||||
|
else()
|
||||||
|
FetchContent_Declare(
|
||||||
|
asio
|
||||||
|
URL ${asio_DOWNLOAD_URL}
|
||||||
|
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
|
||||||
|
OVERRIDE_FIND_PACKAGE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
FetchContent_GetProperties(asio)
|
||||||
|
if(NOT asio_POPULATED)
|
||||||
|
FetchContent_Populate(asio)
|
||||||
|
|
||||||
|
add_library(asio INTERFACE)
|
||||||
|
add_library(asio::asio ALIAS asio)
|
||||||
|
|
||||||
|
target_include_directories(asio INTERFACE ${asio_SOURCE_DIR}/asio/include)
|
||||||
|
target_compile_definitions(asio INTERFACE ASIO_STANDALONE ASIO_NO_DEPRECATED)
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(asio INTERFACE Threads::Threads)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# macro see @ https://stackoverflow.com/a/40217291/1746503
|
||||||
|
macro(get_win32_winnt version)
|
||||||
|
if(CMAKE_SYSTEM_VERSION)
|
||||||
|
set(ver ${CMAKE_SYSTEM_VERSION})
|
||||||
|
string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
|
||||||
|
string(REGEX MATCH "^([0-9]+)" verMajor ${ver})
|
||||||
|
# Check for Windows 10, b/c we'll need to convert to hex 'A'.
|
||||||
|
if("${verMajor}" MATCHES "10")
|
||||||
|
set(verMajor "A")
|
||||||
|
string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
|
||||||
|
endif("${verMajor}" MATCHES "10")
|
||||||
|
# Remove all remaining '.' characters.
|
||||||
|
string(REPLACE "." "" ver ${ver})
|
||||||
|
# Prepend each digit with a zero.
|
||||||
|
string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver})
|
||||||
|
set(${version} "0x${ver}")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
if(NOT DEFINED _WIN32_WINNT)
|
||||||
|
get_win32_winnt(ver)
|
||||||
|
set(_WIN32_WINNT ${ver})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Set _WIN32_WINNET=${_WIN32_WINNT}")
|
||||||
|
|
||||||
|
target_compile_definitions(asio INTERFACE _WIN32_WINNT=${_WIN32_WINNT} WIN32_LEAN_AND_MEAN)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# import targets:
|
||||||
|
# asio::asio
|
@ -6,7 +6,7 @@ include(FetchContent)
|
|||||||
message(STATUS "get jsoncpp ...")
|
message(STATUS "get jsoncpp ...")
|
||||||
|
|
||||||
set(jsoncpp_DOWNLOAD_URL
|
set(jsoncpp_DOWNLOAD_URL
|
||||||
"https://github.com/open-source-parsers/jsoncpp/archive/1.9.5.tar.gz"
|
"https://github.com/open-source-parsers/jsoncpp/archive/1.9.6.tar.gz"
|
||||||
CACHE STRING "")
|
CACHE STRING "")
|
||||||
|
|
||||||
if(jsoncpp_LOCAL_SOURCE)
|
if(jsoncpp_LOCAL_SOURCE)
|
||||||
|
@ -48,6 +48,10 @@ if(NOT opentelemetry_cpp_POPULATED)
|
|||||||
ON
|
ON
|
||||||
CACHE BOOL "")
|
CACHE BOOL "")
|
||||||
|
|
||||||
|
set(WITH_STL
|
||||||
|
"CXX20"
|
||||||
|
CACHE STRING "")
|
||||||
|
|
||||||
set(OTELCPP_PROTO_PATH
|
set(OTELCPP_PROTO_PATH
|
||||||
${opentelemetry_proto_SOURCE_DIR}
|
${opentelemetry_proto_SOURCE_DIR}
|
||||||
CACHE PATH "")
|
CACHE PATH "")
|
||||||
|
@ -56,5 +56,5 @@ myst_enable_extensions = [
|
|||||||
|
|
||||||
myst_substitutions = {
|
myst_substitutions = {
|
||||||
"code_site_url": "https://github.com/AimRT/AimRT",
|
"code_site_url": "https://github.com/AimRT/AimRT",
|
||||||
"code_site_root_path_url": "https://github.com/AimRT/AimRT/blob/master",
|
"code_site_root_path_url": "https://github.com/AimRT/AimRT/blob/main",
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,12 @@
|
|||||||
- 优化了 zenoh 插件:
|
- 优化了 zenoh 插件:
|
||||||
- 添加了 zenoh rpc 后端;
|
- 添加了 zenoh rpc 后端;
|
||||||
- 现在可以传入 zenoh 原生配置;
|
- 现在可以传入 zenoh 原生配置;
|
||||||
- mqtt 新增配置项以支持加密传输
|
- mqtt 新增配置项以支持加密传输;
|
||||||
|
- 新增了第三方库 asio,runtime::core 不再引用 boost,改为引用独立的 asio 库,以减轻依赖;
|
||||||
|
|
||||||
|
|
||||||
**次要修改**:
|
**次要修改**:
|
||||||
- 缩短了一些 examples 的文件路径长度;
|
- 缩短了一些 examples 的文件路径长度;
|
||||||
- 修复了一些轻微问题;
|
- 修复了一些轻微问题;
|
||||||
|
- 优化代码结构,移动代码 src/runtime/common/net 至新位置 src/common/net;
|
||||||
|
- 升级 jsoncpp 至 1.9.6 版本以优化一些 cmake 问题;
|
||||||
|
@ -73,6 +73,7 @@ AimRT 中所有的可引用的非协议类型 CMake Target 如下:
|
|||||||
| CMake Target名称 | 作用 | 需要开启的宏 |
|
| CMake Target名称 | 作用 | 需要开启的宏 |
|
||||||
| ---- | ---- | ---- |
|
| ---- | ---- | ---- |
|
||||||
| aimrt::common::util | 一些独立基础工具,如 string、log 等 | |
|
| aimrt::common::util | 一些独立基础工具,如 string、log 等 | |
|
||||||
|
| aimrt::common::net | 一些独立的网络工具,基于 boost asio/beast | AIMRT_BUILD_RUNTIME、AIMRT_BUILD_NET_PLUGIN 或 AIMRT_BUILD_GRPC_PLUGIN |
|
||||||
| aimrt::common::ros2_util | 独立的 ros2 相关的基础工具 | AIMRT_BUILD_WITH_ROS2 |
|
| aimrt::common::ros2_util | 独立的 ros2 相关的基础工具 | AIMRT_BUILD_WITH_ROS2 |
|
||||||
| aimrt::interface::aimrt_module_c_interface | 模块开发接口-C 版本 | |
|
| aimrt::interface::aimrt_module_c_interface | 模块开发接口-C 版本 | |
|
||||||
| aimrt::interface::aimrt_module_cpp_interface | 模块开发接口-CPP 版本 | |
|
| aimrt::interface::aimrt_module_cpp_interface | 模块开发接口-CPP 版本 | |
|
||||||
|
@ -75,7 +75,7 @@ AimRT 目前官方支持两种 IDL:
|
|||||||
`Channel`也叫数据通道,是一种典型的通信拓补概念,其通过`Topic`标识单个数据通道,由发布者`Publisher`和订阅者`Subscriber`组成,订阅者可以获取到发布者发布的数据。`Channel`是一种多对多的拓补结构,`Module`可以向任意数量的`Topic`发布数据,同时可以订阅任意数量的`Topic`。类似的概念如 ROS 中的 Topic、Kafka/RabbitMQ 等消息队列。
|
`Channel`也叫数据通道,是一种典型的通信拓补概念,其通过`Topic`标识单个数据通道,由发布者`Publisher`和订阅者`Subscriber`组成,订阅者可以获取到发布者发布的数据。`Channel`是一种多对多的拓补结构,`Module`可以向任意数量的`Topic`发布数据,同时可以订阅任意数量的`Topic`。类似的概念如 ROS 中的 Topic、Kafka/RabbitMQ 等消息队列。
|
||||||
|
|
||||||
|
|
||||||
在 AimRT 中,Channel 由`接口层`和`后端`两部分组成,两者相互解耦。接口层定义了一层抽象的 Api,表示逻辑层面上的`Channel`;而后端负责实际的 Channel 数据传输,可以有多种类型。AimRT 官方提供了一些 Channel 后端,例如 mqtt、ros 等,使用者也可以自行开发新的 Channel 后端。
|
在 AimRT 中,Channel 由`接口层`和`后端`两部分组成,两者相互解耦。接口层定义了一层抽象的 Api,表示逻辑层面上的`Channel`;而后端负责实际的 Channel 数据传输,可以有多种类型。AimRT 官方提供了一些 Channel 后端,例如 mqtt、ros2 等,使用者也可以自行开发新的 Channel 后端。
|
||||||
|
|
||||||
开发者在使用 AimRT 中的 Channel 功能时,先在业务逻辑层调用接口层的 API,往某个 Topic 中发布数据,或订阅某个 Topic 的数据。然后 AimRT 框架会根据一定的规则,选择一个或几个 Channel 后端进行处理,这些后端将数据通过一些特定的方式发送给其他节点,由其他节点上对应的 Channel 后端接收数据并传递给业务逻辑层。整个逻辑流程如下图所示:
|
开发者在使用 AimRT 中的 Channel 功能时,先在业务逻辑层调用接口层的 API,往某个 Topic 中发布数据,或订阅某个 Topic 的数据。然后 AimRT 框架会根据一定的规则,选择一个或几个 Channel 后端进行处理,这些后端将数据通过一些特定的方式发送给其他节点,由其他节点上对应的 Channel 后端接收数据并传递给业务逻辑层。整个逻辑流程如下图所示:
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ AimRT 目前官方支持两种 IDL:
|
|||||||
## AimRT 中的 "Rpc" 概念
|
## AimRT 中的 "Rpc" 概念
|
||||||
`RPC`也叫远程过程调用,基于请求-回复模型,由客户端`Client`和服务端`Server`组成,`Module`可以创建客户端句柄,发起特定的 RPC 请求,由其指定的、或由框架根据一定规则指定的服务端来接收请求并回复。`Module`也可以创建服务端句柄,提供特定的 RPC 服务,接收处理系统路由过来的请求并回复。类似的概念如 ROS 中的 Services、GRPC/Thrift 等 RPC 框架。
|
`RPC`也叫远程过程调用,基于请求-回复模型,由客户端`Client`和服务端`Server`组成,`Module`可以创建客户端句柄,发起特定的 RPC 请求,由其指定的、或由框架根据一定规则指定的服务端来接收请求并回复。`Module`也可以创建服务端句柄,提供特定的 RPC 服务,接收处理系统路由过来的请求并回复。类似的概念如 ROS 中的 Services、GRPC/Thrift 等 RPC 框架。
|
||||||
|
|
||||||
在 AimRT 中,RPC 也由`接口层`和`后端`两部分组成,两者相互解耦。接口层定义了 RPC 的抽象 Api,而后端则负责实际的 RPC 调用。AimRT 官方提供了一些 RPC 后端,例如 http、ros 等,使用者也可以自行开发新的 RPC 后端。
|
在 AimRT 中,RPC 也由`接口层`和`后端`两部分组成,两者相互解耦。接口层定义了 RPC 的抽象 Api,而后端则负责实际的 RPC 调用。AimRT 官方提供了一些 RPC 后端,例如 http、ros2 等,使用者也可以自行开发新的 RPC 后端。
|
||||||
|
|
||||||
开发者使用 AimRT 的 RPC 功能时,先在业务逻辑层调用接口层 API,通过 Client 发起一个 RPC 调用,AimRT 框架会根据一定的规则选择一个 RPC 后端进行处理,它将数据通过一些特定的方式发送给 Server 节点,由 Server 节点上对应的 Rpc 后端接收数据并传递给业务层,并将业务层的回包传递回 Client 端。整个逻辑流程如下图所示:
|
开发者使用 AimRT 的 RPC 功能时,先在业务逻辑层调用接口层 API,通过 Client 发起一个 RPC 调用,AimRT 框架会根据一定的规则选择一个 RPC 后端进行处理,它将数据通过一些特定的方式发送给 Server 节点,由 Server 节点上对应的 Rpc 后端接收数据并传递给业务层,并将业务层的回包传递回 Client 端。整个逻辑流程如下图所示:
|
||||||
|
|
||||||
|
@ -0,0 +1,184 @@
|
|||||||
|
# Ubuntu 22.04 源码构建
|
||||||
|
|
||||||
|
## 必选依赖
|
||||||
|
|
||||||
|
### CMake
|
||||||
|
|
||||||
|
AimRT 编译所需的最小 CMake 版本为 3.24,Ubuntu 22.04 使用 apt 包管理器安装的 CMake 版本为 3.22 不符合要求,请前往 [CMake 官方网站](https://cmake.org/download/) 下载对应版本进行安装。
|
||||||
|
|
||||||
|
推荐的安装方式有两种
|
||||||
|
|
||||||
|
1. 通过 pip 安装 CMake
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install python3 python3-pip
|
||||||
|
pip install cmake --upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 安装 CMake 官方提供的安装脚本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://github.com/Kitware/CMake/releases/download/v3.30.4/cmake-3.30.4-linux-x86_64.sh
|
||||||
|
sudo bash cmake-3.30.4-linux-x86_64.sh --prefix=/usr/local --skip-license
|
||||||
|
```
|
||||||
|
|
||||||
|
### make/gcc/g++
|
||||||
|
|
||||||
|
Ubuntu 22.04 中 apt 源自带的 gcc 版本为 11.4,适用于 AimRT 构建所用,可以直接安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install make gcc g++
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最小化构建
|
||||||
|
|
||||||
|
将以上内容进行安装后即可进行无外部依赖的最小化构建,构建选项如下所示
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake -B build \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DAIMRT_INSTALL=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=./build/install \
|
||||||
|
-DAIMRT_BUILD_TESTS=OFF \
|
||||||
|
-DAIMRT_BUILD_EXAMPLES=ON \
|
||||||
|
-DAIMRT_BUILD_DOCUMENT=OFF \
|
||||||
|
-DAIMRT_BUILD_RUNTIME=ON \
|
||||||
|
-DAIMRT_BUILD_CLI_TOOLS=OFF \
|
||||||
|
-DAIMRT_BUILD_PYTHON_RUNTIME=OFF \
|
||||||
|
-DAIMRT_USE_FMT_LIB=ON \
|
||||||
|
-DAIMRT_BUILD_WITH_PROTOBUF=ON \
|
||||||
|
-DAIMRT_USE_LOCAL_PROTOC_COMPILER=OFF \
|
||||||
|
-DAIMRT_USE_PROTOC_PYTHON_PLUGIN=OFF \
|
||||||
|
-DAIMRT_BUILD_WITH_ROS2=OFF \
|
||||||
|
-DAIMRT_BUILD_NET_PLUGIN=ON \
|
||||||
|
-DAIMRT_BUILD_MQTT_PLUGIN=OFF \
|
||||||
|
-DAIMRT_BUILD_ZENOH_PLUGIN=OFF \
|
||||||
|
-DAIMRT_BUILD_ICEORYX_PLUGIN=OFF \
|
||||||
|
-DAIMRT_BUILD_ROS2_PLUGIN=OFF \
|
||||||
|
-DAIMRT_BUILD_RECORD_PLAYBACK_PLUGIN=ON \
|
||||||
|
-DAIMRT_BUILD_TIME_MANIPULATOR_PLUGIN=ON \
|
||||||
|
-DAIMRT_BUILD_PARAMETER_PLUGIN=ON \
|
||||||
|
-DAIMRT_BUILD_LOG_CONTROL_PLUGIN=ON \
|
||||||
|
-DAIMRT_BUILD_OPENTELEMETRY_PLUGIN=ON \
|
||||||
|
-DAIMRT_BUILD_GRPC_PLUGIN=ON \
|
||||||
|
-DAIMRT_BUILD_PYTHON_PACKAGE=OFF
|
||||||
|
|
||||||
|
cmake --build build --config Release --target all -j
|
||||||
|
```
|
||||||
|
|
||||||
|
如果要开启其他选项则需要安装对应依赖,具体依赖请参考 [可选依赖](#可选依赖)
|
||||||
|
|
||||||
|
## 可选依赖
|
||||||
|
|
||||||
|
### Python 功能及其相关包
|
||||||
|
|
||||||
|
AimRT 所使用的 Python 版本最低为 3.10,推荐使用 3.10 版本(Ubuntu 22.04 的 apt 源安装版本)。
|
||||||
|
|
||||||
|
AimRT 的 Python 接口依赖 Python 3。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install python3
|
||||||
|
```
|
||||||
|
|
||||||
|
aimrt_cli 工具依赖 Python 3 以及 pyinstaller jinja2 pyyaml 三个库,可以通过以下命令进行安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install python3 python3-pip
|
||||||
|
pip install pyinstaller jinja2 pyyaml --upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
打包生成 aimrt_py 的 whl 包功能依赖 Python 3 以及 build setuptools wheel 等库,可以通过以下命令进行安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install python3 python3-pip
|
||||||
|
pip install build setuptools wheel --upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
以上内容分别对应以下选项
|
||||||
|
|
||||||
|
```bash
|
||||||
|
-DAIMRT_BUILD_PYTHON_RUNTIME=ON
|
||||||
|
-DAIMRT_BUILD_CLI_TOOLS=ON
|
||||||
|
-DAIMRT_BUILD_PYTHON_PACKAGE=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
### ROS2 相关依赖
|
||||||
|
|
||||||
|
AimRT 的 ROS2 相关功能以及 ROS2 插件依赖 ROS2 humble 版本(仅支持该版本),可以参考 [ROS2 官方文档](https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debians.html) 进行安装。
|
||||||
|
|
||||||
|
安装完成后需要设置好相应的环境变量,即
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source /opt/ros/humble/setup.bash
|
||||||
|
```
|
||||||
|
|
||||||
|
可以通过以下命令检查是否设置好相应的环境变量
|
||||||
|
|
||||||
|
```bash
|
||||||
|
printenv | grep -i ROS
|
||||||
|
```
|
||||||
|
|
||||||
|
ROS2 相关依赖对应以下选项
|
||||||
|
|
||||||
|
```bash
|
||||||
|
-DAIMRT_BUILD_WITH_ROS2=ON
|
||||||
|
-DAIMRT_BUILD_ROS2_PLUGIN=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
### Iceoryx 相关依赖
|
||||||
|
|
||||||
|
AimRT 的 Iceoryx 插件依赖 acl 库,可以通过以下命令进行安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install libacl1-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Iceoryx 相关依赖对应以下选项
|
||||||
|
|
||||||
|
```bash
|
||||||
|
-DAIMRT_BUILD_ICEORYX_PLUGIN=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
### Zenoh 相关依赖
|
||||||
|
|
||||||
|
AimRT 的 Zenoh 插件依赖本地的 rust 环境,可以通过以下命令进行安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install curl
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Zenoh 相关依赖对应以下选项
|
||||||
|
|
||||||
|
```bash
|
||||||
|
-DAIMRT_BUILD_ZENOH_PLUGIN=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
### MQTT 相关依赖
|
||||||
|
|
||||||
|
AimRT 的 MQTT 插件依赖 openssl 库,可以通过以下命令进行安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install libssl-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
MQTT 相关依赖对应以下选项
|
||||||
|
|
||||||
|
```bash
|
||||||
|
-DAIMRT_BUILD_MQTT_PLUGIN=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
## 完整构建
|
||||||
|
|
||||||
|
将以上内容进行安装后即可进行完整构建,可以直接运行根目录下的 build.sh 脚本进行构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
AimRT 在构建过程中会使用 FetchContent 从 github 上拉取依赖,如果网络环境不佳,可以使用以下命令将 FetchContent 的源替换为从 gitee 镜像拉取再进行构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source url_cn.bashrc
|
||||||
|
./build.sh $AIMRT_DOWNLOAD_FLAGS
|
||||||
|
```
|
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
# Windows 源码构建
|
||||||
|
|
||||||
|
注意 Windows 平台下部分插件未经过实际测试,其编译选项在 build.bat 中默认关闭,启用后可能存在问题,如果遇到问题请及时反馈。
|
||||||
|
|
||||||
|
## 必选依赖
|
||||||
|
|
||||||
|
### MSVC 编译套件
|
||||||
|
|
||||||
|
当前 AimRT 支持的 MSVC 编译套件版本为 1940,推荐直接安装 [Visual Studio 2022](https://visualstudio.microsoft.com/zh-hans/downloads/) 及以上版本,安装时勾选 C++ 桌面开发模块。
|
||||||
|
|
||||||
|
### CMake
|
||||||
|
|
||||||
|
当前 AimRT 支持的最低 CMake 版本为 3.24,可以通过以下链接下载合适的版本进行安装:
|
||||||
|
|
||||||
|
[CMake 3.24](https://cmake.org/download/)
|
||||||
|
|
||||||
|
## 最小化构建
|
||||||
|
|
||||||
|
将以上内容进行安装后即可进行无外部依赖的最小化构建,构建选项如下所示
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cmake -B build ^
|
||||||
|
-DCMAKE_BUILD_TYPE=Release ^
|
||||||
|
-DAIMRT_INSTALL=ON ^
|
||||||
|
-DCMAKE_INSTALL_PREFIX="./build/install" ^
|
||||||
|
-DAIMRT_BUILD_TESTS=OFF ^
|
||||||
|
-DAIMRT_BUILD_EXAMPLES=ON ^
|
||||||
|
-DAIMRT_BUILD_DOCUMENT=ON ^
|
||||||
|
-DAIMRT_BUILD_RUNTIME=ON ^
|
||||||
|
-DAIMRT_BUILD_CLI_TOOLS=OFF ^
|
||||||
|
-DAIMRT_BUILD_PYTHON_RUNTIME=OFF ^
|
||||||
|
-DAIMRT_USE_FMT_LIB=ON ^
|
||||||
|
-DAIMRT_BUILD_WITH_PROTOBUF=ON ^
|
||||||
|
-DAIMRT_USE_LOCAL_PROTOC_COMPILER=OFF ^
|
||||||
|
-DAIMRT_USE_PROTOC_PYTHON_PLUGIN=OFF ^
|
||||||
|
-DAIMRT_BUILD_WITH_ROS2=OFF ^
|
||||||
|
-DAIMRT_BUILD_NET_PLUGIN=ON ^
|
||||||
|
-DAIMRT_BUILD_MQTT_PLUGIN=OFF ^
|
||||||
|
-DAIMRT_BUILD_ZENOH_PLUGIN=OFF ^
|
||||||
|
-DAIMRT_BUILD_ICEORYX_PLUGIN=OFF ^
|
||||||
|
-DAIMRT_BUILD_ROS2_PLUGIN=OFF ^
|
||||||
|
-DAIMRT_BUILD_RECORD_PLAYBACK_PLUGIN=ON ^
|
||||||
|
-DAIMRT_BUILD_TIME_MANIPULATOR_PLUGIN=ON ^
|
||||||
|
-DAIMRT_BUILD_PARAMETER_PLUGIN=ON ^
|
||||||
|
-DAIMRT_BUILD_LOG_CONTROL_PLUGIN=ON ^
|
||||||
|
-DAIMRT_BUILD_OPENTELEMETRY_PLUGIN=OFF ^
|
||||||
|
-DAIMRT_BUILD_GRPC_PLUGIN=OFF ^
|
||||||
|
-DAIMRT_BUILD_PYTHON_PACKAGE=OFF
|
||||||
|
```
|
||||||
|
|
||||||
|
## 可选依赖
|
||||||
|
|
||||||
|
### Python 及其相关包
|
||||||
|
|
||||||
|
AimRT 在 Windows 平台下支持的 Python 版本最低为 3.11,推荐使用 [Python 3.11](https://www.python.org/downloads/release/python-31110/) 及以上版本。
|
||||||
|
|
||||||
|
安装完成后需要将 Python 添加到系统环境变量中。
|
||||||
|
|
||||||
|
airmt_cli 工具依赖于 Python 3 以及 pyinstaller jinja2 pyyaml 三个库,可以通过以下命令进行安装
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install pyinstaller jinja2 pyyaml --upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
打包生成 aimrt_py 的 whl 包功能依赖 Python 3 以及 build setuptools wheel 等库,可以通过以下命令进行安装
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install build setuptools wheel --upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
以上内容分别对应以下选项
|
||||||
|
|
||||||
|
```shell
|
||||||
|
-DAIMRT_BUILD_PYTHON_RUNTIME=ON
|
||||||
|
-DAIMRT_BUILD_CLI_TOOLS=ON
|
||||||
|
-DAIMRT_BUILD_PYTHON_PACKAGE=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
## 完整构建
|
||||||
|
|
||||||
|
此处完整构建不包含未经充分测试的插件,直接运行 build.bat 即可。
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./build.bat
|
||||||
|
```
|
@ -1,19 +1,10 @@
|
|||||||
|
|
||||||
# 引用与安装(CPP)
|
# 安装与引用(CPP)
|
||||||
|
|
||||||
|
## 系统要求
|
||||||
|
|
||||||
在开发 C++ 工程时,您可以通过两种方式引用 AimRT:
|
当前 AimRT 官方支持的操作系统和编译套件包括:
|
||||||
- [推荐] 基于 CMake FetchContent,通过源码进行引用;
|
- Ubuntu 22.04
|
||||||
- 安装后,基于 CMake find_package 进行引用;
|
|
||||||
|
|
||||||
AimRT 比较轻量,推荐用户直接基于源码进行引用。如果要使用基于安装的方式进行引用,AimRT 也提供了两种方式:
|
|
||||||
- 从源码编译安装;
|
|
||||||
- 二进制安装;
|
|
||||||
|
|
||||||
|
|
||||||
## 编译环境要求
|
|
||||||
AimRT 兼容 linux、windows 等主流操作系统,编译器需要能够支持 c++20,CMake 版本需要 3.24 或以上。我们已经在以下操作系统和编译器上测试过:
|
|
||||||
- Ubuntu22.04
|
|
||||||
- gcc-11.4
|
- gcc-11.4
|
||||||
- gcc-12.4
|
- gcc-12.4
|
||||||
- gcc-13.3
|
- gcc-13.3
|
||||||
@ -21,20 +12,34 @@ AimRT 兼容 linux、windows 等主流操作系统,编译器需要能够支持
|
|||||||
- clang-16.0.6
|
- clang-16.0.6
|
||||||
- clang-17.0.6
|
- clang-17.0.6
|
||||||
- clang-18.1.8
|
- clang-18.1.8
|
||||||
- Windows11
|
- Windows
|
||||||
- MSVC-19.40
|
- MSVC-1940
|
||||||
|
|
||||||
请注意:
|
除以上列出的系统外,理论上所有兼容以上环境的系统均可以编译运行 AimRT。
|
||||||
- 在编译构建时,AimRT 可能通过源码方式引用一些第三方依赖,如果出现网络问题,可以参考[CMake](../concepts/cmake.md)文档进行处理。
|
|
||||||
- 在打开某些选项、编译某些插件时,AimRT 可能需要额外引用一些第三方依赖,细节请参考对应插件的文档、CMake 代码文件或构建时的提示。以下是一些示例:
|
|
||||||
- 如果要编译 ROS2 相关接口/插件,AimRT 会通过`find_package`的方式在本地寻找 rclcpp 等依赖,请确保本地安装有[ROS2 Humble](https://docs.ros.org/en/humble/)。
|
|
||||||
- 如果要构建 Python 接口、cli 工具等,AimRT 会通过`find_package`的方式在本地寻找 Python 依赖,请确保本地安装有 Python3 及相关的 python 包,缺失相应包在 CMake 生成过程中会告警不会编译相应内容。
|
|
||||||
- Zenoh 插件需要本地安装有 rust 环境,在 Ubuntu 上可通过 `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` 进行安装,没有 rust 环境则不会编译 zenoh 插件。
|
|
||||||
- Iceoryx 插件依赖 libacl,在 ubuntu 上可通过 `sudo apt install libacl1-dev` 进行安装,选项开启但缺失相应包会报错。
|
|
||||||
- Boost 依赖由于其内容较大,CMake 会首先检查本地是否有 1.82.0 及以上版本的 boost,如果有则使用本地安装的 boost,如果没有则进行下载。
|
|
||||||
|
|
||||||
|
Ubuntu 22.04 为推荐系统,所有测试以及二进制包均基于此系统,Windows 平台下仅支持 MSVC 编译器且插件支持较为有限。
|
||||||
|
|
||||||
## 通过源码引用
|
ROS2 相关内容目前仅支持 humble 版本。
|
||||||
|
|
||||||
|
## 安装方式
|
||||||
|
|
||||||
|
当前 AimRT 的 C++ 接口仅支持从源码构建安装。
|
||||||
|
|
||||||
|
### 源码构建
|
||||||
|
|
||||||
|
[Ubuntu Linux 22.04 源码构建](build_from_source_ubuntu.md)
|
||||||
|
|
||||||
|
[Windows 源码构建](build_from_source_windows.md)
|
||||||
|
|
||||||
|
## 引用方式
|
||||||
|
|
||||||
|
在开发 C++ 工程时,您可以通过两种方式引用 AimRT:
|
||||||
|
- [推荐] 基于 CMake FetchContent,通过源码进行引用;
|
||||||
|
- 安装后,基于 CMake find_package 进行引用;
|
||||||
|
|
||||||
|
AimRT 比较轻量,推荐用户直接基于源码进行引用。
|
||||||
|
|
||||||
|
### 通过源码引用
|
||||||
|
|
||||||
您可以参考以下 CMake 代码引用 AimRT,注意需要将`GIT_TAG`版本改为你想引用的版本:
|
您可以参考以下 CMake 代码引用 AimRT,注意需要将`GIT_TAG`版本改为你想引用的版本:
|
||||||
```cmake
|
```cmake
|
||||||
@ -62,37 +67,11 @@ target_link_libraries(
|
|||||||
PUBLIC aimrt::interface::aimrt_module_cpp_interface)
|
PUBLIC aimrt::interface::aimrt_module_cpp_interface)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 安装后find_package引用
|
### 安装后find_package引用
|
||||||
|
|
||||||
请注意:使用 **install 后 find_package 引用**这种方式,只能引用部分功能,只能基于 pkg 模式开发,无法使用 app 模式开发、或开发 aimrt 插件。
|
请注意:使用 **install 后 find_package 引用**这种方式,只能引用部分功能,只能基于 pkg 模式开发,无法使用 app 模式开发、或开发 aimrt 插件。
|
||||||
|
|
||||||
### 安装方式一:从源码构建安装
|
参考 [源码构建](build_from_source_ubuntu.md) 运行 build.sh 脚本进行构建,在构建时可以修改 `CMAKE_INSTALL_PREFIX` 指定安装目录,完成安装后,参考以下步骤完成引用:
|
||||||
|
|
||||||
基于源码编译 AimRT 非常简单,可参考以下步骤:
|
|
||||||
- 首先请确认本地环境符合要求;
|
|
||||||
- 通过 git 等方式下载源码;
|
|
||||||
- 直接执行 AimRT 源码根路径下的 build 脚本执行编译、安装;
|
|
||||||
- linux 下请执行 build.sh;
|
|
||||||
- windows 下请执行 build.bat;
|
|
||||||
- 可以修改 build 脚本中的 CMake 选项以开关一些功能;
|
|
||||||
- 可以修改 build 脚本中的`CMAKE_INSTALL_PREFIX`选项指定安装地址;
|
|
||||||
- 如果遇到网络问题无法下载一些依赖,请参考[AimRT中的CMake](../concepts/cmake.md)文档中的说明;
|
|
||||||
|
|
||||||
|
|
||||||
### 安装方式二:从二进制包安装
|
|
||||||
|
|
||||||
***TODO***
|
|
||||||
|
|
||||||
<!-- 您可以直接在`AimRT 的发布页面`上下载一些主流平台上编译好的二进制包并安装。
|
|
||||||
|
|
||||||
注意:
|
|
||||||
- 部分插件只在一些平台上提供,这和插件本身所需的组件依赖的平台有关。
|
|
||||||
- AimRT 二进制安装包直接支持的平台较少,但并不意味 AimRT 仅支持这些平台。AimRT 本身比较轻量,没有太多依赖,鼓励使用源码形式安装/引用。 -->
|
|
||||||
|
|
||||||
|
|
||||||
### 安装完成后,使用CMake find_package进行引用
|
|
||||||
|
|
||||||
完成安装后,参考以下步骤完成引用:
|
|
||||||
- 如果没有安装在系统路径,则需要在自己项目的 CMake 中设置 CMAKE_PREFIX_PATH 到 AimRT 的安装目录,例如:
|
- 如果没有安装在系统路径,则需要在自己项目的 CMake 中设置 CMAKE_PREFIX_PATH 到 AimRT 的安装目录,例如:
|
||||||
```cmake
|
```cmake
|
||||||
list(APPEND CMAKE_PREFIX_PATH "/path/to/aimrt/install")
|
list(APPEND CMAKE_PREFIX_PATH "/path/to/aimrt/install")
|
||||||
|
@ -12,10 +12,10 @@ AimRT官方测试过的最低 Python 版本是 3.10,Linux 系统 glibc 的最
|
|||||||
|
|
||||||
我们在以下系统和 python 版本上测试过 `aimrt_py` 包:
|
我们在以下系统和 python 版本上测试过 `aimrt_py` 包:
|
||||||
|
|
||||||
- Ubuntu22.04
|
- Ubuntu 22.04
|
||||||
- python3.10
|
- python 3.10
|
||||||
- Windows11
|
- Windows 10
|
||||||
- python3.11
|
- python 3.11
|
||||||
|
|
||||||
|
|
||||||
请注意,如果您想要使用 AimRT-Python 中的 RPC 或 Channel 功能,当前只支持以 protobuf 作为协议,在使用时需要在本地安装有 protobuf python 包,您可以通过 `pip install protobuf` 来安装。
|
请注意,如果您想要使用 AimRT-Python 中的 RPC 或 Channel 功能,当前只支持以 protobuf 作为协议,在使用时需要在本地安装有 protobuf python 包,您可以通过 `pip install protobuf` 来安装。
|
||||||
@ -28,109 +28,11 @@ AimRT官方测试过的最低 Python 版本是 3.10,Linux 系统 glibc 的最
|
|||||||
|
|
||||||
## 二进制安装
|
## 二进制安装
|
||||||
|
|
||||||
***TODO***
|
您可以直接在 [AimRT 的发布页面](https://github.com/AimRT/AimRT/releases) 中找到 aimrt_py 的 whl 文件,通过 pip 安装。
|
||||||
|
|
||||||
<!-- 您可以直接在 `AimRT 的发布页面` 上下载一些主流平台上编译好的二进制包,并在其中找到 aimrt_py 的 whl 文件,通过 pip 安装。 -->
|
|
||||||
|
|
||||||
## 源码编译安装
|
## 源码编译安装
|
||||||
|
|
||||||
首先通过 git 等方式下载源码,然后基于 CMake 进行构建编译,构建完成后在 build/aimrt_py_package/dist 路径下有 aimrt_py 的 whl 文件,最后通过 pip 安装。
|
首先通过 git 等方式下载源码,然后参考 [Ubuntu 源码构建](build_from_source_ubuntu.md)/ [Windows 源码构建](build_from_source_windows.md) 进行构建编译,构建完成后在 build/aimrt_py_pkg/dist 路径下有 aimrt_py 的 whl 文件,最后通过 pip 安装。
|
||||||
|
|
||||||
以下是在 Linux 平台(以 Ubuntu 22.04 为例)和 Windows 平台(使用 MSVC 工具链)上的编译安装方法。
|
|
||||||
|
|
||||||
### Linux 平台(以 Ubuntu 22.04 为例)
|
|
||||||
|
|
||||||
1. 下载源码
|
|
||||||
2. 安装编译依赖
|
|
||||||
|
|
||||||
全量编译本项目需要安装 ros2(humble 版本,安装指引见 [ros2 installation](https://docs.ros.org/en/humble/Installation.html)),如果您不需要使用 ros2 插件可以在 build.sh 文件中将以下选项更改为 OFF:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
-DAIMRT_BUILD_WITH_ROS2=ON \
|
|
||||||
-DAIMRT_BUILD_ROS2_PLUGIN=ON \
|
|
||||||
# ...
|
|
||||||
```
|
|
||||||
|
|
||||||
为支持打包为 .whl 文件,需要安装 python 模块 build、 setuptools 和 wheel,其中 setuptools 最低要求版本为 61.0,推荐直接安装最新版本,可以使用如下命令安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install build setuptools wheel --upgrade
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 安装编译工具链
|
|
||||||
|
|
||||||
为编译项目还需要安装 CMake 和 make,可以使用如下命令安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install cmake make
|
|
||||||
```
|
|
||||||
|
|
||||||
CMake 的最低版本要求为 3.24,如果系统中的版本低于 3.24,可以到 [CMake 官网](https://cmake.org/download/) 下载最新版本的 CMake 并安装。
|
|
||||||
|
|
||||||
编译项目还需要使用编译器,推荐使用 GCC 11.4 或更高版本,在 Ubuntu 22.04 上可以使用如下命令安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install gcc g++
|
|
||||||
```
|
|
||||||
|
|
||||||
如果您的 gcc 版本低于 11.4,可以到 [GCC 官网](https://gcc.gnu.org/) 下载最新版本的 GCC 并安装。
|
|
||||||
|
|
||||||
4. 执行 build.sh 脚本编译生成 .whl 文件
|
|
||||||
|
|
||||||
进入 aimrt 项目文件夹,执行 build.sh 脚本,命令如下
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./build.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
编译完成后可以在 `build/aimrt_py_pkg/dist` 目录下找到 `aimrt_py*.whl` 文件,使用不同的 python 环境、系统架构和仓库版本文件名会略有不同,例如使用 CPython3.10 在 x86_64 架构下编译 0.7.0 版本仓库生成的文件名为 `aimrt_py-0.7.0-cp310-cp310-linux_x86_64.whl`。
|
|
||||||
|
|
||||||
5. 使用 pip 安装 .whl 文件
|
|
||||||
|
|
||||||
使用 pip 安装编译生成的 .whl 文件,命令如下
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install build/aimrt_py_pkg/dist/aimrt_py*.whl
|
|
||||||
```
|
|
||||||
|
|
||||||
安装完成后即可使用 aimrt_py 包。
|
|
||||||
|
|
||||||
### Windows 平台 (使用 MSVC 工具链)
|
|
||||||
|
|
||||||
1. 下载源码
|
|
||||||
2. 安装编译依赖
|
|
||||||
|
|
||||||
Windows 平台不支持 ros2、mqtt、opentelemetry 插件,build.bat 文件中默认关闭了这些插件。
|
|
||||||
|
|
||||||
为支持打包为 .whl 文件,需要安装 python 模块 build 和 setuptools,可以使用如下命令安装
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pip install build setuptools
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 安装编译工具链
|
|
||||||
|
|
||||||
为编译项目还需要安装 Visual Studio 2019 或 Visual Studio 2022(推荐),可以到 [Visual Studio 官网](https://visualstudio.microsoft.com/zh-hans/vs/) 下载并安装。
|
|
||||||
|
|
||||||
4. 执行 build.bat 脚本编译生成 .whl 文件
|
|
||||||
|
|
||||||
在 Command Prompt 中,进入 aimrt 项目文件夹,执行 build.bat 脚本,命令如下:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
./build.bat
|
|
||||||
```
|
|
||||||
|
|
||||||
编译完成后可以在 `build\aimrt_py_pkg\dist` 目录下找到 `aimrt_py*.whl` 文件,使用不同的 python 环境、系统架构和仓库版本文件名会略有不同,例如使用 CPython3.10 在 x86_64 架构下编译 0.7.0 版本仓库生成的文件名为 `aimrt_py-0.7.0-cp310-cp310-win_amd64.whl`。
|
|
||||||
|
|
||||||
5. 使用 pip 安装 .whl 文件
|
|
||||||
|
|
||||||
使用 pip 安装编译生成的 .whl 文件,命令如下
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pip install build\aimrt_py_pkg\dist\aimrt_py*.whl
|
|
||||||
```
|
|
||||||
|
|
||||||
安装完成后即可使用 aimrt_py 包。
|
|
||||||
|
|
||||||
## 插件安装说明
|
## 插件安装说明
|
||||||
|
|
||||||
@ -144,6 +46,6 @@ ls -l $(pip show aimrt_py | grep Location | awk '{print $2 "/aimrt_py"}')
|
|||||||
|
|
||||||
该命令会显示安装路径下的所有文件,其中文件名后缀以 plugin 结尾的文件即为插件文件(linux 下为 `*_plugin.so`, windows 下为 `*_plugin.dll`)。
|
该命令会显示安装路径下的所有文件,其中文件名后缀以 plugin 结尾的文件即为插件文件(linux 下为 `*_plugin.so`, windows 下为 `*_plugin.dll`)。
|
||||||
|
|
||||||
PyPI 安装方式中不含 mqtt、ros2 等插件,如果需要使用这些插件,可以通过源码编译或者下载二进制的方式安装。
|
<!-- PyPI 安装方式中不含 mqtt、ros2 等插件,如果需要使用这些插件,可以通过源码编译或者下载二进制的方式安装。 -->
|
||||||
|
|
||||||
Windows 平台暂不支持 ros2、mqtt、opentelemetry 等插件。
|
Windows 平台暂不支持 ros2、mqtt、opentelemetry 等插件。
|
||||||
|
@ -19,5 +19,5 @@ echo "clang-format done"
|
|||||||
echo "cmake-format done"
|
echo "cmake-format done"
|
||||||
|
|
||||||
# autopep8, apt install python3-autopep8
|
# autopep8, apt install python3-autopep8
|
||||||
{ find . -maxdepth 1 -name "*.py" -print; find ./src -name "*.py" -print; } | xargs autopep8 -i --global-config ./.pycodestyle
|
{ find . -maxdepth 1 -name "*.py" ! -name "*pb2.py" -print; find ./src -name "*.py" ! -name "*pb2.py" -print; } | xargs autopep8 -i --global-config ./.pycodestyle
|
||||||
echo "python format done"
|
echo "python format done"
|
||||||
|
@ -8,3 +8,9 @@ add_subdirectory(util)
|
|||||||
if(AIMRT_BUILD_WITH_ROS2)
|
if(AIMRT_BUILD_WITH_ROS2)
|
||||||
add_subdirectory(ros2_util)
|
add_subdirectory(ros2_util)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(AIMRT_BUILD_RUNTIME)
|
||||||
|
if(AIMRT_BUILD_NET_PLUGIN OR AIMRT_BUILD_GRPC_PLUGIN)
|
||||||
|
add_subdirectory(net)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "util/log_util.h"
|
#include "util/log_util.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioHttpClient : public std::enable_shared_from_this<AsioHttpClient> {
|
class AsioHttpClient : public std::enable_shared_from_this<AsioHttpClient> {
|
||||||
public:
|
public:
|
||||||
@ -322,6 +322,10 @@ class AsioHttpClient : public std::enable_shared_from_this<AsioHttpClient> {
|
|||||||
if (first_time_entry_) [[unlikely]] {
|
if (first_time_entry_) [[unlikely]] {
|
||||||
first_time_entry_ = false;
|
first_time_entry_ = false;
|
||||||
|
|
||||||
|
AIMRT_TRACE("Http cli session create a new connect to {}:{}",
|
||||||
|
session_options_ptr_->host,
|
||||||
|
session_options_ptr_->service);
|
||||||
|
|
||||||
// resolve
|
// resolve
|
||||||
asio::ip::tcp::resolver resolver(session_socket_strand_);
|
asio::ip::tcp::resolver resolver(session_socket_strand_);
|
||||||
auto const dst = co_await resolver.async_resolve(
|
auto const dst = co_await resolver.async_resolve(
|
||||||
@ -604,4 +608,4 @@ class AsioHttpClientPool
|
|||||||
std::unordered_map<std::string, std::shared_ptr<AsioHttpClient>> client_map_;
|
std::unordered_map<std::string, std::shared_ptr<AsioHttpClient>> client_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -18,7 +18,7 @@
|
|||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
#include "util/url_parser.h"
|
#include "util/url_parser.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioHttpServer : public std::enable_shared_from_this<AsioHttpServer> {
|
class AsioHttpServer : public std::enable_shared_from_this<AsioHttpServer> {
|
||||||
public:
|
public:
|
||||||
@ -822,4 +822,4 @@ class AsioHttpServer : public std::enable_shared_from_this<AsioHttpServer> {
|
|||||||
std::list<std::shared_ptr<Session>> session_ptr_list_; // session池
|
std::list<std::shared_ptr<Session>> session_ptr_list_; // session池
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -8,7 +8,7 @@
|
|||||||
#include "net/asio_tools.h"
|
#include "net/asio_tools.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
@ -473,4 +473,4 @@ TEST(NET_TEST, Http_server_handle) {
|
|||||||
t_cli.join();
|
t_cli.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -15,7 +15,7 @@
|
|||||||
#include "util/log_util.h"
|
#include "util/log_util.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioTcpClient : public std::enable_shared_from_this<AsioTcpClient> {
|
class AsioTcpClient : public std::enable_shared_from_this<AsioTcpClient> {
|
||||||
public:
|
public:
|
||||||
@ -185,7 +185,7 @@ class AsioTcpClient : public std::enable_shared_from_this<AsioTcpClient> {
|
|||||||
try {
|
try {
|
||||||
remote_addr_ = aimrt::common::util::SSToString(session_options_ptr_->svr_ep);
|
remote_addr_ = aimrt::common::util::SSToString(session_options_ptr_->svr_ep);
|
||||||
|
|
||||||
AIMRT_TRACE("Tcp cli session start create a new connect to {}.", RemoteAddr());
|
AIMRT_TRACE("Tcp cli session create a new connect to {}.", RemoteAddr());
|
||||||
co_await sock_.async_connect(session_options_ptr_->svr_ep,
|
co_await sock_.async_connect(session_options_ptr_->svr_ep,
|
||||||
boost::asio::use_awaitable);
|
boost::asio::use_awaitable);
|
||||||
|
|
||||||
@ -592,4 +592,4 @@ class AsioTcpClientPool
|
|||||||
std::unordered_map<size_t, std::shared_ptr<AsioTcpClient>> client_map_;
|
std::unordered_map<size_t, std::shared_ptr<AsioTcpClient>> client_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -16,7 +16,7 @@
|
|||||||
#include "util/log_util.h"
|
#include "util/log_util.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioTcpServer : public std::enable_shared_from_this<AsioTcpServer> {
|
class AsioTcpServer : public std::enable_shared_from_this<AsioTcpServer> {
|
||||||
public:
|
public:
|
||||||
@ -615,4 +615,4 @@ class AsioTcpServer : public std::enable_shared_from_this<AsioTcpServer> {
|
|||||||
std::unordered_map<Tcp::endpoint, std::shared_ptr<Session>> session_ptr_map_;
|
std::unordered_map<Tcp::endpoint, std::shared_ptr<Session>> session_ptr_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -7,7 +7,7 @@
|
|||||||
#include "net/asio_tcp_svr.h"
|
#include "net/asio_tcp_svr.h"
|
||||||
#include "net/asio_tools.h"
|
#include "net/asio_tools.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
|
|
||||||
@ -95,4 +95,4 @@ TEST(NET_TEST, Tcp_base) {
|
|||||||
t_cli.join();
|
t_cli.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief asio执行工具
|
* @brief asio执行工具
|
||||||
@ -185,4 +185,4 @@ class AsioExecutor {
|
|||||||
std::vector<std::function<void()>> stop_func_vec_;
|
std::vector<std::function<void()>> stop_func_vec_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -15,7 +15,7 @@
|
|||||||
#include "util/log_util.h"
|
#include "util/log_util.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioUdpClient : public std::enable_shared_from_this<AsioUdpClient> {
|
class AsioUdpClient : public std::enable_shared_from_this<AsioUdpClient> {
|
||||||
public:
|
public:
|
||||||
@ -484,4 +484,4 @@ class AsioUdpClientPool
|
|||||||
std::unordered_map<size_t, std::shared_ptr<AsioUdpClient>> client_map_;
|
std::unordered_map<size_t, std::shared_ptr<AsioUdpClient>> client_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -17,7 +17,7 @@
|
|||||||
#include "util/log_util.h"
|
#include "util/log_util.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioUdpServer : public std::enable_shared_from_this<AsioUdpServer> {
|
class AsioUdpServer : public std::enable_shared_from_this<AsioUdpServer> {
|
||||||
public:
|
public:
|
||||||
@ -423,4 +423,4 @@ class AsioUdpServer : public std::enable_shared_from_this<AsioUdpServer> {
|
|||||||
std::unordered_map<Udp::endpoint, std::shared_ptr<Session>> session_ptr_map_;
|
std::unordered_map<Udp::endpoint, std::shared_ptr<Session>> session_ptr_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -8,7 +8,7 @@
|
|||||||
#include "net/asio_udp_svr.h"
|
#include "net/asio_udp_svr.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
|
|
||||||
@ -85,4 +85,4 @@ TEST(NET_TEST, UDP_base) {
|
|||||||
t_cli.join();
|
t_cli.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -16,7 +16,7 @@
|
|||||||
#include "util/log_util.h"
|
#include "util/log_util.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioWebSocketClient
|
class AsioWebSocketClient
|
||||||
: public std::enable_shared_from_this<AsioWebSocketClient> {
|
: public std::enable_shared_from_this<AsioWebSocketClient> {
|
||||||
@ -201,6 +201,10 @@ class AsioWebSocketClient
|
|||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
namespace websocket = boost::beast::websocket;
|
namespace websocket = boost::beast::websocket;
|
||||||
|
|
||||||
|
AIMRT_TRACE("WebSocket cli session create a new connect to {}:{}",
|
||||||
|
session_options_ptr_->host,
|
||||||
|
session_options_ptr_->service);
|
||||||
|
|
||||||
// resolve
|
// resolve
|
||||||
asio::ip::tcp::resolver resolver(session_socket_strand_);
|
asio::ip::tcp::resolver resolver(session_socket_strand_);
|
||||||
auto const dst = co_await resolver.async_resolve(
|
auto const dst = co_await resolver.async_resolve(
|
||||||
@ -593,4 +597,4 @@ class AsioWebSocketClientPool
|
|||||||
std::unordered_map<std::string, std::shared_ptr<AsioWebSocketClient>> client_map_;
|
std::unordered_map<std::string, std::shared_ptr<AsioWebSocketClient>> client_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -17,7 +17,7 @@
|
|||||||
#include "util/log_util.h"
|
#include "util/log_util.h"
|
||||||
#include "util/string_util.h"
|
#include "util/string_util.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
class AsioWebSocketServer : public std::enable_shared_from_this<AsioWebSocketServer> {
|
class AsioWebSocketServer : public std::enable_shared_from_this<AsioWebSocketServer> {
|
||||||
public:
|
public:
|
||||||
@ -613,4 +613,4 @@ class AsioWebSocketServer : public std::enable_shared_from_this<AsioWebSocketSer
|
|||||||
std::unordered_map<Tcp::endpoint, std::shared_ptr<Session>> session_ptr_map_;
|
std::unordered_map<Tcp::endpoint, std::shared_ptr<Session>> session_ptr_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -7,7 +7,7 @@
|
|||||||
#include "net/asio_ws_cli.h"
|
#include "net/asio_ws_cli.h"
|
||||||
#include "net/asio_ws_svr.h"
|
#include "net/asio_ws_svr.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
|
|
||||||
@ -96,4 +96,4 @@ TEST(NET_TEST, WebSocket_base) {
|
|||||||
t_svr.join();
|
t_svr.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -9,7 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief http 派发器
|
* @brief http 派发器
|
||||||
@ -47,4 +47,4 @@ class HttpDispatcher {
|
|||||||
std::list<std::pair<std::regex, HttpHandle>> http_handle_list_;
|
std::list<std::pair<std::regex, HttpHandle>> http_handle_list_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "net/http_dispatcher.h"
|
#include "net/http_dispatcher.h"
|
||||||
|
|
||||||
namespace aimrt::runtime::common::net {
|
namespace aimrt::common::net {
|
||||||
|
|
||||||
TEST(HTTP_DISPATCHER_TEST, HttpDispatcher_CASE1) {
|
TEST(HTTP_DISPATCHER_TEST, HttpDispatcher_CASE1) {
|
||||||
using TestHttpDispatcher = HttpDispatcher<std::string(void)>;
|
using TestHttpDispatcher = HttpDispatcher<std::string(void)>;
|
||||||
@ -220,4 +220,4 @@ TEST(HTTP_DISPATCHER_TEST, HttpDispatcher_CASE3) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aimrt::runtime::common::net
|
} // namespace aimrt::common::net
|
@ -7,7 +7,6 @@
|
|||||||
#include <source_location>
|
#include <source_location>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
#include "util/block_queue.h"
|
#include "util/block_queue.h"
|
||||||
#include "util/exception.h"
|
#include "util/exception.h"
|
||||||
|
@ -17,14 +17,14 @@
|
|||||||
|
|
||||||
|
|
||||||
配置文件:
|
配置文件:
|
||||||
- [examples_plugins_opentelemetry_plugin_pb_rpc_cfg.yaml](./install/linux/bin/cfg/examples_plugins_opentelemetry_plugin_pb_rpc_cfg.yaml)
|
- [examples_plugins_opentelemetry_plugin_pb_rpc_trace_cfg.yaml](./install/linux/bin/cfg/examples_plugins_opentelemetry_plugin_pb_rpc_trace_cfg.yaml)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
运行方式(linux):
|
运行方式(linux):
|
||||||
- 开启 `AIMRT_BUILD_EXAMPLES`、`AIMRT_BUILD_OPENTELEMETRY_PLUGIN` 选项编译 AimRT;
|
- 开启 `AIMRT_BUILD_EXAMPLES`、`AIMRT_BUILD_OPENTELEMETRY_PLUGIN` 选项编译 AimRT;
|
||||||
- 将启动配置中的 `trace_otlp_http_exporter_url` 配置为 collector 或 jaejer 的上报地址,详情请参考插件文档;
|
- 将启动配置中的 `trace_otlp_http_exporter_url` 配置为 collector 或 jaejer 的上报地址,详情请参考插件文档;
|
||||||
- 直接运行 build 目录下`start_examples_plugins_opentelemetry_plugin_pb_rpc.sh`脚本启动进程;
|
- 直接运行 build 目录下`start_examples_plugins_opentelemetry_plugin_pb_rpc_trace.sh`脚本启动进程;
|
||||||
- 在 jaejer 平台上观察 rpc trace 数据;
|
- 在 jaejer 平台上观察 rpc trace 数据;
|
||||||
- 键入`ctrl-c`停止进程;
|
- 键入`ctrl-c`停止进程;
|
||||||
|
|
||||||
@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
|
|
||||||
配置文件:
|
配置文件:
|
||||||
- [examples_plugins_opentelemetry_plugin_pb_chn_cfg.yaml](./install/linux/bin/cfg/examples_plugins_opentelemetry_plugin_pb_chn_cfg.yaml)
|
- [examples_plugins_opentelemetry_plugin_pb_chn_trace_cfg.yaml](./install/linux/bin/cfg/examples_plugins_opentelemetry_plugin_pb_chn_trace_cfg.yaml)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -61,7 +61,7 @@
|
|||||||
运行方式(linux):
|
运行方式(linux):
|
||||||
- 开启 `AIMRT_BUILD_EXAMPLES`、`AIMRT_BUILD_OPENTELEMETRY_PLUGIN` 选项编译 AimRT;
|
- 开启 `AIMRT_BUILD_EXAMPLES`、`AIMRT_BUILD_OPENTELEMETRY_PLUGIN` 选项编译 AimRT;
|
||||||
- 将启动配置中的 `trace_otlp_http_exporter_url` 配置为 collector 或 jaejer 的上报地址,详情请参考插件文档;
|
- 将启动配置中的 `trace_otlp_http_exporter_url` 配置为 collector 或 jaejer 的上报地址,详情请参考插件文档;
|
||||||
- 直接运行 build 目录下`start_examples_plugins_opentelemetry_plugin_pb_chn.sh`脚本启动进程;
|
- 直接运行 build 目录下`start_examples_plugins_opentelemetry_plugin_pb_chn_trace.sh`脚本启动进程;
|
||||||
- 在 jaejer 平台上观察 channel trace 数据;
|
- 在 jaejer 平台上观察 channel trace 数据;
|
||||||
- 键入`ctrl-c`停止进程;
|
- 键入`ctrl-c`停止进程;
|
||||||
|
|
||||||
@ -69,3 +69,17 @@
|
|||||||
说明:
|
说明:
|
||||||
- 此示例基于 protobuf channel local 后端示例,通过 **opentelemetry_plugin** 中的 `otp_trace` 类型 filter 上报 channel trace 数据;
|
- 此示例基于 protobuf channel local 后端示例,通过 **opentelemetry_plugin** 中的 `otp_trace` 类型 filter 上报 channel trace 数据;
|
||||||
|
|
||||||
|
|
||||||
|
## rpc metrics
|
||||||
|
|
||||||
|
一个基于 **opentelemetry_plugin** 的 rpc metrics 示例,演示内容包括:
|
||||||
|
- 如何在启动时加载 **opentelemetry_plugin**;
|
||||||
|
- 如何为 rpc 配置 metrics 功能;
|
||||||
|
|
||||||
|
|
||||||
|
## channel metrics
|
||||||
|
|
||||||
|
一个基于 **opentelemetry_plugin** 的 channel metrics 示例,演示内容包括:
|
||||||
|
- 如何在启动时加载 **opentelemetry_plugin**;
|
||||||
|
- 如何为 channel 配置 metrics 功能;
|
||||||
|
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
# Copyright (c) 2023, AgiBot Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
|
||||||
|
aimrt:
|
||||||
|
plugin:
|
||||||
|
plugins:
|
||||||
|
- name: opentelemetry_plugin
|
||||||
|
path: ./libaimrt_opentelemetry_plugin.so
|
||||||
|
options:
|
||||||
|
node_name: example_channel_node
|
||||||
|
metrics_otlp_http_exporter_url: http://localhost:4318/v1/metrics
|
||||||
|
attributes:
|
||||||
|
- key: sn
|
||||||
|
val: 123456
|
||||||
|
log:
|
||||||
|
core_lvl: INFO # Trace/Debug/Info/Warn/Error/Fatal/Off
|
||||||
|
backends:
|
||||||
|
- type: console
|
||||||
|
executor:
|
||||||
|
executors:
|
||||||
|
- name: work_thread_pool
|
||||||
|
type: asio_thread
|
||||||
|
options:
|
||||||
|
thread_num: 4
|
||||||
|
channel:
|
||||||
|
backends:
|
||||||
|
- type: local
|
||||||
|
options:
|
||||||
|
subscriber_use_inline_executor: false
|
||||||
|
subscriber_executor: work_thread_pool
|
||||||
|
pub_topics_options:
|
||||||
|
- topic_name: "(.*)"
|
||||||
|
enable_backends: [local]
|
||||||
|
enable_filters: [otp_metrics]
|
||||||
|
sub_topics_options:
|
||||||
|
- topic_name: "(.*)"
|
||||||
|
enable_backends: [local]
|
||||||
|
enable_filters: [otp_metrics]
|
||||||
|
module:
|
||||||
|
pkgs:
|
||||||
|
- path: ./libpb_chn_pub_pkg.so
|
||||||
|
enable_modules: [NormalPublisherModule]
|
||||||
|
- path: ./libpb_chn_sub_pkg.so
|
||||||
|
enable_modules: [NormalSubscriberModule]
|
||||||
|
modules:
|
||||||
|
- name: NormalPublisherModule
|
||||||
|
log_lvl: INFO
|
||||||
|
- name: NormalSubscriberModule
|
||||||
|
log_lvl: INFO
|
||||||
|
|
||||||
|
# Module custom configuration
|
||||||
|
NormalPublisherModule:
|
||||||
|
topic_name: test_topic
|
||||||
|
channel_frq: 0.5
|
||||||
|
|
||||||
|
NormalSubscriberModule:
|
||||||
|
topic_name: test_topic
|
@ -0,0 +1,58 @@
|
|||||||
|
# Copyright (c) 2023, AgiBot Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
|
||||||
|
aimrt:
|
||||||
|
plugin:
|
||||||
|
plugins:
|
||||||
|
- name: opentelemetry_plugin
|
||||||
|
path: ./libaimrt_opentelemetry_plugin.so
|
||||||
|
options:
|
||||||
|
node_name: example_rpc_node
|
||||||
|
metrics_otlp_http_exporter_url: http://localhost:4318/v1/metrics
|
||||||
|
attributes:
|
||||||
|
- key: sn
|
||||||
|
val: 123456
|
||||||
|
log:
|
||||||
|
core_lvl: INFO # Trace/Debug/Info/Warn/Error/Fatal/Off
|
||||||
|
backends:
|
||||||
|
- type: console
|
||||||
|
executor:
|
||||||
|
executors:
|
||||||
|
- name: work_thread_pool
|
||||||
|
type: asio_thread
|
||||||
|
options:
|
||||||
|
thread_num: 4
|
||||||
|
- name: timeout_handle
|
||||||
|
type: time_wheel
|
||||||
|
options:
|
||||||
|
bind_executor: work_thread_pool
|
||||||
|
rpc:
|
||||||
|
backends:
|
||||||
|
- type: local
|
||||||
|
options:
|
||||||
|
timeout_executor: timeout_handle
|
||||||
|
clients_options:
|
||||||
|
- func_name: "(.*)"
|
||||||
|
enable_backends: [local]
|
||||||
|
enable_filters: [otp_metrics]
|
||||||
|
servers_options:
|
||||||
|
- func_name: "(.*)"
|
||||||
|
enable_backends: [local]
|
||||||
|
enable_filters: [otp_metrics]
|
||||||
|
module:
|
||||||
|
pkgs:
|
||||||
|
- path: ./libpb_rpc_client_pkg.so
|
||||||
|
enable_modules: [NormalRpcCoClientModule]
|
||||||
|
- path: ./libpb_rpc_server_pkg.so
|
||||||
|
enable_modules: [NormalRpcCoServerModule]
|
||||||
|
modules:
|
||||||
|
- name: NormalRpcCoClientModule
|
||||||
|
log_lvl: INFO
|
||||||
|
- name: NormalRpcCoServerModule
|
||||||
|
log_lvl: INFO
|
||||||
|
|
||||||
|
# Module custom configuration
|
||||||
|
NormalRpcCoClientModule:
|
||||||
|
rpc_frq: 0.5
|
||||||
|
|
||||||
|
NormalRpcCoServerModule:
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
./aimrt_main --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_chn_metrics_cfg.yaml
|
@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
./aimrt_main --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_chn_cfg.yaml
|
./aimrt_main --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_chn_trace_cfg.yaml
|
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
./aimrt_main --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_rpc_metrics_cfg.yaml
|
@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
./aimrt_main --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_rpc_cfg.yaml
|
./aimrt_main --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_rpc_trace_cfg.yaml
|
@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
.\aimrt_main.exe --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_chn_cfg.yaml
|
.\aimrt_main.exe --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_chn_trace_cfg.yaml
|
@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
.\aimrt_main.exe --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_rpc_cfg.yaml
|
.\aimrt_main.exe --cfg_file_path=./cfg/examples_plugins_opentelemetry_plugin_pb_rpc_trace_cfg.yaml
|
@ -31,12 +31,20 @@
|
|||||||
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_pb_rpc_client.sh`脚本启动客户端(cli 进程);
|
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_pb_rpc_client.sh`脚本启动客户端(cli 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- aimrt client 调用 native ros2 server:
|
- aimrt client 调用 native ros2 server:
|
||||||
- 在终端运行 build 目录下`native_ros2_pb_rpc_server`进程启动原生 ros2 服务端;
|
- 在 build 目录下运行以下命令启动原生 ros2 服务端:
|
||||||
|
```bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_pb_rpc_server
|
||||||
|
```
|
||||||
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_pb_rpc_client.sh`脚本启动客户端(cli 进程);
|
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_pb_rpc_client.sh`脚本启动客户端(cli 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- native ros2 client 调用 aimrt server:
|
- native ros2 client 调用 aimrt server:
|
||||||
- 在终端运行 build 目录下`start_examples_plugins_ros2_plugin_pb_rpc_server.sh`脚本启动服务端(srv 进程);
|
- 在终端运行 build 目录下`start_examples_plugins_ros2_plugin_pb_rpc_server.sh`脚本启动服务端(srv 进程);
|
||||||
- 开启新的终端运行 build 目录下`native_ros2_pb_rpc_client`进程启动原生 ros2 客户端;
|
- 开启新的终端,在 build 目录下运行以下命令启动原生 ros2 客户端:
|
||||||
|
```bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_pb_rpc_client
|
||||||
|
```
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
|
|
||||||
|
|
||||||
@ -82,12 +90,22 @@
|
|||||||
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_rpc_client.sh`脚本启动客户端(cli 进程);
|
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_rpc_client.sh`脚本启动客户端(cli 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- aimrt client 调用 native ros2 server:
|
- aimrt client 调用 native ros2 server:
|
||||||
- 在终端运行 build 目录下`native_ros2_rpc_server`进程启动原生 ros2 服务端;
|
- 在 build 目录下运行以下命令启动原生 ros2 服务端:
|
||||||
|
```bash
|
||||||
|
source install/share/example_ros2/local_setup.bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_rpc_server
|
||||||
|
```
|
||||||
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_rpc_client.sh`脚本启动客户端(cli 进程);
|
- 开启新的终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_rpc_client.sh`脚本启动客户端(cli 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- native ros2 client 调用 aimrt server:
|
- native ros2 client 调用 aimrt server:
|
||||||
- 在终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_rpc_server.sh`脚本启动服务端(srv 进程);
|
- 在终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_rpc_server.sh`脚本启动服务端(srv 进程);
|
||||||
- 开启新的终端运行 build 目录下`native_ros2_rpc_client`进程启动原生 ros2 客户端;
|
- 开启新的终端,在 build 目录下运行以下命令启动原生 ros2 客户端:
|
||||||
|
```bash
|
||||||
|
source install/share/example_ros2/local_setup.bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_rpc_client
|
||||||
|
```
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
|
|
||||||
|
|
||||||
@ -161,12 +179,20 @@
|
|||||||
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_pb_chn_pub.sh`脚本启动发布端(pub 进程);
|
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_pb_chn_pub.sh`脚本启动发布端(pub 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- aimrt publisher 向 native ros2 subscriber 发布数据:
|
- aimrt publisher 向 native ros2 subscriber 发布数据:
|
||||||
- 在终端运行 build 目录下`native_ros2_pb_chn_subscriber`进程启动原生 ros2 订阅端;
|
- 在 build 目录下运行以下命令启动原生 ros2 订阅端:
|
||||||
|
```bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_pb_chn_subscriber
|
||||||
|
```
|
||||||
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_pb_chn_pub.sh`脚本启动发布端(pub 进程);
|
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_pb_chn_pub.sh`脚本启动发布端(pub 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- native ros2 publisher 向 aimrt subscriber 发布数据:
|
- native ros2 publisher 向 aimrt subscriber 发布数据:
|
||||||
- 在终端运行 build 目录下`start_examples_plugins_ros_plugin_pb_chn_sub.sh`脚本启动订阅端(sub 进程);
|
- 在终端运行 build 目录下`start_examples_plugins_ros_plugin_pb_chn_sub.sh`脚本启动订阅端(sub 进程);
|
||||||
- 开启新的终端运行 build 目录下`native_ros2_pb_chn_publisher`进程启动原生 ros2 发布端;
|
- 开启新的终端,在 build 目录下运行以下命令启动原生 ros2 发布端:
|
||||||
|
```bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_pb_chn_publisher
|
||||||
|
```
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
|
|
||||||
|
|
||||||
@ -213,12 +239,22 @@
|
|||||||
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_ros2_chn_pub.sh`脚本启动发布端(pub 进程);
|
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_ros2_chn_pub.sh`脚本启动发布端(pub 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- aimrt publisher 向 native ros2 subscriber 发布数据:
|
- aimrt publisher 向 native ros2 subscriber 发布数据:
|
||||||
- 在终端运行 build 目录下`native_ros2_chn_subscriber`进程启动原生 ros2 订阅端;
|
- 在 build 目录下运行以下命令启动原生 ros2 订阅端:
|
||||||
|
```bash
|
||||||
|
source install/share/example_ros2/local_setup.bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_chn_subscriber
|
||||||
|
```
|
||||||
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_ros2_chn_pub.sh`脚本启动发布端(pub 进程);
|
- 再开启一个新的终端窗口运行`start_examples_plugins_ros2_plugin_ros2_chn_pub.sh`脚本启动发布端(pub 进程);
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
- native ros2 publisher 向 aimrt subscriber 发布数据:
|
- native ros2 publisher 向 aimrt subscriber 发布数据:
|
||||||
- 在终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_chn_sub.sh`脚本启动订阅端(sub 进程);
|
- 在终端运行 build 目录下`start_examples_plugins_ros2_plugin_ros2_chn_sub.sh`脚本启动订阅端(sub 进程);
|
||||||
- 开启新的终端运行 build 目录下`native_ros2_chn_publisher`进程启动原生 ros2 发布端;
|
- 开启新的终端,在 build 目录下运行以下命令启动原生 ros2 发布端:
|
||||||
|
```bash
|
||||||
|
source install/share/example_ros2/local_setup.bash
|
||||||
|
source install/share/ros2_plugin_proto/local_setup.bash
|
||||||
|
native_ros2_chn_publisher
|
||||||
|
```
|
||||||
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
- 分别在两个终端键入`ctrl-c`停止对应进程;
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import threading
|
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
import aimrt_py
|
import aimrt_py
|
||||||
import yaml
|
import yaml
|
||||||
import time
|
|
||||||
|
|
||||||
global_aimrt_core = None
|
global_aimrt_core = None
|
||||||
running_flag = True
|
running_flag = True
|
||||||
@ -73,7 +74,7 @@ def main():
|
|||||||
thread_loop = threading.Thread(target=Loop)
|
thread_loop = threading.Thread(target=Loop)
|
||||||
thread_loop.start()
|
thread_loop.start()
|
||||||
|
|
||||||
# wait for shutdown
|
# Wait for shutdown
|
||||||
while thread_start.is_alive():
|
while thread_start.is_alive():
|
||||||
thread_start.join(1.0)
|
thread_start.join(1.0)
|
||||||
|
|
||||||
|
24
src/examples/py/parameter/README.md
Normal file
24
src/examples/py/parameter/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# parameter example
|
||||||
|
|
||||||
|
一个基于 App 模式创建模块的方式启动的 python parameter 示例,演示内容包括:
|
||||||
|
- 如何以 App 模式创建模块并启动;
|
||||||
|
- 如何使用 Log 功能;
|
||||||
|
- 如何使用 Parameter 功能;
|
||||||
|
|
||||||
|
核心代码:
|
||||||
|
- [examples_py_parameter_app.py](./examples_py_parameter_app.py)
|
||||||
|
|
||||||
|
|
||||||
|
配置文件:
|
||||||
|
- [examples_py_parameter_app_cfg.yaml](./cfg/examples_py_parameter_app_cfg.yaml)
|
||||||
|
|
||||||
|
|
||||||
|
运行方式(linux):
|
||||||
|
- 安装 `aimrt_py` 包;
|
||||||
|
- 直接运行本目录下[start_examples_py_parameter_app.sh](./start_examples_py_parameter_app.sh)脚本启动进程;
|
||||||
|
- 键入`ctrl-c`停止进程;
|
||||||
|
|
||||||
|
|
||||||
|
说明:
|
||||||
|
- 此示例使用 App 模式,在 main 函数中启动 `AimRTCore` 实例,并创建了一个 `ParameterModule` 模块句柄,使用该句柄在两个线程中分别调用 `SetParameter` 和 `GetParameter` 接口,分别进行设置参数和读取参数的操作;
|
||||||
|
- 可以在启动后观察控制台打印出来的日志,了解框架运行情况;
|
12
src/examples/py/parameter/cfg/examples_py_parameter_cfg.yaml
Normal file
12
src/examples/py/parameter/cfg/examples_py_parameter_cfg.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Copyright (c) 2023, AgiBot Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
|
||||||
|
aimrt:
|
||||||
|
log:
|
||||||
|
core_lvl: INFO # Trace/Debug/Info/Warn/Error/Fatal/Off
|
||||||
|
backends:
|
||||||
|
- type: console
|
||||||
|
module:
|
||||||
|
modules:
|
||||||
|
- name: ParameterModule
|
||||||
|
log_lvl: INFO
|
104
src/examples/py/parameter/examples_py_parameter_app.py
Normal file
104
src/examples/py/parameter/examples_py_parameter_app.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# Copyright (c) 2023, AgiBot Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
import aimrt_py
|
||||||
|
|
||||||
|
global_aimrt_core = None
|
||||||
|
running_flag = True
|
||||||
|
|
||||||
|
|
||||||
|
def signal_handler(sig, _):
|
||||||
|
global global_aimrt_core
|
||||||
|
global running_flag
|
||||||
|
|
||||||
|
if (global_aimrt_core and (sig == signal.SIGINT or sig == signal.SIGTERM)):
|
||||||
|
global_aimrt_core.Shutdown()
|
||||||
|
running_flag = False
|
||||||
|
return
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Example parameter app.')
|
||||||
|
parser.add_argument('--cfg_file_path', type=str, default="", help='config file path')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
|
||||||
|
print("AimRT start.")
|
||||||
|
|
||||||
|
aimrt_core = aimrt_py.Core()
|
||||||
|
|
||||||
|
global global_aimrt_core
|
||||||
|
global_aimrt_core = aimrt_core
|
||||||
|
|
||||||
|
core_options = aimrt_py.CoreOptions()
|
||||||
|
core_options.cfg_file_path = args.cfg_file_path
|
||||||
|
aimrt_core.Initialize(core_options)
|
||||||
|
|
||||||
|
module_handle = aimrt_core.CreateModule("ParameterModule")
|
||||||
|
assert (isinstance(module_handle, aimrt_py.CoreRef))
|
||||||
|
|
||||||
|
parameter_handle = module_handle.GetParameterHandle()
|
||||||
|
|
||||||
|
# Start aimrt core
|
||||||
|
thread_start = threading.Thread(target=aimrt_core.Start)
|
||||||
|
thread_start.start()
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def SetParameterLoop():
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), "Start SetParameterLoop.")
|
||||||
|
count = 0
|
||||||
|
global running_flag
|
||||||
|
while running_flag:
|
||||||
|
count += 1
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), f"SetParameterLoop count: {count} -------------------------")
|
||||||
|
parameter_handle.SetParameter(f"key-{count}", f"val-{count}")
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), f"Set parameter, key: 'key-{count}', val: 'val-{count}'")
|
||||||
|
time.sleep(1)
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), "SetParameterLoop stopped.")
|
||||||
|
|
||||||
|
def GetParameterLoop():
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), "Start GetParameterLoop.")
|
||||||
|
count = 0
|
||||||
|
global running_flag
|
||||||
|
while running_flag:
|
||||||
|
count += 1
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), f"GetParameterLoop count: {count} -------------------------")
|
||||||
|
value = parameter_handle.GetParameter(f"key-{count}")
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), f"Get parameter, key: 'key-{count}', val: '{value}'")
|
||||||
|
time.sleep(1)
|
||||||
|
aimrt_py.info(module_handle.GetLogger(), "GetParameterLoop stopped.")
|
||||||
|
|
||||||
|
thread_set_parameter = threading.Thread(target=SetParameterLoop)
|
||||||
|
thread_get_parameter = threading.Thread(target=GetParameterLoop)
|
||||||
|
|
||||||
|
thread_set_parameter.start()
|
||||||
|
time.sleep(0.5)
|
||||||
|
thread_get_parameter.start()
|
||||||
|
|
||||||
|
while thread_start.is_alive():
|
||||||
|
thread_start.join(1.0)
|
||||||
|
|
||||||
|
while thread_set_parameter.is_alive():
|
||||||
|
thread_set_parameter.join(1.0)
|
||||||
|
|
||||||
|
while thread_get_parameter.is_alive():
|
||||||
|
thread_get_parameter.join(1.0)
|
||||||
|
|
||||||
|
global_aimrt_core = None
|
||||||
|
|
||||||
|
print("AimRT exit.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
3
src/examples/py/parameter/start_examples_py_parameter.sh
Executable file
3
src/examples/py/parameter/start_examples_py_parameter.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
python3 examples_py_parameter_app.py --cfg_file_path ./cfg/examples_py_parameter_cfg.yaml
|
@ -2,15 +2,14 @@
|
|||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import threading
|
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
import threading
|
||||||
|
|
||||||
import aimrt_py
|
import aimrt_py
|
||||||
|
|
||||||
from google.protobuf.json_format import MessageToJson
|
|
||||||
import rpc_pb2
|
|
||||||
import rpc_aimrt_rpc_pb2
|
import rpc_aimrt_rpc_pb2
|
||||||
|
import rpc_pb2
|
||||||
|
from google.protobuf.json_format import MessageToJson
|
||||||
|
|
||||||
global_aimrt_core = None
|
global_aimrt_core = None
|
||||||
|
|
||||||
|
350
src/examples/py/py_tests.py
Normal file
350
src/examples/py/py_tests.py
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import time
|
||||||
|
from multiprocessing import Process, Queue
|
||||||
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class TestResult:
|
||||||
|
SUCCESS = 0
|
||||||
|
EXPECTED_OUTPUT_NOT_FOUND = 1
|
||||||
|
FORBIDDEN_OUTPUT_FOUND = 2
|
||||||
|
EXIT_STRING_NOT_FOUND = 3
|
||||||
|
|
||||||
|
|
||||||
|
def run_program_with_timeout(script_path: str, timeout_seconds: int) -> Tuple[str, str]:
|
||||||
|
with tempfile.NamedTemporaryFile(mode='w+', suffix='.log', delete=False) as temp_file:
|
||||||
|
process = subprocess.Popen(script_path, stdout=temp_file, stderr=temp_file,
|
||||||
|
text=True, shell=True, cwd=os.path.dirname(script_path),
|
||||||
|
bufsize=1, universal_newlines=True, preexec_fn=os.setsid)
|
||||||
|
|
||||||
|
try:
|
||||||
|
process.wait(timeout=timeout_seconds)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
# Send SIGTERM signal to the process group
|
||||||
|
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
|
||||||
|
# Wait for a short time to allow the process to terminate
|
||||||
|
time.sleep(1)
|
||||||
|
if process.poll() is None:
|
||||||
|
# If the process still hasn't terminated, forcefully terminate it
|
||||||
|
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
|
||||||
|
|
||||||
|
# Ensure the process has ended
|
||||||
|
process.wait()
|
||||||
|
|
||||||
|
# Flush the file buffer
|
||||||
|
temp_file.flush()
|
||||||
|
os.fsync(temp_file.fileno())
|
||||||
|
|
||||||
|
# Read the log file content
|
||||||
|
temp_file.seek(0)
|
||||||
|
log_content = temp_file.read()
|
||||||
|
|
||||||
|
os.remove(temp_file.name)
|
||||||
|
|
||||||
|
return log_content
|
||||||
|
|
||||||
|
|
||||||
|
def run_and_capture(script_path: str, timeout: int, queue: Queue, program_name: str) -> None:
|
||||||
|
log_content = run_program_with_timeout(script_path, timeout)
|
||||||
|
queue.put((program_name, log_content))
|
||||||
|
|
||||||
|
|
||||||
|
def check_result(log_content: str, expected_outputs: List[str], forbidden_outputs: List[str]) -> TestResult:
|
||||||
|
RED = "\033[91m"
|
||||||
|
RESET = "\033[0m"
|
||||||
|
|
||||||
|
# prepare expected outputs
|
||||||
|
expected_outputs_lines = []
|
||||||
|
for expected_output in expected_outputs:
|
||||||
|
expected_outputs_lines.extend(expected_output.splitlines())
|
||||||
|
|
||||||
|
log_lines = log_content.splitlines()
|
||||||
|
expected_index = 0
|
||||||
|
for log_line in log_lines:
|
||||||
|
if expected_index < len(expected_outputs_lines) and expected_outputs_lines[expected_index] in log_line:
|
||||||
|
expected_index += 1
|
||||||
|
all_expected_found = expected_index == len(expected_outputs_lines)
|
||||||
|
|
||||||
|
if not all_expected_found:
|
||||||
|
print(f"{RED}Expected outputs not found: {expected_outputs_lines[expected_index:]}{RESET}")
|
||||||
|
return TestResult.EXPECTED_OUTPUT_NOT_FOUND
|
||||||
|
|
||||||
|
forbidden_found = any(forbidden_output in log_content for forbidden_output in forbidden_outputs)
|
||||||
|
if forbidden_found:
|
||||||
|
print(f"{RED}Forbidden output found in log content{RESET}")
|
||||||
|
return TestResult.FORBIDDEN_OUTPUT_FOUND
|
||||||
|
|
||||||
|
exit_str = "AimRT exit."
|
||||||
|
exit_found = exit_str in log_content
|
||||||
|
|
||||||
|
if not exit_found:
|
||||||
|
print(f"{RED}Exit string not found: {exit_str}{RESET}")
|
||||||
|
return TestResult.EXIT_STRING_NOT_FOUND
|
||||||
|
|
||||||
|
return TestResult.SUCCESS
|
||||||
|
|
||||||
|
|
||||||
|
def single_test(script_path: str,
|
||||||
|
expected_outputs: List[str],
|
||||||
|
forbidden_outputs: List[str],
|
||||||
|
timeout: int,
|
||||||
|
print_output: bool = False) -> TestResult:
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
|
||||||
|
print("\n" + "=" * 40)
|
||||||
|
print(f"Running test: {os.path.basename(script_path)}")
|
||||||
|
|
||||||
|
log_content = run_program_with_timeout(script_path, timeout)
|
||||||
|
|
||||||
|
if print_output:
|
||||||
|
print(log_content)
|
||||||
|
|
||||||
|
end_time = time.perf_counter()
|
||||||
|
print(f"Total time taken: {end_time - start_time:.2f} seconds")
|
||||||
|
|
||||||
|
result = check_result(log_content, expected_outputs, forbidden_outputs)
|
||||||
|
|
||||||
|
print("=" * 40 + "\n")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def paired_test(server_script: str,
|
||||||
|
client_script: str,
|
||||||
|
server_expected_outputs: List[str],
|
||||||
|
client_expected_outputs: List[str],
|
||||||
|
server_forbidden_outputs: List[str],
|
||||||
|
client_forbidden_outputs: List[str],
|
||||||
|
timeout: int,
|
||||||
|
print_server_output: bool = False,
|
||||||
|
print_client_output: bool = False) -> Tuple[TestResult, TestResult]:
|
||||||
|
start_time = time.perf_counter()
|
||||||
|
|
||||||
|
print("\n" + "=" * 40)
|
||||||
|
print(f"Running paired test: {os.path.basename(server_script)} and\n" +
|
||||||
|
f" {os.path.basename(client_script)}")
|
||||||
|
output_queue = Queue()
|
||||||
|
|
||||||
|
server_process = Process(target=run_and_capture, args=(server_script, timeout, output_queue, "Server"))
|
||||||
|
client_process = Process(target=run_and_capture, args=(client_script, timeout, output_queue, "Client"))
|
||||||
|
|
||||||
|
server_process.start()
|
||||||
|
client_process.start()
|
||||||
|
|
||||||
|
server_process.join()
|
||||||
|
client_process.join()
|
||||||
|
|
||||||
|
end_time = time.perf_counter()
|
||||||
|
print(f"Total time taken: {end_time - start_time:.2f} seconds")
|
||||||
|
|
||||||
|
while not output_queue.empty():
|
||||||
|
program_name, log_content = output_queue.get()
|
||||||
|
if program_name == "Server":
|
||||||
|
server_log_content = log_content
|
||||||
|
if print_server_output:
|
||||||
|
print(f"\nServer Output:")
|
||||||
|
print(log_content)
|
||||||
|
elif program_name == "Client":
|
||||||
|
client_log_content = log_content
|
||||||
|
if print_client_output:
|
||||||
|
print(f"\nClient Output:")
|
||||||
|
print(log_content)
|
||||||
|
|
||||||
|
server_result = check_result(server_log_content, server_expected_outputs, server_forbidden_outputs)
|
||||||
|
client_result = check_result(client_log_content, client_expected_outputs, client_forbidden_outputs)
|
||||||
|
|
||||||
|
print("=" * 40 + "\n")
|
||||||
|
|
||||||
|
return server_result, client_result
|
||||||
|
|
||||||
|
|
||||||
|
def generate_test_report(test_results: Dict[str, TestResult]) -> str:
|
||||||
|
# ANSI escape sequences for colors
|
||||||
|
RESET = "\033[0m"
|
||||||
|
BOLD = "\033[1m"
|
||||||
|
RED = "\033[31m"
|
||||||
|
GREEN = "\033[32m"
|
||||||
|
YELLOW = "\033[33m"
|
||||||
|
BLUE = "\033[34m"
|
||||||
|
MAGENTA = "\033[35m"
|
||||||
|
CYAN = "\033[36m"
|
||||||
|
WHITE = "\033[37m"
|
||||||
|
|
||||||
|
total_tests = len(test_results)
|
||||||
|
successful_tests = sum(1 for result in test_results.values() if result == TestResult.SUCCESS)
|
||||||
|
not_found_tests = sum(1 for result in test_results.values() if result == TestResult.EXPECTED_OUTPUT_NOT_FOUND)
|
||||||
|
forbidden_tests = sum(1 for result in test_results.values() if result == TestResult.FORBIDDEN_OUTPUT_FOUND)
|
||||||
|
exit_failed_tests = sum(1 for result in test_results.values() if result == TestResult.EXIT_STRING_NOT_FOUND)
|
||||||
|
not_run_tests = sum(1 for result in test_results.values() if result is None)
|
||||||
|
|
||||||
|
report = f"""
|
||||||
|
{CYAN}{BOLD}╔═══════════════════════════════════════════╗
|
||||||
|
║ Test Report Summary ║
|
||||||
|
╚═══════════════════════════════════════════╝{RESET}
|
||||||
|
|
||||||
|
{WHITE}Total tests: {CYAN}{total_tests}
|
||||||
|
{GREEN}Successful tests: {successful_tests}
|
||||||
|
{RED}Failed tests: {not_found_tests + exit_failed_tests}
|
||||||
|
{YELLOW}• Expected Output Not Found: {not_found_tests}
|
||||||
|
{MAGENTA}• Forbidden Output Found: {forbidden_tests}
|
||||||
|
{RED}• Exit String Not Found: {exit_failed_tests}
|
||||||
|
{BLUE}Not run tests: {not_run_tests}
|
||||||
|
|
||||||
|
{YELLOW}{BOLD}Detailed Results:{RESET}
|
||||||
|
"""
|
||||||
|
for test_name, result in test_results.items():
|
||||||
|
if result == TestResult.SUCCESS:
|
||||||
|
status = f"{GREEN}✔ Success{RESET}"
|
||||||
|
elif result == TestResult.EXPECTED_OUTPUT_NOT_FOUND:
|
||||||
|
status = f"{YELLOW}⚠ Expected Output Not Found{RESET}"
|
||||||
|
elif result == TestResult.FORBIDDEN_OUTPUT_FOUND:
|
||||||
|
status = f"{MAGENTA}✘ Forbidden Output Found{RESET}"
|
||||||
|
elif result == TestResult.EXIT_STRING_NOT_FOUND:
|
||||||
|
status = f"{RED}✘ Exit String Not Found{RESET}"
|
||||||
|
else: # result is None
|
||||||
|
status = f"{BLUE}- Not Run{RESET}"
|
||||||
|
report += f" {CYAN}•{RESET} {test_name:<20} {status}\n"
|
||||||
|
|
||||||
|
success_rate = (successful_tests / (total_tests - not_run_tests)) * 100 if (total_tests - not_run_tests) > 0 else 0
|
||||||
|
overall_success_rate = (successful_tests / total_tests) * 100 if total_tests > 0 else 0
|
||||||
|
report += f"\n{YELLOW}Success Rate (excluding not run): {WHITE}{success_rate:.2f}%{RESET}"
|
||||||
|
report += f"\n{YELLOW}Overall Success Rate: {WHITE}{overall_success_rate:.2f}%{RESET}"
|
||||||
|
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser(description="Run Python tests")
|
||||||
|
parser.add_argument("-p", "--print-output", action="store_true", help="Print test output", default=False)
|
||||||
|
parser.add_argument("-t", "--test", type=str, help="Test name", default="all")
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = parse_args()
|
||||||
|
try:
|
||||||
|
test_results = {"app mode": None, "registration mode": None,
|
||||||
|
"http rpc server": None, "http rpc client": None,
|
||||||
|
"grpc rpc server": None, "grpc rpc client": None,
|
||||||
|
"ros2 rpc server": None, "ros2 rpc client": None,
|
||||||
|
"http channel sub": None, "http channel pub": None,
|
||||||
|
"ros2 channel sub": None, "ros2 channel pub": None,
|
||||||
|
"parameter": None}
|
||||||
|
|
||||||
|
common_forbidden_outputs = ["[Error]", "[Fatal]", "Traceback (most recent call last):"]
|
||||||
|
|
||||||
|
# build pb_rpc and pb_chn
|
||||||
|
if args.test in ["all", "rpc"] or "rpc" in args.test:
|
||||||
|
subprocess.run(["bash", os.path.join(os.getcwd(), "pb_rpc", "build_examples_py_pb_rpc.sh")],
|
||||||
|
cwd=os.path.join(os.getcwd(), "pb_rpc"))
|
||||||
|
if args.test in ["all", "channel"] or "channel" in args.test:
|
||||||
|
subprocess.run(["bash", os.path.join(os.getcwd(), "pb_chn", "build_examples_py_pb_chn.sh")],
|
||||||
|
cwd=os.path.join(os.getcwd(), "pb_chn"))
|
||||||
|
|
||||||
|
if args.test in ["all", "app mode", "helloworld"]:
|
||||||
|
test_results["app mode"] = single_test(
|
||||||
|
os.path.join(os.getcwd(), "helloworld", "start_examples_py_helloworld_app_mode.sh"),
|
||||||
|
expected_outputs=["{'key1': 'val1', 'key2': 'val2'}", "Loop count: 1", "Loop count: 2"],
|
||||||
|
forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=3,
|
||||||
|
print_output=args.print_output)
|
||||||
|
|
||||||
|
if args.test in ["all", "registration mode", "helloworld"]:
|
||||||
|
test_results["registration mode"] = single_test(
|
||||||
|
os.path.join(os.getcwd(), "helloworld", "start_examples_py_helloworld_registration_mode.sh"),
|
||||||
|
expected_outputs=["{'key1': 'val1', 'key2': 'val2'}"] + ["run test task"] * 3,
|
||||||
|
forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=2,
|
||||||
|
print_output=args.print_output)
|
||||||
|
|
||||||
|
rpc_server_expected_outputs = ["Server handle new rpc call."]
|
||||||
|
rpc_client_expected_outputs = ["Call rpc done, status: suc, code 0, msg: OK"]
|
||||||
|
|
||||||
|
if args.test in ["all", "rpc", "http rpc"]:
|
||||||
|
test_results["http rpc server"], test_results["http rpc client"] = paired_test(
|
||||||
|
os.path.join(os.getcwd(), "pb_rpc", "start_examples_py_pb_rpc_http_server.sh"),
|
||||||
|
os.path.join(os.getcwd(), "pb_rpc", "start_examples_py_pb_rpc_http_client.sh"),
|
||||||
|
server_expected_outputs=rpc_server_expected_outputs,
|
||||||
|
client_expected_outputs=rpc_client_expected_outputs,
|
||||||
|
server_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
client_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=2,
|
||||||
|
print_server_output=args.print_output,
|
||||||
|
print_client_output=args.print_output)
|
||||||
|
|
||||||
|
if args.test in ["all", "rpc", "grpc rpc"]:
|
||||||
|
test_results["grpc rpc server"], test_results["grpc rpc client"] = paired_test(
|
||||||
|
os.path.join(os.getcwd(), "pb_rpc", "start_examples_py_pb_rpc_grpc_server.sh"),
|
||||||
|
os.path.join(os.getcwd(), "pb_rpc", "start_examples_py_pb_rpc_grpc_client.sh"),
|
||||||
|
server_expected_outputs=rpc_server_expected_outputs,
|
||||||
|
client_expected_outputs=rpc_client_expected_outputs,
|
||||||
|
server_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
client_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=2,
|
||||||
|
print_server_output=args.print_output,
|
||||||
|
print_client_output=args.print_output)
|
||||||
|
|
||||||
|
if args.test in ["all", "rpc", "ros2 rpc"]:
|
||||||
|
test_results["ros2 rpc server"], test_results["ros2 rpc client"] = paired_test(
|
||||||
|
os.path.join(os.getcwd(), "pb_rpc", "start_examples_py_pb_rpc_ros2_server.sh"),
|
||||||
|
os.path.join(os.getcwd(), "pb_rpc", "start_examples_py_pb_rpc_ros2_client.sh"),
|
||||||
|
server_expected_outputs=rpc_server_expected_outputs,
|
||||||
|
client_expected_outputs=rpc_client_expected_outputs,
|
||||||
|
server_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
client_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=2,
|
||||||
|
print_server_output=args.print_output,
|
||||||
|
print_client_output=args.print_output)
|
||||||
|
|
||||||
|
channel_sub_expected_outputs = ["Get new pb event, data: {", "\"msg\": \"example msg\"", "\"num\": 123456"]
|
||||||
|
channel_pub_expected_outputs = ["Publish new pb event, data: {", "\"msg\": \"example msg\"", "\"num\": 123456"]
|
||||||
|
|
||||||
|
if args.test in ["all", "channel", "http channel"]:
|
||||||
|
test_results["http channel sub"], test_results["http channel pub"] = paired_test(
|
||||||
|
os.path.join(os.getcwd(), "pb_chn", "start_examples_py_pb_chn_http_sub.sh"),
|
||||||
|
os.path.join(os.getcwd(), "pb_chn", "start_examples_py_pb_chn_http_pub.sh"),
|
||||||
|
server_expected_outputs=channel_sub_expected_outputs,
|
||||||
|
client_expected_outputs=channel_pub_expected_outputs,
|
||||||
|
server_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
client_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=3,
|
||||||
|
print_server_output=args.print_output,
|
||||||
|
print_client_output=args.print_output)
|
||||||
|
|
||||||
|
if args.test in ["all", "channel", "ros2 channel"]:
|
||||||
|
test_results["ros2 channel sub"], test_results["ros2 channel pub"] = paired_test(
|
||||||
|
os.path.join(os.getcwd(), "pb_chn", "start_examples_py_pb_chn_ros2_sub.sh"),
|
||||||
|
os.path.join(os.getcwd(), "pb_chn", "start_examples_py_pb_chn_ros2_pub.sh"),
|
||||||
|
server_expected_outputs=channel_sub_expected_outputs,
|
||||||
|
client_expected_outputs=channel_pub_expected_outputs,
|
||||||
|
server_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
client_forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=3,
|
||||||
|
print_server_output=args.print_output,
|
||||||
|
print_client_output=args.print_output)
|
||||||
|
|
||||||
|
if args.test in ["all", "parameter"]:
|
||||||
|
test_results["parameter"] = single_test(
|
||||||
|
os.path.join(os.getcwd(), "parameter", "start_examples_py_parameter.sh"),
|
||||||
|
expected_outputs=["Start SetParameterLoop.",
|
||||||
|
"SetParameterLoop count: 1 -------------------------",
|
||||||
|
"Set parameter, key: 'key-1', val: 'val-1'",
|
||||||
|
"Start GetParameterLoop.",
|
||||||
|
"GetParameterLoop count: 1 -------------------------",
|
||||||
|
"Get parameter, key: 'key-1', val: 'val-1'"],
|
||||||
|
forbidden_outputs=common_forbidden_outputs,
|
||||||
|
timeout=3,
|
||||||
|
print_output=args.print_output)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nTests interrupted by user")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An unexpected error occurred: {e}")
|
||||||
|
finally:
|
||||||
|
report = generate_test_report(test_results)
|
||||||
|
print(report)
|
@ -34,7 +34,7 @@ target_link_libraries(
|
|||||||
${CUR_TARGET_NAME}
|
${CUR_TARGET_NAME}
|
||||||
PRIVATE aimrt::interface::aimrt_core_plugin_interface
|
PRIVATE aimrt::interface::aimrt_core_plugin_interface
|
||||||
aimrt::runtime::core
|
aimrt::runtime::core
|
||||||
aimrt::runtime::common::net
|
aimrt::common::net
|
||||||
nghttp2::nghttp2)
|
nghttp2::nghttp2)
|
||||||
|
|
||||||
# Add -Werror option
|
# Add -Werror option
|
||||||
|
@ -43,7 +43,7 @@ using HttpHandleType = Awaitable<void>(const RequestPtr&, ResponsePtr&);
|
|||||||
|
|
||||||
using HttpHandle = std::function<HttpHandleType>;
|
using HttpHandle = std::function<HttpHandleType>;
|
||||||
|
|
||||||
namespace net = aimrt::runtime::common::net;
|
namespace net = aimrt::common::net;
|
||||||
using Dispatcher = net::HttpDispatcher<HttpHandleType>;
|
using Dispatcher = net::HttpDispatcher<HttpHandleType>;
|
||||||
|
|
||||||
namespace chrono = std::chrono;
|
namespace chrono = std::chrono;
|
||||||
|
@ -78,7 +78,7 @@ bool GrpcPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
|
|
||||||
init_flag_ = true;
|
init_flag_ = true;
|
||||||
|
|
||||||
asio_executor_ptr_ = std::make_shared<runtime::common::net::AsioExecutor>(options_.thread_num);
|
asio_executor_ptr_ = std::make_shared<aimrt::common::net::AsioExecutor>(options_.thread_num);
|
||||||
|
|
||||||
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPostInitLog,
|
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPostInitLog,
|
||||||
[this] { SetPluginLogger(); });
|
[this] { SetPluginLogger(); });
|
||||||
|
@ -42,7 +42,7 @@ class GrpcPlugin : public AimRTCorePluginBase {
|
|||||||
|
|
||||||
bool init_flag_ = false;
|
bool init_flag_ = false;
|
||||||
|
|
||||||
std::shared_ptr<runtime::common::net::AsioExecutor> asio_executor_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioExecutor> asio_executor_ptr_;
|
||||||
|
|
||||||
std::shared_ptr<plugins::grpc_plugin::server::AsioHttp2Server> http2_svr_ptr_;
|
std::shared_ptr<plugins::grpc_plugin::server::AsioHttp2Server> http2_svr_ptr_;
|
||||||
std::shared_ptr<plugins::grpc_plugin::client::AsioHttp2ClientPool> http2_cli_pool_ptr_;
|
std::shared_ptr<plugins::grpc_plugin::client::AsioHttp2ClientPool> http2_cli_pool_ptr_;
|
||||||
|
@ -35,7 +35,7 @@ using ResponsePtr = std::shared_ptr<Response>;
|
|||||||
|
|
||||||
using HttpHandle = std::function<Awaitable<void>(const RequestPtr&, ResponsePtr&)>;
|
using HttpHandle = std::function<Awaitable<void>(const RequestPtr&, ResponsePtr&)>;
|
||||||
|
|
||||||
namespace net = aimrt::runtime::common::net;
|
namespace net = aimrt::common::net;
|
||||||
using Dispatcher = net::HttpDispatcher<Awaitable<void>(const RequestPtr&, ResponsePtr&)>;
|
using Dispatcher = net::HttpDispatcher<Awaitable<void>(const RequestPtr&, ResponsePtr&)>;
|
||||||
|
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
|
@ -33,12 +33,8 @@ target_include_directories(
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
${CUR_TARGET_NAME}
|
${CUR_TARGET_NAME}
|
||||||
PRIVATE aimrt::interface::aimrt_core_plugin_interface
|
PRIVATE aimrt::interface::aimrt_core_plugin_interface
|
||||||
aimrt::runtime::common::net
|
aimrt::common::net
|
||||||
aimrt::runtime::core
|
aimrt::runtime::core)
|
||||||
Boost::beast)
|
|
||||||
|
|
||||||
# Set compile definitions of target
|
|
||||||
target_compile_definitions(${CUR_TARGET_NAME} INTERFACE BOOST_ASIO_NO_DEPRECATED)
|
|
||||||
|
|
||||||
# Set compile options of target
|
# Set compile options of target
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
@ -165,12 +165,12 @@ bool HttpChannelBackend::Subscribe(
|
|||||||
|
|
||||||
http_subscribe_wrapper_map_.emplace(pattern, std::move(sub_tool_unique_ptr));
|
http_subscribe_wrapper_map_.emplace(pattern, std::move(sub_tool_unique_ptr));
|
||||||
|
|
||||||
runtime::common::net::AsioHttpServer::HttpHandle<http::dynamic_body> http_handle =
|
aimrt::common::net::AsioHttpServer::HttpHandle<http::dynamic_body> http_handle =
|
||||||
[this, topic_name = info.topic_name, sub_tool_ptr](
|
[this, topic_name = info.topic_name, sub_tool_ptr](
|
||||||
const http::request<http::dynamic_body>& req,
|
const http::request<http::dynamic_body>& req,
|
||||||
http::response<http::dynamic_body>& rsp,
|
http::response<http::dynamic_body>& rsp,
|
||||||
std::chrono::nanoseconds timeout)
|
std::chrono::nanoseconds timeout)
|
||||||
-> asio::awaitable<runtime::common::net::AsioHttpServer::HttpHandleStatus> {
|
-> asio::awaitable<aimrt::common::net::AsioHttpServer::HttpHandleStatus> {
|
||||||
// 获取序列化类型
|
// 获取序列化类型
|
||||||
std::string serialization_type;
|
std::string serialization_type;
|
||||||
auto req_content_type_itr = req.find(http::field::content_type);
|
auto req_content_type_itr = req.find(http::field::content_type);
|
||||||
@ -224,7 +224,7 @@ bool HttpChannelBackend::Subscribe(
|
|||||||
|
|
||||||
sub_tool_ptr->DoSubscribeCallback(ctx_ptr, serialization_type, buffer_array_view);
|
sub_tool_ptr->DoSubscribeCallback(ctx_ptr, serialization_type, buffer_array_view);
|
||||||
|
|
||||||
co_return runtime::common::net::AsioHttpServer::HttpHandleStatus::kOk;
|
co_return aimrt::common::net::AsioHttpServer::HttpHandleStatus::kOk;
|
||||||
};
|
};
|
||||||
|
|
||||||
http_svr_ptr_->RegisterHttpHandleFunc<http::dynamic_body>(
|
http_svr_ptr_->RegisterHttpHandleFunc<http::dynamic_body>(
|
||||||
@ -337,7 +337,7 @@ void HttpChannelBackend::Publish(runtime::core::channel::MsgWrapper& msg_wrapper
|
|||||||
asio::co_spawn(
|
asio::co_spawn(
|
||||||
*io_ptr_,
|
*io_ptr_,
|
||||||
[this, server_url, req_ptr]() -> asio::awaitable<void> {
|
[this, server_url, req_ptr]() -> asio::awaitable<void> {
|
||||||
runtime::common::net::AsioHttpClient::Options cli_options{
|
aimrt::common::net::AsioHttpClient::Options cli_options{
|
||||||
.host = server_url.host,
|
.host = server_url.host,
|
||||||
.service = server_url.service};
|
.service = server_url.service};
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ class HttpChannelBackend : public runtime::core::channel::ChannelBackendBase {
|
|||||||
public:
|
public:
|
||||||
HttpChannelBackend(
|
HttpChannelBackend(
|
||||||
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioHttpClientPool>& http_cli_pool_ptr,
|
const std::shared_ptr<aimrt::common::net::AsioHttpClientPool>& http_cli_pool_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioHttpServer>& http_svr_ptr)
|
const std::shared_ptr<aimrt::common::net::AsioHttpServer>& http_svr_ptr)
|
||||||
: io_ptr_(io_ptr),
|
: io_ptr_(io_ptr),
|
||||||
http_cli_pool_ptr_(http_cli_pool_ptr),
|
http_cli_pool_ptr_(http_cli_pool_ptr),
|
||||||
http_svr_ptr_(http_svr_ptr) {}
|
http_svr_ptr_(http_svr_ptr) {}
|
||||||
@ -69,8 +69,8 @@ class HttpChannelBackend : public runtime::core::channel::ChannelBackendBase {
|
|||||||
const runtime::core::channel::ChannelRegistry* channel_registry_ptr_ = nullptr;
|
const runtime::core::channel::ChannelRegistry* channel_registry_ptr_ = nullptr;
|
||||||
|
|
||||||
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioHttpClientPool> http_cli_pool_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioHttpClientPool> http_cli_pool_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioHttpServer> http_svr_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioHttpServer> http_svr_ptr_;
|
||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
std::string,
|
std::string,
|
||||||
|
@ -104,12 +104,12 @@ bool HttpRpcBackend::RegisterServiceFunc(
|
|||||||
std::string pattern =
|
std::string pattern =
|
||||||
std::string("/rpc") + std::string(GetRealFuncName(service_func_wrapper.info.func_name));
|
std::string("/rpc") + std::string(GetRealFuncName(service_func_wrapper.info.func_name));
|
||||||
|
|
||||||
runtime::common::net::AsioHttpServer::HttpHandle<http::dynamic_body> http_handle =
|
aimrt::common::net::AsioHttpServer::HttpHandle<http::dynamic_body> http_handle =
|
||||||
[this, &service_func_wrapper](
|
[this, &service_func_wrapper](
|
||||||
const http::request<http::dynamic_body>& req,
|
const http::request<http::dynamic_body>& req,
|
||||||
http::response<http::dynamic_body>& rsp,
|
http::response<http::dynamic_body>& rsp,
|
||||||
std::chrono::nanoseconds timeout)
|
std::chrono::nanoseconds timeout)
|
||||||
-> asio::awaitable<runtime::common::net::AsioHttpServer::HttpHandleStatus> {
|
-> asio::awaitable<aimrt::common::net::AsioHttpServer::HttpHandleStatus> {
|
||||||
// 创建 service invoke wrapper
|
// 创建 service invoke wrapper
|
||||||
auto service_invoke_wrapper_ptr = std::make_shared<runtime::core::rpc::InvokeWrapper>(
|
auto service_invoke_wrapper_ptr = std::make_shared<runtime::core::rpc::InvokeWrapper>(
|
||||||
runtime::core::rpc::InvokeWrapper{.info = service_func_wrapper.info});
|
runtime::core::rpc::InvokeWrapper{.info = service_func_wrapper.info});
|
||||||
@ -258,7 +258,7 @@ bool HttpRpcBackend::RegisterServiceFunc(
|
|||||||
|
|
||||||
AIMRT_CHECK_ERROR_THROW(ret_code == 0, "Handle rpc failed, code: {}.", ret_code);
|
AIMRT_CHECK_ERROR_THROW(ret_code == 0, "Handle rpc failed, code: {}.", ret_code);
|
||||||
|
|
||||||
co_return runtime::common::net::AsioHttpServer::HttpHandleStatus::kOk;
|
co_return aimrt::common::net::AsioHttpServer::HttpHandleStatus::kOk;
|
||||||
};
|
};
|
||||||
|
|
||||||
http_svr_ptr_->RegisterHttpHandleFunc<http::dynamic_body>(
|
http_svr_ptr_->RegisterHttpHandleFunc<http::dynamic_body>(
|
||||||
@ -354,7 +354,7 @@ void HttpRpcBackend::Invoke(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
runtime::common::net::AsioHttpClient::Options cli_options{
|
aimrt::common::net::AsioHttpClient::Options cli_options{
|
||||||
.host = std::string(url->host),
|
.host = std::string(url->host),
|
||||||
.service = std::string(url->service)};
|
.service = std::string(url->service)};
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ class HttpRpcBackend : public runtime::core::rpc::RpcBackendBase {
|
|||||||
public:
|
public:
|
||||||
HttpRpcBackend(
|
HttpRpcBackend(
|
||||||
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioHttpClientPool>& http_cli_pool_ptr,
|
const std::shared_ptr<aimrt::common::net::AsioHttpClientPool>& http_cli_pool_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioHttpServer>& http_svr_ptr)
|
const std::shared_ptr<aimrt::common::net::AsioHttpServer>& http_svr_ptr)
|
||||||
: io_ptr_(io_ptr),
|
: io_ptr_(io_ptr),
|
||||||
http_cli_pool_ptr_(http_cli_pool_ptr),
|
http_cli_pool_ptr_(http_cli_pool_ptr),
|
||||||
http_svr_ptr_(http_svr_ptr) {}
|
http_svr_ptr_(http_svr_ptr) {}
|
||||||
@ -75,8 +75,8 @@ class HttpRpcBackend : public runtime::core::rpc::RpcBackendBase {
|
|||||||
std::unordered_map<std::string_view, std::string_view> client_server_url_map_;
|
std::unordered_map<std::string_view, std::string_view> client_server_url_map_;
|
||||||
|
|
||||||
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioHttpClientPool> http_cli_pool_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioHttpClientPool> http_cli_pool_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioHttpServer> http_svr_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioHttpServer> http_svr_ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::plugins::net_plugin
|
} // namespace aimrt::plugins::net_plugin
|
@ -109,15 +109,15 @@ bool NetPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
|
|
||||||
init_flag_ = true;
|
init_flag_ = true;
|
||||||
|
|
||||||
asio_executor_ptr_ = std::make_shared<runtime::common::net::AsioExecutor>(options_.thread_num);
|
asio_executor_ptr_ = std::make_shared<aimrt::common::net::AsioExecutor>(options_.thread_num);
|
||||||
|
|
||||||
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPostInitLog,
|
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPostInitLog,
|
||||||
[this] { SetPluginLogger(); });
|
[this] { SetPluginLogger(); });
|
||||||
|
|
||||||
// http
|
// http
|
||||||
if (options_.http_options) {
|
if (options_.http_options) {
|
||||||
http_cli_pool_ptr_ = std::make_shared<runtime::common::net::AsioHttpClientPool>(asio_executor_ptr_->IO());
|
http_cli_pool_ptr_ = std::make_shared<aimrt::common::net::AsioHttpClientPool>(asio_executor_ptr_->IO());
|
||||||
http_svr_ptr_ = std::make_shared<runtime::common::net::AsioHttpServer>(asio_executor_ptr_->IO());
|
http_svr_ptr_ = std::make_shared<aimrt::common::net::AsioHttpServer>(asio_executor_ptr_->IO());
|
||||||
|
|
||||||
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPreInitRpc,
|
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPreInitRpc,
|
||||||
[this] { RegisterHttpRpcBackend(); });
|
[this] { RegisterHttpRpcBackend(); });
|
||||||
@ -129,11 +129,11 @@ bool NetPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
runtime::core::AimRTCore::State::kPreStart,
|
runtime::core::AimRTCore::State::kPreStart,
|
||||||
[this] {
|
[this] {
|
||||||
http_cli_pool_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
http_cli_pool_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
||||||
http_cli_pool_ptr_->Initialize(runtime::common::net::AsioHttpClientPool::Options{});
|
http_cli_pool_ptr_->Initialize(aimrt::common::net::AsioHttpClientPool::Options{});
|
||||||
http_cli_pool_ptr_->Start();
|
http_cli_pool_ptr_->Start();
|
||||||
|
|
||||||
http_svr_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
http_svr_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
||||||
http_svr_ptr_->Initialize(runtime::common::net::AsioHttpServer::Options{
|
http_svr_ptr_->Initialize(aimrt::common::net::AsioHttpServer::Options{
|
||||||
.ep = {boost::asio::ip::make_address_v4(options_.http_options->listen_ip),
|
.ep = {boost::asio::ip::make_address_v4(options_.http_options->listen_ip),
|
||||||
options_.http_options->listen_port}});
|
options_.http_options->listen_port}});
|
||||||
http_svr_ptr_->Start();
|
http_svr_ptr_->Start();
|
||||||
@ -149,9 +149,9 @@ bool NetPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
|
|
||||||
// tcp
|
// tcp
|
||||||
if (options_.tcp_options) {
|
if (options_.tcp_options) {
|
||||||
tcp_cli_pool_ptr_ = std::make_shared<runtime::common::net::AsioTcpClientPool>(asio_executor_ptr_->IO());
|
tcp_cli_pool_ptr_ = std::make_shared<aimrt::common::net::AsioTcpClientPool>(asio_executor_ptr_->IO());
|
||||||
tcp_msg_handle_registry_ptr_ = std::make_shared<MsgHandleRegistry<boost::asio::ip::tcp::endpoint>>();
|
tcp_msg_handle_registry_ptr_ = std::make_shared<MsgHandleRegistry<boost::asio::ip::tcp::endpoint>>();
|
||||||
tcp_svr_ptr_ = std::make_shared<runtime::common::net::AsioTcpServer>(asio_executor_ptr_->IO());
|
tcp_svr_ptr_ = std::make_shared<aimrt::common::net::AsioTcpServer>(asio_executor_ptr_->IO());
|
||||||
|
|
||||||
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPreInitChannel,
|
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPreInitChannel,
|
||||||
[this] { RegisterTcpChannelBackend(); });
|
[this] { RegisterTcpChannelBackend(); });
|
||||||
@ -160,12 +160,12 @@ bool NetPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
runtime::core::AimRTCore::State::kPreStart,
|
runtime::core::AimRTCore::State::kPreStart,
|
||||||
[this] {
|
[this] {
|
||||||
tcp_cli_pool_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
tcp_cli_pool_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
||||||
tcp_cli_pool_ptr_->Initialize(runtime::common::net::AsioTcpClientPool::Options{});
|
tcp_cli_pool_ptr_->Initialize(aimrt::common::net::AsioTcpClientPool::Options{});
|
||||||
tcp_cli_pool_ptr_->Start();
|
tcp_cli_pool_ptr_->Start();
|
||||||
|
|
||||||
tcp_svr_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
tcp_svr_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
||||||
tcp_svr_ptr_->RegisterMsgHandle(tcp_msg_handle_registry_ptr_->GetMsgHandleFunc());
|
tcp_svr_ptr_->RegisterMsgHandle(tcp_msg_handle_registry_ptr_->GetMsgHandleFunc());
|
||||||
tcp_svr_ptr_->Initialize(runtime::common::net::AsioTcpServer::Options{
|
tcp_svr_ptr_->Initialize(aimrt::common::net::AsioTcpServer::Options{
|
||||||
.ep = {boost::asio::ip::make_address_v4(options_.tcp_options->listen_ip),
|
.ep = {boost::asio::ip::make_address_v4(options_.tcp_options->listen_ip),
|
||||||
options_.tcp_options->listen_port}});
|
options_.tcp_options->listen_port}});
|
||||||
tcp_svr_ptr_->Start();
|
tcp_svr_ptr_->Start();
|
||||||
@ -181,9 +181,9 @@ bool NetPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
|
|
||||||
// udp
|
// udp
|
||||||
if (options_.udp_options) {
|
if (options_.udp_options) {
|
||||||
udp_cli_pool_ptr_ = std::make_shared<runtime::common::net::AsioUdpClientPool>(asio_executor_ptr_->IO());
|
udp_cli_pool_ptr_ = std::make_shared<aimrt::common::net::AsioUdpClientPool>(asio_executor_ptr_->IO());
|
||||||
udp_msg_handle_registry_ptr_ = std::make_shared<MsgHandleRegistry<boost::asio::ip::udp::endpoint>>();
|
udp_msg_handle_registry_ptr_ = std::make_shared<MsgHandleRegistry<boost::asio::ip::udp::endpoint>>();
|
||||||
udp_svr_ptr_ = std::make_shared<runtime::common::net::AsioUdpServer>(asio_executor_ptr_->IO());
|
udp_svr_ptr_ = std::make_shared<aimrt::common::net::AsioUdpServer>(asio_executor_ptr_->IO());
|
||||||
|
|
||||||
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPreInitChannel,
|
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPreInitChannel,
|
||||||
[this] { RegisterUdpChannelBackend(); });
|
[this] { RegisterUdpChannelBackend(); });
|
||||||
@ -192,12 +192,12 @@ bool NetPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
runtime::core::AimRTCore::State::kPreStart,
|
runtime::core::AimRTCore::State::kPreStart,
|
||||||
[this] {
|
[this] {
|
||||||
udp_cli_pool_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
udp_cli_pool_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
||||||
udp_cli_pool_ptr_->Initialize(runtime::common::net::AsioUdpClientPool::Options{});
|
udp_cli_pool_ptr_->Initialize(aimrt::common::net::AsioUdpClientPool::Options{});
|
||||||
udp_cli_pool_ptr_->Start();
|
udp_cli_pool_ptr_->Start();
|
||||||
|
|
||||||
udp_svr_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
udp_svr_ptr_->SetLogger(WrapAimRTLoggerRef(GetLogger()));
|
||||||
udp_svr_ptr_->RegisterMsgHandle(udp_msg_handle_registry_ptr_->GetMsgHandleFunc());
|
udp_svr_ptr_->RegisterMsgHandle(udp_msg_handle_registry_ptr_->GetMsgHandleFunc());
|
||||||
udp_svr_ptr_->Initialize(runtime::common::net::AsioUdpServer::Options{
|
udp_svr_ptr_->Initialize(aimrt::common::net::AsioUdpServer::Options{
|
||||||
.ep = {boost::asio::ip::make_address_v4(options_.udp_options->listen_ip),
|
.ep = {boost::asio::ip::make_address_v4(options_.udp_options->listen_ip),
|
||||||
options_.udp_options->listen_port},
|
options_.udp_options->listen_port},
|
||||||
.max_package_size = options_.udp_options->max_pkg_size});
|
.max_package_size = options_.udp_options->max_pkg_size});
|
||||||
|
@ -67,18 +67,18 @@ class NetPlugin : public AimRTCorePluginBase {
|
|||||||
|
|
||||||
bool init_flag_ = false;
|
bool init_flag_ = false;
|
||||||
|
|
||||||
std::shared_ptr<runtime::common::net::AsioExecutor> asio_executor_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioExecutor> asio_executor_ptr_;
|
||||||
|
|
||||||
std::shared_ptr<runtime::common::net::AsioHttpClientPool> http_cli_pool_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioHttpClientPool> http_cli_pool_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioHttpServer> http_svr_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioHttpServer> http_svr_ptr_;
|
||||||
|
|
||||||
std::shared_ptr<runtime::common::net::AsioTcpClientPool> tcp_cli_pool_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioTcpClientPool> tcp_cli_pool_ptr_;
|
||||||
std::shared_ptr<MsgHandleRegistry<boost::asio::ip::tcp::endpoint>> tcp_msg_handle_registry_ptr_;
|
std::shared_ptr<MsgHandleRegistry<boost::asio::ip::tcp::endpoint>> tcp_msg_handle_registry_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioTcpServer> tcp_svr_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioTcpServer> tcp_svr_ptr_;
|
||||||
|
|
||||||
std::shared_ptr<runtime::common::net::AsioUdpClientPool> udp_cli_pool_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioUdpClientPool> udp_cli_pool_ptr_;
|
||||||
std::shared_ptr<MsgHandleRegistry<boost::asio::ip::udp::endpoint>> udp_msg_handle_registry_ptr_;
|
std::shared_ptr<MsgHandleRegistry<boost::asio::ip::udp::endpoint>> udp_msg_handle_registry_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioUdpServer> udp_svr_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioUdpServer> udp_svr_ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::plugins::net_plugin
|
} // namespace aimrt::plugins::net_plugin
|
||||||
|
@ -289,7 +289,7 @@ void TcpChannelBackend::Publish(runtime::core::channel::MsgWrapper& msg_wrapper)
|
|||||||
boost::asio::co_spawn(
|
boost::asio::co_spawn(
|
||||||
*io_ptr_,
|
*io_ptr_,
|
||||||
[this, server_ep, msg_buf_ptr]() -> boost::asio::awaitable<void> {
|
[this, server_ep, msg_buf_ptr]() -> boost::asio::awaitable<void> {
|
||||||
runtime::common::net::AsioTcpClient::Options client_options{
|
aimrt::common::net::AsioTcpClient::Options client_options{
|
||||||
.svr_ep = server_ep};
|
.svr_ep = server_ep};
|
||||||
|
|
||||||
auto cli = co_await tcp_cli_pool_ptr_->GetClient(client_options);
|
auto cli = co_await tcp_cli_pool_ptr_->GetClient(client_options);
|
||||||
|
@ -29,8 +29,8 @@ class TcpChannelBackend : public runtime::core::channel::ChannelBackendBase {
|
|||||||
public:
|
public:
|
||||||
TcpChannelBackend(
|
TcpChannelBackend(
|
||||||
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioTcpClientPool>& tcp_cli_pool_ptr,
|
const std::shared_ptr<aimrt::common::net::AsioTcpClientPool>& tcp_cli_pool_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioTcpServer>& tcp_svr_ptr,
|
const std::shared_ptr<aimrt::common::net::AsioTcpServer>& tcp_svr_ptr,
|
||||||
const std::shared_ptr<TcpMsgHandleRegistry>& msg_handle_registry_ptr)
|
const std::shared_ptr<TcpMsgHandleRegistry>& msg_handle_registry_ptr)
|
||||||
: io_ptr_(io_ptr),
|
: io_ptr_(io_ptr),
|
||||||
tcp_cli_pool_ptr_(tcp_cli_pool_ptr),
|
tcp_cli_pool_ptr_(tcp_cli_pool_ptr),
|
||||||
@ -68,9 +68,9 @@ class TcpChannelBackend : public runtime::core::channel::ChannelBackendBase {
|
|||||||
const runtime::core::channel::ChannelRegistry* channel_registry_ptr_ = nullptr;
|
const runtime::core::channel::ChannelRegistry* channel_registry_ptr_ = nullptr;
|
||||||
|
|
||||||
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioTcpClientPool> tcp_cli_pool_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioTcpClientPool> tcp_cli_pool_ptr_;
|
||||||
std::shared_ptr<TcpMsgHandleRegistry> msg_handle_registry_ptr_;
|
std::shared_ptr<TcpMsgHandleRegistry> msg_handle_registry_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioTcpServer> tcp_svr_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioTcpServer> tcp_svr_ptr_;
|
||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
std::string,
|
std::string,
|
||||||
|
@ -286,7 +286,7 @@ void UdpChannelBackend::Publish(runtime::core::channel::MsgWrapper& msg_wrapper)
|
|||||||
boost::asio::co_spawn(
|
boost::asio::co_spawn(
|
||||||
*io_ptr_,
|
*io_ptr_,
|
||||||
[this, server_ep, msg_buf_ptr]() -> boost::asio::awaitable<void> {
|
[this, server_ep, msg_buf_ptr]() -> boost::asio::awaitable<void> {
|
||||||
runtime::common::net::AsioUdpClient::Options client_options{
|
aimrt::common::net::AsioUdpClient::Options client_options{
|
||||||
.svr_ep = server_ep};
|
.svr_ep = server_ep};
|
||||||
|
|
||||||
auto cli = co_await udp_cli_pool_ptr_->GetClient(client_options);
|
auto cli = co_await udp_cli_pool_ptr_->GetClient(client_options);
|
||||||
|
@ -29,8 +29,8 @@ class UdpChannelBackend : public runtime::core::channel::ChannelBackendBase {
|
|||||||
public:
|
public:
|
||||||
UdpChannelBackend(
|
UdpChannelBackend(
|
||||||
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
const std::shared_ptr<boost::asio::io_context>& io_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioUdpClientPool>& udp_cli_pool_ptr,
|
const std::shared_ptr<aimrt::common::net::AsioUdpClientPool>& udp_cli_pool_ptr,
|
||||||
const std::shared_ptr<runtime::common::net::AsioUdpServer>& udp_svr_ptr,
|
const std::shared_ptr<aimrt::common::net::AsioUdpServer>& udp_svr_ptr,
|
||||||
const std::shared_ptr<UdpMsgHandleRegistry>& msg_handle_registry_ptr)
|
const std::shared_ptr<UdpMsgHandleRegistry>& msg_handle_registry_ptr)
|
||||||
: io_ptr_(io_ptr),
|
: io_ptr_(io_ptr),
|
||||||
udp_cli_pool_ptr_(udp_cli_pool_ptr),
|
udp_cli_pool_ptr_(udp_cli_pool_ptr),
|
||||||
@ -68,9 +68,9 @@ class UdpChannelBackend : public runtime::core::channel::ChannelBackendBase {
|
|||||||
const runtime::core::channel::ChannelRegistry* channel_registry_ptr_ = nullptr;
|
const runtime::core::channel::ChannelRegistry* channel_registry_ptr_ = nullptr;
|
||||||
|
|
||||||
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
std::shared_ptr<boost::asio::io_context> io_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioUdpClientPool> udp_cli_pool_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioUdpClientPool> udp_cli_pool_ptr_;
|
||||||
std::shared_ptr<UdpMsgHandleRegistry> msg_handle_registry_ptr_;
|
std::shared_ptr<UdpMsgHandleRegistry> msg_handle_registry_ptr_;
|
||||||
std::shared_ptr<runtime::common::net::AsioUdpServer> udp_svr_ptr_;
|
std::shared_ptr<aimrt::common::net::AsioUdpServer> udp_svr_ptr_;
|
||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
std::string,
|
std::string,
|
||||||
|
@ -16,16 +16,14 @@ class ContextCarrier : public opentelemetry::context::propagation::TextMapCarrie
|
|||||||
: ctx_ref_(ctx_ref) {}
|
: ctx_ref_(ctx_ref) {}
|
||||||
ContextCarrier() = default;
|
ContextCarrier() = default;
|
||||||
|
|
||||||
virtual opentelemetry::nostd::string_view Get(
|
virtual std::string_view Get(std::string_view key) const noexcept override {
|
||||||
opentelemetry::nostd::string_view key) const noexcept override {
|
|
||||||
std::string real_key = std::string(kCtxKeyPrefix) + std::string(key);
|
std::string real_key = std::string(kCtxKeyPrefix) + std::string(key);
|
||||||
return ToNoStdStringView(ctx_ref_.GetMetaValue(real_key));
|
return ctx_ref_.GetMetaValue(real_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Set(opentelemetry::nostd::string_view key,
|
virtual void Set(std::string_view key, std::string_view value) noexcept override {
|
||||||
opentelemetry::nostd::string_view value) noexcept override {
|
|
||||||
std::string real_key = std::string(kCtxKeyPrefix) + std::string(key);
|
std::string real_key = std::string(kCtxKeyPrefix) + std::string(key);
|
||||||
ctx_ref_.SetMetaValue(real_key, ToStdStringView(value));
|
ctx_ref_.SetMetaValue(real_key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContetxRefType ctx_ref_;
|
ContetxRefType ctx_ref_;
|
||||||
|
@ -19,9 +19,14 @@ struct convert<aimrt::plugins::opentelemetry_plugin::OpenTelemetryPlugin::Option
|
|||||||
Node node;
|
Node node;
|
||||||
|
|
||||||
node["node_name"] = rhs.node_name;
|
node["node_name"] = rhs.node_name;
|
||||||
|
|
||||||
node["trace_otlp_http_exporter_url"] = rhs.trace_otlp_http_exporter_url;
|
node["trace_otlp_http_exporter_url"] = rhs.trace_otlp_http_exporter_url;
|
||||||
node["force_trace"] = rhs.force_trace;
|
node["force_trace"] = rhs.force_trace;
|
||||||
|
|
||||||
|
node["metrics_otlp_http_exporter_url"] = rhs.metrics_otlp_http_exporter_url;
|
||||||
|
node["metrics_export_interval_ms"] = rhs.metrics_export_interval_ms;
|
||||||
|
node["metrics_export_timeout_ms"] = rhs.metrics_export_timeout_ms;
|
||||||
|
|
||||||
node["attributes"] = YAML::Node();
|
node["attributes"] = YAML::Node();
|
||||||
for (const auto& attribute : rhs.attributes) {
|
for (const auto& attribute : rhs.attributes) {
|
||||||
Node attribute_node;
|
Node attribute_node;
|
||||||
@ -37,11 +42,22 @@ struct convert<aimrt::plugins::opentelemetry_plugin::OpenTelemetryPlugin::Option
|
|||||||
if (!node.IsMap()) return false;
|
if (!node.IsMap()) return false;
|
||||||
|
|
||||||
rhs.node_name = node["node_name"].as<std::string>();
|
rhs.node_name = node["node_name"].as<std::string>();
|
||||||
rhs.trace_otlp_http_exporter_url = node["trace_otlp_http_exporter_url"].as<std::string>();
|
|
||||||
|
if (node["trace_otlp_http_exporter_url"])
|
||||||
|
rhs.trace_otlp_http_exporter_url = node["trace_otlp_http_exporter_url"].as<std::string>();
|
||||||
|
|
||||||
if (node["force_trace"])
|
if (node["force_trace"])
|
||||||
rhs.force_trace = node["force_trace"].as<bool>();
|
rhs.force_trace = node["force_trace"].as<bool>();
|
||||||
|
|
||||||
|
if (node["metrics_otlp_http_exporter_url"])
|
||||||
|
rhs.metrics_otlp_http_exporter_url = node["metrics_otlp_http_exporter_url"].as<std::string>();
|
||||||
|
|
||||||
|
if (node["metrics_export_interval_ms"])
|
||||||
|
rhs.metrics_export_interval_ms = node["metrics_export_interval_ms"].as<uint32_t>();
|
||||||
|
|
||||||
|
if (node["metrics_export_timeout_ms"])
|
||||||
|
rhs.metrics_export_timeout_ms = node["metrics_export_timeout_ms"].as<uint32_t>();
|
||||||
|
|
||||||
for (const auto& attribute_node : node["attributes"]) {
|
for (const auto& attribute_node : node["attributes"]) {
|
||||||
auto attribute = Options::Attribute{
|
auto attribute = Options::Attribute{
|
||||||
.key = attribute_node["key"].as<std::string>(),
|
.key = attribute_node["key"].as<std::string>(),
|
||||||
@ -57,6 +73,8 @@ struct convert<aimrt::plugins::opentelemetry_plugin::OpenTelemetryPlugin::Option
|
|||||||
|
|
||||||
namespace trace_api = opentelemetry::trace;
|
namespace trace_api = opentelemetry::trace;
|
||||||
namespace trace_sdk = opentelemetry::sdk::trace;
|
namespace trace_sdk = opentelemetry::sdk::trace;
|
||||||
|
namespace metrics_api = opentelemetry::metrics;
|
||||||
|
namespace metric_sdk = opentelemetry::sdk::metrics;
|
||||||
namespace resource = opentelemetry::sdk::resource;
|
namespace resource = opentelemetry::sdk::resource;
|
||||||
namespace otlp = opentelemetry::exporter::otlp;
|
namespace otlp = opentelemetry::exporter::otlp;
|
||||||
|
|
||||||
@ -84,17 +102,55 @@ bool OpenTelemetryPlugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcep
|
|||||||
}
|
}
|
||||||
auto resource = resource::Resource::Create(resource_attributes);
|
auto resource = resource::Resource::Create(resource_attributes);
|
||||||
|
|
||||||
otlp::OtlpHttpExporterOptions opts;
|
|
||||||
opts.url = options_.trace_otlp_http_exporter_url;
|
|
||||||
auto exporter = otlp::OtlpHttpExporterFactory::Create(opts);
|
|
||||||
|
|
||||||
trace_sdk::BatchSpanProcessorOptions bsp_opts{};
|
|
||||||
auto processor = trace_sdk::BatchSpanProcessorFactory::Create(std::move(exporter), bsp_opts);
|
|
||||||
|
|
||||||
provider_ = trace_sdk::TracerProviderFactory::Create(std::move(processor), resource);
|
|
||||||
|
|
||||||
propagator_ = std::make_shared<trace_api::propagation::HttpTraceContext>();
|
propagator_ = std::make_shared<trace_api::propagation::HttpTraceContext>();
|
||||||
|
|
||||||
|
// trace
|
||||||
|
if (!options_.trace_otlp_http_exporter_url.empty()) {
|
||||||
|
enable_trace_ = true;
|
||||||
|
|
||||||
|
otlp::OtlpHttpExporterOptions opts;
|
||||||
|
opts.url = options_.trace_otlp_http_exporter_url;
|
||||||
|
auto exporter = otlp::OtlpHttpExporterFactory::Create(opts);
|
||||||
|
|
||||||
|
trace_sdk::BatchSpanProcessorOptions bsp_opts{};
|
||||||
|
auto processor = trace_sdk::BatchSpanProcessorFactory::Create(std::move(exporter), bsp_opts);
|
||||||
|
|
||||||
|
trace_provider_ = trace_sdk::TracerProviderFactory::Create(std::move(processor), resource);
|
||||||
|
|
||||||
|
tracer_ = trace_provider_->GetTracer(options_.node_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// metrics
|
||||||
|
if (!options_.metrics_otlp_http_exporter_url.empty()) {
|
||||||
|
enable_metrics_ = true;
|
||||||
|
|
||||||
|
otlp::OtlpHttpMetricExporterOptions opts;
|
||||||
|
opts.url = options_.metrics_otlp_http_exporter_url;
|
||||||
|
auto exporter = otlp::OtlpHttpMetricExporterFactory::Create(opts);
|
||||||
|
|
||||||
|
metric_sdk::PeriodicExportingMetricReaderOptions reader_opts{};
|
||||||
|
reader_opts.export_interval_millis = std::chrono::milliseconds(options_.metrics_export_interval_ms);
|
||||||
|
reader_opts.export_timeout_millis = std::chrono::milliseconds(options_.metrics_export_timeout_ms);
|
||||||
|
|
||||||
|
auto reader =
|
||||||
|
metric_sdk::PeriodicExportingMetricReaderFactory::Create(std::move(exporter), reader_opts);
|
||||||
|
|
||||||
|
auto views = metric_sdk::ViewRegistryFactory::Create();
|
||||||
|
|
||||||
|
auto context = metric_sdk::MeterContextFactory::Create(std::move(views), resource);
|
||||||
|
context->AddMetricReader(std::move(reader));
|
||||||
|
|
||||||
|
meter_provider_ = metric_sdk::MeterProviderFactory::Create(std::move(context));
|
||||||
|
|
||||||
|
meter_ = meter_provider_->GetMeter(options_.node_name);
|
||||||
|
|
||||||
|
chn_pub_msg_num_counter_ = meter_->CreateUInt64Counter("chn.pub.msg_num", "Total num of channel publish msg");
|
||||||
|
chn_sub_msg_num_counter_ = meter_->CreateUInt64Counter("chn.sub.msg_num", "Total num of channel subscribe msg");
|
||||||
|
|
||||||
|
chn_pub_msg_size_counter_ = meter_->CreateUInt64Counter("chn.pub.msg_size", "Total size of channel publish msg", "bytes");
|
||||||
|
chn_sub_msg_size_counter_ = meter_->CreateUInt64Counter("chn.sub.msg_size", "Total size of channel subscribe msg", "bytes");
|
||||||
|
}
|
||||||
|
|
||||||
// register hook
|
// register hook
|
||||||
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPostInitLog,
|
core_ptr_->RegisterHookFunc(runtime::core::AimRTCore::State::kPostInitLog,
|
||||||
[this] { SetPluginLogger(); });
|
[this] { SetPluginLogger(); });
|
||||||
@ -118,7 +174,12 @@ void OpenTelemetryPlugin::Shutdown() noexcept {
|
|||||||
try {
|
try {
|
||||||
if (!init_flag_) return;
|
if (!init_flag_) return;
|
||||||
|
|
||||||
provider_.reset();
|
meter_.reset();
|
||||||
|
meter_provider_.reset();
|
||||||
|
|
||||||
|
tracer_.reset();
|
||||||
|
trace_provider_.reset();
|
||||||
|
|
||||||
propagator_.reset();
|
propagator_.reset();
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
@ -134,83 +195,120 @@ void OpenTelemetryPlugin::SetPluginLogger() {
|
|||||||
void OpenTelemetryPlugin::RegisterChannelFilter() {
|
void OpenTelemetryPlugin::RegisterChannelFilter() {
|
||||||
auto& channel_manager = core_ptr_->GetChannelManager();
|
auto& channel_manager = core_ptr_->GetChannelManager();
|
||||||
|
|
||||||
channel_manager.SetPassedContextMetaKeys(
|
if (enable_trace_) {
|
||||||
{std::string(kCtxKeyStartNewTrace),
|
channel_manager.AddPassedContextMetaKeys(
|
||||||
std::string(kCtxKeyTraceParent),
|
{std::string(kCtxKeyStartNewTrace),
|
||||||
std::string(kCtxKeyTraceState)});
|
std::string(kCtxKeyTraceParent),
|
||||||
|
std::string(kCtxKeyTraceState)});
|
||||||
|
|
||||||
channel_manager.RegisterPublishFilter(
|
channel_manager.RegisterPublishFilter(
|
||||||
"otp_trace",
|
"otp_trace",
|
||||||
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
ChannelFilter(trace_api::SpanKind::kProducer, true, msg_wrapper, std::move(h));
|
ChannelTraceFilter(ChannelFilterType::kPublisher, true, msg_wrapper, std::move(h));
|
||||||
});
|
});
|
||||||
|
|
||||||
channel_manager.RegisterPublishFilter(
|
channel_manager.RegisterPublishFilter(
|
||||||
"otp_simple_trace",
|
"otp_simple_trace",
|
||||||
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
ChannelFilter(trace_api::SpanKind::kProducer, false, msg_wrapper, std::move(h));
|
ChannelTraceFilter(ChannelFilterType::kPublisher, false, msg_wrapper, std::move(h));
|
||||||
});
|
});
|
||||||
|
|
||||||
channel_manager.RegisterSubscribeFilter(
|
channel_manager.RegisterSubscribeFilter(
|
||||||
"otp_trace",
|
"otp_trace",
|
||||||
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
ChannelFilter(trace_api::SpanKind::kConsumer, true, msg_wrapper, std::move(h));
|
ChannelTraceFilter(ChannelFilterType::kSubscriber, true, msg_wrapper, std::move(h));
|
||||||
});
|
});
|
||||||
|
|
||||||
channel_manager.RegisterSubscribeFilter(
|
channel_manager.RegisterSubscribeFilter(
|
||||||
"otp_simple_trace",
|
"otp_simple_trace",
|
||||||
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
ChannelFilter(trace_api::SpanKind::kConsumer, false, msg_wrapper, std::move(h));
|
ChannelTraceFilter(ChannelFilterType::kSubscriber, false, msg_wrapper, std::move(h));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable_metrics_) {
|
||||||
|
channel_manager.RegisterPublishFilter(
|
||||||
|
"otp_metrics",
|
||||||
|
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
|
ChannelMetricsFilter(ChannelFilterType::kPublisher, msg_wrapper, std::move(h));
|
||||||
|
});
|
||||||
|
|
||||||
|
channel_manager.RegisterSubscribeFilter(
|
||||||
|
"otp_metrics",
|
||||||
|
[this](aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
|
ChannelMetricsFilter(ChannelFilterType::kSubscriber, msg_wrapper, std::move(h));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenTelemetryPlugin::RegisterRpcFilter() {
|
void OpenTelemetryPlugin::RegisterRpcFilter() {
|
||||||
auto& rpc_manager = core_ptr_->GetRpcManager();
|
auto& rpc_manager = core_ptr_->GetRpcManager();
|
||||||
|
|
||||||
rpc_manager.SetPassedContextMetaKeys(
|
if (enable_trace_) {
|
||||||
{std::string(kCtxKeyStartNewTrace),
|
rpc_manager.AddPassedContextMetaKeys(
|
||||||
std::string(kCtxKeyTraceParent),
|
{std::string(kCtxKeyStartNewTrace),
|
||||||
std::string(kCtxKeyTraceState)});
|
std::string(kCtxKeyTraceParent),
|
||||||
|
std::string(kCtxKeyTraceState)});
|
||||||
|
|
||||||
rpc_manager.RegisterClientFilter(
|
rpc_manager.RegisterClientFilter(
|
||||||
"otp_trace",
|
"otp_trace",
|
||||||
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
RpcFilter(trace_api::SpanKind::kClient, true, wrapper_ptr, std::move(h));
|
RpcTraceFilter(RpcFilterType::kClient, true, wrapper_ptr, std::move(h));
|
||||||
});
|
});
|
||||||
|
|
||||||
rpc_manager.RegisterClientFilter(
|
rpc_manager.RegisterClientFilter(
|
||||||
"otp_simple_trace",
|
"otp_simple_trace",
|
||||||
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
RpcFilter(trace_api::SpanKind::kClient, false, wrapper_ptr, std::move(h));
|
RpcTraceFilter(RpcFilterType::kClient, false, wrapper_ptr, std::move(h));
|
||||||
});
|
});
|
||||||
|
|
||||||
rpc_manager.RegisterServerFilter(
|
rpc_manager.RegisterServerFilter(
|
||||||
"otp_trace",
|
"otp_trace",
|
||||||
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
RpcFilter(trace_api::SpanKind::kServer, true, wrapper_ptr, std::move(h));
|
RpcTraceFilter(RpcFilterType::kServer, true, wrapper_ptr, std::move(h));
|
||||||
});
|
});
|
||||||
|
|
||||||
rpc_manager.RegisterServerFilter(
|
rpc_manager.RegisterServerFilter(
|
||||||
"otp_simple_trace",
|
"otp_simple_trace",
|
||||||
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
RpcFilter(trace_api::SpanKind::kServer, false, wrapper_ptr, std::move(h));
|
RpcTraceFilter(RpcFilterType::kServer, false, wrapper_ptr, std::move(h));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable_metrics_) {
|
||||||
|
rpc_manager.RegisterClientFilter(
|
||||||
|
"otp_metrics",
|
||||||
|
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
|
RpcMetricsFilter(RpcFilterType::kClient, wrapper_ptr, std::move(h));
|
||||||
|
});
|
||||||
|
|
||||||
|
rpc_manager.RegisterServerFilter(
|
||||||
|
"otp_metrics",
|
||||||
|
[this](const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
|
RpcMetricsFilter(RpcFilterType::kServer, wrapper_ptr, std::move(h));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenTelemetryPlugin::ChannelFilter(
|
void OpenTelemetryPlugin::ChannelTraceFilter(
|
||||||
opentelemetry::trace::SpanKind kind,
|
ChannelFilterType type,
|
||||||
bool upload_msg,
|
bool upload_msg,
|
||||||
aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
auto ctx_ref = msg_wrapper.ctx_ref;
|
auto ctx_ref = msg_wrapper.ctx_ref;
|
||||||
|
const auto& info = msg_wrapper.info;
|
||||||
|
|
||||||
// 如果设置了全局强制trace,或者context强制设置了start_new_trace,或者上层传递了span,则新启动一个span
|
// 如果设置了全局强制trace,或者context强制设置了start_new_trace,或者上层传递了span,则新启动一个span
|
||||||
bool start_new_trace = options_.force_trace;
|
bool start_new_trace = options_.force_trace;
|
||||||
@ -221,21 +319,20 @@ void OpenTelemetryPlugin::ChannelFilter(
|
|||||||
ctx_ref.SetMetaValue(kCtxKeyStartNewTrace, "true");
|
ctx_ref.SetMetaValue(kCtxKeyStartNewTrace, "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tracer = provider_->GetTracer(options_.node_name);
|
|
||||||
ContextCarrier carrier(ctx_ref);
|
ContextCarrier carrier(ctx_ref);
|
||||||
|
|
||||||
// 解压传进来的context,得到父span
|
// 解压传进来的context,得到父span
|
||||||
trace_api::StartSpanOptions op{
|
trace_api::StartSpanOptions op;
|
||||||
.kind = kind,
|
op.kind = (type == ChannelFilterType::kPublisher)
|
||||||
};
|
? trace_api::SpanKind::kProducer
|
||||||
|
: trace_api::SpanKind::kConsumer;
|
||||||
|
|
||||||
opentelemetry::context::Context input_ot_ctx;
|
opentelemetry::context::Context input_ot_ctx;
|
||||||
auto extract_ctx = propagator_->Extract(carrier, input_ot_ctx);
|
auto extract_ctx = propagator_->Extract(carrier, input_ot_ctx);
|
||||||
|
|
||||||
auto extract_ctx_val = extract_ctx.GetValue(trace_api::kSpanKey);
|
auto extract_ctx_val = extract_ctx.GetValue(trace_api::kSpanKey);
|
||||||
if (!::opentelemetry::nostd::holds_alternative<::opentelemetry::nostd::monostate>(extract_ctx_val)) {
|
if (!std::holds_alternative<std::monostate>(extract_ctx_val)) {
|
||||||
auto parent_span =
|
auto parent_span = std::get<std::shared_ptr<::opentelemetry::trace::Span>>(extract_ctx_val);
|
||||||
::opentelemetry::nostd::get<::opentelemetry::nostd::shared_ptr<::opentelemetry::trace::Span>>(extract_ctx_val);
|
|
||||||
op.parent = parent_span->GetContext();
|
op.parent = parent_span->GetContext();
|
||||||
start_new_trace = true;
|
start_new_trace = true;
|
||||||
}
|
}
|
||||||
@ -248,20 +345,24 @@ void OpenTelemetryPlugin::ChannelFilter(
|
|||||||
|
|
||||||
// 需要启动一个新trace
|
// 需要启动一个新trace
|
||||||
std::string span_name = msg_wrapper.info.topic_name + "/" + msg_wrapper.info.msg_type;
|
std::string span_name = msg_wrapper.info.topic_name + "/" + msg_wrapper.info.msg_type;
|
||||||
auto span = tracer->StartSpan(ToNoStdStringView(span_name), op);
|
auto span = tracer_->StartSpan(span_name, op);
|
||||||
|
|
||||||
|
// 先发布数据
|
||||||
|
h(msg_wrapper);
|
||||||
|
|
||||||
// 将当前span的context打包
|
// 将当前span的context打包
|
||||||
opentelemetry::context::Context output_ot_ctx(trace_api::kSpanKey, span);
|
opentelemetry::context::Context output_ot_ctx(trace_api::kSpanKey, span);
|
||||||
propagator_->Inject(carrier, output_ot_ctx);
|
propagator_->Inject(carrier, output_ot_ctx);
|
||||||
|
|
||||||
|
// 添加base信息
|
||||||
|
span->SetAttribute("module_name", info.module_name);
|
||||||
|
|
||||||
// 添加context中的属性
|
// 添加context中的属性
|
||||||
auto keys = ctx_ref.GetMetaKeys();
|
auto keys = ctx_ref.GetMetaKeys();
|
||||||
for (auto& itr : keys) {
|
for (auto& item : keys) {
|
||||||
span->SetAttribute(ToNoStdStringView(itr), ToNoStdStringView(ctx_ref.GetMetaValue(itr)));
|
span->SetAttribute(item, ctx_ref.GetMetaValue(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
h(msg_wrapper);
|
|
||||||
|
|
||||||
if (upload_msg) {
|
if (upload_msg) {
|
||||||
// 序列化包成json
|
// 序列化包成json
|
||||||
auto buf_ptr = aimrt::runtime::core::channel::TrySerializeMsgWithCache(msg_wrapper, "json");
|
auto buf_ptr = aimrt::runtime::core::channel::TrySerializeMsgWithCache(msg_wrapper, "json");
|
||||||
@ -274,8 +375,8 @@ void OpenTelemetryPlugin::ChannelFilter(
|
|||||||
span->End();
|
span->End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenTelemetryPlugin::RpcFilter(
|
void OpenTelemetryPlugin::RpcTraceFilter(
|
||||||
opentelemetry::trace::SpanKind kind,
|
RpcFilterType type,
|
||||||
bool upload_msg,
|
bool upload_msg,
|
||||||
const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
@ -290,21 +391,20 @@ void OpenTelemetryPlugin::RpcFilter(
|
|||||||
ctx_ref.SetMetaValue(kCtxKeyStartNewTrace, "true");
|
ctx_ref.SetMetaValue(kCtxKeyStartNewTrace, "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tracer = provider_->GetTracer(options_.node_name);
|
|
||||||
ContextCarrier carrier(ctx_ref);
|
ContextCarrier carrier(ctx_ref);
|
||||||
|
|
||||||
// 解压传进来的context,得到父span
|
// 解压传进来的context,得到父span
|
||||||
trace_api::StartSpanOptions op{
|
trace_api::StartSpanOptions op;
|
||||||
.kind = kind,
|
op.kind = (type == RpcFilterType::kClient)
|
||||||
};
|
? trace_api::SpanKind::kClient
|
||||||
|
: trace_api::SpanKind::kServer;
|
||||||
|
|
||||||
opentelemetry::context::Context input_ot_ctx;
|
opentelemetry::context::Context input_ot_ctx;
|
||||||
auto extract_ctx = propagator_->Extract(carrier, input_ot_ctx);
|
auto extract_ctx = propagator_->Extract(carrier, input_ot_ctx);
|
||||||
|
|
||||||
auto extract_ctx_val = extract_ctx.GetValue(trace_api::kSpanKey);
|
auto extract_ctx_val = extract_ctx.GetValue(trace_api::kSpanKey);
|
||||||
if (!::opentelemetry::nostd::holds_alternative<::opentelemetry::nostd::monostate>(extract_ctx_val)) {
|
if (!std::holds_alternative<std::monostate>(extract_ctx_val)) {
|
||||||
auto parent_span =
|
auto parent_span = std::get<std::shared_ptr<::opentelemetry::trace::Span>>(extract_ctx_val);
|
||||||
::opentelemetry::nostd::get<::opentelemetry::nostd::shared_ptr<::opentelemetry::trace::Span>>(extract_ctx_val);
|
|
||||||
op.parent = parent_span->GetContext();
|
op.parent = parent_span->GetContext();
|
||||||
start_new_trace = true;
|
start_new_trace = true;
|
||||||
}
|
}
|
||||||
@ -316,18 +416,12 @@ void OpenTelemetryPlugin::RpcFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 需要启动一个新trace
|
// 需要启动一个新trace
|
||||||
auto span = tracer->StartSpan(ToNoStdStringView(ctx_ref.GetFunctionName()), op);
|
auto span = tracer_->StartSpan(ctx_ref.GetFunctionName(), op);
|
||||||
|
|
||||||
// 将当前span的context打包
|
// 将当前span的context打包
|
||||||
opentelemetry::context::Context output_ot_ctx(trace_api::kSpanKey, span);
|
opentelemetry::context::Context output_ot_ctx(trace_api::kSpanKey, span);
|
||||||
propagator_->Inject(carrier, output_ot_ctx);
|
propagator_->Inject(carrier, output_ot_ctx);
|
||||||
|
|
||||||
// 添加context中的属性
|
|
||||||
auto keys = ctx_ref.GetMetaKeys();
|
|
||||||
for (auto& itr : keys) {
|
|
||||||
span->SetAttribute(ToNoStdStringView(itr), ToNoStdStringView(ctx_ref.GetMetaValue(itr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapper_ptr->callback =
|
wrapper_ptr->callback =
|
||||||
[upload_msg,
|
[upload_msg,
|
||||||
wrapper_ptr,
|
wrapper_ptr,
|
||||||
@ -339,6 +433,18 @@ void OpenTelemetryPlugin::RpcFilter(
|
|||||||
span->SetStatus(trace_api::StatusCode::kError, status.ToString());
|
span->SetStatus(trace_api::StatusCode::kError, status.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto ctx_ref = wrapper_ptr->ctx_ref;
|
||||||
|
const auto& info = wrapper_ptr->info;
|
||||||
|
|
||||||
|
// 添加base信息
|
||||||
|
span->SetAttribute("module_name", info.module_name);
|
||||||
|
|
||||||
|
// 添加context中的属性
|
||||||
|
auto keys = ctx_ref.GetMetaKeys();
|
||||||
|
for (auto& item : keys) {
|
||||||
|
span->SetAttribute(item, ctx_ref.GetMetaValue(item));
|
||||||
|
}
|
||||||
|
|
||||||
if (upload_msg) {
|
if (upload_msg) {
|
||||||
// 序列化req/rsp为json
|
// 序列化req/rsp为json
|
||||||
auto req_buf_ptr = aimrt::runtime::core::rpc::TrySerializeReqWithCache(*wrapper_ptr, "json");
|
auto req_buf_ptr = aimrt::runtime::core::rpc::TrySerializeReqWithCache(*wrapper_ptr, "json");
|
||||||
@ -362,4 +468,78 @@ void OpenTelemetryPlugin::RpcFilter(
|
|||||||
h(wrapper_ptr);
|
h(wrapper_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenTelemetryPlugin::ChannelMetricsFilter(
|
||||||
|
ChannelFilterType type,
|
||||||
|
aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h) {
|
||||||
|
// publish msg first
|
||||||
|
h(msg_wrapper);
|
||||||
|
|
||||||
|
// get counter
|
||||||
|
metrics_api::Counter<uint64_t>* msg_num_counter_ptr = nullptr;
|
||||||
|
metrics_api::Counter<uint64_t>* msg_size_counter_ptr = nullptr;
|
||||||
|
|
||||||
|
if (type == ChannelFilterType::kPublisher) {
|
||||||
|
msg_num_counter_ptr = chn_pub_msg_num_counter_.get();
|
||||||
|
msg_size_counter_ptr = chn_pub_msg_size_counter_.get();
|
||||||
|
} else {
|
||||||
|
msg_num_counter_ptr = chn_sub_msg_num_counter_.get();
|
||||||
|
msg_size_counter_ptr = chn_sub_msg_size_counter_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// make labels
|
||||||
|
auto ctx_ref = msg_wrapper.ctx_ref;
|
||||||
|
const auto& info = msg_wrapper.info;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> labels{
|
||||||
|
{"topic_name", info.topic_name},
|
||||||
|
{"msg_type", info.msg_type},
|
||||||
|
{"module_name", info.module_name},
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO 这里是否有必要?对性能影响有多大?
|
||||||
|
auto keys = ctx_ref.GetMetaKeys();
|
||||||
|
for (auto& item : keys) {
|
||||||
|
labels.emplace(item, ctx_ref.GetMetaValue(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
// msg num
|
||||||
|
msg_num_counter_ptr->Add(1, labels);
|
||||||
|
|
||||||
|
// msg size
|
||||||
|
std::string_view serialization_type;
|
||||||
|
size_t msg_size = 0;
|
||||||
|
|
||||||
|
const auto& serialization_cache = msg_wrapper.serialization_cache;
|
||||||
|
|
||||||
|
if (serialization_cache.size() == 1) {
|
||||||
|
serialization_type = serialization_cache.begin()->first;
|
||||||
|
msg_size = serialization_cache.begin()->second->BufferSize();
|
||||||
|
} else {
|
||||||
|
auto serialization_type_span = info.msg_type_support_ref.SerializationTypesSupportedListSpan();
|
||||||
|
|
||||||
|
for (auto item : serialization_type_span) {
|
||||||
|
auto cur_serialization_type = aimrt::util::ToStdStringView(item);
|
||||||
|
|
||||||
|
auto finditr = serialization_cache.find(cur_serialization_type);
|
||||||
|
if (finditr == serialization_cache.end()) [[unlikely]]
|
||||||
|
continue;
|
||||||
|
|
||||||
|
serialization_type = cur_serialization_type;
|
||||||
|
msg_size = finditr->second->BufferSize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
labels.emplace("serialization_type", serialization_type);
|
||||||
|
msg_size_counter_ptr->Add(msg_size, labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenTelemetryPlugin::RpcMetricsFilter(
|
||||||
|
RpcFilterType type,
|
||||||
|
const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h) {
|
||||||
|
h(wrapper_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aimrt::plugins::opentelemetry_plugin
|
} // namespace aimrt::plugins::opentelemetry_plugin
|
||||||
|
@ -8,9 +8,26 @@
|
|||||||
|
|
||||||
#include "aimrt_core_plugin_interface/aimrt_core_plugin_base.h"
|
#include "aimrt_core_plugin_interface/aimrt_core_plugin_base.h"
|
||||||
|
|
||||||
#include <opentelemetry/trace/propagation/http_trace_context.h>
|
#include "opentelemetry/context/propagation/text_map_propagator.h"
|
||||||
|
#include "opentelemetry/exporters/otlp/otlp_environment.h"
|
||||||
|
#include "opentelemetry/exporters/otlp/otlp_http.h"
|
||||||
#include "opentelemetry/exporters/otlp/otlp_http_exporter_factory.h"
|
#include "opentelemetry/exporters/otlp/otlp_http_exporter_factory.h"
|
||||||
#include "opentelemetry/exporters/otlp/otlp_http_exporter_options.h"
|
#include "opentelemetry/exporters/otlp/otlp_http_exporter_options.h"
|
||||||
|
#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h"
|
||||||
|
#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h"
|
||||||
|
#include "opentelemetry/metrics/meter_provider.h"
|
||||||
|
#include "opentelemetry/metrics/provider.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_options.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/meter_context.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/meter_context_factory.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/meter_provider.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/meter_provider_factory.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/metric_reader.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/push_metric_exporter.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/state/filtered_ordered_attribute_map.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/view/view_registry.h"
|
||||||
|
#include "opentelemetry/sdk/metrics/view/view_registry_factory.h"
|
||||||
#include "opentelemetry/sdk/trace/batch_span_processor_factory.h"
|
#include "opentelemetry/sdk/trace/batch_span_processor_factory.h"
|
||||||
#include "opentelemetry/sdk/trace/batch_span_processor_options.h"
|
#include "opentelemetry/sdk/trace/batch_span_processor_options.h"
|
||||||
#include "opentelemetry/sdk/trace/exporter.h"
|
#include "opentelemetry/sdk/trace/exporter.h"
|
||||||
@ -20,10 +37,12 @@
|
|||||||
#include "opentelemetry/sdk/trace/tracer_provider.h"
|
#include "opentelemetry/sdk/trace/tracer_provider.h"
|
||||||
#include "opentelemetry/sdk/trace/tracer_provider_factory.h"
|
#include "opentelemetry/sdk/trace/tracer_provider_factory.h"
|
||||||
#include "opentelemetry/sdk/version/version.h"
|
#include "opentelemetry/sdk/version/version.h"
|
||||||
|
#include "opentelemetry/trace/propagation/http_trace_context.h"
|
||||||
#include "opentelemetry/trace/provider.h"
|
#include "opentelemetry/trace/provider.h"
|
||||||
#include "opentelemetry/trace/scope.h"
|
#include "opentelemetry/trace/scope.h"
|
||||||
#include "opentelemetry/trace/span.h"
|
#include "opentelemetry/trace/span.h"
|
||||||
#include "opentelemetry/trace/span_context.h"
|
#include "opentelemetry/trace/span_context.h"
|
||||||
|
#include "opentelemetry/trace/span_metadata.h"
|
||||||
#include "opentelemetry/trace/tracer.h"
|
#include "opentelemetry/trace/tracer.h"
|
||||||
#include "opentelemetry/trace/tracer_provider.h"
|
#include "opentelemetry/trace/tracer_provider.h"
|
||||||
|
|
||||||
@ -36,9 +55,14 @@ class OpenTelemetryPlugin : public AimRTCorePluginBase {
|
|||||||
public:
|
public:
|
||||||
struct Options {
|
struct Options {
|
||||||
std::string node_name;
|
std::string node_name;
|
||||||
|
|
||||||
std::string trace_otlp_http_exporter_url;
|
std::string trace_otlp_http_exporter_url;
|
||||||
bool force_trace = false;
|
bool force_trace = false;
|
||||||
|
|
||||||
|
std::string metrics_otlp_http_exporter_url;
|
||||||
|
uint32_t metrics_export_interval_ms = 15000;
|
||||||
|
uint32_t metrics_export_timeout_ms = 5000;
|
||||||
|
|
||||||
struct Attribute {
|
struct Attribute {
|
||||||
std::string key;
|
std::string key;
|
||||||
std::string val;
|
std::string val;
|
||||||
@ -60,18 +84,38 @@ class OpenTelemetryPlugin : public AimRTCorePluginBase {
|
|||||||
void RegisterChannelFilter();
|
void RegisterChannelFilter();
|
||||||
void RegisterRpcFilter();
|
void RegisterRpcFilter();
|
||||||
|
|
||||||
void ChannelFilter(
|
enum class ChannelFilterType {
|
||||||
opentelemetry::trace::SpanKind kind,
|
kPublisher,
|
||||||
|
kSubscriber
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RpcFilterType {
|
||||||
|
kClient,
|
||||||
|
kServer
|
||||||
|
};
|
||||||
|
|
||||||
|
void ChannelTraceFilter(
|
||||||
|
ChannelFilterType type,
|
||||||
bool upload_msg,
|
bool upload_msg,
|
||||||
aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h);
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h);
|
||||||
|
|
||||||
void RpcFilter(
|
void RpcTraceFilter(
|
||||||
opentelemetry::trace::SpanKind kind,
|
RpcFilterType type,
|
||||||
bool upload_msg,
|
bool upload_msg,
|
||||||
const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h);
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h);
|
||||||
|
|
||||||
|
void ChannelMetricsFilter(
|
||||||
|
ChannelFilterType type,
|
||||||
|
aimrt::runtime::core::channel::MsgWrapper& msg_wrapper,
|
||||||
|
aimrt::runtime::core::channel::FrameworkAsyncChannelHandle&& h);
|
||||||
|
|
||||||
|
void RpcMetricsFilter(
|
||||||
|
RpcFilterType type,
|
||||||
|
const std::shared_ptr<aimrt::runtime::core::rpc::InvokeWrapper>& wrapper_ptr,
|
||||||
|
aimrt::runtime::core::rpc::FrameworkAsyncRpcHandle&& h);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
runtime::core::AimRTCore* core_ptr_ = nullptr;
|
runtime::core::AimRTCore* core_ptr_ = nullptr;
|
||||||
|
|
||||||
@ -79,8 +123,31 @@ class OpenTelemetryPlugin : public AimRTCorePluginBase {
|
|||||||
|
|
||||||
bool init_flag_ = false;
|
bool init_flag_ = false;
|
||||||
|
|
||||||
std::shared_ptr<opentelemetry::trace::TracerProvider> provider_;
|
|
||||||
std::shared_ptr<opentelemetry::context::propagation::TextMapPropagator> propagator_;
|
std::shared_ptr<opentelemetry::context::propagation::TextMapPropagator> propagator_;
|
||||||
|
|
||||||
|
// trace
|
||||||
|
bool enable_trace_ = false;
|
||||||
|
std::shared_ptr<opentelemetry::trace::TracerProvider> trace_provider_;
|
||||||
|
std::shared_ptr<opentelemetry::trace::Tracer> tracer_;
|
||||||
|
|
||||||
|
// metrics
|
||||||
|
bool enable_metrics_ = false;
|
||||||
|
std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider_;
|
||||||
|
std::shared_ptr<opentelemetry::metrics::Meter> meter_;
|
||||||
|
|
||||||
|
using u64_counter = std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>>;
|
||||||
|
|
||||||
|
u64_counter chn_pub_msg_num_counter_;
|
||||||
|
u64_counter chn_sub_msg_num_counter_;
|
||||||
|
u64_counter chn_pub_msg_size_counter_;
|
||||||
|
u64_counter chn_sub_msg_size_counter_;
|
||||||
|
|
||||||
|
u64_counter rpc_client_invoke_num_counter_;
|
||||||
|
u64_counter rpc_server_invoke_num_counter_;
|
||||||
|
u64_counter rpc_client_req_size_counter_;
|
||||||
|
u64_counter rpc_client_rsp_size_counter_;
|
||||||
|
u64_counter rpc_server_req_size_counter_;
|
||||||
|
u64_counter rpc_server_rsp_size_counter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aimrt::plugins::opentelemetry_plugin
|
} // namespace aimrt::plugins::opentelemetry_plugin
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "opentelemetry/nostd/string_view.h"
|
|
||||||
|
|
||||||
namespace aimrt::plugins::opentelemetry_plugin {
|
namespace aimrt::plugins::opentelemetry_plugin {
|
||||||
|
|
||||||
static constexpr std::string_view kCtxKeyPrefix = "aimrt_otp-";
|
static constexpr std::string_view kCtxKeyPrefix = "aimrt_otp-";
|
||||||
@ -15,12 +13,4 @@ static constexpr std::string_view kCtxKeyStartNewTrace = "aimrt_otp-start_new_tr
|
|||||||
static constexpr std::string_view kCtxKeyTraceParent = "aimrt_otp-traceparent";
|
static constexpr std::string_view kCtxKeyTraceParent = "aimrt_otp-traceparent";
|
||||||
static constexpr std::string_view kCtxKeyTraceState = "aimrt_otp-tracestate";
|
static constexpr std::string_view kCtxKeyTraceState = "aimrt_otp-tracestate";
|
||||||
|
|
||||||
inline opentelemetry::nostd::string_view ToNoStdStringView(std::string_view s) {
|
|
||||||
return opentelemetry::nostd::string_view(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string_view ToStdStringView(opentelemetry::nostd::string_view s) {
|
|
||||||
return std::string_view(s.data(), s.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace aimrt::plugins::opentelemetry_plugin
|
} // namespace aimrt::plugins::opentelemetry_plugin
|
@ -225,6 +225,11 @@ void RecordAction::RegisterGetTypeSupportFunc(
|
|||||||
get_type_support_func_ = get_type_support_func;
|
get_type_support_func_ = get_type_support_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t RecordAction::GetDbFileSize() const {
|
||||||
|
if (cur_db_file_path_.empty() || !std::filesystem::exists(cur_db_file_path_)) return 0;
|
||||||
|
return std::filesystem::file_size(cur_db_file_path_);
|
||||||
|
}
|
||||||
|
|
||||||
void RecordAction::AddRecord(OneRecord&& record) {
|
void RecordAction::AddRecord(OneRecord&& record) {
|
||||||
if (state_.load() != State::kStart) [[unlikely]] {
|
if (state_.load() != State::kStart) [[unlikely]] {
|
||||||
return;
|
return;
|
||||||
@ -365,9 +370,10 @@ void RecordAction::AddRecordImpl(OneRecord&& record) {
|
|||||||
if (db_ == nullptr) [[unlikely]] {
|
if (db_ == nullptr) [[unlikely]] {
|
||||||
// first record
|
// first record
|
||||||
OpenNewDb(record.timestamp);
|
OpenNewDb(record.timestamp);
|
||||||
} else if (cur_data_size_ > max_bag_size_) [[unlikely]] {
|
} else if (cur_data_size_ * estimated_overhead_ >= max_bag_size_) [[unlikely]] {
|
||||||
// check db size
|
size_t original_cur_data_size = cur_data_size_;
|
||||||
cur_data_size_ = 0;
|
cur_data_size_ = 0;
|
||||||
|
estimated_overhead_ = std::max(1.0, static_cast<double>(GetDbFileSize()) / original_cur_data_size);
|
||||||
OpenNewDb(record.timestamp);
|
OpenNewDb(record.timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,17 +424,17 @@ void RecordAction::OpenNewDb(uint64_t start_timestamp) {
|
|||||||
|
|
||||||
std::string cur_db_file_name = bag_base_name_ + "_" + std::to_string(cur_db_file_index_) + ".db3";
|
std::string cur_db_file_name = bag_base_name_ + "_" + std::to_string(cur_db_file_index_) + ".db3";
|
||||||
|
|
||||||
auto db_file_path = (real_bag_path_ / cur_db_file_name).string();
|
cur_db_file_path_ = (real_bag_path_ / cur_db_file_name).string();
|
||||||
|
|
||||||
++cur_db_file_index_;
|
++cur_db_file_index_;
|
||||||
|
|
||||||
// open db
|
// open db
|
||||||
int ret = sqlite3_open(db_file_path.c_str(), &db_);
|
int ret = sqlite3_open(cur_db_file_path_.c_str(), &db_);
|
||||||
AIMRT_CHECK_ERROR_THROW(ret == SQLITE_OK,
|
AIMRT_CHECK_ERROR_THROW(ret == SQLITE_OK,
|
||||||
"Sqlite3 open db file failed, path: {}, ret: {}, error info: {}",
|
"Sqlite3 open db file failed, path: {}, ret: {}, error info: {}",
|
||||||
db_file_path, ret, sqlite3_errmsg(db_));
|
cur_db_file_path_, ret, sqlite3_errmsg(db_));
|
||||||
|
|
||||||
AIMRT_TRACE("Open new db, path: {}", db_file_path);
|
AIMRT_TRACE("Open new db, path: {}", cur_db_file_path_);
|
||||||
|
|
||||||
// sqlite3_exec(db_, "PRAGMA synchronous = OFF; ", 0, 0, 0);
|
// sqlite3_exec(db_, "PRAGMA synchronous = OFF; ", 0, 0, 0);
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ class RecordAction {
|
|||||||
|
|
||||||
void OpenNewDb(uint64_t start_timestamp);
|
void OpenNewDb(uint64_t start_timestamp);
|
||||||
void CloseDb();
|
void CloseDb();
|
||||||
|
size_t GetDbFileSize() const;
|
||||||
|
|
||||||
enum class State : uint32_t {
|
enum class State : uint32_t {
|
||||||
kPreInit,
|
kPreInit,
|
||||||
@ -101,12 +102,14 @@ class RecordAction {
|
|||||||
|
|
||||||
size_t max_bag_size_ = 0;
|
size_t max_bag_size_ = 0;
|
||||||
size_t cur_data_size_ = 0;
|
size_t cur_data_size_ = 0;
|
||||||
|
double estimated_overhead_ = 1.5;
|
||||||
|
|
||||||
size_t cur_exec_count_ = 0;
|
size_t cur_exec_count_ = 0;
|
||||||
std::deque<std::shared_ptr<aimrt::util::BufferArrayView>> buf_array_view_cache_;
|
std::deque<std::shared_ptr<aimrt::util::BufferArrayView>> buf_array_view_cache_;
|
||||||
std::deque<std::vector<char>> buf_cache_;
|
std::deque<std::vector<char>> buf_cache_;
|
||||||
|
|
||||||
std::filesystem::path real_bag_path_;
|
std::filesystem::path real_bag_path_;
|
||||||
|
std::string cur_db_file_path_;
|
||||||
std::string bag_base_name_;
|
std::string bag_base_name_;
|
||||||
|
|
||||||
uint32_t cur_db_file_index_ = 0;
|
uint32_t cur_db_file_index_ = 0;
|
||||||
|
@ -221,7 +221,7 @@ bool Ros2ChannelBackend::RegisterPublishType(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AIMRT_INFO("ros backend register publish type for topic '{}' success.", info.topic_name);
|
AIMRT_INFO("ros2 backend register publish type for topic '{}' success.", info.topic_name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -236,7 +236,7 @@ bool Ros2ChannelBackend::RegisterPublishType(
|
|||||||
ros2_node_ptr_->create_publisher<ros2_plugin_proto::msg::RosMsgWrapper>(real_ros2_topic_name, qos));
|
ros2_node_ptr_->create_publisher<ros2_plugin_proto::msg::RosMsgWrapper>(real_ros2_topic_name, qos));
|
||||||
}
|
}
|
||||||
|
|
||||||
AIMRT_INFO("ros backend register publish type for topic '{}' success, real ros2 topic name is '{}'.",
|
AIMRT_INFO("ros2 backend register publish type for topic '{}' success, real ros2 topic name is '{}'.",
|
||||||
info.topic_name, real_ros2_topic_name);
|
info.topic_name, real_ros2_topic_name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -56,7 +56,10 @@ bool Ros2Plugin::Initialize(runtime::core::AimRTCore* core_ptr) noexcept {
|
|||||||
|
|
||||||
rclcpp::InitOptions op;
|
rclcpp::InitOptions op;
|
||||||
op.shutdown_on_signal = false;
|
op.shutdown_on_signal = false;
|
||||||
rclcpp::init(0, nullptr, op);
|
|
||||||
|
if (!rclcpp::ok()) {
|
||||||
|
rclcpp::init(0, nullptr, op);
|
||||||
|
}
|
||||||
|
|
||||||
ros2_node_ptr_ = std::make_shared<rclcpp::Node>(options_.node_name);
|
ros2_node_ptr_ = std::make_shared<rclcpp::Node>(options_.node_name);
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
set_namespace()
|
set_namespace()
|
||||||
|
|
||||||
add_subdirectory(common)
|
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(main)
|
add_subdirectory(main)
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
# Copyright (c) 2023, AgiBot Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
|
|
||||||
set_namespace()
|
|
||||||
|
|
||||||
add_subdirectory(net)
|
|
@ -35,7 +35,7 @@ target_include_directories(
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
${CUR_TARGET_NAME}
|
${CUR_TARGET_NAME}
|
||||||
PUBLIC ${CMAKE_DL_LIBS}
|
PUBLIC ${CMAKE_DL_LIBS}
|
||||||
Boost::asio
|
asio::asio
|
||||||
yaml-cpp::yaml-cpp
|
yaml-cpp::yaml-cpp
|
||||||
TBB::tbb
|
TBB::tbb
|
||||||
aimrt::interface::aimrt_module_cpp_interface
|
aimrt::interface::aimrt_module_cpp_interface
|
||||||
|
@ -356,7 +356,7 @@ void ChannelManager::RegisterSubscribeFilter(std::string_view name, FrameworkAsy
|
|||||||
subscribe_filter_manager_.RegisterFilter(name, std::move(filter));
|
subscribe_filter_manager_.RegisterFilter(name, std::move(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelManager::SetPassedContextMetaKeys(const std::unordered_set<std::string>& keys) {
|
void ChannelManager::AddPassedContextMetaKeys(const std::unordered_set<std::string>& keys) {
|
||||||
AIMRT_CHECK_ERROR_THROW(
|
AIMRT_CHECK_ERROR_THROW(
|
||||||
state_.load() == State::kPreInit,
|
state_.load() == State::kPreInit,
|
||||||
"Method can only be called when state is 'PreInit'.");
|
"Method can only be called when state is 'PreInit'.");
|
||||||
|
@ -80,7 +80,7 @@ class ChannelManager {
|
|||||||
void RegisterPublishFilter(std::string_view name, FrameworkAsyncChannelFilter&& filter);
|
void RegisterPublishFilter(std::string_view name, FrameworkAsyncChannelFilter&& filter);
|
||||||
void RegisterSubscribeFilter(std::string_view name, FrameworkAsyncChannelFilter&& filter);
|
void RegisterSubscribeFilter(std::string_view name, FrameworkAsyncChannelFilter&& filter);
|
||||||
|
|
||||||
void SetPassedContextMetaKeys(const std::unordered_set<std::string>& keys);
|
void AddPassedContextMetaKeys(const std::unordered_set<std::string>& keys);
|
||||||
|
|
||||||
bool Subscribe(SubscribeWrapper&& wrapper) {
|
bool Subscribe(SubscribeWrapper&& wrapper) {
|
||||||
return channel_backend_manager_.Subscribe(std::move(wrapper));
|
return channel_backend_manager_.Subscribe(std::move(wrapper));
|
||||||
|
@ -61,7 +61,7 @@ void AsioStrandExecutor::Initialize(std::string_view name,
|
|||||||
io_ptr,
|
io_ptr,
|
||||||
"Invalide bind asio thread executor name, can not get asio io context.");
|
"Invalide bind asio thread executor name, can not get asio io context.");
|
||||||
|
|
||||||
strand_ptr_ = std::make_unique<Strand>(boost::asio::make_strand(*io_ptr));
|
strand_ptr_ = std::make_unique<Strand>(asio::make_strand(*io_ptr));
|
||||||
|
|
||||||
options_node = options_;
|
options_node = options_;
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ void AsioStrandExecutor::Shutdown() {
|
|||||||
|
|
||||||
void AsioStrandExecutor::Execute(aimrt::executor::Task&& task) noexcept {
|
void AsioStrandExecutor::Execute(aimrt::executor::Task&& task) noexcept {
|
||||||
try {
|
try {
|
||||||
boost::asio::post(*strand_ptr_, std::move(task));
|
asio::post(*strand_ptr_, std::move(task));
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
AIMRT_ERROR("{}", e.what());
|
AIMRT_ERROR("{}", e.what());
|
||||||
}
|
}
|
||||||
@ -88,10 +88,10 @@ void AsioStrandExecutor::Execute(aimrt::executor::Task&& task) noexcept {
|
|||||||
void AsioStrandExecutor::ExecuteAt(
|
void AsioStrandExecutor::ExecuteAt(
|
||||||
std::chrono::system_clock::time_point tp, aimrt::executor::Task&& task) noexcept {
|
std::chrono::system_clock::time_point tp, aimrt::executor::Task&& task) noexcept {
|
||||||
try {
|
try {
|
||||||
auto timer_ptr = std::make_shared<boost::asio::system_timer>(*strand_ptr_);
|
auto timer_ptr = std::make_shared<asio::system_timer>(*strand_ptr_);
|
||||||
timer_ptr->expires_at(tp);
|
timer_ptr->expires_at(tp);
|
||||||
timer_ptr->async_wait([this, timer_ptr,
|
timer_ptr->async_wait([this, timer_ptr,
|
||||||
task{std::move(task)}](boost::system::error_code ec) {
|
task{std::move(task)}](asio::error_code ec) {
|
||||||
if (ec) [[unlikely]] {
|
if (ec) [[unlikely]] {
|
||||||
AIMRT_ERROR("Asio strand executor '{}' timer get err, code '{}', msg: {}",
|
AIMRT_ERROR("Asio strand executor '{}' timer get err, code '{}', msg: {}",
|
||||||
Name(), ec.value(), ec.message());
|
Name(), ec.value(), ec.message());
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "yaml-cpp/yaml.h"
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include "asio.hpp"
|
||||||
|
|
||||||
namespace aimrt::runtime::core::executor {
|
namespace aimrt::runtime::core::executor {
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ class AsioStrandExecutor : public ExecutorBase {
|
|||||||
kShutdown,
|
kShutdown,
|
||||||
};
|
};
|
||||||
|
|
||||||
using GetAsioHandle = std::function<boost::asio::io_context*(std::string_view)>;
|
using GetAsioHandle = std::function<asio::io_context*(std::string_view)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AsioStrandExecutor()
|
AsioStrandExecutor()
|
||||||
@ -66,7 +66,7 @@ class AsioStrandExecutor : public ExecutorBase {
|
|||||||
|
|
||||||
GetAsioHandle get_asio_handle_;
|
GetAsioHandle get_asio_handle_;
|
||||||
|
|
||||||
using Strand = boost::asio::strand<boost::asio::io_context::executor_type>;
|
using Strand = asio::strand<asio::io_context::executor_type>;
|
||||||
std::unique_ptr<Strand> strand_ptr_;
|
std::unique_ptr<Strand> strand_ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,9 +63,9 @@ void AsioThreadExecutor::Initialize(std::string_view name,
|
|||||||
options_.thread_num > 0,
|
options_.thread_num > 0,
|
||||||
"Invalide asio thread executor options, thread num is zero.");
|
"Invalide asio thread executor options, thread num is zero.");
|
||||||
|
|
||||||
io_ptr_ = std::make_unique<boost::asio::io_context>(options_.thread_num);
|
io_ptr_ = std::make_unique<asio::io_context>(options_.thread_num);
|
||||||
work_guard_ptr_ = std::make_unique<
|
work_guard_ptr_ = std::make_unique<
|
||||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(
|
asio::executor_work_guard<asio::io_context::executor_type>>(
|
||||||
io_ptr_->get_executor());
|
io_ptr_->get_executor());
|
||||||
|
|
||||||
thread_id_vec_.resize(options_.thread_num);
|
thread_id_vec_.resize(options_.thread_num);
|
||||||
@ -156,7 +156,7 @@ void AsioThreadExecutor::Execute(aimrt::executor::Task&& task) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boost::asio::post(*io_ptr_, std::move(task));
|
asio::post(*io_ptr_, std::move(task));
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
fprintf(stderr, "Asio thread executor '%s' execute Task get exception: %s\n", name_.c_str(), e.what());
|
fprintf(stderr, "Asio thread executor '%s' execute Task get exception: %s\n", name_.c_str(), e.what());
|
||||||
}
|
}
|
||||||
@ -188,10 +188,10 @@ void AsioThreadExecutor::ExecuteAt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto timer_ptr = std::make_shared<boost::asio::system_timer>(*io_ptr_);
|
auto timer_ptr = std::make_shared<asio::system_timer>(*io_ptr_);
|
||||||
timer_ptr->expires_at(tp);
|
timer_ptr->expires_at(tp);
|
||||||
timer_ptr->async_wait([this, timer_ptr,
|
timer_ptr->async_wait([this, timer_ptr,
|
||||||
task{std::move(task)}](boost::system::error_code ec) {
|
task{std::move(task)}](asio::error_code ec) {
|
||||||
if (ec) [[unlikely]] {
|
if (ec) [[unlikely]] {
|
||||||
AIMRT_ERROR("Asio thread executor '{}' timer get err, code '{}', msg: {}",
|
AIMRT_ERROR("Asio thread executor '{}' timer get err, code '{}', msg: {}",
|
||||||
Name(), ec.value(), ec.message());
|
Name(), ec.value(), ec.message());
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include "yaml-cpp/yaml.h"
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include "asio.hpp"
|
||||||
|
|
||||||
namespace aimrt::runtime::core::executor {
|
namespace aimrt::runtime::core::executor {
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class AsioThreadExecutor : public ExecutorBase {
|
|||||||
void SetLogger(const std::shared_ptr<aimrt::common::util::LoggerWrapper>& logger_ptr) { logger_ptr_ = logger_ptr; }
|
void SetLogger(const std::shared_ptr<aimrt::common::util::LoggerWrapper>& logger_ptr) { logger_ptr_ = logger_ptr; }
|
||||||
const aimrt::common::util::LoggerWrapper& GetLogger() const { return *logger_ptr_; }
|
const aimrt::common::util::LoggerWrapper& GetLogger() const { return *logger_ptr_; }
|
||||||
|
|
||||||
boost::asio::io_context* IOCTX() { return io_ptr_.get(); }
|
asio::io_context* IOCTX() { return io_ptr_.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
@ -78,9 +78,9 @@ class AsioThreadExecutor : public ExecutorBase {
|
|||||||
uint32_t queue_warn_threshold_;
|
uint32_t queue_warn_threshold_;
|
||||||
std::atomic_uint32_t queue_task_num_ = 0;
|
std::atomic_uint32_t queue_task_num_ = 0;
|
||||||
|
|
||||||
std::unique_ptr<boost::asio::io_context> io_ptr_;
|
std::unique_ptr<asio::io_context> io_ptr_;
|
||||||
std::unique_ptr<
|
std::unique_ptr<
|
||||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>
|
asio::executor_work_guard<asio::io_context::executor_type>>
|
||||||
work_guard_ptr_;
|
work_guard_ptr_;
|
||||||
|
|
||||||
std::vector<std::thread::id> thread_id_vec_;
|
std::vector<std::thread::id> thread_id_vec_;
|
||||||
|
@ -177,7 +177,7 @@ void ExecutorManager::RegisterAsioExecutorGenFunc() {
|
|||||||
auto ptr = std::make_unique<AsioStrandExecutor>();
|
auto ptr = std::make_unique<AsioStrandExecutor>();
|
||||||
ptr->SetLogger(logger_ptr_);
|
ptr->SetLogger(logger_ptr_);
|
||||||
ptr->RegisterGetAsioHandle(
|
ptr->RegisterGetAsioHandle(
|
||||||
[this](std::string_view name) -> boost::asio::io_context* {
|
[this](std::string_view name) -> asio::io_context* {
|
||||||
auto itr = std::find_if(
|
auto itr = std::find_if(
|
||||||
executor_vec_.begin(),
|
executor_vec_.begin(),
|
||||||
executor_vec_.end(),
|
executor_vec_.end(),
|
||||||
|
@ -23,7 +23,7 @@ thread_bind_cpu: [0]
|
|||||||
[&is_executed]() mutable { is_executed = true; });
|
[&is_executed]() mutable { is_executed = true; });
|
||||||
|
|
||||||
guard_thread_executor.Execute(std::ref(task));
|
guard_thread_executor.Execute(std::ref(task));
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
EXPECT_TRUE(is_executed);
|
EXPECT_TRUE(is_executed);
|
||||||
|
|
||||||
guard_thread_executor.Shutdown();
|
guard_thread_executor.Shutdown();
|
||||||
|
@ -24,7 +24,7 @@ thread_bind_cpu: [0]
|
|||||||
[&is_executed]() mutable { is_executed = true; });
|
[&is_executed]() mutable { is_executed = true; });
|
||||||
|
|
||||||
simple_thread_executor.Execute(std::ref(task));
|
simple_thread_executor.Execute(std::ref(task));
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
EXPECT_TRUE(is_executed);
|
EXPECT_TRUE(is_executed);
|
||||||
|
|
||||||
simple_thread_executor.Shutdown();
|
simple_thread_executor.Shutdown();
|
||||||
|
@ -347,7 +347,7 @@ void RpcManager::RegisterServerFilter(std::string_view name, FrameworkAsyncRpcFi
|
|||||||
server_filter_manager_.RegisterFilter(name, std::move(filter));
|
server_filter_manager_.RegisterFilter(name, std::move(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RpcManager::SetPassedContextMetaKeys(const std::unordered_set<std::string>& keys) {
|
void RpcManager::AddPassedContextMetaKeys(const std::unordered_set<std::string>& keys) {
|
||||||
AIMRT_CHECK_ERROR_THROW(
|
AIMRT_CHECK_ERROR_THROW(
|
||||||
state_.load() == State::kPreInit,
|
state_.load() == State::kPreInit,
|
||||||
"Method can only be called when state is 'PreInit'.");
|
"Method can only be called when state is 'PreInit'.");
|
||||||
|
@ -83,7 +83,7 @@ class RpcManager {
|
|||||||
void RegisterClientFilter(std::string_view name, FrameworkAsyncRpcFilter&& filter);
|
void RegisterClientFilter(std::string_view name, FrameworkAsyncRpcFilter&& filter);
|
||||||
void RegisterServerFilter(std::string_view name, FrameworkAsyncRpcFilter&& filter);
|
void RegisterServerFilter(std::string_view name, FrameworkAsyncRpcFilter&& filter);
|
||||||
|
|
||||||
void SetPassedContextMetaKeys(const std::unordered_set<std::string>& keys);
|
void AddPassedContextMetaKeys(const std::unordered_set<std::string>& keys);
|
||||||
|
|
||||||
const RpcRegistry* GetRpcRegistry() const;
|
const RpcRegistry* GetRpcRegistry() const;
|
||||||
const std::vector<RpcBackendBase*>& GetUsedRpcBackend() const;
|
const std::vector<RpcBackendBase*>& GetUsedRpcBackend() const;
|
||||||
|
@ -33,6 +33,10 @@ target_link_libraries(
|
|||||||
PRIVATE gflags::gflags
|
PRIVATE gflags::gflags
|
||||||
aimrt::runtime::core)
|
aimrt::runtime::core)
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||||
|
set_target_properties(${CUR_TARGET_NAME} PROPERTIES LINK_FLAGS "-s")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Add -Werror option
|
# Add -Werror option
|
||||||
include(AddWerror)
|
include(AddWerror)
|
||||||
add_werror(${CUR_TARGET_NAME})
|
add_werror(${CUR_TARGET_NAME})
|
||||||
|
@ -87,8 +87,7 @@ int32_t main(int32_t argc, char** argv) {
|
|||||||
signal(SIGTERM, SignalHandler);
|
signal(SIGTERM, SignalHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "AimRT start." << std::endl;
|
std::cout << "AimRT start, version: " << util::GetAimRTVersion() << std::endl;
|
||||||
PrintVersion();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AimRTCore core;
|
AimRTCore core;
|
||||||
|
@ -32,7 +32,7 @@ inline void PyPublish(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void ExportPublisherRef(pybind11::object m) {
|
inline void ExportPublisherRef(pybind11::object m) {
|
||||||
using namespace aimrt::channel;
|
using aimrt::channel::PublisherRef;
|
||||||
|
|
||||||
pybind11::class_<PublisherRef>(std::move(m), "PublisherRef")
|
pybind11::class_<PublisherRef>(std::move(m), "PublisherRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
@ -41,7 +41,10 @@ inline void ExportPublisherRef(pybind11::object m) {
|
|||||||
.def("Publish", &PyPublish);
|
.def("Publish", &PyPublish);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline pybind11::bytes channel_empty_py_bytes;
|
inline const pybind11::bytes& GetChannelEmptyPyBytes() {
|
||||||
|
static const pybind11::bytes kChannelEmptyPyBytes = pybind11::bytes("");
|
||||||
|
return kChannelEmptyPyBytes;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool PySubscribe(
|
inline bool PySubscribe(
|
||||||
aimrt::channel::SubscriberRef& subscriber_ref,
|
aimrt::channel::SubscriberRef& subscriber_ref,
|
||||||
@ -62,7 +65,7 @@ inline bool PySubscribe(
|
|||||||
auto ctx_ref = aimrt::channel::ContextRef(ctx_ptr);
|
auto ctx_ref = aimrt::channel::ContextRef(ctx_ptr);
|
||||||
|
|
||||||
if (msg_buf.empty()) [[unlikely]] {
|
if (msg_buf.empty()) [[unlikely]] {
|
||||||
callback(ctx_ref.GetSerializationType(), channel_empty_py_bytes);
|
callback(ctx_ref.GetSerializationType(), GetChannelEmptyPyBytes());
|
||||||
} else {
|
} else {
|
||||||
auto msg_buf_bytes = pybind11::bytes(msg_buf);
|
auto msg_buf_bytes = pybind11::bytes(msg_buf);
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ inline bool PySubscribe(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void ExportSubscriberRef(pybind11::object m) {
|
inline void ExportSubscriberRef(pybind11::object m) {
|
||||||
using namespace aimrt::channel;
|
using aimrt::channel::SubscriberRef;
|
||||||
|
|
||||||
pybind11::class_<SubscriberRef>(std::move(m), "SubscriberRef")
|
pybind11::class_<SubscriberRef>(std::move(m), "SubscriberRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
@ -87,7 +90,7 @@ inline void ExportSubscriberRef(pybind11::object m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void ExportChannelHandleRef(pybind11::object m) {
|
inline void ExportChannelHandleRef(pybind11::object m) {
|
||||||
using namespace aimrt::channel;
|
using aimrt::channel::ChannelHandleRef;
|
||||||
|
|
||||||
pybind11::class_<ChannelHandleRef>(std::move(m), "ChannelHandleRef")
|
pybind11::class_<ChannelHandleRef>(std::move(m), "ChannelHandleRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace aimrt::runtime::python_runtime {
|
namespace aimrt::runtime::python_runtime {
|
||||||
|
|
||||||
inline void ExportConfiguratorRef(pybind11::object m) {
|
inline void ExportConfiguratorRef(pybind11::object m) {
|
||||||
using namespace aimrt::configurator;
|
using aimrt::configurator::ConfiguratorRef;
|
||||||
|
|
||||||
pybind11::class_<ConfiguratorRef>(std::move(m), "ConfiguratorRef")
|
pybind11::class_<ConfiguratorRef>(std::move(m), "ConfiguratorRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
namespace aimrt::runtime::python_runtime {
|
namespace aimrt::runtime::python_runtime {
|
||||||
|
|
||||||
inline void ExportModuleInfo(pybind11::object m) {
|
inline void ExportModuleInfo(pybind11::object m) {
|
||||||
using namespace aimrt;
|
|
||||||
|
|
||||||
pybind11::class_<ModuleInfo>(std::move(m), "ModuleInfo")
|
pybind11::class_<ModuleInfo>(std::move(m), "ModuleInfo")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
.def_readwrite("name", &ModuleInfo::name)
|
.def_readwrite("name", &ModuleInfo::name)
|
||||||
@ -26,8 +24,6 @@ inline void ExportModuleInfo(pybind11::object m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void ExportCoreRef(pybind11::object m) {
|
inline void ExportCoreRef(pybind11::object m) {
|
||||||
using namespace aimrt;
|
|
||||||
|
|
||||||
pybind11::class_<CoreRef>(std::move(m), "CoreRef")
|
pybind11::class_<CoreRef>(std::move(m), "CoreRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
.def("__bool__", &CoreRef::operator bool)
|
.def("__bool__", &CoreRef::operator bool)
|
||||||
@ -36,7 +32,8 @@ inline void ExportCoreRef(pybind11::object m) {
|
|||||||
.def("GetLogger", &CoreRef::GetLogger)
|
.def("GetLogger", &CoreRef::GetLogger)
|
||||||
.def("GetExecutorManager", &CoreRef::GetExecutorManager)
|
.def("GetExecutorManager", &CoreRef::GetExecutorManager)
|
||||||
.def("GetRpcHandle", &CoreRef::GetRpcHandle)
|
.def("GetRpcHandle", &CoreRef::GetRpcHandle)
|
||||||
.def("GetChannelHandle", &CoreRef::GetChannelHandle);
|
.def("GetChannelHandle", &CoreRef::GetChannelHandle)
|
||||||
|
.def("GetParameterHandle", &CoreRef::GetParameterHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aimrt::runtime::python_runtime
|
} // namespace aimrt::runtime::python_runtime
|
@ -13,7 +13,7 @@
|
|||||||
namespace aimrt::runtime::python_runtime {
|
namespace aimrt::runtime::python_runtime {
|
||||||
|
|
||||||
inline void ExportCoreOptions(pybind11::object m) {
|
inline void ExportCoreOptions(pybind11::object m) {
|
||||||
using namespace aimrt::runtime::core;
|
using aimrt::runtime::core::AimRTCore;
|
||||||
|
|
||||||
pybind11::class_<AimRTCore::Options>(std::move(m), "CoreOptions")
|
pybind11::class_<AimRTCore::Options>(std::move(m), "CoreOptions")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
@ -21,7 +21,7 @@ inline void ExportCoreOptions(pybind11::object m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void PyCoreStart(aimrt::runtime::core::AimRTCore& core) {
|
inline void PyCoreStart(aimrt::runtime::core::AimRTCore& core) {
|
||||||
// 阻塞之前需要释放gil锁
|
// Release GIL before blocking
|
||||||
pybind11::gil_scoped_release release;
|
pybind11::gil_scoped_release release;
|
||||||
core.Start();
|
core.Start();
|
||||||
pybind11::gil_scoped_acquire acquire;
|
pybind11::gil_scoped_acquire acquire;
|
||||||
@ -39,7 +39,7 @@ inline aimrt::CoreRef PyCoreCreateModule(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void ExportCore(pybind11::object m) {
|
inline void ExportCore(pybind11::object m) {
|
||||||
using namespace aimrt::runtime::core;
|
using aimrt::runtime::core::AimRTCore;
|
||||||
|
|
||||||
pybind11::class_<AimRTCore>(std::move(m), "Core")
|
pybind11::class_<AimRTCore>(std::move(m), "Core")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
namespace aimrt::runtime::python_runtime {
|
namespace aimrt::runtime::python_runtime {
|
||||||
|
|
||||||
inline void ExportExecutorManagerRef(pybind11::object m) {
|
inline void ExportExecutorManagerRef(pybind11::object m) {
|
||||||
using namespace aimrt::executor;
|
using aimrt::executor::ExecutorManagerRef;
|
||||||
|
|
||||||
pybind11::class_<ExecutorManagerRef>(std::move(m), "ExecutorManagerRef")
|
pybind11::class_<ExecutorManagerRef>(std::move(m), "ExecutorManagerRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
@ -43,7 +43,7 @@ inline void PyExecutorRefExecuteAfterWrapper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void ExportExecutorRef(pybind11::object m) {
|
inline void ExportExecutorRef(pybind11::object m) {
|
||||||
using namespace aimrt::executor;
|
using aimrt::executor::ExecutorRef;
|
||||||
|
|
||||||
pybind11::class_<ExecutorRef>(std::move(m), "ExecutorRef")
|
pybind11::class_<ExecutorRef>(std::move(m), "ExecutorRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace aimrt::runtime::python_runtime {
|
namespace aimrt::runtime::python_runtime {
|
||||||
|
|
||||||
inline void ExportLoggerRef(pybind11::object m) {
|
inline void ExportLoggerRef(pybind11::object m) {
|
||||||
using namespace aimrt::logger;
|
using aimrt::logger::LoggerRef;
|
||||||
|
|
||||||
pybind11::class_<LoggerRef>(std::move(m), "LoggerRef")
|
pybind11::class_<LoggerRef>(std::move(m), "LoggerRef")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
|
@ -33,8 +33,6 @@ class PyModuleBaseAdapter : public ModuleBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline void ExportModuleBase(pybind11::object m) {
|
inline void ExportModuleBase(pybind11::object m) {
|
||||||
using namespace aimrt;
|
|
||||||
|
|
||||||
pybind11::class_<ModuleBase, PyModuleBaseAdapter, std::shared_ptr<ModuleBase>>(std::move(m), "ModuleBase")
|
pybind11::class_<ModuleBase, PyModuleBaseAdapter, std::shared_ptr<ModuleBase>>(std::move(m), "ModuleBase")
|
||||||
.def(pybind11::init<>())
|
.def(pybind11::init<>())
|
||||||
.def("Info", &ModuleBase::Info)
|
.def("Info", &ModuleBase::Info)
|
||||||
|
22
src/runtime/python_runtime/export_parameter.h
Normal file
22
src/runtime/python_runtime/export_parameter.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) 2023, AgiBot Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "aimrt_module_cpp_interface/parameter/parameter_handle.h"
|
||||||
|
|
||||||
|
#include "pybind11/pybind11.h"
|
||||||
|
|
||||||
|
namespace aimrt::runtime::python_runtime {
|
||||||
|
|
||||||
|
inline void ExportParameter(pybind11::object m) {
|
||||||
|
using aimrt::parameter::ParameterHandleRef;
|
||||||
|
|
||||||
|
pybind11::class_<ParameterHandleRef>(std::move(m), "ParameterHandleRef")
|
||||||
|
.def(pybind11::init<>())
|
||||||
|
.def("__bool__", &ParameterHandleRef::operator bool)
|
||||||
|
.def("GetParameter", &ParameterHandleRef::GetParameter)
|
||||||
|
.def("SetParameter", &ParameterHandleRef::SetParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aimrt::runtime::python_runtime
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user