From 44da815c1d52601686797fdcfbf82e6f6c7f1a8f Mon Sep 17 00:00:00 2001 From: PonomarevDA Date: Tue, 3 Feb 2026 21:52:43 +0300 Subject: [PATCH] docs: add migration guide --- docs/migration_guide_v0_5_to_v0_6.md | 144 +++++++++++++++++++++++++++ docs/migration_guide_v0_6_to_v0_7.md | 130 ++++++++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 docs/migration_guide_v0_5_to_v0_6.md create mode 100644 docs/migration_guide_v0_6_to_v0_7.md diff --git a/docs/migration_guide_v0_5_to_v0_6.md b/docs/migration_guide_v0_5_to_v0_6.md new file mode 100644 index 0000000..3b955ae --- /dev/null +++ b/docs/migration_guide_v0_5_to_v0_6.md @@ -0,0 +1,144 @@ +# libdcnode v0.5.x → v0.6.x Migration Guide + +This guide summarizes the breaking changes between v0.5.x and v0.6.0 and provides concrete migration steps and code updates. The key theme is the **new standalone library build model** and **explicit platform/params hooks**. + +## Summary + +v0.6.0 turns libdcnode into a standalone CMake library with explicit integration points. The previous “source-include” model is removed. Your application must now: + +- `add_subdirectory(libdcnode)` and link `libdcnode::libdcnode`. +- Provide a `ParamsApi` and `PlatformApi` at runtime. +- Include headers via the new `libdcnode/...` paths. + +## Breaking Changes + +1. **Build integration changed** + v0.5.x expected you to include libdcnode sources directly in your app and set CMake variables. In v0.6.0, libdcnode is a standalone static library with its own `CMakeLists.txt` and exported target `libdcnode::libdcnode`. + +2. **New `uavcanInitApplication` signature** + v0.5.x: + `int16_t uavcanInitApplication(uint8_t node_id);` + + v0.6.x: + `int16_t uavcanInitApplication(ParamsApi params_api, PlatformApi platform_api, const AppInfo* app_info);` + +3. **Explicit platform hooks** + The platform functions are now provided via `PlatformApi` (function pointers for time, restart, UID, CAN driver). The weak default implementations that existed in `src/weak.c` are no longer linked. + +4. **Explicit params API** + Parameters are now accessed via a function table (`ParamsApi`) instead of global functions. The library no longer reaches into the app’s `params.*` globals directly. + +5. **Header paths moved under `include/libdcnode`** + All public headers are now under `include/libdcnode/...` and should be included as `#include "libdcnode/..."`. + +## Migration Steps + +1. **Update CMake integration** + v0.5.x used a variable-based model; v0.6.0 uses `add_subdirectory` and linking: + +```cmake +# libdcnode +add_subdirectory(${ROOT_DIR} ${CMAKE_BINARY_DIR}/libdcnode) + +# platform config +set(CAN_PLATFORM socketcan) # bxcan, fdcan, socketcan +include(${ROOT_DIR}/platform_specific/${CAN_PLATFORM}/config.cmake) + +# libparams +set(LIBPARAMS_PLATFORM ubuntu) # stm32f103, stm32g0b1, ubuntu +include(libparams.cmake) + +# application target +add_executable(${PROJECT_NAME} ... ${DRONECAN_PLATFORM_SOURCES} ...) +target_include_directories(${PROJECT_NAME} PRIVATE ... ${DRONECAN_PLATFORM_HEADERS} ...) +target_link_libraries(${PROJECT_NAME} PRIVATE libdcnode::libdcnode) +``` + +2. **Update includes** + +```cpp +// v0.5.x +#include "dronecan.h" +#include "publisher.hpp" +#include "subscriber.hpp" + +// v0.6.x +#include "libdcnode/dronecan.h" +#include "libdcnode/publisher.hpp" +#include "libdcnode/subscriber.hpp" +#include "libdcnode/can_driver.h" +``` + +3. **Implement `ParamsApi` and `PlatformApi`** + v0.6.0 requires explicit API structs at init time. The Ubuntu example in `examples/ubuntu/main.cpp` shows the full wiring. + +```cpp +ParamsApi params_api = { + .getName = paramsGetName, + .isInteger = paramsIsInteger, + .isString = paramsIsString, + .find = paramsFind, + .save = paramsSave, + .resetToDefault = paramsResetToDefault, + .integer = { + .setValue = paramsSetIntegerValue, + .getValue = paramsGetIntegerValue, + .getMin = paramsGetIntegerMin, + .getMax = paramsGetIntegerMax, + .getDef = paramsGetIntegerDef, + }, + .string = { + .setValue = paramsSetStringValue, + .getValue = paramsGetStringValue, + }, +}; + +PlatformApi platform_api = { + .getTimeMs = platformSpecificGetTimeMs, + .requestRestart = platformSpecificRequestRestart, + .readUniqueId = platformSpecificReadUniqueID, + .can = { + .init = canDriverInit, + .recv = canDriverReceive, + .send = canDriverTransmit, + .getRxOverflowCount = canDriverGetRxOverflowCount, + .getErrorCount = canDriverGetErrorCount, + }, +}; + +AppInfo app_info = { + .node_id = node_id, + .node_name = APP_NODE_NAME, + .vcs_commit = GIT_HASH >> 32, + .sw_version_major = APP_VERSION_MAJOR, + .sw_version_minor = APP_VERSION_MINOR, + .hw_version_major = HW_VERSION_MAJOR, + .hw_version_minor = HW_VERSION_MINOR, +}; + +uavcanInitApplication(params_api, platform_api, &app_info); +``` + +4. **Provide platform callbacks** + The app must implement: + +```cpp +uint32_t platformSpecificGetTimeMs(); +bool platformSpecificRequestRestart(); +void platformSpecificReadUniqueID(uint8_t out_uid[16]); +``` + +No weak defaults are linked in v0.6.0. + +## v0.6.0 Behavior Changes to Note + +- Node info data (name, SW/HW versions, VCS commit) now comes from `AppInfo` rather than preprocessor macros in libdcnode. +- Param and platform access are delegated through function tables instead of direct function calls. + +## Upgrade Checklist + +- Convert your build to `add_subdirectory` + `target_link_libraries(... libdcnode::libdcnode)`. +- Update header include paths to `libdcnode/...`. +- Provide `ParamsApi` and `PlatformApi` at `uavcanInitApplication()`. +- Implement required platform callbacks (time, restart, UID). +- Ensure params wiring matches your existing `libparams` usage. diff --git a/docs/migration_guide_v0_6_to_v0_7.md b/docs/migration_guide_v0_6_to_v0_7.md new file mode 100644 index 0000000..42b5910 --- /dev/null +++ b/docs/migration_guide_v0_6_to_v0_7.md @@ -0,0 +1,130 @@ +# libdcnode v0.6.x → v0.7.x Migration Guide + +This guide covers changes introduced in v0.7.0 and verifies that v0.7.1 and v0.7.2 do not add additional breaking API changes. It focuses on upgrade steps, build impacts, and code updates needed to move from v0.6.x to v0.7.x safely. + +## Summary + +v0.7.x introduces build-time DSDL code generation and reorganizes DSDL headers. The core C API is still present, but the library now requires a C++ toolchain because `src/dronecan.c` became `src/dronecan.cpp` and `include/libdcnode/dronecan.h` now includes `include/libdcnode/platform.hpp` (C++). Existing serialization headers were moved under `include/libdcnode/legacy`, and new generated message types are provided via `dronecan_msgs.h`. + +## Breaking Changes + +1. C++ is now required + The core implementation is compiled as C++ (`src/dronecan.cpp`) and `dronecan.h` includes `platform.hpp`, which uses C++ constructs. Pure C-only builds that previously included `dronecan.h` will fail. Your application must be compiled as C++ (or at least any translation unit including `dronecan.h`). + +2. DSDL headers moved to legacy paths + All manually maintained DSDL headers previously under `include/libdcnode/uavcan/...` and `include/libdcnode/dronecan/...` were moved under `include/libdcnode/legacy/...`. Any includes that use the old paths must be updated. + +3. New generated DSDL types and field layout + v0.7.x generates DSDL messages at configure time via `Libs/dronecan_dsdlc`. The generated types use different names and struct layouts (e.g., dynamic arrays become `{ .len, .data }`). If you switch to generated types, you must update message types and field access. + +4. Macro name collisions if you mix legacy and generated headers + Some generated headers define the same macro names as legacy headers. If you include both, you can get redefinition conflicts. Choose one serialization path per translation unit. The Ubuntu example uses `#undef` as a temporary workaround; you should avoid mixing where possible. + +## Migration Steps + +1. Update submodules + The DSDL source tree and compiler are now submodules. Ensure they are present: + +```bash +git submodule update --init --recursive +``` + +2. Build system updates + v0.7.x generates serialization during CMake configure. `CMakeLists.txt` already wires this up when you add the library via `add_subdirectory(libdcnode)`. Make sure Python 3 is available and `requirements.txt` is installed if you run tests or regenerate code. + +3. Pick a serialization path + +Option A. Use generated DSDL (recommended for v0.7.x) +- Include `dronecan_msgs.h` (generated in the build tree and added to include paths by CMake). +- Use the new C++ wrappers in `include/libdcnode/pub.hpp` and `include/libdcnode/sub.hpp`. +- Update types and field access to generated layout. + +Option B. Keep legacy serialization (minimal code changes) +- Update includes from `libdcnode/uavcan/...` to `libdcnode/legacy/uavcan/...`. +- Update includes from `libdcnode/dronecan/...` to `libdcnode/legacy/dronecan/...`. +- Continue to use `include/libdcnode/publisher.hpp` and `include/libdcnode/subscriber.hpp`. +- Do not include `dronecan_msgs.h` in the same translation unit to avoid macro conflicts. + +4. Update platform API includes + The platform API types now live in `include/libdcnode/platform.hpp`. This header is included by `dronecan.h`, so any file that includes `dronecan.h` must be compiled as C++. + +## Code Update Examples + +### Example 1: ArrayCommand fields and types + +v0.6.x (legacy types) + +```cpp +ArrayCommand_t msg; +for (size_t i = 0; i < msg.size; i++) { + if (msg.commads[i].actuator_id == 0) { + // ... + } +} +``` + +v0.7.x (generated types) + +```cpp +uavcan_equipment_actuator_ArrayCommand msg; +for (size_t i = 0; i < msg.commands.len; i++) { + if (msg.commands.data[i].actuator_id == 0) { + // ... + } +} +``` + +### Example 2: RawCommand size access + +v0.6.x + +```cpp +void rc_callback(const RawCommand_t& msg) { + std::cout << msg.size << std::endl; +} +``` + +v0.7.x + +```cpp +void rc_callback(const uavcan_equipment_esc_RawCommand& msg) { + std::cout << msg.cmd.len << std::endl; +} +``` + +### Example 3: New pub/sub wrappers + +v0.6.x + +```cpp +DronecanSubscriber raw_command_sub; +raw_command_sub.init(&rc_callback); + +DronecanPeriodicPublisher circuit_status(2.0f); +``` + +v0.7.x + +```cpp +libdcnode::DronecanSub raw_command_sub; +raw_command_sub.init(&rc_callback); + +libdcnode::DronecanPeriodicPub circuit_status(2.0f); +``` + +## v0.7.1 and v0.7.2 Notes + +No additional breaking API changes were introduced after v0.7.0. Changes in v0.7.1 and v0.7.2 are build and safety improvements: +- DSDL generation now avoids rewriting files unnecessarily and fixes the `canard.h` include path. +- `DRONECAN_MAX_SUBS_NUMBER` default increased to 15. +- New pub/sub wrappers (`pub.hpp`, `sub.hpp`) gained minor improvements and safer subscription handling. +- README and example updates only. + +## Upgrade Checklist + +- Ensure a C++ compiler is used for any translation unit including `libdcnode/dronecan.h`. +- Update submodules and ensure the DSDL generator is present. +- Decide on generated DSDL vs legacy headers and update includes accordingly. +- If using generated DSDL, update message types and field access for dynamic arrays. +- Avoid mixing legacy headers and generated headers in the same translation unit. +- Rebuild and run the Ubuntu example or your tests to validate NodeStatus/GetNodeInfo behavior.