diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..1ec078b --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -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) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index fb53f46..2dc9623 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -11,16 +11,67 @@ jobs: with: fetch-depth: 0 - - name: Verify merge commit + # ── 自动标签:从合并进来的 PR body 提取 v*.*.* ── + - name: Auto-tag from merged PR + id: autotag run: | - PARENTS=$(git log --format="%P" -1 | wc -w) - [ "$PARENTS" -ge 2 ] || exit 78 + set -e + # 已有标签 → 跳过 + 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 id: tag run: | 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" - name: Install cross-compilers @@ -51,6 +102,12 @@ jobs: cmake --install "build-$name" --prefix "dist/$pkg" 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 run: | TAG="${{ steps.tag.outputs.tag }}" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b3825fb --- /dev/null +++ b/CHANGELOG.md @@ -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_()` → `dr_send_()` + - `datarouter_on_recv_()` → `dr_on_recv_()` + - `DATAROUTER_SEND_sensor` → `DR_SEND_sensor` + - `datarouter_port_t` → `dr_port_t` + - 配置宏 `DATAROUTER_SEND(...)` / `DATAROUTER_RECV(...)` → `DR_SEND(...)` / `DR_RECV(...)` +- **发送函数不再接收 port_id**:`dr_send_(data, len)` 自动广播到所有 send_type 匹配的端口 +- **端口移除 `recv_type`**:端口只保留 `send_type` + handler 列表,接收侧由用户自行调用 `dr_on_recv_()` + +### 🚀 新功能 + +- **自动广播路由**:调用 `dr_send_(data, len)` 时遍历所有端口,自动匹配 `send_type`,逐一调用 handler +- **外部配置覆盖**:`datarouter.h` 通过 `__has_include()` 优先加载用户配置,找不到时回退到库默认配置 +- **配置模板**:新增 `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 diff --git a/CMakeLists.txt b/CMakeLists.txt index e032277..be5fab3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,81 +3,69 @@ project(DataRouter C) set(CMAKE_C_STANDARD 11) -# ======== 静态库 ======== -add_library(DataRouter STATIC datarouter.c) -target_include_directories(DataRouter PUBLIC - $ - $ -) +# ── 选项 ────────────────────────────────────────────────────── -# ======== 共享库(可选,通过 BUILD_SHARED 控制) ======== -option(BUILD_SHARED "Build shared library" ON) -if(BUILD_SHARED) - add_library(DataRouter_shared SHARED datarouter.c) - target_include_directories(DataRouter_shared PUBLIC - $ - $ - ) - set_target_properties(DataRouter_shared PROPERTIES OUTPUT_NAME DataRouter) +option(DR_SOURCE_ONLY "Provide source/include vars instead of building lib" OFF) +option(DR_COMPILE_CHECK "Build compile-compatibility tests for each Cortex-M variant" OFF) + +# 源码路径变量:嵌入式项目直接 target_sources() 使用 +set(DR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/datarouter.c CACHE INTERNAL "") +set(DR_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "") + +# ── 编译兼容性矩阵 (仅在 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" + ) + 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() -# ======== 示例程序 ======== +# ── 源码直用模式(嵌入式项目) ────────────────────────────── + +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) add_executable(example example.c) target_link_libraries(example DataRouter) endif() -# ======== 测试 ======== if(BUILD_TESTING OR NOT DEFINED BUILD_TESTING) enable_testing() add_executable(test_datarouter tests/test_datarouter.c) target_link_libraries(test_datarouter DataRouter) add_test(NAME datarouter COMMAND test_datarouter) 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) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..7705720 --- /dev/null +++ b/CMakePresets.json @@ -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" } + ] +} diff --git a/DESIGN.md b/DESIGN.md index 15cfa8d..c671a88 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -2,14 +2,14 @@ ## 1. 设计目标 -轻量级 C 语言数据路由库。发送与接收能力分开声明,端口绑定 `send_type` 和外设 handler 列表。调用 `datarouter_send_(data, len)` 时自动遍历端口表,广播到所有 `send_type` 匹配的端口。 +轻量级 C 语言数据路由库。发送与接收能力分开声明,端口绑定 `send_type` 和外设 handler 列表。调用 `dr_send_(data, len)` 时自动遍历端口表,广播到所有 `send_type` 匹配的端口。 ### 核心设计 ``` -DATAROUTER_SEND_CAPABILITIES DATAROUTER_RECV_CAPABILITIES - DATAROUTER_SEND(sensor, ...) DATAROUTER_RECV(rtcm, ...) - DATAROUTER_SEND(status, ...) DATAROUTER_RECV(command, ...) +DR_SEND_CAPABILITIES DR_RECV_CAPABILITIES + DR_SEND(sensor, ...) DR_RECV(rtcm, ...) + DR_SEND(status, ...) DR_RECV(command, ...) │ │ ▼ ▼ 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` 注册物理外设发送函数 | | 自动广播 | `send_(data, len)` 遍历所有端口,自动匹配 send_type | | 不关心物理外设 | 库不依赖任何外设 API,只调用用户提供的 handler | @@ -46,7 +46,7 @@ left to right direction rectangle "用户代码" as User { component "应用逻辑\n调 send_(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 "接收回调\non_recv_()" as Callbacks } @@ -68,7 +68,7 @@ Callbacks --> Impl : 实现 on_recv_ | 文件 | 职责 | |------|------| -| `datarouter_config.h` | 声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` | +| `dr_config.h` | 声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` | | `datarouter.h` | 公共 API + X-macro 展开 | | `datarouter.c` | 端口表 + send 遍历 + 弱符号回调 | | `example.c` | 使用示例 | @@ -81,29 +81,29 @@ Callbacks --> Impl : 实现 on_recv_ ### 3.1 配置声明 ```c -#define DATAROUTER_SEND_CAPABILITIES \ - DATAROUTER_SEND(sensor, "Sensor data report") \ - DATAROUTER_SEND(status, "Device status report") +#define DR_SEND_CAPABILITIES \ + DR_SEND(sensor, "Sensor data report") \ + DR_SEND(status, "Device status report") -#define DATAROUTER_RECV_CAPABILITIES \ - DATAROUTER_RECV(rtcm, "RTCM correction data") \ - DATAROUTER_RECV(command, "Remote control command") +#define DR_RECV_CAPABILITIES \ + DR_RECV(rtcm, "RTCM correction data") \ + DR_RECV(command, "Remote control command") ``` ### 3.2 展开产物 ``` -DATAROUTER_SEND_CAPABILITIES 展开: +DR_SEND_CAPABILITIES 展开: enum: sensor = 0, status = 1, SEND_CAP_COUNT = 2 - 发送函数: int datarouter_send_sensor(const void *data, size_t len); - int datarouter_send_status(const void *data, size_t len); + 发送函数: int dr_send_sensor(const void *data, size_t len); + int dr_send_status(const void *data, size_t len); 元数据: send_names[] = {"sensor", "status"} send_descs[] = {"Sensor data report", "Device status report"} -DATAROUTER_RECV_CAPABILITIES 展开: +DR_RECV_CAPABILITIES 展开: enum: rtcm = 0, command = 1, RECV_CAP_COUNT = 2 - 接收回调: void datarouter_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_rtcm(uint32_t port, const void*, size_t); + void dr_on_recv_command(uint32_t port, const void*, size_t); 弱符号默认: 空实现,用户覆盖 元数据: recv_names[] = {"rtcm", "command"} recv_descs[] = {"RTCM correction data", "Remote control command"} @@ -127,18 +127,18 @@ DATAROUTER_RECV_CAPABILITIES 展开: @startuml == 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 -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 -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: 发送函数声明 -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: 接收回调声明 == datarouter.c == @@ -159,17 +159,17 @@ datarouter.c -> "7~8": send_names[] / send_descs[] / recv_names[] / recv_descs[] @startuml skinparam classAttributeIconSize 0 -enum "datarouter_send_cap" as S { SENSOR, STATUS, SEND_CAP_COUNT } -enum "datarouter_recv_cap" as R { RTCM, COMMAND, RECV_CAP_COUNT } +enum "dr_send_cap" as S { SENSOR, STATUS, SEND_CAP_COUNT } +enum "dr_recv_cap" as R { RTCM, COMMAND, RECV_CAP_COUNT } class "port_entry_t" as Entry { - int send_type - - datarouter_send_handler_t handlers[] + - dr_send_handler_t handlers[] - int count - 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) } @@ -193,11 +193,11 @@ Recv --> Entry : 用户根据业务调对应回调 ### 5.2 `port_entry_t` ```c -#define DATAROUTER_MAX_HANDLERS_PER_PORT 4 +#define DR_MAX_HANDLERS_PER_PORT 4 typedef struct { 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; uint8_t in_use; } port_entry_t; @@ -206,8 +206,8 @@ typedef struct { ### 5.3 端口表 ```c -#define DATAROUTER_MAX_PORTS 64 -static port_entry_t ports[DATAROUTER_MAX_PORTS]; +#define DR_MAX_PORTS 64 +static port_entry_t ports[DR_MAX_PORTS]; static uint8_t initialized; ``` @@ -218,30 +218,30 @@ static uint8_t initialized; ### 6.1 初始化 ```c -void datarouter_init(void); // 幂等初始化 -void datarouter_reset(void); // 重置全部状态 +void dr_init(void); // 幂等初始化 +void dr_reset(void); // 重置全部状态 ``` ### 6.2 端口管理 ```c -datarouter_port_t datarouter_port_create(void); -void datarouter_port_delete(datarouter_port_t port); +dr_port_t dr_port_create(void); +void dr_port_delete(dr_port_t port); -void datarouter_port_set_send_type(port, int cap_id); -int datarouter_port_get_send_type(port); +void dr_port_set_send_type(port, int cap_id); +int dr_port_get_send_type(port); -int datarouter_port_add_handler(port, handler); -int datarouter_port_remove_handler(port, handler); -void datarouter_port_clear_handlers(port); -int datarouter_port_handler_count(port); +int dr_port_add_handler(port, handler); +int dr_port_remove_handler(port, handler); +void dr_port_clear_handlers(port); +int dr_port_handler_count(port); ``` ### 6.3 发送触发函数(每个 SEND 能力生成一个) ```c -int datarouter_send_sensor(const void *data, size_t len); -int datarouter_send_status(const void *data, size_t len); +int dr_send_sensor(const void *data, size_t len); +int dr_send_status(const void *data, size_t len); ``` 返回值:0 成功 / -1 未初始化 / -2 无端口匹配该 send_type @@ -249,8 +249,8 @@ int datarouter_send_status(const void *data, size_t len); ### 6.4 接收回调(每个 RECV 能力生成一个声明) ```c -void datarouter_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_rtcm(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 能力元数据 ```c -int datarouter_send_cap_count(void); -const char *datarouter_send_cap_name(int cap_id); -const char *datarouter_send_cap_desc(int cap_id); +int dr_send_cap_count(void); +const char *dr_send_cap_name(int cap_id); +const char *dr_send_cap_desc(int cap_id); -int datarouter_recv_cap_count(void); -const char *datarouter_recv_cap_name(int cap_id); -const char *datarouter_recv_cap_desc(int cap_id); +int dr_recv_cap_count(void); +const char *dr_recv_cap_name(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 @startuml actor "应用" as App -participant "datarouter_send_sensor()" as Send +participant "dr_send_sensor()" as Send participant "端口表 ports[]" as Table participant "handlers[]" as HList participant "外设" as Dev @@ -349,16 +349,16 @@ Idle --> Created : 复用 ID ### 场景 1:sensor 广播到 UART + TCP + CAN ```c -datarouter_port_t p1 = datarouter_port_create(); -datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor); -datarouter_port_add_handler(p1, uart_send); -datarouter_port_add_handler(p1, tcp_send); +dr_port_t p1 = dr_port_create(); +dr_port_set_send_type(p1, DR_SEND_sensor); +dr_port_add_handler(p1, uart_send); +dr_port_add_handler(p1, tcp_send); -datarouter_port_t p2 = datarouter_port_create(); -datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor); -datarouter_port_add_handler(p2, can_send); +dr_port_t p2 = dr_port_create(); +dr_port_set_send_type(p2, DR_SEND_sensor); +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) // → tcp_send(p1, "temp:25.3", 9) // → can_send(p2, "temp:25.3", 9) @@ -367,16 +367,16 @@ datarouter_send_sensor("temp:25.3", 9); ### 场景 2:仅接收 ```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); } -// 外设收到后:datarouter_on_recv_rtcm(port, data, len); +// 外设收到后:dr_on_recv_rtcm(port, data, len); ``` ### 场景 3:运行时移除 handler ```c -datarouter_port_remove_handler(p1, tcp_send); +dr_port_remove_handler(p1, tcp_send); // 下次 send_sensor 不再触发 tcp ``` @@ -415,17 +415,17 @@ Weak ..> Result : 后备 ## 11. 配置扩展 ```c -#define DATAROUTER_SEND_CAPABILITIES \ - DATAROUTER_SEND(sensor, "Sensor data") \ - DATAROUTER_SEND(debug, "Debug log") /* 新增 */ +#define DR_SEND_CAPABILITIES \ + DR_SEND(sensor, "Sensor data") \ + DR_SEND(debug, "Debug log") /* 新增 */ -#define DATAROUTER_RECV_CAPABILITIES \ - DATAROUTER_RECV(rtcm, "RTCM data") \ - DATAROUTER_RECV(ota, "OTA firmware") /* 新增 */ +#define DR_RECV_CAPABILITIES \ + DR_RECV(rtcm, "RTCM data") \ + DR_RECV(ota, "OTA firmware") /* 新增 */ ``` ```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" ``` --- diff --git a/README.md b/README.md index ddd54a1..960516d 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # DataRouter -轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口绑定 `send_type` 和外设 handler 列表。调用 `datarouter_send_(data, len)` 时自动广播到所有匹配端口。 +轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口绑定 `send_type` 和外设 handler 列表。调用 `dr_send_(data, len)` 时自动广播到所有匹配端口。 ## 概念 | 术语 | 说明 | |------|------| -| **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `datarouter_send_(data, len)` | -| **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `datarouter_on_recv_(port, data, len)` | +| **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `dr_send_(data, len)` | +| **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `dr_on_recv_(port, data, len)` | | **端口 (Port)** | 运行期创建的连接点,包含 `send_type` + handler 列表 | | **Handler** | 用户实现的物理外设发送函数,一个端口可注册多个(默认上限 4) | @@ -15,19 +15,19 @@ ### 1. 声明能力 -创建自己的 `datarouter_config.h`(可参考 `datarouter_config_template.h`): +创建自己的 `dr_config.h`(可参考 `dr_config_template.h`): ```c -#define DATAROUTER_SEND_CAPABILITIES \ - DATAROUTER_SEND(sensor, "Sensor data report") \ - DATAROUTER_SEND(status, "Device status report") +#define DR_SEND_CAPABILITIES \ + DR_SEND(sensor, "Sensor data report") \ + DR_SEND(status, "Device status report") -#define DATAROUTER_RECV_CAPABILITIES \ - DATAROUTER_RECV(rtcm, "RTCM correction data") \ - DATAROUTER_RECV(command, "Remote control command") +#define DR_RECV_CAPABILITIES \ + DR_RECV(rtcm, "RTCM correction data") \ + DR_RECV(command, "Remote control command") ``` -> 库自带默认配置。将你的 `datarouter_config.h` 放到项目目录, +> 库自带默认配置。将你的 `dr_config.h` 放到项目目录, > 编译时添加 `-I /path/to/your/config` 即可覆盖。无需修改库源码。 > > ```cmake @@ -51,25 +51,25 @@ static void tcp_send(uint32_t port_id, const void *data, size_t len) { ### 3. 创建端口 ```c -datarouter_init(); +dr_init(); /* —— 传感器上报:sensor 报文走 UART + TCP —— */ -datarouter_port_t tx = datarouter_port_create(); -datarouter_port_set_send_type(tx, DATAROUTER_SEND_sensor); -datarouter_port_add_handler(tx, uart_send); -datarouter_port_add_handler(tx, tcp_send); +dr_port_t tx = dr_port_create(); +dr_port_set_send_type(tx, DR_SEND_sensor); +dr_port_add_handler(tx, uart_send); +dr_port_add_handler(tx, tcp_send); /* 不指定端口,库自动广播到所有 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. 实现接收回调 ```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); } ``` @@ -79,30 +79,30 @@ void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) { ### 初始化 ```c -void datarouter_init(void); // 幂等初始化 -void datarouter_reset(void); // 重置全部状态 +void dr_init(void); // 幂等初始化 +void dr_reset(void); // 重置全部状态 ``` ### 端口管理 ```c -datarouter_port_t datarouter_port_create(void); // 创建端口 -void datarouter_port_delete(datarouter_port_t port); // 删除 +dr_port_t dr_port_create(void); // 创建端口 +void dr_port_delete(dr_port_t port); // 删除 -void datarouter_port_set_send_type(port, int cap_id); // 设置发送类型 -int datarouter_port_get_send_type(port); // -1 = 未设置 +void dr_port_set_send_type(port, int cap_id); // 设置发送类型 +int dr_port_get_send_type(port); // -1 = 未设置 -int datarouter_port_add_handler(port, handler); // 注册外设 handler -int datarouter_port_remove_handler(port, handler); // 移除 -void datarouter_port_clear_handlers(port); // 清除全部 -int datarouter_port_handler_count(port); // 当前数量 +int dr_port_add_handler(port, handler); // 注册外设 handler +int dr_port_remove_handler(port, handler); // 移除 +void dr_port_clear_handlers(port); // 清除全部 +int dr_port_handler_count(port); // 当前数量 ``` ### 发送触发(每个 SEND 能力生成一个) ```c -int datarouter_send_sensor(const void *data, size_t len); // 0 成功 -int datarouter_send_status(const void *data, size_t len); // -1 未初始化 +int dr_send_sensor(const void *data, size_t len); // 0 成功 +int dr_send_status(const void *data, size_t len); // -1 未初始化 // -2 无匹配端口 ``` @@ -111,8 +111,8 @@ int datarouter_send_status(const void *data, size_t len); // -1 未初始化 ### 接收回调(每个 RECV 能力生成一个声明) ```c -void datarouter_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_rtcm(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 -int datarouter_send_cap_count(void); -const char *datarouter_send_cap_name(int cap_id); -const char *datarouter_send_cap_desc(int cap_id); +int dr_send_cap_count(void); +const char *dr_send_cap_name(int cap_id); +const char *dr_send_cap_desc(int cap_id); -int datarouter_recv_cap_count(void); -const char *datarouter_recv_cap_name(int cap_id); -const char *datarouter_recv_cap_desc(int cap_id); +int dr_recv_cap_count(void); +const char *dr_recv_cap_name(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 │ handlers[1]=tcp_send → TCP @@ -155,9 +155,65 @@ cmake --build build 可选配置: ```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 @@ -172,10 +228,10 @@ ctest --test-dir build ## 文件结构 ``` -datarouter_config.h 发送 + 接收能力配置(用户可覆盖) +dr_config.h 发送 + 接收能力配置(用户可覆盖) datarouter.h 公共 API + X-macro 展开 datarouter.c 实现(端口表 + send 遍历) -datarouter_config_template.h 外部配置模板 +dr_config_template.h 外部配置模板 example.c 使用示例 tests/test_datarouter.c 单元测试(22 用例) DESIGN.md 详细设计文档(含 PlantUML 图) diff --git a/build/DataRouterConfig.cmake b/build/DataRouterConfig.cmake new file mode 100644 index 0000000..a68423a --- /dev/null +++ b/build/DataRouterConfig.cmake @@ -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) diff --git a/build/example b/build/example index 6e019f2..c2ee587 100755 Binary files a/build/example and b/build/example differ diff --git a/build/test_datarouter b/build/test_datarouter index 4615576..2a205d0 100755 Binary files a/build/test_datarouter and b/build/test_datarouter differ diff --git a/datarouter.c b/datarouter.c index b3064b3..8cc2c76 100644 --- a/datarouter.c +++ b/datarouter.c @@ -6,70 +6,70 @@ #include #if defined(__GNUC__) || defined(__clang__) -#define DATAROUTER_WEAK __attribute__((weak)) +#define DR_WEAK __attribute__((weak)) #else -#define DATAROUTER_WEAK +#define DR_WEAK #endif -#ifndef DATAROUTER_MAX_PORTS -#define DATAROUTER_MAX_PORTS 64 +#ifndef DR_MAX_PORTS +#define DR_MAX_PORTS 64 #endif typedef struct { 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; uint8_t in_use; } port_entry_t; -static port_entry_t ports[DATAROUTER_MAX_PORTS]; +static port_entry_t ports[DR_MAX_PORTS]; static uint8_t initialized; /* ---- 元数据 ---- */ static const char *send_names[] = { -#define DATAROUTER_SEND(id, desc) #id, - DATAROUTER_SEND_CAPABILITIES -#undef DATAROUTER_SEND +#define DR_SEND(id, desc) #id, + DR_SEND_CAPABILITIES +#undef DR_SEND }; static const char *send_descs[] = { -#define DATAROUTER_SEND(id, desc) desc, - DATAROUTER_SEND_CAPABILITIES -#undef DATAROUTER_SEND +#define DR_SEND(id, desc) desc, + DR_SEND_CAPABILITIES +#undef DR_SEND }; static const char *recv_names[] = { -#define DATAROUTER_RECV(id, desc) #id, - DATAROUTER_RECV_CAPABILITIES -#undef DATAROUTER_RECV +#define DR_RECV(id, desc) #id, + DR_RECV_CAPABILITIES +#undef DR_RECV }; static const char *recv_descs[] = { -#define DATAROUTER_RECV(id, desc) desc, - DATAROUTER_RECV_CAPABILITIES -#undef DATAROUTER_RECV +#define DR_RECV(id, desc) desc, + DR_RECV_CAPABILITIES +#undef DR_RECV }; /* ---- 弱符号接收回调 ---- */ -#define DATAROUTER_RECV(id, desc) \ - DATAROUTER_WEAK void datarouter_on_recv_##id( \ +#define DR_RECV(id, desc) \ + DR_WEAK void dr_on_recv_##id( \ uint32_t port_id, const void *data, size_t len) \ { (void)port_id; (void)data; (void)len; } -DATAROUTER_RECV_CAPABILITIES -#undef DATAROUTER_RECV +DR_RECV_CAPABILITIES +#undef DR_RECV /* ---- 发送触发函数 ---- */ -#define DATAROUTER_SEND(id, desc) \ - int datarouter_send_##id(const void *data, size_t len) \ +#define DR_SEND(id, desc) \ + int dr_send_##id(const void *data, size_t len) \ { \ if (!initialized) return -1; \ 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].send_type != DATAROUTER_SEND_##id) continue; \ + if (ports[_p].send_type != DR_SEND_##id) continue; \ for (int _h = 0; _h < ports[_p].count; _h++) { \ ports[_p].handlers[_h](_p, data, len); \ called = 1; \ @@ -77,74 +77,74 @@ DATAROUTER_RECV_CAPABILITIES } \ return called ? 0 : -2; \ } -DATAROUTER_SEND_CAPABILITIES -#undef DATAROUTER_SEND +DR_SEND_CAPABILITIES +#undef DR_SEND /* ---- 端口管理 ---- */ -void datarouter_init(void) +void dr_init(void) { if (initialized) return; memset(ports, 0, sizeof(ports)); initialized = 1; } -void datarouter_reset(void) +void dr_reset(void) { initialized = 0; 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; - for (int i = 0; i < DATAROUTER_MAX_PORTS; i++) { + if (!initialized) return DR_INVALID_PORT; + for (int i = 0; i < DR_MAX_PORTS; i++) { if (!ports[i].in_use) { ports[i].in_use = 1; ports[i].send_type = -1; 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 (port < 0 || port >= DATAROUTER_MAX_PORTS) return; + if (port < 0 || port >= DR_MAX_PORTS) return; 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 (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; } -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 (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; } -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 (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1; - if (ports[port].count >= DATAROUTER_MAX_HANDLERS_PER_PORT) return -2; + if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1; + if (ports[port].count >= DR_MAX_HANDLERS_PER_PORT) return -2; for (int i = 0; i < ports[port].count; i++) if (ports[port].handlers[i] == handler) return -3; ports[port].handlers[ports[port].count++] = handler; 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 (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++) { if (ports[port].handlers[i] == handler) { 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; } -void datarouter_port_clear_handlers(datarouter_port_t port) +void dr_port_clear_handlers(dr_port_t port) { 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; } -int datarouter_port_handler_count(datarouter_port_t port) +int dr_port_handler_count(dr_port_t port) { 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; } /* ---- 元数据查询 ---- */ -int datarouter_send_cap_count(void) { return DATAROUTER_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 *datarouter_send_cap_desc(int c) { return (c<0||c>=DATAROUTER_SEND_CAP_COUNT)?NULL:send_descs[c]; } +int dr_send_cap_count(void) { return DR_SEND_CAP_COUNT; } +const char *dr_send_cap_name(int c) { return (c<0||c>=DR_SEND_CAP_COUNT)?NULL:send_names[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; } -const char *datarouter_recv_cap_name(int c) { return (c<0||c>=DATAROUTER_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]; } +int dr_recv_cap_count(void) { return DR_RECV_CAP_COUNT; } +const char *dr_recv_cap_name(int c) { return (c<0||c>=DR_RECV_CAP_COUNT)?NULL:recv_names[c]; } +const char *dr_recv_cap_desc(int c) { return (c<0||c>=DR_RECV_CAP_COUNT)?NULL:recv_descs[c]; } diff --git a/datarouter.h b/datarouter.h index ba1163b..ff89a33 100644 --- a/datarouter.h +++ b/datarouter.h @@ -4,20 +4,20 @@ * * ## 概念 * - * - **发送能力**:编译期声明的可发送报文类型,生成 datarouter_send_(data, len) - * - **接收能力**:编译期声明的可接收报文类型,生成 datarouter_on_recv_(port, data, len) + * - **发送能力**:编译期声明的可发送报文类型,生成 dr_send_(data, len) + * - **接收能力**:编译期声明的可接收报文类型,生成 dr_on_recv_(port, data, len) * - **端口**:运行期创建的连接点,包含 send_type + handler 列表 * * ## 路由 * - * 调用 datarouter_send_(data, len) 时,库遍历所有端口, + * 调用 dr_send_(data, len) 时,库遍历所有端口, * 找到 send_type 匹配的端口,逐一调用其全部 handler。无需指定从哪个端口发送。 * - * 接收侧由用户自行调用 datarouter_on_recv_(port, data, len) 处理外设收到的数据。 + * 接收侧由用户自行调用 dr_on_recv_(port, data, len) 处理外设收到的数据。 */ -#ifndef DATAROUTER_H -#define DATAROUTER_H +#ifndef DR_H +#define DR_H #include #include @@ -38,75 +38,75 @@ extern "C" { /* ========== 发送能力枚举 ========== */ -enum datarouter_send_cap { -#define DATAROUTER_SEND(id, desc) DATAROUTER_SEND_##id, - DATAROUTER_SEND_CAPABILITIES -#undef DATAROUTER_SEND - DATAROUTER_SEND_CAP_COUNT +enum dr_send_cap { +#define DR_SEND(id, desc) DR_SEND_##id, + DR_SEND_CAPABILITIES +#undef DR_SEND + DR_SEND_CAP_COUNT }; /* ========== 接收能力枚举 ========== */ -enum datarouter_recv_cap { -#define DATAROUTER_RECV(id, desc) DATAROUTER_RECV_##id, - DATAROUTER_RECV_CAPABILITIES -#undef DATAROUTER_RECV - DATAROUTER_RECV_CAP_COUNT +enum dr_recv_cap { +#define DR_RECV(id, desc) DR_RECV_##id, + DR_RECV_CAPABILITIES +#undef DR_RECV + DR_RECV_CAP_COUNT }; /* ========== 外设发送 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 -#define DATAROUTER_MAX_HANDLERS_PER_PORT 4 +#ifndef DR_MAX_HANDLERS_PER_PORT +#define DR_MAX_HANDLERS_PER_PORT 4 #endif /* ========== 发送触发函数 ========== */ -#define DATAROUTER_SEND(id, desc) \ - int datarouter_send_##id(const void *data, size_t len); -DATAROUTER_SEND_CAPABILITIES -#undef DATAROUTER_SEND +#define DR_SEND(id, desc) \ + int dr_send_##id(const void *data, size_t len); +DR_SEND_CAPABILITIES +#undef DR_SEND /* ========== 接收回调声明 ========== */ -#define DATAROUTER_RECV(id, desc) \ - void datarouter_on_recv_##id(uint32_t port_id, const void *data, size_t len); -DATAROUTER_RECV_CAPABILITIES -#undef DATAROUTER_RECV +#define DR_RECV(id, desc) \ + void dr_on_recv_##id(uint32_t port_id, const void *data, size_t len); +DR_RECV_CAPABILITIES +#undef DR_RECV /* ========== 端口管理 API ========== */ -typedef int32_t datarouter_port_t; -#define DATAROUTER_INVALID_PORT ((datarouter_port_t)-1) +typedef int32_t dr_port_t; +#define DR_INVALID_PORT ((dr_port_t)-1) -void datarouter_init(void); -void datarouter_reset(void); +void dr_init(void); +void dr_reset(void); -datarouter_port_t datarouter_port_create(void); -void datarouter_port_delete(datarouter_port_t port); +dr_port_t dr_port_create(void); +void dr_port_delete(dr_port_t port); -void datarouter_port_set_send_type(datarouter_port_t port, int cap_id); -int datarouter_port_get_send_type(datarouter_port_t port); +void dr_port_set_send_type(dr_port_t port, int cap_id); +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 datarouter_port_remove_handler(datarouter_port_t port, datarouter_send_handler_t handler); -void datarouter_port_clear_handlers(datarouter_port_t port); -int datarouter_port_handler_count(datarouter_port_t port); +int dr_port_add_handler(dr_port_t port, dr_send_handler_t handler); +int dr_port_remove_handler(dr_port_t port, dr_send_handler_t handler); +void dr_port_clear_handlers(dr_port_t port); +int dr_port_handler_count(dr_port_t port); /* ========== 能力元数据查询 ========== */ -int datarouter_send_cap_count(void); -const char *datarouter_send_cap_name(int cap_id); -const char *datarouter_send_cap_desc(int cap_id); +int dr_send_cap_count(void); +const char *dr_send_cap_name(int cap_id); +const char *dr_send_cap_desc(int cap_id); -int datarouter_recv_cap_count(void); -const char *datarouter_recv_cap_name(int cap_id); -const char *datarouter_recv_cap_desc(int cap_id); +int dr_recv_cap_count(void); +const char *dr_recv_cap_name(int cap_id); +const char *dr_recv_cap_desc(int cap_id); #ifdef __cplusplus } #endif -#endif /* DATAROUTER_H */ \ No newline at end of file +#endif /* DR_H */ \ No newline at end of file diff --git a/datarouter_config.h b/datarouter_config.h index 8086134..ba590b4 100644 --- a/datarouter_config.h +++ b/datarouter_config.h @@ -6,35 +6,35 @@ * 用户可自定义此文件以实现自己的报文类型: * * 1. 复制当前文件到你的项目目录 - * 2. 按需修改 DATAROUTER_SEND_CAPABILITIES / DATAROUTER_RECV_CAPABILITIES + * 2. 按需修改 DR_SEND_CAPABILITIES / DR_RECV_CAPABILITIES * 3. 编译时添加 -I /path/to/your/config 覆盖库的默认配置 * * 覆盖后库将使用你的版本,无需修改库源代码。 */ -#ifndef DATAROUTER_CONFIG_H -#define DATAROUTER_CONFIG_H +#ifndef DR_CONFIG_H +#define DR_CONFIG_H /** - * @def DATAROUTER_SEND_CAPABILITIES + * @def DR_SEND_CAPABILITIES * @brief 发送能力列表 * - * 每行格式:DATAROUTER_SEND(标识符, "描述") - * 每项生成:发送触发函数 datarouter_send_(port, data, len) + * 每行格式:DR_SEND(标识符, "描述") + * 每项生成:发送触发函数 dr_send_(port, data, len) */ -#define DATAROUTER_SEND_CAPABILITIES \ - DATAROUTER_SEND(sensor, "Sensor data report") \ - DATAROUTER_SEND(status, "Device status report") +#define DR_SEND_CAPABILITIES \ + DR_SEND(sensor, "Sensor data report") \ + DR_SEND(status, "Device status report") /** - * @def DATAROUTER_RECV_CAPABILITIES + * @def DR_RECV_CAPABILITIES * @brief 接收能力列表 * - * 每行格式:DATAROUTER_RECV(标识符, "描述") - * 每项生成:接收回调声明 datarouter_on_recv_(port, data, len) + * 每行格式:DR_RECV(标识符, "描述") + * 每项生成:接收回调声明 dr_on_recv_(port, data, len) */ -#define DATAROUTER_RECV_CAPABILITIES \ - DATAROUTER_RECV(rtcm, "RTCM correction data") \ - DATAROUTER_RECV(command, "Remote control command") +#define DR_RECV_CAPABILITIES \ + DR_RECV(rtcm, "RTCM correction data") \ + DR_RECV(command, "Remote control command") -#endif /* DATAROUTER_CONFIG_H */ \ No newline at end of file +#endif /* DR_CONFIG_H */ \ No newline at end of file diff --git a/datarouter_config_template.h b/datarouter_config_template.h index d102e4f..752a7af 100644 --- a/datarouter_config_template.h +++ b/datarouter_config_template.h @@ -4,48 +4,48 @@ * * 使用方法: * 1. 将此文件复制到你的项目目录,重命名为 datarouter_config.h - * 2. 修改下面的 DATAROUTER_SEND_CAPABILITIES 和 DATAROUTER_RECV_CAPABILITIES + * 2. 修改下面的 DR_SEND_CAPABILITIES 和 DR_RECV_CAPABILITIES * 3. 编译时添加 -I /path/to/your/project * 4. 库将自动使用你的配置,无需修改库源代码 * * 格式说明: - * 发送能力:DATAROUTER_SEND(标识符, "描述") - * 接收能力:DATAROUTER_RECV(标识符, "描述") + * 发送能力:DR_SEND(标识符, "描述") + * 接收能力:DR_RECV(标识符, "描述") * * 标识符只能包含字母、数字、下划线。 * 描述为字符串字面量。 * * 示例配置: * // 传感器设备:只需发送 - * #define DATAROUTER_SEND_CAPABILITIES \ - * DATAROUTER_SEND(sensor, "Sensor data report") - * #define DATAROUTER_RECV_CAPABILITIES + * #define DR_SEND_CAPABILITIES \ + * DR_SEND(sensor, "Sensor data report") + * #define DR_RECV_CAPABILITIES * * // 遥控设备:只需接收 - * #define DATAROUTER_SEND_CAPABILITIES - * #define DATAROUTER_RECV_CAPABILITIES \ - * DATAROUTER_RECV(command, "Remote command") + * #define DR_SEND_CAPABILITIES + * #define DR_RECV_CAPABILITIES \ + * DR_RECV(command, "Remote command") * * // 网关设备:同时收发 - * #define DATAROUTER_SEND_CAPABILITIES \ - * DATAROUTER_SEND(status, "Status report") - * #define DATAROUTER_RECV_CAPABILITIES \ - * DATAROUTER_RECV(config, "Configuration update") + * #define DR_SEND_CAPABILITIES \ + * DR_SEND(status, "Status report") + * #define DR_RECV_CAPABILITIES \ + * DR_RECV(config, "Configuration update") */ -#ifndef DATAROUTER_CONFIG_H -#define DATAROUTER_CONFIG_H +#ifndef DR_CONFIG_H +#define DR_CONFIG_H /* ========== 在此声明你的发送能力 ========== */ -#define DATAROUTER_SEND_CAPABILITIES \ - DATAROUTER_SEND(sensor, "Sensor data report") \ - DATAROUTER_SEND(status, "Device status report") +#define DR_SEND_CAPABILITIES \ + DR_SEND(sensor, "Sensor data report") \ + DR_SEND(status, "Device status report") /* ========== 在此声明你的接收能力 ========== */ -#define DATAROUTER_RECV_CAPABILITIES \ - DATAROUTER_RECV(rtcm, "RTCM correction data") \ - DATAROUTER_RECV(command, "Remote control command") +#define DR_RECV_CAPABILITIES \ + DR_RECV(rtcm, "RTCM correction data") \ + DR_RECV(command, "Remote control command") -#endif /* DATAROUTER_CONFIG_H */ \ No newline at end of file +#endif /* DR_CONFIG_H */ \ No newline at end of file diff --git a/example.c b/example.c index 5895b5e..6bca696 100644 --- a/example.c +++ b/example.c @@ -1,7 +1,7 @@ /** * @file example.c * - * 调用 datarouter_send_sensor(data, len) 无需指定端口, + * 调用 dr_send_sensor(data, len) 无需指定端口, * 库自动广播到所有 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); } -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); } int main(void) { - datarouter_init(); + dr_init(); 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, - datarouter_send_cap_name(i), datarouter_send_cap_desc(i)); + dr_send_cap_name(i), dr_send_cap_desc(i)); /* * 创建两个端口,都设 send_type=sensor,各绑不同外设。 - * 调用 datarouter_send_sensor() 时两个端口同时触发。 + * 调用 dr_send_sensor() 时两个端口同时触发。 */ - datarouter_port_t p1 = datarouter_port_create(); - datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p1, uart_send); - datarouter_port_add_handler(p1, tcp_send); + dr_port_t p1 = dr_port_create(); + dr_port_set_send_type(p1, DR_SEND_sensor); + dr_port_add_handler(p1, uart_send); + dr_port_add_handler(p1, tcp_send); - datarouter_port_t p2 = datarouter_port_create(); - datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p2, can_send); + dr_port_t p2 = dr_port_create(); + dr_port_set_send_type(p2, DR_SEND_sensor); + dr_port_add_handler(p2, can_send); /* 不指定端口,自动广播到所有 sensor 端口 */ 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,下次发送不再触发它 */ printf("\n--- remove TCP handler from p1, resend ---\n"); - datarouter_port_remove_handler(p1, tcp_send); - datarouter_send_sensor("temperature:26.1", 16); + dr_port_remove_handler(p1, tcp_send); + dr_send_sensor("temperature:26.1", 16); /* 接收侧:用户自行调用回调 */ 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"); - datarouter_port_delete(p2); - datarouter_send_sensor("temperature:27.0", 16); + dr_port_delete(p2); + dr_send_sensor("temperature:27.0", 16); - datarouter_port_delete(p1); + dr_port_delete(p1); return 0; } diff --git a/tests/test_datarouter.c b/tests/test_datarouter.c index 9e81b7b..facb0c2 100644 --- a/tests/test_datarouter.c +++ b/tests/test_datarouter.c @@ -16,14 +16,14 @@ static const char *_cur_name; #define FIXTURE_MAX 16 typedef struct { - datarouter_port_t ports[FIXTURE_MAX]; + dr_port_t ports[FIXTURE_MAX]; int count; } fixture_t; #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_CLEAN(f) do { for (int _i = 0; _i < (f)->count; _i++) datarouter_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_CLEAN(f) do { for (int _i = 0; _i < (f)->count; _i++) dr_port_delete((f)->ports[_i]); } while (0) +#define FIXTURE_CREATE(f) ({ dr_port_t _p = dr_port_create(); FIXTURE_PUSH(f, _p); _p; }) #define TEST_START(name) \ static void test_##name(void) \ @@ -68,7 +68,7 @@ static void reset_h(void) { _h_cnt = 0; _h_pos = 0; } * ================================================================ */ TEST_START(error_uninit) - CHECK(datarouter_send_sensor("d", 1) == -1, "expected -1"); + CHECK(dr_send_sensor("d", 1) == -1, "expected -1"); TEST_END() /* ================================================================ @@ -82,22 +82,22 @@ TEST_END() TEST_START(port_create_max) int c = 0; for (int i = 0; i < 64; i++) { - datarouter_port_t p = datarouter_port_create(); - if (p == DATAROUTER_INVALID_PORT) break; + dr_port_t p = dr_port_create(); + if (p == DR_INVALID_PORT) break; FIXTURE_PUSH(&_fix, p); 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_START(port_delete_invalid) - datarouter_port_delete(-1); datarouter_port_delete(999); + dr_port_delete(-1); dr_port_delete(999); TEST_END() TEST_START(port_default_state) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - CHECK(datarouter_port_get_send_type(p) == -1, NULL); - CHECK(datarouter_port_handler_count(p) == 0, NULL); + dr_port_t p = FIXTURE_CREATE(&_fix); + CHECK(dr_port_get_send_type(p) == -1, NULL); + CHECK(dr_port_handler_count(p) == 0, NULL); TEST_END() /* ================================================================ @@ -105,26 +105,26 @@ TEST_END() * ================================================================ */ TEST_START(send_type_set_get) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); - CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL); - datarouter_port_set_send_type(p, -1); - CHECK(datarouter_port_get_send_type(p) == -1, NULL); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p, DR_SEND_sensor); + CHECK(dr_port_get_send_type(p) == DR_SEND_sensor, NULL); + dr_port_set_send_type(p, -1); + CHECK(dr_port_get_send_type(p) == -1, NULL); TEST_END() TEST_START(handler_add_remove) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - CHECK(datarouter_port_add_handler(p, _h) == 0, NULL); - CHECK(datarouter_port_handler_count(p) == 1, NULL); - CHECK(datarouter_port_remove_handler(p, _h) == 0, NULL); - CHECK(datarouter_port_handler_count(p) == 0, NULL); + dr_port_t p = FIXTURE_CREATE(&_fix); + CHECK(dr_port_add_handler(p, _h) == 0, NULL); + CHECK(dr_port_handler_count(p) == 1, NULL); + CHECK(dr_port_remove_handler(p, _h) == 0, NULL); + CHECK(dr_port_handler_count(p) == 0, NULL); TEST_END() TEST_START(handler_clear) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_add_handler(p, _h); - datarouter_port_clear_handlers(p); - CHECK(datarouter_port_handler_count(p) == 0, NULL); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_add_handler(p, _h); + dr_port_clear_handlers(p); + CHECK(dr_port_handler_count(p) == 0, NULL); TEST_END() /* ================================================================ @@ -133,39 +133,39 @@ TEST_END() TEST_START(send_no_match_port) /* 没有端口配置该 send_type */ - CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2"); + CHECK(dr_send_sensor("d", 1) == -2, "expected -2"); TEST_END() TEST_START(send_one_port_one_handler) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p, _h); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p, DR_SEND_sensor); + dr_port_add_handler(p, _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_port[0] == (int)p, "port=%d", _h_port[0]); TEST_END() TEST_START(send_one_port_multi_handler) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p, _h); - datarouter_port_add_handler(p, _h2); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p, DR_SEND_sensor); + dr_port_add_handler(p, _h); + dr_port_add_handler(p, _h2); 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); TEST_END() TEST_START(send_multi_ports_same_type) /* 两个端口同类型,各一个 handler */ - datarouter_port_t p1 = FIXTURE_CREATE(&_fix); - datarouter_port_t p2 = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor); - datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p1, _h); - datarouter_port_add_handler(p2, _h); + dr_port_t p1 = FIXTURE_CREATE(&_fix); + dr_port_t p2 = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p1, DR_SEND_sensor); + dr_port_set_send_type(p2, DR_SEND_sensor); + dr_port_add_handler(p1, _h); + dr_port_add_handler(p2, _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); /* p1 和 p2 各触发一次 */ CHECK((_h_port[0]==p1 && _h_port[1]==p2) || @@ -173,80 +173,80 @@ TEST_START(send_multi_ports_same_type) TEST_END() TEST_START(send_multi_port_multi_handler) - datarouter_port_t p1 = FIXTURE_CREATE(&_fix); - datarouter_port_t p2 = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor); - datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p1, _h); - datarouter_port_add_handler(p1, _h2); /* p1 两个 */ - datarouter_port_add_handler(p2, _h3); /* p2 一个 */ + dr_port_t p1 = FIXTURE_CREATE(&_fix); + dr_port_t p2 = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p1, DR_SEND_sensor); + dr_port_set_send_type(p2, DR_SEND_sensor); + dr_port_add_handler(p1, _h); + dr_port_add_handler(p1, _h2); /* p1 两个 */ + dr_port_add_handler(p2, _h3); /* p2 一个 */ 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); TEST_END() TEST_START(send_type_filter) /* 两个端口不同类型,只触发匹配的 */ - datarouter_port_t p1 = FIXTURE_CREATE(&_fix); - datarouter_port_t p2 = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor); - datarouter_port_set_send_type(p2, DATAROUTER_SEND_status); - datarouter_port_add_handler(p1, _h); - datarouter_port_add_handler(p2, _h); + dr_port_t p1 = FIXTURE_CREATE(&_fix); + dr_port_t p2 = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p1, DR_SEND_sensor); + dr_port_set_send_type(p2, DR_SEND_status); + dr_port_add_handler(p1, _h); + dr_port_add_handler(p2, _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_port[0] == (int)p1, "only p1 should fire"); TEST_END() TEST_START(send_after_remove_handler) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p, _h); - reset_h(); datarouter_send_sensor("d", 1); CHECK(_h_cnt == 1, NULL); - datarouter_port_remove_handler(p, _h); - CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2 after remove"); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p, DR_SEND_sensor); + dr_port_add_handler(p, _h); + reset_h(); dr_send_sensor("d", 1); CHECK(_h_cnt == 1, NULL); + dr_port_remove_handler(p, _h); + CHECK(dr_send_sensor("d", 1) == -2, "expected -2 after remove"); TEST_END() TEST_START(send_after_delete_port) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p, _h); - datarouter_port_delete(p); - CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2"); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p, DR_SEND_sensor); + dr_port_add_handler(p, _h); + dr_port_delete(p); + CHECK(dr_send_sensor("d", 1) == -2, "expected -2"); _fix.count--; TEST_END() TEST_START(send_zero_length) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p, _h); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p, DR_SEND_sensor); + dr_port_add_handler(p, _h); reset_h(); - CHECK(datarouter_send_sensor("x", 0) == 0, NULL); + CHECK(dr_send_sensor("x", 0) == 0, NULL); CHECK(_h_cnt == 1, NULL); TEST_END() TEST_START(send_null_data) - datarouter_port_t p = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); - datarouter_port_add_handler(p, _h); + dr_port_t p = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p, DR_SEND_sensor); + dr_port_add_handler(p, _h); reset_h(); - CHECK(datarouter_send_sensor(NULL, 0) == 0, NULL); + CHECK(dr_send_sensor(NULL, 0) == 0, NULL); CHECK(_h_cnt == 1, NULL); TEST_END() TEST_START(send_multi_cap) /* 发送 status 不影响 sensor 端口 */ - datarouter_port_t p1 = FIXTURE_CREATE(&_fix); - datarouter_port_t p2 = FIXTURE_CREATE(&_fix); - datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor); - datarouter_port_set_send_type(p2, DATAROUTER_SEND_status); - datarouter_port_add_handler(p1, _h); - datarouter_port_add_handler(p2, _h); + dr_port_t p1 = FIXTURE_CREATE(&_fix); + dr_port_t p2 = FIXTURE_CREATE(&_fix); + dr_port_set_send_type(p1, DR_SEND_sensor); + dr_port_set_send_type(p2, DR_SEND_status); + dr_port_add_handler(p1, _h); + dr_port_add_handler(p2, _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(datarouter_send_status("d", 1) == 0, NULL); + CHECK(dr_send_status("d", 1) == 0, NULL); CHECK(_h_cnt == 2, "status: cnt=%d", _h_cnt); TEST_END() @@ -255,12 +255,12 @@ TEST_END() * ================================================================ */ 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++; } TEST_START(recv_callback) _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); TEST_END() @@ -269,19 +269,19 @@ TEST_END() * ================================================================ */ TEST_START(send_cap_meta) - CHECK(datarouter_send_cap_count() == 2, NULL); - CHECK(strcmp(datarouter_send_cap_name(0), "sensor") == 0, NULL); - CHECK(strcmp(datarouter_send_cap_desc(0), "Sensor data report") == 0, NULL); - CHECK(datarouter_send_cap_name(-1) == NULL, NULL); - CHECK(datarouter_send_cap_name(99) == NULL, NULL); + CHECK(dr_send_cap_count() == 2, NULL); + CHECK(strcmp(dr_send_cap_name(0), "sensor") == 0, NULL); + CHECK(strcmp(dr_send_cap_desc(0), "Sensor data report") == 0, NULL); + CHECK(dr_send_cap_name(-1) == NULL, NULL); + CHECK(dr_send_cap_name(99) == NULL, NULL); TEST_END() TEST_START(recv_cap_meta) - CHECK(datarouter_recv_cap_count() == 2, NULL); - CHECK(strcmp(datarouter_recv_cap_name(0), "rtcm") == 0, NULL); - CHECK(strcmp(datarouter_recv_cap_desc(0), "RTCM correction data") == 0, NULL); - CHECK(datarouter_recv_cap_name(-1) == NULL, NULL); - CHECK(datarouter_recv_cap_desc(99) == NULL, NULL); + CHECK(dr_recv_cap_count() == 2, NULL); + CHECK(strcmp(dr_recv_cap_name(0), "rtcm") == 0, NULL); + CHECK(strcmp(dr_recv_cap_desc(0), "RTCM correction data") == 0, NULL); + CHECK(dr_recv_cap_name(-1) == NULL, NULL); + CHECK(dr_recv_cap_desc(99) == NULL, NULL); TEST_END() /* ================================================================ @@ -297,7 +297,7 @@ int main(void) printf("[uninitialized]\n"); RUN(error_uninit); - datarouter_init(); + dr_init(); printf("\n[port management]\n"); RUN(port_create_basic); @@ -306,7 +306,7 @@ int main(void) RUN(port_default_state); printf("\n"); - datarouter_reset(); datarouter_init(); + dr_reset(); dr_init(); printf("[send_type & handler]\n"); RUN(send_type_set_get); RUN(handler_add_remove);