feat: 添加CM3/4/7的硬件与软件浮点单元构建矩阵,变更api接口为dr_* #21
@@ -0,0 +1,34 @@
|
|||||||
|
name: CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
host:
|
||||||
|
runs-on: ubuntu-builder
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Host build + tests
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build-host \
|
||||||
|
-DBUILD_TESTING=ON -DBUILD_EXAMPLES=ON
|
||||||
|
cmake --build build-host
|
||||||
|
ctest --test-dir build-host --output-on-failure
|
||||||
|
|
||||||
|
cortex-m:
|
||||||
|
runs-on: ubuntu-builder
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install ARM GCC
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y gcc-arm-none-eabi
|
||||||
|
|
||||||
|
- name: Cortex-M compile matrix (DR_COMPILE_CHECK)
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build-matrix -DDR_COMPILE_CHECK=ON
|
||||||
|
cmake --build build-matrix --parallel $(nproc)
|
||||||
@@ -11,16 +11,67 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Verify merge commit
|
# ── 自动标签:从合并进来的 PR body 提取 v*.*.* ──
|
||||||
|
- name: Auto-tag from merged PR
|
||||||
|
id: autotag
|
||||||
run: |
|
run: |
|
||||||
PARENTS=$(git log --format="%P" -1 | wc -w)
|
set -e
|
||||||
[ "$PARENTS" -ge 2 ] || exit 78
|
|
||||||
|
|
||||||
|
# 已有标签 → 跳过
|
||||||
|
EXISTING=$(git tag --points-at HEAD | grep '^v' | head -n1)
|
||||||
|
if [ -n "$EXISTING" ]; then
|
||||||
|
echo "Tag $EXISTING already exists"
|
||||||
|
echo "tag=$EXISTING" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 非 merge commit → 跳过(直接 push 不处理)
|
||||||
|
PARENTS=$(git log --format="%P" -1 | wc -w)
|
||||||
|
if [ "$PARENTS" -lt 2 ]; then
|
||||||
|
echo "Not a merge commit, skip auto-tag"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 从 merge commit message 提取 PR 号
|
||||||
|
COMMIT_MSG=$(git log --format="%B" -1)
|
||||||
|
PR_NUM=$(echo "$COMMIT_MSG" | grep -oP '#\K\d+' | head -1)
|
||||||
|
if [ -z "$PR_NUM" ]; then
|
||||||
|
echo "No PR number found in merge message"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Merge commit for PR #$PR_NUM"
|
||||||
|
|
||||||
|
# 通过 Gitea API 获取 PR body,提取版本号
|
||||||
|
API="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/pulls/${PR_NUM}"
|
||||||
|
TOKEN="${{ gitea.token }}"
|
||||||
|
PR_BODY=$(curl -s -H "Authorization: token ${TOKEN}" "${API}" | \
|
||||||
|
python3 -c "import sys,json,re;pr=json.load(sys.stdin);body=pr.get('body','') or '';m=re.search(r'v\d+\.\d+\.\d+',body);print(m.group() if m else '')")
|
||||||
|
|
||||||
|
if [ -z "$PR_BODY" ]; then
|
||||||
|
echo "No version pattern v*.*.* found in PR body"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION="$PR_BODY"
|
||||||
|
echo "Found version: $VERSION"
|
||||||
|
|
||||||
|
# 创建本地标签
|
||||||
|
git config user.email "ci@datarouter"
|
||||||
|
git config user.name "DataRouter CI"
|
||||||
|
git tag -a "$VERSION" -m "Release $VERSION"
|
||||||
|
echo "Created local tag: $VERSION"
|
||||||
|
|
||||||
|
# 推送到远端(不会触发本 workflow — 仅匹配 branches: [main])
|
||||||
|
git push "https://${TOKEN}@${{ gitea.server_url }}/${{ gitea.repository }}" "$VERSION"
|
||||||
|
echo "Pushed tag: $VERSION"
|
||||||
|
echo "tag=$VERSION" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# ── 读取标签(已有标签 / auto-tag 创建的标签)──
|
||||||
- name: Read tag from HEAD
|
- name: Read tag from HEAD
|
||||||
id: tag
|
id: tag
|
||||||
run: |
|
run: |
|
||||||
TAG=$(git tag --points-at HEAD | grep '^v' | head -n1)
|
TAG=$(git tag --points-at HEAD | grep '^v' | head -n1)
|
||||||
[ -n "$TAG" ] || exit 78
|
[ -n "$TAG" ] || { echo "No version tag on HEAD"; exit 78; }
|
||||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Install cross-compilers
|
- name: Install cross-compilers
|
||||||
@@ -51,6 +102,12 @@ jobs:
|
|||||||
cmake --install "build-$name" --prefix "dist/$pkg"
|
cmake --install "build-$name" --prefix "dist/$pkg"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
- name: Cortex-M compile matrix
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build-cortex-m -DDR_COMPILE_CHECK=ON
|
||||||
|
cmake --build build-cortex-m --parallel $(nproc)
|
||||||
|
echo "--- Cortex-M build matrix: all variants passed ---"
|
||||||
|
|
||||||
- name: Create release & upload assets
|
- name: Create release & upload assets
|
||||||
run: |
|
run: |
|
||||||
TAG="${{ steps.tag.outputs.tag }}"
|
TAG="${{ steps.tag.outputs.tag }}"
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### ⚠ Breaking Changes
|
||||||
|
|
||||||
|
- **API 前缀重命名**:所有 `datarouter_*` / `DATAROUTER_*` 改为 `dr_*` / `DR_*`
|
||||||
|
- `datarouter_init()` → `dr_init()`
|
||||||
|
- `datarouter_port_create()` → `dr_port_create()`
|
||||||
|
- `datarouter_send_<id>()` → `dr_send_<id>()`
|
||||||
|
- `datarouter_on_recv_<id>()` → `dr_on_recv_<id>()`
|
||||||
|
- `DATAROUTER_SEND_sensor` → `DR_SEND_sensor`
|
||||||
|
- `datarouter_port_t` → `dr_port_t`
|
||||||
|
- 配置宏 `DATAROUTER_SEND(...)` / `DATAROUTER_RECV(...)` → `DR_SEND(...)` / `DR_RECV(...)`
|
||||||
|
- **发送函数不再接收 port_id**:`dr_send_<id>(data, len)` 自动广播到所有 send_type 匹配的端口
|
||||||
|
- **端口移除 `recv_type`**:端口只保留 `send_type` + handler 列表,接收侧由用户自行调用 `dr_on_recv_<id>()`
|
||||||
|
|
||||||
|
### 🚀 新功能
|
||||||
|
|
||||||
|
- **自动广播路由**:调用 `dr_send_<id>(data, len)` 时遍历所有端口,自动匹配 `send_type`,逐一调用 handler
|
||||||
|
- **外部配置覆盖**:`datarouter.h` 通过 `__has_include(<datarouter_config.h>)` 优先加载用户配置,找不到时回退到库默认配置
|
||||||
|
- **配置模板**:新增 `datarouter_config_template.h` 供用户快速自定义
|
||||||
|
- **CMake Presets**:新增 `CMakePresets.json`,覆盖 7 种构建配置
|
||||||
|
- **Cortex-M 编译矩阵**:`DR_COMPILE_CHECK=ON` 自动检测 `arm-none-eabi-gcc`,验证 CM3 / CM4(soft/hard) / CM7(soft/hard-sp/hard-dp) 6 个变体的编译兼容性
|
||||||
|
- **嵌入式源文件直用模式**:`DR_SOURCE_ONLY=ON` 只暴露源码路径,用户将 `datarouter.c` 加入自身 target 以继承全部编译标志,消除 VFP/Thumb ABI 不匹配
|
||||||
|
- **Gitea CI 工作流**:新增 `.gitea/workflows/ci.yml`,PR/推送时执行 host 测试 + Cortex-M 编译矩阵
|
||||||
|
- **Release 工作流更新**:`.gitea/workflows/release.yml` 新增 Cortex-M compile matrix 步骤
|
||||||
|
|
||||||
|
### ✨ 增强
|
||||||
|
|
||||||
|
- 支持一个端口注册多个 handler(默认上限 4),发送时逐一调用
|
||||||
|
- 运行时通过 `dr_port_remove_handler()` / `dr_port_clear_handlers()` 动态改变路由
|
||||||
|
- 发送能力和接收能力分开声明,按需组合
|
||||||
|
|
||||||
|
### 📚 文档
|
||||||
|
|
||||||
|
- 新增 `DESIGN.md`(含 8 幅 PlantUML 架构图)
|
||||||
|
- 新增 `TEST_CASES.md`(22 个测试用例文档)
|
||||||
|
- 新增 `CHANGELOG.md`
|
||||||
|
- `README.md` 全面更新,覆盖嵌入式构建、Preset 用法、API 参考
|
||||||
|
- 所有源文件添加中文 Doxygen 注释
|
||||||
|
|
||||||
|
### 🧪 测试
|
||||||
|
|
||||||
|
- 22 个单元测试,覆盖端口管理、send_type/handler 设置、自动广播路由、类型过滤、移除/删除后路由、接收回调、能力元数据
|
||||||
|
|
||||||
|
### 🐛 修复
|
||||||
|
|
||||||
|
- 修复 ARM 交叉编译时 VFP 参数不匹配问题(通过 `DR_SOURCE_ONLY` 模式)
|
||||||
|
- 修复 `#undef` 宏名称残留旧前缀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.0.0] - 2024-01-01
|
||||||
|
|
||||||
|
### 🚀 新功能
|
||||||
|
|
||||||
|
- 初始版本发布
|
||||||
|
- X-macro 代码生成:编译期声明通道,自动生成枚举、发送函数、回调声明
|
||||||
|
- 动态端口管理:创建、删除、运行时切换能力
|
||||||
|
- 弱符号回调默认实现
|
||||||
|
- Gitea Release 工作流:自动化构建 linux-amd64 / linux-arm64 / linux-armhf / windows-amd64 / baremetal-arm32
|
||||||
+51
-63
@@ -3,81 +3,69 @@ project(DataRouter C)
|
|||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
|
||||||
# ======== 静态库 ========
|
# ── 选项 ──────────────────────────────────────────────────────
|
||||||
add_library(DataRouter STATIC datarouter.c)
|
|
||||||
target_include_directories(DataRouter PUBLIC
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
|
||||||
$<INSTALL_INTERFACE:include>
|
|
||||||
)
|
|
||||||
|
|
||||||
# ======== 共享库(可选,通过 BUILD_SHARED 控制) ========
|
option(DR_SOURCE_ONLY "Provide source/include vars instead of building lib" OFF)
|
||||||
option(BUILD_SHARED "Build shared library" ON)
|
option(DR_COMPILE_CHECK "Build compile-compatibility tests for each Cortex-M variant" OFF)
|
||||||
if(BUILD_SHARED)
|
|
||||||
add_library(DataRouter_shared SHARED datarouter.c)
|
# 源码路径变量:嵌入式项目直接 target_sources() 使用
|
||||||
target_include_directories(DataRouter_shared PUBLIC
|
set(DR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/datarouter.c CACHE INTERNAL "")
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
set(DR_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")
|
||||||
$<INSTALL_INTERFACE:include>
|
|
||||||
|
# ── 编译兼容性矩阵 (仅在 host 编译器和 ARM GCC 均可用时生效) ──
|
||||||
|
|
||||||
|
if(DR_COMPILE_CHECK)
|
||||||
|
find_program(ARM_GCC arm-none-eabi-gcc)
|
||||||
|
if(ARM_GCC)
|
||||||
|
message(STATUS "ARM GCC found: ${ARM_GCC}")
|
||||||
|
set(ARM_MATRIX
|
||||||
|
"cm3; -mcpu=cortex-m3 -mthumb -mfloat-abi=soft"
|
||||||
|
"cm4-soft; -mcpu=cortex-m4 -mthumb -mfloat-abi=soft"
|
||||||
|
"cm4-hard; -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard"
|
||||||
|
"cm7-soft; -mcpu=cortex-m7 -mthumb -mfloat-abi=soft"
|
||||||
|
"cm7-hard; -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard"
|
||||||
)
|
)
|
||||||
set_target_properties(DataRouter_shared PROPERTIES OUTPUT_NAME DataRouter)
|
foreach(ENTRY ${ARM_MATRIX})
|
||||||
|
string(REPLACE ";" "|" ENTRY "${ENTRY}")
|
||||||
|
string(REPLACE "|" ";" ITEM "${ENTRY}")
|
||||||
|
list(GET ITEM 0 VARIANT)
|
||||||
|
list(REMOVE_AT ITEM 0)
|
||||||
|
string(REPLACE ";" " " FLAGS "${ITEM}")
|
||||||
|
set(TARGET "check_${VARIANT}")
|
||||||
|
add_custom_target(${TARGET}
|
||||||
|
COMMAND ${ARM_GCC} ${FLAGS}
|
||||||
|
-c ${CMAKE_CURRENT_SOURCE_DIR}/datarouter.c
|
||||||
|
-I${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
-o ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.o
|
||||||
|
COMMENT "Compile check: ${VARIANT} (${FLAGS})"
|
||||||
|
)
|
||||||
|
message(STATUS " compile check: ${VARIANT} (make ${TARGET})")
|
||||||
|
endforeach()
|
||||||
|
else()
|
||||||
|
message(WARNING "arm-none-eabi-gcc not found; skipping ARM compile checks")
|
||||||
|
endif()
|
||||||
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ======== 示例程序 ========
|
# ── 源码直用模式(嵌入式项目) ──────────────────────────────
|
||||||
|
|
||||||
|
if(DR_SOURCE_ONLY)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ── 常规库构建 ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
add_library(DataRouter STATIC datarouter.c)
|
||||||
|
target_include_directories(DataRouter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
if(BUILD_EXAMPLES OR NOT DEFINED BUILD_EXAMPLES)
|
if(BUILD_EXAMPLES OR NOT DEFINED BUILD_EXAMPLES)
|
||||||
add_executable(example example.c)
|
add_executable(example example.c)
|
||||||
target_link_libraries(example DataRouter)
|
target_link_libraries(example DataRouter)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ======== 测试 ========
|
|
||||||
if(BUILD_TESTING OR NOT DEFINED BUILD_TESTING)
|
if(BUILD_TESTING OR NOT DEFINED BUILD_TESTING)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_executable(test_datarouter tests/test_datarouter.c)
|
add_executable(test_datarouter tests/test_datarouter.c)
|
||||||
target_link_libraries(test_datarouter DataRouter)
|
target_link_libraries(test_datarouter DataRouter)
|
||||||
add_test(NAME datarouter COMMAND test_datarouter)
|
add_test(NAME datarouter COMMAND test_datarouter)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ======== 安装规则 ========
|
|
||||||
|
|
||||||
# 静态库 → lib/
|
|
||||||
install(TARGETS DataRouter
|
|
||||||
EXPORT DataRouterTargets
|
|
||||||
ARCHIVE DESTINATION lib
|
|
||||||
)
|
|
||||||
|
|
||||||
# 共享库 → lib/(可选)
|
|
||||||
if(TARGET DataRouter_shared)
|
|
||||||
install(TARGETS DataRouter_shared
|
|
||||||
EXPORT DataRouterTargets
|
|
||||||
ARCHIVE DESTINATION lib # .lib (Windows import lib)
|
|
||||||
LIBRARY DESTINATION lib # .so
|
|
||||||
RUNTIME DESTINATION lib # .dll
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# 示例 → bin/
|
|
||||||
if(TARGET example)
|
|
||||||
install(TARGETS example RUNTIME DESTINATION bin)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# 头文件 → include/
|
|
||||||
install(FILES datarouter.h DESTINATION include)
|
|
||||||
|
|
||||||
# 文档 → share/
|
|
||||||
install(FILES datarouter_config_template.h LICENSE DESTINATION share)
|
|
||||||
if(EXISTS ${CMAKE_SOURCE_DIR}/README.md)
|
|
||||||
install(FILES README.md DESTINATION share)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# CMake 包配置文件 → cmake/
|
|
||||||
set(INCLUDE_INSTALL_DIR include)
|
|
||||||
set(LIB_INSTALL_DIR lib)
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
configure_package_config_file(
|
|
||||||
cmake/DataRouterConfig.cmake.in
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/DataRouterConfig.cmake
|
|
||||||
INSTALL_DESTINATION cmake
|
|
||||||
PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR
|
|
||||||
)
|
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/DataRouterConfig.cmake DESTINATION cmake)
|
|
||||||
install(EXPORT DataRouterTargets FILE DataRouterTargets.cmake DESTINATION cmake)
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"displayName": "Host (native) build",
|
||||||
|
"description": "Build with host compiler for development, testing, and examples",
|
||||||
|
"binaryDir": "${sourceDir}/build/default",
|
||||||
|
"cacheVariables": {
|
||||||
|
"BUILD_TESTING": "ON",
|
||||||
|
"BUILD_EXAMPLES": "ON"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cm3",
|
||||||
|
"displayName": "Cortex-M3 (soft-float)",
|
||||||
|
"description": "ARM Cortex-M3, no FPU, software float ABI. Requires arm-none-eabi-gcc in PATH.",
|
||||||
|
"binaryDir": "${sourceDir}/build/cm3",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_FLAGS": "-mcpu=cortex-m3 -mthumb -mfloat-abi=soft -Wall -Werror",
|
||||||
|
"DR_SOURCE_ONLY": "ON",
|
||||||
|
"BUILD_TESTING": "OFF",
|
||||||
|
"BUILD_EXAMPLES": "OFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cm4-soft",
|
||||||
|
"displayName": "Cortex-M4 (soft-float)",
|
||||||
|
"description": "ARM Cortex-M4, FPU present but soft-float ABI. Requires arm-none-eabi-gcc.",
|
||||||
|
"binaryDir": "${sourceDir}/build/cm4-soft",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_FLAGS": "-mcpu=cortex-m4 -mthumb -mfloat-abi=soft -Wall -Werror",
|
||||||
|
"DR_SOURCE_ONLY": "ON",
|
||||||
|
"BUILD_TESTING": "OFF",
|
||||||
|
"BUILD_EXAMPLES": "OFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cm4-hard",
|
||||||
|
"displayName": "Cortex-M4F (hard-float, FPv4-SP-D16)",
|
||||||
|
"description": "ARM Cortex-M4 with single-precision FPU, hard-float ABI. Requires arm-none-eabi-gcc.",
|
||||||
|
"binaryDir": "${sourceDir}/build/cm4-hard",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_FLAGS": "-mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -Wall -Werror",
|
||||||
|
"DR_SOURCE_ONLY": "ON",
|
||||||
|
"BUILD_TESTING": "OFF",
|
||||||
|
"BUILD_EXAMPLES": "OFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cm7-soft",
|
||||||
|
"displayName": "Cortex-M7 (soft-float)",
|
||||||
|
"description": "ARM Cortex-M7, FPU present but soft-float ABI. Requires arm-none-eabi-gcc.",
|
||||||
|
"binaryDir": "${sourceDir}/build/cm7-soft",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_FLAGS": "-mcpu=cortex-m7 -mthumb -mfloat-abi=soft -Wall -Werror",
|
||||||
|
"DR_SOURCE_ONLY": "ON",
|
||||||
|
"BUILD_TESTING": "OFF",
|
||||||
|
"BUILD_EXAMPLES": "OFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cm7-hard-sp",
|
||||||
|
"displayName": "Cortex-M7F (hard-float, FPv5-SP-D16, single)",
|
||||||
|
"description": "ARM Cortex-M7 with single-precision FPU, hard-float ABI. Requires arm-none-eabi-gcc.",
|
||||||
|
"binaryDir": "${sourceDir}/build/cm7-hard-sp",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_FLAGS": "-mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard -Wall -Werror",
|
||||||
|
"DR_SOURCE_ONLY": "ON",
|
||||||
|
"BUILD_TESTING": "OFF",
|
||||||
|
"BUILD_EXAMPLES": "OFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cm7-hard-dp",
|
||||||
|
"displayName": "Cortex-M7F (hard-float, FPv5-D16, double)",
|
||||||
|
"description": "ARM Cortex-M7 with double-precision FPU, hard-float ABI. Requires arm-none-eabi-gcc.",
|
||||||
|
"binaryDir": "${sourceDir}/build/cm7-hard-dp",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_FLAGS": "-mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -Wall -Werror",
|
||||||
|
"DR_SOURCE_ONLY": "ON",
|
||||||
|
"BUILD_TESTING": "OFF",
|
||||||
|
"BUILD_EXAMPLES": "OFF"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buildPresets": [
|
||||||
|
{ "name": "default", "configurePreset": "default" },
|
||||||
|
{ "name": "cm3", "configurePreset": "cm3" },
|
||||||
|
{ "name": "cm4-soft", "configurePreset": "cm4-soft" },
|
||||||
|
{ "name": "cm4-hard", "configurePreset": "cm4-hard" },
|
||||||
|
{ "name": "cm7-soft", "configurePreset": "cm7-soft" },
|
||||||
|
{ "name": "cm7-hard-sp", "configurePreset": "cm7-hard-sp" },
|
||||||
|
{ "name": "cm7-hard-dp", "configurePreset": "cm7-hard-dp" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
## 1. 设计目标
|
## 1. 设计目标
|
||||||
|
|
||||||
轻量级 C 语言数据路由库。发送与接收能力分开声明,端口绑定 `send_type` 和外设 handler 列表。调用 `datarouter_send_<id>(data, len)` 时自动遍历端口表,广播到所有 `send_type` 匹配的端口。
|
轻量级 C 语言数据路由库。发送与接收能力分开声明,端口绑定 `send_type` 和外设 handler 列表。调用 `dr_send_<id>(data, len)` 时自动遍历端口表,广播到所有 `send_type` 匹配的端口。
|
||||||
|
|
||||||
### 核心设计
|
### 核心设计
|
||||||
|
|
||||||
```
|
```
|
||||||
DATAROUTER_SEND_CAPABILITIES DATAROUTER_RECV_CAPABILITIES
|
DR_SEND_CAPABILITIES DR_RECV_CAPABILITIES
|
||||||
DATAROUTER_SEND(sensor, ...) DATAROUTER_RECV(rtcm, ...)
|
DR_SEND(sensor, ...) DR_RECV(rtcm, ...)
|
||||||
DATAROUTER_SEND(status, ...) DATAROUTER_RECV(command, ...)
|
DR_SEND(status, ...) DR_RECV(command, ...)
|
||||||
│ │
|
│ │
|
||||||
▼ ▼
|
▼ ▼
|
||||||
send_sensor(data, len) on_recv_rtcm(port, data, len)
|
send_sensor(data, len) on_recv_rtcm(port, data, len)
|
||||||
@@ -28,7 +28,7 @@ DATAROUTER_SEND_CAPABILITIES DATAROUTER_RECV_CAPABILITIES
|
|||||||
| 原则 | 说明 |
|
| 原则 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| 收发分离 | 发送/接收能力在配置中分开声明,按需组合 |
|
| 收发分离 | 发送/接收能力在配置中分开声明,按需组合 |
|
||||||
| 编译期确定能力 | 所有能力在 `datarouter_config.h` 中声明,库自动生成代码 |
|
| 编译期确定能力 | 所有能力在 `dr_config.h` 中声明,库自动生成代码 |
|
||||||
| 运行期绑定外设 | 端口创建后,通过 `add_handler` 注册物理外设发送函数 |
|
| 运行期绑定外设 | 端口创建后,通过 `add_handler` 注册物理外设发送函数 |
|
||||||
| 自动广播 | `send_<id>(data, len)` 遍历所有端口,自动匹配 send_type |
|
| 自动广播 | `send_<id>(data, len)` 遍历所有端口,自动匹配 send_type |
|
||||||
| 不关心物理外设 | 库不依赖任何外设 API,只调用用户提供的 handler |
|
| 不关心物理外设 | 库不依赖任何外设 API,只调用用户提供的 handler |
|
||||||
@@ -46,7 +46,7 @@ left to right direction
|
|||||||
|
|
||||||
rectangle "用户代码" as User {
|
rectangle "用户代码" as User {
|
||||||
component "应用逻辑\n调 send_<id>(data, len)" as App
|
component "应用逻辑\n调 send_<id>(data, len)" as App
|
||||||
component "datarouter_config.h\n声明能力" as Cfg
|
component "dr_config.h\n声明能力" as Cfg
|
||||||
component "外设 handler\nUART / TCP / CAN" as Handlers
|
component "外设 handler\nUART / TCP / CAN" as Handlers
|
||||||
component "接收回调\non_recv_<id>()" as Callbacks
|
component "接收回调\non_recv_<id>()" as Callbacks
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ Callbacks --> Impl : 实现 on_recv_<id>
|
|||||||
|
|
||||||
| 文件 | 职责 |
|
| 文件 | 职责 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `datarouter_config.h` | 声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` |
|
| `dr_config.h` | 声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` |
|
||||||
| `datarouter.h` | 公共 API + X-macro 展开 |
|
| `datarouter.h` | 公共 API + X-macro 展开 |
|
||||||
| `datarouter.c` | 端口表 + send 遍历 + 弱符号回调 |
|
| `datarouter.c` | 端口表 + send 遍历 + 弱符号回调 |
|
||||||
| `example.c` | 使用示例 |
|
| `example.c` | 使用示例 |
|
||||||
@@ -81,29 +81,29 @@ Callbacks --> Impl : 实现 on_recv_<id>
|
|||||||
### 3.1 配置声明
|
### 3.1 配置声明
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#define DATAROUTER_SEND_CAPABILITIES \
|
#define DR_SEND_CAPABILITIES \
|
||||||
DATAROUTER_SEND(sensor, "Sensor data report") \
|
DR_SEND(sensor, "Sensor data report") \
|
||||||
DATAROUTER_SEND(status, "Device status report")
|
DR_SEND(status, "Device status report")
|
||||||
|
|
||||||
#define DATAROUTER_RECV_CAPABILITIES \
|
#define DR_RECV_CAPABILITIES \
|
||||||
DATAROUTER_RECV(rtcm, "RTCM correction data") \
|
DR_RECV(rtcm, "RTCM correction data") \
|
||||||
DATAROUTER_RECV(command, "Remote control command")
|
DR_RECV(command, "Remote control command")
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.2 展开产物
|
### 3.2 展开产物
|
||||||
|
|
||||||
```
|
```
|
||||||
DATAROUTER_SEND_CAPABILITIES 展开:
|
DR_SEND_CAPABILITIES 展开:
|
||||||
enum: sensor = 0, status = 1, SEND_CAP_COUNT = 2
|
enum: sensor = 0, status = 1, SEND_CAP_COUNT = 2
|
||||||
发送函数: int datarouter_send_sensor(const void *data, size_t len);
|
发送函数: int dr_send_sensor(const void *data, size_t len);
|
||||||
int datarouter_send_status(const void *data, size_t len);
|
int dr_send_status(const void *data, size_t len);
|
||||||
元数据: send_names[] = {"sensor", "status"}
|
元数据: send_names[] = {"sensor", "status"}
|
||||||
send_descs[] = {"Sensor data report", "Device status report"}
|
send_descs[] = {"Sensor data report", "Device status report"}
|
||||||
|
|
||||||
DATAROUTER_RECV_CAPABILITIES 展开:
|
DR_RECV_CAPABILITIES 展开:
|
||||||
enum: rtcm = 0, command = 1, RECV_CAP_COUNT = 2
|
enum: rtcm = 0, command = 1, RECV_CAP_COUNT = 2
|
||||||
接收回调: void datarouter_on_recv_rtcm(uint32_t port, const void*, size_t);
|
接收回调: void dr_on_recv_rtcm(uint32_t port, const void*, size_t);
|
||||||
void datarouter_on_recv_command(uint32_t port, const void*, size_t);
|
void dr_on_recv_command(uint32_t port, const void*, size_t);
|
||||||
弱符号默认: 空实现,用户覆盖
|
弱符号默认: 空实现,用户覆盖
|
||||||
元数据: recv_names[] = {"rtcm", "command"}
|
元数据: recv_names[] = {"rtcm", "command"}
|
||||||
recv_descs[] = {"RTCM correction data", "Remote control command"}
|
recv_descs[] = {"RTCM correction data", "Remote control command"}
|
||||||
@@ -127,18 +127,18 @@ DATAROUTER_RECV_CAPABILITIES 展开:
|
|||||||
@startuml
|
@startuml
|
||||||
== datarouter.h ==
|
== datarouter.h ==
|
||||||
|
|
||||||
-> datarouter_config.h: 获得两组宏列表
|
-> dr_config.h: 获得两组宏列表
|
||||||
|
|
||||||
datarouter.h -> "1": #define DATAROUTER_SEND(id,desc) DATAROUTER_SEND_##id,
|
datarouter.h -> "1": #define DR_SEND(id,desc) DR_SEND_##id,
|
||||||
note right: 发送 enum
|
note right: 发送 enum
|
||||||
|
|
||||||
datarouter.h -> "2": #define DATAROUTER_RECV(id,desc) DATAROUTER_RECV_##id,
|
datarouter.h -> "2": #define DR_RECV(id,desc) DR_RECV_##id,
|
||||||
note right: 接收 enum
|
note right: 接收 enum
|
||||||
|
|
||||||
datarouter.h -> "3": #define DATAROUTER_SEND(id,desc) int send_##id(data, len);
|
datarouter.h -> "3": #define DR_SEND(id,desc) int send_##id(data, len);
|
||||||
note right: 发送函数声明
|
note right: 发送函数声明
|
||||||
|
|
||||||
datarouter.h -> "4": #define DATAROUTER_RECV(id,desc) void on_recv_##id(...);
|
datarouter.h -> "4": #define DR_RECV(id,desc) void on_recv_##id(...);
|
||||||
note right: 接收回调声明
|
note right: 接收回调声明
|
||||||
|
|
||||||
== datarouter.c ==
|
== datarouter.c ==
|
||||||
@@ -159,17 +159,17 @@ datarouter.c -> "7~8": send_names[] / send_descs[] / recv_names[] / recv_descs[]
|
|||||||
@startuml
|
@startuml
|
||||||
skinparam classAttributeIconSize 0
|
skinparam classAttributeIconSize 0
|
||||||
|
|
||||||
enum "datarouter_send_cap" as S { SENSOR, STATUS, SEND_CAP_COUNT }
|
enum "dr_send_cap" as S { SENSOR, STATUS, SEND_CAP_COUNT }
|
||||||
enum "datarouter_recv_cap" as R { RTCM, COMMAND, RECV_CAP_COUNT }
|
enum "dr_recv_cap" as R { RTCM, COMMAND, RECV_CAP_COUNT }
|
||||||
|
|
||||||
class "port_entry_t" as Entry {
|
class "port_entry_t" as Entry {
|
||||||
- int send_type
|
- int send_type
|
||||||
- datarouter_send_handler_t handlers[]
|
- dr_send_handler_t handlers[]
|
||||||
- int count
|
- int count
|
||||||
- uint8_t in_use
|
- uint8_t in_use
|
||||||
}
|
}
|
||||||
|
|
||||||
class "datarouter_send_handler_t" as Handler {
|
class "dr_send_handler_t" as Handler {
|
||||||
+ void (*)(uint32_t port_id, const void *data, size_t len)
|
+ void (*)(uint32_t port_id, const void *data, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,11 +193,11 @@ Recv --> Entry : 用户根据业务调对应回调
|
|||||||
### 5.2 `port_entry_t`
|
### 5.2 `port_entry_t`
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#define DATAROUTER_MAX_HANDLERS_PER_PORT 4
|
#define DR_MAX_HANDLERS_PER_PORT 4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int send_type;
|
int send_type;
|
||||||
datarouter_send_handler_t handlers[DATAROUTER_MAX_HANDLERS_PER_PORT];
|
dr_send_handler_t handlers[DR_MAX_HANDLERS_PER_PORT];
|
||||||
int count;
|
int count;
|
||||||
uint8_t in_use;
|
uint8_t in_use;
|
||||||
} port_entry_t;
|
} port_entry_t;
|
||||||
@@ -206,8 +206,8 @@ typedef struct {
|
|||||||
### 5.3 端口表
|
### 5.3 端口表
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#define DATAROUTER_MAX_PORTS 64
|
#define DR_MAX_PORTS 64
|
||||||
static port_entry_t ports[DATAROUTER_MAX_PORTS];
|
static port_entry_t ports[DR_MAX_PORTS];
|
||||||
static uint8_t initialized;
|
static uint8_t initialized;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -218,30 +218,30 @@ static uint8_t initialized;
|
|||||||
### 6.1 初始化
|
### 6.1 初始化
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void datarouter_init(void); // 幂等初始化
|
void dr_init(void); // 幂等初始化
|
||||||
void datarouter_reset(void); // 重置全部状态
|
void dr_reset(void); // 重置全部状态
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6.2 端口管理
|
### 6.2 端口管理
|
||||||
|
|
||||||
```c
|
```c
|
||||||
datarouter_port_t datarouter_port_create(void);
|
dr_port_t dr_port_create(void);
|
||||||
void datarouter_port_delete(datarouter_port_t port);
|
void dr_port_delete(dr_port_t port);
|
||||||
|
|
||||||
void datarouter_port_set_send_type(port, int cap_id);
|
void dr_port_set_send_type(port, int cap_id);
|
||||||
int datarouter_port_get_send_type(port);
|
int dr_port_get_send_type(port);
|
||||||
|
|
||||||
int datarouter_port_add_handler(port, handler);
|
int dr_port_add_handler(port, handler);
|
||||||
int datarouter_port_remove_handler(port, handler);
|
int dr_port_remove_handler(port, handler);
|
||||||
void datarouter_port_clear_handlers(port);
|
void dr_port_clear_handlers(port);
|
||||||
int datarouter_port_handler_count(port);
|
int dr_port_handler_count(port);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6.3 发送触发函数(每个 SEND 能力生成一个)
|
### 6.3 发送触发函数(每个 SEND 能力生成一个)
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int datarouter_send_sensor(const void *data, size_t len);
|
int dr_send_sensor(const void *data, size_t len);
|
||||||
int datarouter_send_status(const void *data, size_t len);
|
int dr_send_status(const void *data, size_t len);
|
||||||
```
|
```
|
||||||
|
|
||||||
返回值:0 成功 / -1 未初始化 / -2 无端口匹配该 send_type
|
返回值:0 成功 / -1 未初始化 / -2 无端口匹配该 send_type
|
||||||
@@ -249,8 +249,8 @@ int datarouter_send_status(const void *data, size_t len);
|
|||||||
### 6.4 接收回调(每个 RECV 能力生成一个声明)
|
### 6.4 接收回调(每个 RECV 能力生成一个声明)
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len);
|
void dr_on_recv_rtcm(uint32_t port_id, const void *data, size_t len);
|
||||||
void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len);
|
void dr_on_recv_command(uint32_t port_id, const void *data, size_t len);
|
||||||
```
|
```
|
||||||
|
|
||||||
库提供弱符号默认空实现。
|
库提供弱符号默认空实现。
|
||||||
@@ -258,13 +258,13 @@ void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len);
|
|||||||
### 6.5 能力元数据
|
### 6.5 能力元数据
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int datarouter_send_cap_count(void);
|
int dr_send_cap_count(void);
|
||||||
const char *datarouter_send_cap_name(int cap_id);
|
const char *dr_send_cap_name(int cap_id);
|
||||||
const char *datarouter_send_cap_desc(int cap_id);
|
const char *dr_send_cap_desc(int cap_id);
|
||||||
|
|
||||||
int datarouter_recv_cap_count(void);
|
int dr_recv_cap_count(void);
|
||||||
const char *datarouter_recv_cap_name(int cap_id);
|
const char *dr_recv_cap_name(int cap_id);
|
||||||
const char *datarouter_recv_cap_desc(int cap_id);
|
const char *dr_recv_cap_desc(int cap_id);
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -276,7 +276,7 @@ const char *datarouter_recv_cap_desc(int cap_id);
|
|||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
actor "应用" as App
|
actor "应用" as App
|
||||||
participant "datarouter_send_sensor()" as Send
|
participant "dr_send_sensor()" as Send
|
||||||
participant "端口表 ports[]" as Table
|
participant "端口表 ports[]" as Table
|
||||||
participant "handlers[]" as HList
|
participant "handlers[]" as HList
|
||||||
participant "外设" as Dev
|
participant "外设" as Dev
|
||||||
@@ -349,16 +349,16 @@ Idle --> Created : 复用 ID
|
|||||||
### 场景 1:sensor 广播到 UART + TCP + CAN
|
### 场景 1:sensor 广播到 UART + TCP + CAN
|
||||||
|
|
||||||
```c
|
```c
|
||||||
datarouter_port_t p1 = datarouter_port_create();
|
dr_port_t p1 = dr_port_create();
|
||||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p1, uart_send);
|
dr_port_add_handler(p1, uart_send);
|
||||||
datarouter_port_add_handler(p1, tcp_send);
|
dr_port_add_handler(p1, tcp_send);
|
||||||
|
|
||||||
datarouter_port_t p2 = datarouter_port_create();
|
dr_port_t p2 = dr_port_create();
|
||||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p2, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p2, can_send);
|
dr_port_add_handler(p2, can_send);
|
||||||
|
|
||||||
datarouter_send_sensor("temp:25.3", 9);
|
dr_send_sensor("temp:25.3", 9);
|
||||||
// → uart_send(p1, "temp:25.3", 9)
|
// → uart_send(p1, "temp:25.3", 9)
|
||||||
// → tcp_send(p1, "temp:25.3", 9)
|
// → tcp_send(p1, "temp:25.3", 9)
|
||||||
// → can_send(p2, "temp:25.3", 9)
|
// → can_send(p2, "temp:25.3", 9)
|
||||||
@@ -367,16 +367,16 @@ datarouter_send_sensor("temp:25.3", 9);
|
|||||||
### 场景 2:仅接收
|
### 场景 2:仅接收
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) {
|
void dr_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) {
|
||||||
apply_rtcm_correction(data, len);
|
apply_rtcm_correction(data, len);
|
||||||
}
|
}
|
||||||
// 外设收到后:datarouter_on_recv_rtcm(port, data, len);
|
// 外设收到后:dr_on_recv_rtcm(port, data, len);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 场景 3:运行时移除 handler
|
### 场景 3:运行时移除 handler
|
||||||
|
|
||||||
```c
|
```c
|
||||||
datarouter_port_remove_handler(p1, tcp_send);
|
dr_port_remove_handler(p1, tcp_send);
|
||||||
// 下次 send_sensor 不再触发 tcp
|
// 下次 send_sensor 不再触发 tcp
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -415,17 +415,17 @@ Weak ..> Result : 后备
|
|||||||
## 11. 配置扩展
|
## 11. 配置扩展
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#define DATAROUTER_SEND_CAPABILITIES \
|
#define DR_SEND_CAPABILITIES \
|
||||||
DATAROUTER_SEND(sensor, "Sensor data") \
|
DR_SEND(sensor, "Sensor data") \
|
||||||
DATAROUTER_SEND(debug, "Debug log") /* 新增 */
|
DR_SEND(debug, "Debug log") /* 新增 */
|
||||||
|
|
||||||
#define DATAROUTER_RECV_CAPABILITIES \
|
#define DR_RECV_CAPABILITIES \
|
||||||
DATAROUTER_RECV(rtcm, "RTCM data") \
|
DR_RECV(rtcm, "RTCM data") \
|
||||||
DATAROUTER_RECV(ota, "OTA firmware") /* 新增 */
|
DR_RECV(ota, "OTA firmware") /* 新增 */
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128 -DDATAROUTER_MAX_HANDLERS_PER_PORT=8"
|
cmake -DCMAKE_C_FLAGS="-DDR_MAX_PORTS=128 -DDR_MAX_HANDLERS_PER_PORT=8"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# DataRouter
|
# DataRouter
|
||||||
|
|
||||||
轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口绑定 `send_type` 和外设 handler 列表。调用 `datarouter_send_<id>(data, len)` 时自动广播到所有匹配端口。
|
轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口绑定 `send_type` 和外设 handler 列表。调用 `dr_send_<id>(data, len)` 时自动广播到所有匹配端口。
|
||||||
|
|
||||||
## 概念
|
## 概念
|
||||||
|
|
||||||
| 术语 | 说明 |
|
| 术语 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `datarouter_send_<id>(data, len)` |
|
| **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `dr_send_<id>(data, len)` |
|
||||||
| **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `datarouter_on_recv_<id>(port, data, len)` |
|
| **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `dr_on_recv_<id>(port, data, len)` |
|
||||||
| **端口 (Port)** | 运行期创建的连接点,包含 `send_type` + handler 列表 |
|
| **端口 (Port)** | 运行期创建的连接点,包含 `send_type` + handler 列表 |
|
||||||
| **Handler** | 用户实现的物理外设发送函数,一个端口可注册多个(默认上限 4) |
|
| **Handler** | 用户实现的物理外设发送函数,一个端口可注册多个(默认上限 4) |
|
||||||
|
|
||||||
@@ -15,19 +15,19 @@
|
|||||||
|
|
||||||
### 1. 声明能力
|
### 1. 声明能力
|
||||||
|
|
||||||
创建自己的 `datarouter_config.h`(可参考 `datarouter_config_template.h`):
|
创建自己的 `dr_config.h`(可参考 `dr_config_template.h`):
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#define DATAROUTER_SEND_CAPABILITIES \
|
#define DR_SEND_CAPABILITIES \
|
||||||
DATAROUTER_SEND(sensor, "Sensor data report") \
|
DR_SEND(sensor, "Sensor data report") \
|
||||||
DATAROUTER_SEND(status, "Device status report")
|
DR_SEND(status, "Device status report")
|
||||||
|
|
||||||
#define DATAROUTER_RECV_CAPABILITIES \
|
#define DR_RECV_CAPABILITIES \
|
||||||
DATAROUTER_RECV(rtcm, "RTCM correction data") \
|
DR_RECV(rtcm, "RTCM correction data") \
|
||||||
DATAROUTER_RECV(command, "Remote control command")
|
DR_RECV(command, "Remote control command")
|
||||||
```
|
```
|
||||||
|
|
||||||
> 库自带默认配置。将你的 `datarouter_config.h` 放到项目目录,
|
> 库自带默认配置。将你的 `dr_config.h` 放到项目目录,
|
||||||
> 编译时添加 `-I /path/to/your/config` 即可覆盖。无需修改库源码。
|
> 编译时添加 `-I /path/to/your/config` 即可覆盖。无需修改库源码。
|
||||||
>
|
>
|
||||||
> ```cmake
|
> ```cmake
|
||||||
@@ -51,25 +51,25 @@ static void tcp_send(uint32_t port_id, const void *data, size_t len) {
|
|||||||
### 3. 创建端口
|
### 3. 创建端口
|
||||||
|
|
||||||
```c
|
```c
|
||||||
datarouter_init();
|
dr_init();
|
||||||
|
|
||||||
/* —— 传感器上报:sensor 报文走 UART + TCP —— */
|
/* —— 传感器上报:sensor 报文走 UART + TCP —— */
|
||||||
datarouter_port_t tx = datarouter_port_create();
|
dr_port_t tx = dr_port_create();
|
||||||
datarouter_port_set_send_type(tx, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(tx, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(tx, uart_send);
|
dr_port_add_handler(tx, uart_send);
|
||||||
datarouter_port_add_handler(tx, tcp_send);
|
dr_port_add_handler(tx, tcp_send);
|
||||||
|
|
||||||
/* 不指定端口,库自动广播到所有 send_type=sensor 的端口 */
|
/* 不指定端口,库自动广播到所有 send_type=sensor 的端口 */
|
||||||
datarouter_send_sensor("temperature:25.3", 16); // → UART + TCP
|
dr_send_sensor("temperature:25.3", 16); // → UART + TCP
|
||||||
|
|
||||||
/* —— 接收:实现回调,外设数据到达后自行调用 —— */
|
/* —— 接收:实现回调,外设数据到达后自行调用 —— */
|
||||||
datarouter_on_recv_rtcm(rx_port, data, len);
|
dr_on_recv_rtcm(rx_port, data, len);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. 实现接收回调
|
### 4. 实现接收回调
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) {
|
void dr_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) {
|
||||||
apply_rtcm_correction(data, len);
|
apply_rtcm_correction(data, len);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -79,30 +79,30 @@ void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) {
|
|||||||
### 初始化
|
### 初始化
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void datarouter_init(void); // 幂等初始化
|
void dr_init(void); // 幂等初始化
|
||||||
void datarouter_reset(void); // 重置全部状态
|
void dr_reset(void); // 重置全部状态
|
||||||
```
|
```
|
||||||
|
|
||||||
### 端口管理
|
### 端口管理
|
||||||
|
|
||||||
```c
|
```c
|
||||||
datarouter_port_t datarouter_port_create(void); // 创建端口
|
dr_port_t dr_port_create(void); // 创建端口
|
||||||
void datarouter_port_delete(datarouter_port_t port); // 删除
|
void dr_port_delete(dr_port_t port); // 删除
|
||||||
|
|
||||||
void datarouter_port_set_send_type(port, int cap_id); // 设置发送类型
|
void dr_port_set_send_type(port, int cap_id); // 设置发送类型
|
||||||
int datarouter_port_get_send_type(port); // -1 = 未设置
|
int dr_port_get_send_type(port); // -1 = 未设置
|
||||||
|
|
||||||
int datarouter_port_add_handler(port, handler); // 注册外设 handler
|
int dr_port_add_handler(port, handler); // 注册外设 handler
|
||||||
int datarouter_port_remove_handler(port, handler); // 移除
|
int dr_port_remove_handler(port, handler); // 移除
|
||||||
void datarouter_port_clear_handlers(port); // 清除全部
|
void dr_port_clear_handlers(port); // 清除全部
|
||||||
int datarouter_port_handler_count(port); // 当前数量
|
int dr_port_handler_count(port); // 当前数量
|
||||||
```
|
```
|
||||||
|
|
||||||
### 发送触发(每个 SEND 能力生成一个)
|
### 发送触发(每个 SEND 能力生成一个)
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int datarouter_send_sensor(const void *data, size_t len); // 0 成功
|
int dr_send_sensor(const void *data, size_t len); // 0 成功
|
||||||
int datarouter_send_status(const void *data, size_t len); // -1 未初始化
|
int dr_send_status(const void *data, size_t len); // -1 未初始化
|
||||||
// -2 无匹配端口
|
// -2 无匹配端口
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -111,8 +111,8 @@ int datarouter_send_status(const void *data, size_t len); // -1 未初始化
|
|||||||
### 接收回调(每个 RECV 能力生成一个声明)
|
### 接收回调(每个 RECV 能力生成一个声明)
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len);
|
void dr_on_recv_rtcm(uint32_t port_id, const void *data, size_t len);
|
||||||
void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len);
|
void dr_on_recv_command(uint32_t port_id, const void *data, size_t len);
|
||||||
```
|
```
|
||||||
|
|
||||||
库提供弱符号默认空实现,用户定义同名函数覆盖。
|
库提供弱符号默认空实现,用户定义同名函数覆盖。
|
||||||
@@ -120,19 +120,19 @@ void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len);
|
|||||||
### 能力元数据(两组独立)
|
### 能力元数据(两组独立)
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int datarouter_send_cap_count(void);
|
int dr_send_cap_count(void);
|
||||||
const char *datarouter_send_cap_name(int cap_id);
|
const char *dr_send_cap_name(int cap_id);
|
||||||
const char *datarouter_send_cap_desc(int cap_id);
|
const char *dr_send_cap_desc(int cap_id);
|
||||||
|
|
||||||
int datarouter_recv_cap_count(void);
|
int dr_recv_cap_count(void);
|
||||||
const char *datarouter_recv_cap_name(int cap_id);
|
const char *dr_recv_cap_name(int cap_id);
|
||||||
const char *datarouter_recv_cap_desc(int cap_id);
|
const char *dr_recv_cap_desc(int cap_id);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 路由模型
|
## 路由模型
|
||||||
|
|
||||||
```
|
```
|
||||||
datarouter_send_sensor("temperature:25.3", 16)
|
dr_send_sensor("temperature:25.3", 16)
|
||||||
│
|
│
|
||||||
├─→ port 0 (send_type=sensor) handlers[0]=uart_send → UART
|
├─→ port 0 (send_type=sensor) handlers[0]=uart_send → UART
|
||||||
│ handlers[1]=tcp_send → TCP
|
│ handlers[1]=tcp_send → TCP
|
||||||
@@ -155,9 +155,65 @@ cmake --build build
|
|||||||
可选配置:
|
可选配置:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128 -DDATAROUTER_MAX_HANDLERS_PER_PORT=8"
|
cmake -DCMAKE_C_FLAGS="-DDR_MAX_PORTS=128 -DDR_MAX_HANDLERS_PER_PORT=8"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 嵌入式 / Cortex-M 构建
|
||||||
|
|
||||||
|
库支持 `arm-none-eabi-gcc` 交叉编译,提供 **7 个 CMake preset** 覆盖常见 Cortex-M 目标:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 列出所有 preset
|
||||||
|
cmake --list-presets
|
||||||
|
|
||||||
|
# Cortex-M3(软浮点)
|
||||||
|
cmake --preset cm3
|
||||||
|
cmake --build --preset cm3
|
||||||
|
|
||||||
|
# Cortex-M4F(硬件浮点,单精度)
|
||||||
|
cmake --preset cm4-hard
|
||||||
|
cmake --build --preset cm4-hard
|
||||||
|
|
||||||
|
# Cortex-M7F(硬件浮点,双精度)
|
||||||
|
cmake --preset cm7-hard-dp
|
||||||
|
cmake --build --preset cm7-hard-dp
|
||||||
|
```
|
||||||
|
|
||||||
|
> 使用 preset 编译需要 `arm-none-eabi-gcc` 在 PATH 中。
|
||||||
|
> 各 preset 均启用 `DR_SOURCE_ONLY` 模式——只提供源文件路径,
|
||||||
|
> 你需要将 `datarouter.c` 加入自己的 target 以继承项目编译标志:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# 你的 CMakeLists.txt
|
||||||
|
set(DR_SOURCE_ONLY ON)
|
||||||
|
FetchContent_MakeAvailable(datarouter)
|
||||||
|
target_sources(my_app PRIVATE ${datarouter_SOURCE_DIR}/datarouter.c)
|
||||||
|
target_include_directories(my_app PRIVATE ${datarouter_SOURCE_DIR})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 编译兼容性矩阵
|
||||||
|
|
||||||
|
启用 `DR_COMPILE_CHECK` 可自动检测 `arm-none-eabi-gcc` 并对 CM3/CM4/CM7
|
||||||
|
各变体执行编译验证:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake -B build-check -DDR_COMPILE_CHECK=ON
|
||||||
|
cmake --build build-check # 生成 check_cm3, check_cm4-hard, … 等 target
|
||||||
|
# 或单独检查某个变体:
|
||||||
|
make check_cm7-hard-dp
|
||||||
|
```
|
||||||
|
|
||||||
|
### 内置 CMake Preset 列表
|
||||||
|
|
||||||
|
| Preset | 目标 | FPU | ABI |
|
||||||
|
|--------|------|-----|-----|
|
||||||
|
| `cm3` | Cortex-M3 | 无 | soft |
|
||||||
|
| `cm4-soft` | Cortex-M4 | 无 | soft |
|
||||||
|
| `cm4-hard` | Cortex-M4F | FPv4-SP-D16 | hard |
|
||||||
|
| `cm7-soft` | Cortex-M7 | 无 | soft |
|
||||||
|
| `cm7-hard-sp` | Cortex-M7F | FPv5-SP-D16 | hard |
|
||||||
|
| `cm7-hard-dp` | Cortex-M7F | FPv5-D16 | hard |
|
||||||
|
|
||||||
## 测试
|
## 测试
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -172,10 +228,10 @@ ctest --test-dir build
|
|||||||
## 文件结构
|
## 文件结构
|
||||||
|
|
||||||
```
|
```
|
||||||
datarouter_config.h 发送 + 接收能力配置(用户可覆盖)
|
dr_config.h 发送 + 接收能力配置(用户可覆盖)
|
||||||
datarouter.h 公共 API + X-macro 展开
|
datarouter.h 公共 API + X-macro 展开
|
||||||
datarouter.c 实现(端口表 + send 遍历)
|
datarouter.c 实现(端口表 + send 遍历)
|
||||||
datarouter_config_template.h 外部配置模板
|
dr_config_template.h 外部配置模板
|
||||||
example.c 使用示例
|
example.c 使用示例
|
||||||
tests/test_datarouter.c 单元测试(22 用例)
|
tests/test_datarouter.c 单元测试(22 用例)
|
||||||
DESIGN.md 详细设计文档(含 PlantUML 图)
|
DESIGN.md 详细设计文档(含 PlantUML 图)
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
|
||||||
|
####### Any changes to this file will be overwritten by the next CMake run ####
|
||||||
|
####### The input file was DataRouterConfig.cmake.in ########
|
||||||
|
|
||||||
|
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../" ABSOLUTE)
|
||||||
|
|
||||||
|
macro(set_and_check _var _file)
|
||||||
|
set(${_var} "${_file}")
|
||||||
|
if(NOT EXISTS "${_file}")
|
||||||
|
message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(check_required_components _NAME)
|
||||||
|
foreach(comp ${${_NAME}_FIND_COMPONENTS})
|
||||||
|
if(NOT ${_NAME}_${comp}_FOUND)
|
||||||
|
if(${_NAME}_FIND_REQUIRED_${comp})
|
||||||
|
set(${_NAME}_FOUND FALSE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
####################################################################################
|
||||||
|
|
||||||
|
set_and_check(DataRouter_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")
|
||||||
|
set_and_check(DataRouter_LIBRARY_DIR "${PACKAGE_PREFIX_DIR}/lib")
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/DataRouterTargets.cmake" OPTIONAL)
|
||||||
|
|
||||||
|
if(NOT TARGET DataRouter::DataRouter)
|
||||||
|
add_library(DataRouter::DataRouter STATIC IMPORTED)
|
||||||
|
set_target_properties(DataRouter::DataRouter PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${DataRouter_LIBRARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}DataRouter${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${DataRouter_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_required_components(DataRouter)
|
||||||
Binary file not shown.
Binary file not shown.
+56
-56
@@ -6,70 +6,70 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#define DATAROUTER_WEAK __attribute__((weak))
|
#define DR_WEAK __attribute__((weak))
|
||||||
#else
|
#else
|
||||||
#define DATAROUTER_WEAK
|
#define DR_WEAK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DATAROUTER_MAX_PORTS
|
#ifndef DR_MAX_PORTS
|
||||||
#define DATAROUTER_MAX_PORTS 64
|
#define DR_MAX_PORTS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int send_type;
|
int send_type;
|
||||||
datarouter_send_handler_t handlers[DATAROUTER_MAX_HANDLERS_PER_PORT];
|
dr_send_handler_t handlers[DR_MAX_HANDLERS_PER_PORT];
|
||||||
int count;
|
int count;
|
||||||
uint8_t in_use;
|
uint8_t in_use;
|
||||||
} port_entry_t;
|
} port_entry_t;
|
||||||
|
|
||||||
static port_entry_t ports[DATAROUTER_MAX_PORTS];
|
static port_entry_t ports[DR_MAX_PORTS];
|
||||||
static uint8_t initialized;
|
static uint8_t initialized;
|
||||||
|
|
||||||
/* ---- 元数据 ---- */
|
/* ---- 元数据 ---- */
|
||||||
|
|
||||||
static const char *send_names[] = {
|
static const char *send_names[] = {
|
||||||
#define DATAROUTER_SEND(id, desc) #id,
|
#define DR_SEND(id, desc) #id,
|
||||||
DATAROUTER_SEND_CAPABILITIES
|
DR_SEND_CAPABILITIES
|
||||||
#undef DATAROUTER_SEND
|
#undef DR_SEND
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *send_descs[] = {
|
static const char *send_descs[] = {
|
||||||
#define DATAROUTER_SEND(id, desc) desc,
|
#define DR_SEND(id, desc) desc,
|
||||||
DATAROUTER_SEND_CAPABILITIES
|
DR_SEND_CAPABILITIES
|
||||||
#undef DATAROUTER_SEND
|
#undef DR_SEND
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *recv_names[] = {
|
static const char *recv_names[] = {
|
||||||
#define DATAROUTER_RECV(id, desc) #id,
|
#define DR_RECV(id, desc) #id,
|
||||||
DATAROUTER_RECV_CAPABILITIES
|
DR_RECV_CAPABILITIES
|
||||||
#undef DATAROUTER_RECV
|
#undef DR_RECV
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *recv_descs[] = {
|
static const char *recv_descs[] = {
|
||||||
#define DATAROUTER_RECV(id, desc) desc,
|
#define DR_RECV(id, desc) desc,
|
||||||
DATAROUTER_RECV_CAPABILITIES
|
DR_RECV_CAPABILITIES
|
||||||
#undef DATAROUTER_RECV
|
#undef DR_RECV
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ---- 弱符号接收回调 ---- */
|
/* ---- 弱符号接收回调 ---- */
|
||||||
|
|
||||||
#define DATAROUTER_RECV(id, desc) \
|
#define DR_RECV(id, desc) \
|
||||||
DATAROUTER_WEAK void datarouter_on_recv_##id( \
|
DR_WEAK void dr_on_recv_##id( \
|
||||||
uint32_t port_id, const void *data, size_t len) \
|
uint32_t port_id, const void *data, size_t len) \
|
||||||
{ (void)port_id; (void)data; (void)len; }
|
{ (void)port_id; (void)data; (void)len; }
|
||||||
DATAROUTER_RECV_CAPABILITIES
|
DR_RECV_CAPABILITIES
|
||||||
#undef DATAROUTER_RECV
|
#undef DR_RECV
|
||||||
|
|
||||||
/* ---- 发送触发函数 ---- */
|
/* ---- 发送触发函数 ---- */
|
||||||
|
|
||||||
#define DATAROUTER_SEND(id, desc) \
|
#define DR_SEND(id, desc) \
|
||||||
int datarouter_send_##id(const void *data, size_t len) \
|
int dr_send_##id(const void *data, size_t len) \
|
||||||
{ \
|
{ \
|
||||||
if (!initialized) return -1; \
|
if (!initialized) return -1; \
|
||||||
int called = 0; \
|
int called = 0; \
|
||||||
for (uint32_t _p = 0; _p < DATAROUTER_MAX_PORTS; _p++) { \
|
for (uint32_t _p = 0; _p < DR_MAX_PORTS; _p++) { \
|
||||||
if (!ports[_p].in_use) continue; \
|
if (!ports[_p].in_use) continue; \
|
||||||
if (ports[_p].send_type != DATAROUTER_SEND_##id) continue; \
|
if (ports[_p].send_type != DR_SEND_##id) continue; \
|
||||||
for (int _h = 0; _h < ports[_p].count; _h++) { \
|
for (int _h = 0; _h < ports[_p].count; _h++) { \
|
||||||
ports[_p].handlers[_h](_p, data, len); \
|
ports[_p].handlers[_h](_p, data, len); \
|
||||||
called = 1; \
|
called = 1; \
|
||||||
@@ -77,74 +77,74 @@ DATAROUTER_RECV_CAPABILITIES
|
|||||||
} \
|
} \
|
||||||
return called ? 0 : -2; \
|
return called ? 0 : -2; \
|
||||||
}
|
}
|
||||||
DATAROUTER_SEND_CAPABILITIES
|
DR_SEND_CAPABILITIES
|
||||||
#undef DATAROUTER_SEND
|
#undef DR_SEND
|
||||||
|
|
||||||
/* ---- 端口管理 ---- */
|
/* ---- 端口管理 ---- */
|
||||||
|
|
||||||
void datarouter_init(void)
|
void dr_init(void)
|
||||||
{
|
{
|
||||||
if (initialized) return;
|
if (initialized) return;
|
||||||
memset(ports, 0, sizeof(ports));
|
memset(ports, 0, sizeof(ports));
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void datarouter_reset(void)
|
void dr_reset(void)
|
||||||
{
|
{
|
||||||
initialized = 0;
|
initialized = 0;
|
||||||
memset(ports, 0, sizeof(ports));
|
memset(ports, 0, sizeof(ports));
|
||||||
}
|
}
|
||||||
|
|
||||||
datarouter_port_t datarouter_port_create(void)
|
dr_port_t dr_port_create(void)
|
||||||
{
|
{
|
||||||
if (!initialized) return DATAROUTER_INVALID_PORT;
|
if (!initialized) return DR_INVALID_PORT;
|
||||||
for (int i = 0; i < DATAROUTER_MAX_PORTS; i++) {
|
for (int i = 0; i < DR_MAX_PORTS; i++) {
|
||||||
if (!ports[i].in_use) {
|
if (!ports[i].in_use) {
|
||||||
ports[i].in_use = 1;
|
ports[i].in_use = 1;
|
||||||
ports[i].send_type = -1;
|
ports[i].send_type = -1;
|
||||||
ports[i].count = 0;
|
ports[i].count = 0;
|
||||||
return (datarouter_port_t)i;
|
return (dr_port_t)i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DATAROUTER_INVALID_PORT;
|
return DR_INVALID_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void datarouter_port_delete(datarouter_port_t port)
|
void dr_port_delete(dr_port_t port)
|
||||||
{
|
{
|
||||||
if (!initialized) return;
|
if (!initialized) return;
|
||||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS) return;
|
if (port < 0 || port >= DR_MAX_PORTS) return;
|
||||||
ports[port].in_use = 0;
|
ports[port].in_use = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void datarouter_port_set_send_type(datarouter_port_t port, int cap_id)
|
void dr_port_set_send_type(dr_port_t port, int cap_id)
|
||||||
{
|
{
|
||||||
if (!initialized) return;
|
if (!initialized) return;
|
||||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return;
|
if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return;
|
||||||
ports[port].send_type = cap_id;
|
ports[port].send_type = cap_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int datarouter_port_get_send_type(datarouter_port_t port)
|
int dr_port_get_send_type(dr_port_t port)
|
||||||
{
|
{
|
||||||
if (!initialized) return -1;
|
if (!initialized) return -1;
|
||||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
|
if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1;
|
||||||
return ports[port].send_type;
|
return ports[port].send_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int datarouter_port_add_handler(datarouter_port_t port, datarouter_send_handler_t handler)
|
int dr_port_add_handler(dr_port_t port, dr_send_handler_t handler)
|
||||||
{
|
{
|
||||||
if (!initialized) return -1;
|
if (!initialized) return -1;
|
||||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
|
if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1;
|
||||||
if (ports[port].count >= DATAROUTER_MAX_HANDLERS_PER_PORT) return -2;
|
if (ports[port].count >= DR_MAX_HANDLERS_PER_PORT) return -2;
|
||||||
for (int i = 0; i < ports[port].count; i++)
|
for (int i = 0; i < ports[port].count; i++)
|
||||||
if (ports[port].handlers[i] == handler) return -3;
|
if (ports[port].handlers[i] == handler) return -3;
|
||||||
ports[port].handlers[ports[port].count++] = handler;
|
ports[port].handlers[ports[port].count++] = handler;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int datarouter_port_remove_handler(datarouter_port_t port, datarouter_send_handler_t handler)
|
int dr_port_remove_handler(dr_port_t port, dr_send_handler_t handler)
|
||||||
{
|
{
|
||||||
if (!initialized) return -1;
|
if (!initialized) return -1;
|
||||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
|
if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1;
|
||||||
for (int i = 0; i < ports[port].count; i++) {
|
for (int i = 0; i < ports[port].count; i++) {
|
||||||
if (ports[port].handlers[i] == handler) {
|
if (ports[port].handlers[i] == handler) {
|
||||||
ports[port].handlers[i] = ports[port].handlers[--ports[port].count];
|
ports[port].handlers[i] = ports[port].handlers[--ports[port].count];
|
||||||
@@ -154,26 +154,26 @@ int datarouter_port_remove_handler(datarouter_port_t port, datarouter_send_handl
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void datarouter_port_clear_handlers(datarouter_port_t port)
|
void dr_port_clear_handlers(dr_port_t port)
|
||||||
{
|
{
|
||||||
if (!initialized) return;
|
if (!initialized) return;
|
||||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return;
|
if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return;
|
||||||
ports[port].count = 0;
|
ports[port].count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int datarouter_port_handler_count(datarouter_port_t port)
|
int dr_port_handler_count(dr_port_t port)
|
||||||
{
|
{
|
||||||
if (!initialized) return -1;
|
if (!initialized) return -1;
|
||||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
|
if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1;
|
||||||
return ports[port].count;
|
return ports[port].count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- 元数据查询 ---- */
|
/* ---- 元数据查询 ---- */
|
||||||
|
|
||||||
int datarouter_send_cap_count(void) { return DATAROUTER_SEND_CAP_COUNT; }
|
int dr_send_cap_count(void) { return DR_SEND_CAP_COUNT; }
|
||||||
const char *datarouter_send_cap_name(int c) { return (c<0||c>=DATAROUTER_SEND_CAP_COUNT)?NULL:send_names[c]; }
|
const char *dr_send_cap_name(int c) { return (c<0||c>=DR_SEND_CAP_COUNT)?NULL:send_names[c]; }
|
||||||
const char *datarouter_send_cap_desc(int c) { return (c<0||c>=DATAROUTER_SEND_CAP_COUNT)?NULL:send_descs[c]; }
|
const char *dr_send_cap_desc(int c) { return (c<0||c>=DR_SEND_CAP_COUNT)?NULL:send_descs[c]; }
|
||||||
|
|
||||||
int datarouter_recv_cap_count(void) { return DATAROUTER_RECV_CAP_COUNT; }
|
int dr_recv_cap_count(void) { return DR_RECV_CAP_COUNT; }
|
||||||
const char *datarouter_recv_cap_name(int c) { return (c<0||c>=DATAROUTER_RECV_CAP_COUNT)?NULL:recv_names[c]; }
|
const char *dr_recv_cap_name(int c) { return (c<0||c>=DR_RECV_CAP_COUNT)?NULL:recv_names[c]; }
|
||||||
const char *datarouter_recv_cap_desc(int c) { return (c<0||c>=DATAROUTER_RECV_CAP_COUNT)?NULL:recv_descs[c]; }
|
const char *dr_recv_cap_desc(int c) { return (c<0||c>=DR_RECV_CAP_COUNT)?NULL:recv_descs[c]; }
|
||||||
|
|||||||
+46
-46
@@ -4,20 +4,20 @@
|
|||||||
*
|
*
|
||||||
* ## 概念
|
* ## 概念
|
||||||
*
|
*
|
||||||
* - **发送能力**:编译期声明的可发送报文类型,生成 datarouter_send_<id>(data, len)
|
* - **发送能力**:编译期声明的可发送报文类型,生成 dr_send_<id>(data, len)
|
||||||
* - **接收能力**:编译期声明的可接收报文类型,生成 datarouter_on_recv_<id>(port, data, len)
|
* - **接收能力**:编译期声明的可接收报文类型,生成 dr_on_recv_<id>(port, data, len)
|
||||||
* - **端口**:运行期创建的连接点,包含 send_type + handler 列表
|
* - **端口**:运行期创建的连接点,包含 send_type + handler 列表
|
||||||
*
|
*
|
||||||
* ## 路由
|
* ## 路由
|
||||||
*
|
*
|
||||||
* 调用 datarouter_send_<id>(data, len) 时,库遍历所有端口,
|
* 调用 dr_send_<id>(data, len) 时,库遍历所有端口,
|
||||||
* 找到 send_type 匹配的端口,逐一调用其全部 handler。无需指定从哪个端口发送。
|
* 找到 send_type 匹配的端口,逐一调用其全部 handler。无需指定从哪个端口发送。
|
||||||
*
|
*
|
||||||
* 接收侧由用户自行调用 datarouter_on_recv_<id>(port, data, len) 处理外设收到的数据。
|
* 接收侧由用户自行调用 dr_on_recv_<id>(port, data, len) 处理外设收到的数据。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DATAROUTER_H
|
#ifndef DR_H
|
||||||
#define DATAROUTER_H
|
#define DR_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -38,75 +38,75 @@ extern "C" {
|
|||||||
|
|
||||||
/* ========== 发送能力枚举 ========== */
|
/* ========== 发送能力枚举 ========== */
|
||||||
|
|
||||||
enum datarouter_send_cap {
|
enum dr_send_cap {
|
||||||
#define DATAROUTER_SEND(id, desc) DATAROUTER_SEND_##id,
|
#define DR_SEND(id, desc) DR_SEND_##id,
|
||||||
DATAROUTER_SEND_CAPABILITIES
|
DR_SEND_CAPABILITIES
|
||||||
#undef DATAROUTER_SEND
|
#undef DR_SEND
|
||||||
DATAROUTER_SEND_CAP_COUNT
|
DR_SEND_CAP_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ========== 接收能力枚举 ========== */
|
/* ========== 接收能力枚举 ========== */
|
||||||
|
|
||||||
enum datarouter_recv_cap {
|
enum dr_recv_cap {
|
||||||
#define DATAROUTER_RECV(id, desc) DATAROUTER_RECV_##id,
|
#define DR_RECV(id, desc) DR_RECV_##id,
|
||||||
DATAROUTER_RECV_CAPABILITIES
|
DR_RECV_CAPABILITIES
|
||||||
#undef DATAROUTER_RECV
|
#undef DR_RECV
|
||||||
DATAROUTER_RECV_CAP_COUNT
|
DR_RECV_CAP_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ========== 外设发送 handler ========== */
|
/* ========== 外设发送 handler ========== */
|
||||||
|
|
||||||
typedef void (*datarouter_send_handler_t)(uint32_t port_id, const void *data, size_t len);
|
typedef void (*dr_send_handler_t)(uint32_t port_id, const void *data, size_t len);
|
||||||
|
|
||||||
#ifndef DATAROUTER_MAX_HANDLERS_PER_PORT
|
#ifndef DR_MAX_HANDLERS_PER_PORT
|
||||||
#define DATAROUTER_MAX_HANDLERS_PER_PORT 4
|
#define DR_MAX_HANDLERS_PER_PORT 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========== 发送触发函数 ========== */
|
/* ========== 发送触发函数 ========== */
|
||||||
|
|
||||||
#define DATAROUTER_SEND(id, desc) \
|
#define DR_SEND(id, desc) \
|
||||||
int datarouter_send_##id(const void *data, size_t len);
|
int dr_send_##id(const void *data, size_t len);
|
||||||
DATAROUTER_SEND_CAPABILITIES
|
DR_SEND_CAPABILITIES
|
||||||
#undef DATAROUTER_SEND
|
#undef DR_SEND
|
||||||
|
|
||||||
/* ========== 接收回调声明 ========== */
|
/* ========== 接收回调声明 ========== */
|
||||||
|
|
||||||
#define DATAROUTER_RECV(id, desc) \
|
#define DR_RECV(id, desc) \
|
||||||
void datarouter_on_recv_##id(uint32_t port_id, const void *data, size_t len);
|
void dr_on_recv_##id(uint32_t port_id, const void *data, size_t len);
|
||||||
DATAROUTER_RECV_CAPABILITIES
|
DR_RECV_CAPABILITIES
|
||||||
#undef DATAROUTER_RECV
|
#undef DR_RECV
|
||||||
|
|
||||||
/* ========== 端口管理 API ========== */
|
/* ========== 端口管理 API ========== */
|
||||||
|
|
||||||
typedef int32_t datarouter_port_t;
|
typedef int32_t dr_port_t;
|
||||||
#define DATAROUTER_INVALID_PORT ((datarouter_port_t)-1)
|
#define DR_INVALID_PORT ((dr_port_t)-1)
|
||||||
|
|
||||||
void datarouter_init(void);
|
void dr_init(void);
|
||||||
void datarouter_reset(void);
|
void dr_reset(void);
|
||||||
|
|
||||||
datarouter_port_t datarouter_port_create(void);
|
dr_port_t dr_port_create(void);
|
||||||
void datarouter_port_delete(datarouter_port_t port);
|
void dr_port_delete(dr_port_t port);
|
||||||
|
|
||||||
void datarouter_port_set_send_type(datarouter_port_t port, int cap_id);
|
void dr_port_set_send_type(dr_port_t port, int cap_id);
|
||||||
int datarouter_port_get_send_type(datarouter_port_t port);
|
int dr_port_get_send_type(dr_port_t port);
|
||||||
|
|
||||||
int datarouter_port_add_handler(datarouter_port_t port, datarouter_send_handler_t handler);
|
int dr_port_add_handler(dr_port_t port, dr_send_handler_t handler);
|
||||||
int datarouter_port_remove_handler(datarouter_port_t port, datarouter_send_handler_t handler);
|
int dr_port_remove_handler(dr_port_t port, dr_send_handler_t handler);
|
||||||
void datarouter_port_clear_handlers(datarouter_port_t port);
|
void dr_port_clear_handlers(dr_port_t port);
|
||||||
int datarouter_port_handler_count(datarouter_port_t port);
|
int dr_port_handler_count(dr_port_t port);
|
||||||
|
|
||||||
/* ========== 能力元数据查询 ========== */
|
/* ========== 能力元数据查询 ========== */
|
||||||
|
|
||||||
int datarouter_send_cap_count(void);
|
int dr_send_cap_count(void);
|
||||||
const char *datarouter_send_cap_name(int cap_id);
|
const char *dr_send_cap_name(int cap_id);
|
||||||
const char *datarouter_send_cap_desc(int cap_id);
|
const char *dr_send_cap_desc(int cap_id);
|
||||||
|
|
||||||
int datarouter_recv_cap_count(void);
|
int dr_recv_cap_count(void);
|
||||||
const char *datarouter_recv_cap_name(int cap_id);
|
const char *dr_recv_cap_name(int cap_id);
|
||||||
const char *datarouter_recv_cap_desc(int cap_id);
|
const char *dr_recv_cap_desc(int cap_id);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* DATAROUTER_H */
|
#endif /* DR_H */
|
||||||
+16
-16
@@ -6,35 +6,35 @@
|
|||||||
* 用户可自定义此文件以实现自己的报文类型:
|
* 用户可自定义此文件以实现自己的报文类型:
|
||||||
*
|
*
|
||||||
* 1. 复制当前文件到你的项目目录
|
* 1. 复制当前文件到你的项目目录
|
||||||
* 2. 按需修改 DATAROUTER_SEND_CAPABILITIES / DATAROUTER_RECV_CAPABILITIES
|
* 2. 按需修改 DR_SEND_CAPABILITIES / DR_RECV_CAPABILITIES
|
||||||
* 3. 编译时添加 -I /path/to/your/config 覆盖库的默认配置
|
* 3. 编译时添加 -I /path/to/your/config 覆盖库的默认配置
|
||||||
*
|
*
|
||||||
* 覆盖后库将使用你的版本,无需修改库源代码。
|
* 覆盖后库将使用你的版本,无需修改库源代码。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DATAROUTER_CONFIG_H
|
#ifndef DR_CONFIG_H
|
||||||
#define DATAROUTER_CONFIG_H
|
#define DR_CONFIG_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def DATAROUTER_SEND_CAPABILITIES
|
* @def DR_SEND_CAPABILITIES
|
||||||
* @brief 发送能力列表
|
* @brief 发送能力列表
|
||||||
*
|
*
|
||||||
* 每行格式:DATAROUTER_SEND(标识符, "描述")
|
* 每行格式:DR_SEND(标识符, "描述")
|
||||||
* 每项生成:发送触发函数 datarouter_send_<id>(port, data, len)
|
* 每项生成:发送触发函数 dr_send_<id>(port, data, len)
|
||||||
*/
|
*/
|
||||||
#define DATAROUTER_SEND_CAPABILITIES \
|
#define DR_SEND_CAPABILITIES \
|
||||||
DATAROUTER_SEND(sensor, "Sensor data report") \
|
DR_SEND(sensor, "Sensor data report") \
|
||||||
DATAROUTER_SEND(status, "Device status report")
|
DR_SEND(status, "Device status report")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def DATAROUTER_RECV_CAPABILITIES
|
* @def DR_RECV_CAPABILITIES
|
||||||
* @brief 接收能力列表
|
* @brief 接收能力列表
|
||||||
*
|
*
|
||||||
* 每行格式:DATAROUTER_RECV(标识符, "描述")
|
* 每行格式:DR_RECV(标识符, "描述")
|
||||||
* 每项生成:接收回调声明 datarouter_on_recv_<id>(port, data, len)
|
* 每项生成:接收回调声明 dr_on_recv_<id>(port, data, len)
|
||||||
*/
|
*/
|
||||||
#define DATAROUTER_RECV_CAPABILITIES \
|
#define DR_RECV_CAPABILITIES \
|
||||||
DATAROUTER_RECV(rtcm, "RTCM correction data") \
|
DR_RECV(rtcm, "RTCM correction data") \
|
||||||
DATAROUTER_RECV(command, "Remote control command")
|
DR_RECV(command, "Remote control command")
|
||||||
|
|
||||||
#endif /* DATAROUTER_CONFIG_H */
|
#endif /* DR_CONFIG_H */
|
||||||
@@ -4,48 +4,48 @@
|
|||||||
*
|
*
|
||||||
* 使用方法:
|
* 使用方法:
|
||||||
* 1. 将此文件复制到你的项目目录,重命名为 datarouter_config.h
|
* 1. 将此文件复制到你的项目目录,重命名为 datarouter_config.h
|
||||||
* 2. 修改下面的 DATAROUTER_SEND_CAPABILITIES 和 DATAROUTER_RECV_CAPABILITIES
|
* 2. 修改下面的 DR_SEND_CAPABILITIES 和 DR_RECV_CAPABILITIES
|
||||||
* 3. 编译时添加 -I /path/to/your/project
|
* 3. 编译时添加 -I /path/to/your/project
|
||||||
* 4. 库将自动使用你的配置,无需修改库源代码
|
* 4. 库将自动使用你的配置,无需修改库源代码
|
||||||
*
|
*
|
||||||
* 格式说明:
|
* 格式说明:
|
||||||
* 发送能力:DATAROUTER_SEND(标识符, "描述")
|
* 发送能力:DR_SEND(标识符, "描述")
|
||||||
* 接收能力:DATAROUTER_RECV(标识符, "描述")
|
* 接收能力:DR_RECV(标识符, "描述")
|
||||||
*
|
*
|
||||||
* 标识符只能包含字母、数字、下划线。
|
* 标识符只能包含字母、数字、下划线。
|
||||||
* 描述为字符串字面量。
|
* 描述为字符串字面量。
|
||||||
*
|
*
|
||||||
* 示例配置:
|
* 示例配置:
|
||||||
* // 传感器设备:只需发送
|
* // 传感器设备:只需发送
|
||||||
* #define DATAROUTER_SEND_CAPABILITIES \
|
* #define DR_SEND_CAPABILITIES \
|
||||||
* DATAROUTER_SEND(sensor, "Sensor data report")
|
* DR_SEND(sensor, "Sensor data report")
|
||||||
* #define DATAROUTER_RECV_CAPABILITIES
|
* #define DR_RECV_CAPABILITIES
|
||||||
*
|
*
|
||||||
* // 遥控设备:只需接收
|
* // 遥控设备:只需接收
|
||||||
* #define DATAROUTER_SEND_CAPABILITIES
|
* #define DR_SEND_CAPABILITIES
|
||||||
* #define DATAROUTER_RECV_CAPABILITIES \
|
* #define DR_RECV_CAPABILITIES \
|
||||||
* DATAROUTER_RECV(command, "Remote command")
|
* DR_RECV(command, "Remote command")
|
||||||
*
|
*
|
||||||
* // 网关设备:同时收发
|
* // 网关设备:同时收发
|
||||||
* #define DATAROUTER_SEND_CAPABILITIES \
|
* #define DR_SEND_CAPABILITIES \
|
||||||
* DATAROUTER_SEND(status, "Status report")
|
* DR_SEND(status, "Status report")
|
||||||
* #define DATAROUTER_RECV_CAPABILITIES \
|
* #define DR_RECV_CAPABILITIES \
|
||||||
* DATAROUTER_RECV(config, "Configuration update")
|
* DR_RECV(config, "Configuration update")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DATAROUTER_CONFIG_H
|
#ifndef DR_CONFIG_H
|
||||||
#define DATAROUTER_CONFIG_H
|
#define DR_CONFIG_H
|
||||||
|
|
||||||
/* ========== 在此声明你的发送能力 ========== */
|
/* ========== 在此声明你的发送能力 ========== */
|
||||||
|
|
||||||
#define DATAROUTER_SEND_CAPABILITIES \
|
#define DR_SEND_CAPABILITIES \
|
||||||
DATAROUTER_SEND(sensor, "Sensor data report") \
|
DR_SEND(sensor, "Sensor data report") \
|
||||||
DATAROUTER_SEND(status, "Device status report")
|
DR_SEND(status, "Device status report")
|
||||||
|
|
||||||
/* ========== 在此声明你的接收能力 ========== */
|
/* ========== 在此声明你的接收能力 ========== */
|
||||||
|
|
||||||
#define DATAROUTER_RECV_CAPABILITIES \
|
#define DR_RECV_CAPABILITIES \
|
||||||
DATAROUTER_RECV(rtcm, "RTCM correction data") \
|
DR_RECV(rtcm, "RTCM correction data") \
|
||||||
DATAROUTER_RECV(command, "Remote control command")
|
DR_RECV(command, "Remote control command")
|
||||||
|
|
||||||
#endif /* DATAROUTER_CONFIG_H */
|
#endif /* DR_CONFIG_H */
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @file example.c
|
* @file example.c
|
||||||
*
|
*
|
||||||
* 调用 datarouter_send_sensor(data, len) 无需指定端口,
|
* 调用 dr_send_sensor(data, len) 无需指定端口,
|
||||||
* 库自动广播到所有 send_type=sensor 的端口。
|
* 库自动广播到所有 send_type=sensor 的端口。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -23,51 +23,51 @@ static void can_send(uint32_t port_id, const void *data, size_t len)
|
|||||||
printf("[CAN port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
printf("[CAN port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len)
|
void dr_on_recv_command(uint32_t port_id, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
printf("[RX:cmd port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
printf("[RX:cmd port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
datarouter_init();
|
dr_init();
|
||||||
|
|
||||||
printf("Capabilities:\n");
|
printf("Capabilities:\n");
|
||||||
for (int i = 0; i < datarouter_send_cap_count(); i++)
|
for (int i = 0; i < dr_send_cap_count(); i++)
|
||||||
printf(" SEND [%d] %s - %s\n", i,
|
printf(" SEND [%d] %s - %s\n", i,
|
||||||
datarouter_send_cap_name(i), datarouter_send_cap_desc(i));
|
dr_send_cap_name(i), dr_send_cap_desc(i));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 创建两个端口,都设 send_type=sensor,各绑不同外设。
|
* 创建两个端口,都设 send_type=sensor,各绑不同外设。
|
||||||
* 调用 datarouter_send_sensor() 时两个端口同时触发。
|
* 调用 dr_send_sensor() 时两个端口同时触发。
|
||||||
*/
|
*/
|
||||||
datarouter_port_t p1 = datarouter_port_create();
|
dr_port_t p1 = dr_port_create();
|
||||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p1, uart_send);
|
dr_port_add_handler(p1, uart_send);
|
||||||
datarouter_port_add_handler(p1, tcp_send);
|
dr_port_add_handler(p1, tcp_send);
|
||||||
|
|
||||||
datarouter_port_t p2 = datarouter_port_create();
|
dr_port_t p2 = dr_port_create();
|
||||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p2, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p2, can_send);
|
dr_port_add_handler(p2, can_send);
|
||||||
|
|
||||||
/* 不指定端口,自动广播到所有 sensor 端口 */
|
/* 不指定端口,自动广播到所有 sensor 端口 */
|
||||||
printf("\n--- send_sensor (auto-route to ALL sensor ports) ---\n");
|
printf("\n--- send_sensor (auto-route to ALL sensor ports) ---\n");
|
||||||
datarouter_send_sensor("temperature:25.3", 16);
|
dr_send_sensor("temperature:25.3", 16);
|
||||||
|
|
||||||
/* 运行时移除一个 handler,下次发送不再触发它 */
|
/* 运行时移除一个 handler,下次发送不再触发它 */
|
||||||
printf("\n--- remove TCP handler from p1, resend ---\n");
|
printf("\n--- remove TCP handler from p1, resend ---\n");
|
||||||
datarouter_port_remove_handler(p1, tcp_send);
|
dr_port_remove_handler(p1, tcp_send);
|
||||||
datarouter_send_sensor("temperature:26.1", 16);
|
dr_send_sensor("temperature:26.1", 16);
|
||||||
|
|
||||||
/* 接收侧:用户自行调用回调 */
|
/* 接收侧:用户自行调用回调 */
|
||||||
printf("\n--- recv command ---\n");
|
printf("\n--- recv command ---\n");
|
||||||
datarouter_on_recv_command(0, "reboot", 6);
|
dr_on_recv_command(0, "reboot", 6);
|
||||||
|
|
||||||
/* 删除一个端口,触发时不再走它 */
|
/* 删除一个端口,触发时不再走它 */
|
||||||
printf("\n--- delete p2 (CAN), resend ---\n");
|
printf("\n--- delete p2 (CAN), resend ---\n");
|
||||||
datarouter_port_delete(p2);
|
dr_port_delete(p2);
|
||||||
datarouter_send_sensor("temperature:27.0", 16);
|
dr_send_sensor("temperature:27.0", 16);
|
||||||
|
|
||||||
datarouter_port_delete(p1);
|
dr_port_delete(p1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+98
-98
@@ -16,14 +16,14 @@ static const char *_cur_name;
|
|||||||
|
|
||||||
#define FIXTURE_MAX 16
|
#define FIXTURE_MAX 16
|
||||||
typedef struct {
|
typedef struct {
|
||||||
datarouter_port_t ports[FIXTURE_MAX];
|
dr_port_t ports[FIXTURE_MAX];
|
||||||
int count;
|
int count;
|
||||||
} fixture_t;
|
} fixture_t;
|
||||||
|
|
||||||
#define FIXTURE_INIT(f) memset((f), 0, sizeof(*(f)))
|
#define FIXTURE_INIT(f) memset((f), 0, sizeof(*(f)))
|
||||||
#define FIXTURE_PUSH(f, p) do { if ((f)->count < FIXTURE_MAX) (f)->ports[(f)->count++] = (p); } while (0)
|
#define FIXTURE_PUSH(f, p) do { if ((f)->count < FIXTURE_MAX) (f)->ports[(f)->count++] = (p); } while (0)
|
||||||
#define FIXTURE_CLEAN(f) do { for (int _i = 0; _i < (f)->count; _i++) datarouter_port_delete((f)->ports[_i]); } while (0)
|
#define FIXTURE_CLEAN(f) do { for (int _i = 0; _i < (f)->count; _i++) dr_port_delete((f)->ports[_i]); } while (0)
|
||||||
#define FIXTURE_CREATE(f) ({ datarouter_port_t _p = datarouter_port_create(); FIXTURE_PUSH(f, _p); _p; })
|
#define FIXTURE_CREATE(f) ({ dr_port_t _p = dr_port_create(); FIXTURE_PUSH(f, _p); _p; })
|
||||||
|
|
||||||
#define TEST_START(name) \
|
#define TEST_START(name) \
|
||||||
static void test_##name(void) \
|
static void test_##name(void) \
|
||||||
@@ -68,7 +68,7 @@ static void reset_h(void) { _h_cnt = 0; _h_pos = 0; }
|
|||||||
* ================================================================ */
|
* ================================================================ */
|
||||||
|
|
||||||
TEST_START(error_uninit)
|
TEST_START(error_uninit)
|
||||||
CHECK(datarouter_send_sensor("d", 1) == -1, "expected -1");
|
CHECK(dr_send_sensor("d", 1) == -1, "expected -1");
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
/* ================================================================
|
/* ================================================================
|
||||||
@@ -82,22 +82,22 @@ TEST_END()
|
|||||||
TEST_START(port_create_max)
|
TEST_START(port_create_max)
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
datarouter_port_t p = datarouter_port_create();
|
dr_port_t p = dr_port_create();
|
||||||
if (p == DATAROUTER_INVALID_PORT) break;
|
if (p == DR_INVALID_PORT) break;
|
||||||
FIXTURE_PUSH(&_fix, p); c++;
|
FIXTURE_PUSH(&_fix, p); c++;
|
||||||
}
|
}
|
||||||
CHECK(c >= 64, "got %d", c);
|
CHECK(c >= 64, "got %d", c);
|
||||||
CHECK(datarouter_port_create() == DATAROUTER_INVALID_PORT, NULL);
|
CHECK(dr_port_create() == DR_INVALID_PORT, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(port_delete_invalid)
|
TEST_START(port_delete_invalid)
|
||||||
datarouter_port_delete(-1); datarouter_port_delete(999);
|
dr_port_delete(-1); dr_port_delete(999);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(port_default_state)
|
TEST_START(port_default_state)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
CHECK(datarouter_port_get_send_type(p) == -1, NULL);
|
CHECK(dr_port_get_send_type(p) == -1, NULL);
|
||||||
CHECK(datarouter_port_handler_count(p) == 0, NULL);
|
CHECK(dr_port_handler_count(p) == 0, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
/* ================================================================
|
/* ================================================================
|
||||||
@@ -105,26 +105,26 @@ TEST_END()
|
|||||||
* ================================================================ */
|
* ================================================================ */
|
||||||
|
|
||||||
TEST_START(send_type_set_get)
|
TEST_START(send_type_set_get)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
||||||
CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL);
|
CHECK(dr_port_get_send_type(p) == DR_SEND_sensor, NULL);
|
||||||
datarouter_port_set_send_type(p, -1);
|
dr_port_set_send_type(p, -1);
|
||||||
CHECK(datarouter_port_get_send_type(p) == -1, NULL);
|
CHECK(dr_port_get_send_type(p) == -1, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(handler_add_remove)
|
TEST_START(handler_add_remove)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
CHECK(datarouter_port_add_handler(p, _h) == 0, NULL);
|
CHECK(dr_port_add_handler(p, _h) == 0, NULL);
|
||||||
CHECK(datarouter_port_handler_count(p) == 1, NULL);
|
CHECK(dr_port_handler_count(p) == 1, NULL);
|
||||||
CHECK(datarouter_port_remove_handler(p, _h) == 0, NULL);
|
CHECK(dr_port_remove_handler(p, _h) == 0, NULL);
|
||||||
CHECK(datarouter_port_handler_count(p) == 0, NULL);
|
CHECK(dr_port_handler_count(p) == 0, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(handler_clear)
|
TEST_START(handler_clear)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_add_handler(p, _h);
|
dr_port_add_handler(p, _h);
|
||||||
datarouter_port_clear_handlers(p);
|
dr_port_clear_handlers(p);
|
||||||
CHECK(datarouter_port_handler_count(p) == 0, NULL);
|
CHECK(dr_port_handler_count(p) == 0, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
/* ================================================================
|
/* ================================================================
|
||||||
@@ -133,39 +133,39 @@ TEST_END()
|
|||||||
|
|
||||||
TEST_START(send_no_match_port)
|
TEST_START(send_no_match_port)
|
||||||
/* 没有端口配置该 send_type */
|
/* 没有端口配置该 send_type */
|
||||||
CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2");
|
CHECK(dr_send_sensor("d", 1) == -2, "expected -2");
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_one_port_one_handler)
|
TEST_START(send_one_port_one_handler)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p, _h);
|
dr_port_add_handler(p, _h);
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
||||||
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
||||||
CHECK(_h_port[0] == (int)p, "port=%d", _h_port[0]);
|
CHECK(_h_port[0] == (int)p, "port=%d", _h_port[0]);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_one_port_multi_handler)
|
TEST_START(send_one_port_multi_handler)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p, _h);
|
dr_port_add_handler(p, _h);
|
||||||
datarouter_port_add_handler(p, _h2);
|
dr_port_add_handler(p, _h2);
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
||||||
CHECK(_h_cnt == 2, "cnt=%d", _h_cnt);
|
CHECK(_h_cnt == 2, "cnt=%d", _h_cnt);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_multi_ports_same_type)
|
TEST_START(send_multi_ports_same_type)
|
||||||
/* 两个端口同类型,各一个 handler */
|
/* 两个端口同类型,各一个 handler */
|
||||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
dr_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
dr_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
||||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p2, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p1, _h);
|
dr_port_add_handler(p1, _h);
|
||||||
datarouter_port_add_handler(p2, _h);
|
dr_port_add_handler(p2, _h);
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
||||||
CHECK(_h_cnt == 2, "cnt=%d", _h_cnt);
|
CHECK(_h_cnt == 2, "cnt=%d", _h_cnt);
|
||||||
/* p1 和 p2 各触发一次 */
|
/* p1 和 p2 各触发一次 */
|
||||||
CHECK((_h_port[0]==p1 && _h_port[1]==p2) ||
|
CHECK((_h_port[0]==p1 && _h_port[1]==p2) ||
|
||||||
@@ -173,80 +173,80 @@ TEST_START(send_multi_ports_same_type)
|
|||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_multi_port_multi_handler)
|
TEST_START(send_multi_port_multi_handler)
|
||||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
dr_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
dr_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
||||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p2, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p1, _h);
|
dr_port_add_handler(p1, _h);
|
||||||
datarouter_port_add_handler(p1, _h2); /* p1 两个 */
|
dr_port_add_handler(p1, _h2); /* p1 两个 */
|
||||||
datarouter_port_add_handler(p2, _h3); /* p2 一个 */
|
dr_port_add_handler(p2, _h3); /* p2 一个 */
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
||||||
CHECK(_h_cnt == 3, "cnt=%d", _h_cnt);
|
CHECK(_h_cnt == 3, "cnt=%d", _h_cnt);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_type_filter)
|
TEST_START(send_type_filter)
|
||||||
/* 两个端口不同类型,只触发匹配的 */
|
/* 两个端口不同类型,只触发匹配的 */
|
||||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
dr_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
dr_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
||||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_status);
|
dr_port_set_send_type(p2, DR_SEND_status);
|
||||||
datarouter_port_add_handler(p1, _h);
|
dr_port_add_handler(p1, _h);
|
||||||
datarouter_port_add_handler(p2, _h);
|
dr_port_add_handler(p2, _h);
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
||||||
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
||||||
CHECK(_h_port[0] == (int)p1, "only p1 should fire");
|
CHECK(_h_port[0] == (int)p1, "only p1 should fire");
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_after_remove_handler)
|
TEST_START(send_after_remove_handler)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p, _h);
|
dr_port_add_handler(p, _h);
|
||||||
reset_h(); datarouter_send_sensor("d", 1); CHECK(_h_cnt == 1, NULL);
|
reset_h(); dr_send_sensor("d", 1); CHECK(_h_cnt == 1, NULL);
|
||||||
datarouter_port_remove_handler(p, _h);
|
dr_port_remove_handler(p, _h);
|
||||||
CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2 after remove");
|
CHECK(dr_send_sensor("d", 1) == -2, "expected -2 after remove");
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_after_delete_port)
|
TEST_START(send_after_delete_port)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p, _h);
|
dr_port_add_handler(p, _h);
|
||||||
datarouter_port_delete(p);
|
dr_port_delete(p);
|
||||||
CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2");
|
CHECK(dr_send_sensor("d", 1) == -2, "expected -2");
|
||||||
_fix.count--;
|
_fix.count--;
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_zero_length)
|
TEST_START(send_zero_length)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p, _h);
|
dr_port_add_handler(p, _h);
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor("x", 0) == 0, NULL);
|
CHECK(dr_send_sensor("x", 0) == 0, NULL);
|
||||||
CHECK(_h_cnt == 1, NULL);
|
CHECK(_h_cnt == 1, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_null_data)
|
TEST_START(send_null_data)
|
||||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
dr_port_t p = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p, DR_SEND_sensor);
|
||||||
datarouter_port_add_handler(p, _h);
|
dr_port_add_handler(p, _h);
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor(NULL, 0) == 0, NULL);
|
CHECK(dr_send_sensor(NULL, 0) == 0, NULL);
|
||||||
CHECK(_h_cnt == 1, NULL);
|
CHECK(_h_cnt == 1, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(send_multi_cap)
|
TEST_START(send_multi_cap)
|
||||||
/* 发送 status 不影响 sensor 端口 */
|
/* 发送 status 不影响 sensor 端口 */
|
||||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
dr_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
dr_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
dr_port_set_send_type(p1, DR_SEND_sensor);
|
||||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_status);
|
dr_port_set_send_type(p2, DR_SEND_status);
|
||||||
datarouter_port_add_handler(p1, _h);
|
dr_port_add_handler(p1, _h);
|
||||||
datarouter_port_add_handler(p2, _h);
|
dr_port_add_handler(p2, _h);
|
||||||
reset_h();
|
reset_h();
|
||||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
CHECK(dr_send_sensor("d", 1) == 0, NULL);
|
||||||
CHECK(_h_cnt == 1, "sensor: cnt=%d", _h_cnt);
|
CHECK(_h_cnt == 1, "sensor: cnt=%d", _h_cnt);
|
||||||
CHECK(datarouter_send_status("d", 1) == 0, NULL);
|
CHECK(dr_send_status("d", 1) == 0, NULL);
|
||||||
CHECK(_h_cnt == 2, "status: cnt=%d", _h_cnt);
|
CHECK(_h_cnt == 2, "status: cnt=%d", _h_cnt);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
@@ -255,12 +255,12 @@ TEST_END()
|
|||||||
* ================================================================ */
|
* ================================================================ */
|
||||||
|
|
||||||
static int _rx_r;
|
static int _rx_r;
|
||||||
void datarouter_on_recv_rtcm(uint32_t p, const void *d, size_t l)
|
void dr_on_recv_rtcm(uint32_t p, const void *d, size_t l)
|
||||||
{ (void)p; (void)d; (void)l; _rx_r++; }
|
{ (void)p; (void)d; (void)l; _rx_r++; }
|
||||||
|
|
||||||
TEST_START(recv_callback)
|
TEST_START(recv_callback)
|
||||||
_rx_r = 0;
|
_rx_r = 0;
|
||||||
datarouter_on_recv_rtcm(0, "d", 1);
|
dr_on_recv_rtcm(0, "d", 1);
|
||||||
CHECK(_rx_r == 1, "cnt=%d", _rx_r);
|
CHECK(_rx_r == 1, "cnt=%d", _rx_r);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
@@ -269,19 +269,19 @@ TEST_END()
|
|||||||
* ================================================================ */
|
* ================================================================ */
|
||||||
|
|
||||||
TEST_START(send_cap_meta)
|
TEST_START(send_cap_meta)
|
||||||
CHECK(datarouter_send_cap_count() == 2, NULL);
|
CHECK(dr_send_cap_count() == 2, NULL);
|
||||||
CHECK(strcmp(datarouter_send_cap_name(0), "sensor") == 0, NULL);
|
CHECK(strcmp(dr_send_cap_name(0), "sensor") == 0, NULL);
|
||||||
CHECK(strcmp(datarouter_send_cap_desc(0), "Sensor data report") == 0, NULL);
|
CHECK(strcmp(dr_send_cap_desc(0), "Sensor data report") == 0, NULL);
|
||||||
CHECK(datarouter_send_cap_name(-1) == NULL, NULL);
|
CHECK(dr_send_cap_name(-1) == NULL, NULL);
|
||||||
CHECK(datarouter_send_cap_name(99) == NULL, NULL);
|
CHECK(dr_send_cap_name(99) == NULL, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
TEST_START(recv_cap_meta)
|
TEST_START(recv_cap_meta)
|
||||||
CHECK(datarouter_recv_cap_count() == 2, NULL);
|
CHECK(dr_recv_cap_count() == 2, NULL);
|
||||||
CHECK(strcmp(datarouter_recv_cap_name(0), "rtcm") == 0, NULL);
|
CHECK(strcmp(dr_recv_cap_name(0), "rtcm") == 0, NULL);
|
||||||
CHECK(strcmp(datarouter_recv_cap_desc(0), "RTCM correction data") == 0, NULL);
|
CHECK(strcmp(dr_recv_cap_desc(0), "RTCM correction data") == 0, NULL);
|
||||||
CHECK(datarouter_recv_cap_name(-1) == NULL, NULL);
|
CHECK(dr_recv_cap_name(-1) == NULL, NULL);
|
||||||
CHECK(datarouter_recv_cap_desc(99) == NULL, NULL);
|
CHECK(dr_recv_cap_desc(99) == NULL, NULL);
|
||||||
TEST_END()
|
TEST_END()
|
||||||
|
|
||||||
/* ================================================================
|
/* ================================================================
|
||||||
@@ -297,7 +297,7 @@ int main(void)
|
|||||||
printf("[uninitialized]\n");
|
printf("[uninitialized]\n");
|
||||||
RUN(error_uninit);
|
RUN(error_uninit);
|
||||||
|
|
||||||
datarouter_init();
|
dr_init();
|
||||||
|
|
||||||
printf("\n[port management]\n");
|
printf("\n[port management]\n");
|
||||||
RUN(port_create_basic);
|
RUN(port_create_basic);
|
||||||
@@ -306,7 +306,7 @@ int main(void)
|
|||||||
RUN(port_default_state);
|
RUN(port_default_state);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
datarouter_reset(); datarouter_init();
|
dr_reset(); dr_init();
|
||||||
printf("[send_type & handler]\n");
|
printf("[send_type & handler]\n");
|
||||||
RUN(send_type_set_get);
|
RUN(send_type_set_get);
|
||||||
RUN(handler_add_remove);
|
RUN(handler_add_remove);
|
||||||
|
|||||||
Reference in New Issue
Block a user