Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e5bb33c
feat(rtps, cdr): Add `cdr` and `rtps` components
finger563 Jun 15, 2026
293a9fd
address comments
finger563 Jun 15, 2026
f9f4317
improve code
finger563 Jun 15, 2026
64634d9
update readmes
finger563 Jun 15, 2026
82bc51e
suppress cppcheck
finger563 Jun 15, 2026
9ab3e86
fix example docs
finger563 Jun 16, 2026
95979f3
fix some bugs in data parsing so that examples properly communicate. …
finger563 Jun 16, 2026
2f94376
Potential fix for pull request finding 'Empty except'
finger563 Jun 16, 2026
3b529fb
Potential fix for pull request finding
finger563 Jun 16, 2026
c4d76ef
Potential fix for pull request finding
finger563 Jun 16, 2026
78d6a3e
Potential fix for pull request finding
finger563 Jun 16, 2026
81f7bd6
Potential fix for pull request finding
finger563 Jun 16, 2026
70da4b6
Potential fix for pull request finding
finger563 Jun 16, 2026
ac317c6
Potential fix for pull request finding
finger563 Jun 16, 2026
20f4cd3
actually fix issues
finger563 Jun 16, 2026
1390dbe
fix issues
finger563 Jun 16, 2026
aa4cfd2
separate socket and rtps log levels
finger563 Jun 17, 2026
9e16e28
improve robustness and api correctness, esp. w.r.t. string operations
finger563 Jun 17, 2026
1e23f18
fix race
finger563 Jun 17, 2026
3943cb4
improve spec compliance
finger563 Jun 17, 2026
6efb044
wip improved api
finger563 Jun 18, 2026
58bce6d
clean up some more and fix some issues
finger563 Jun 18, 2026
578de25
make the crd de-/serialization format clearer for the example
finger563 Jun 18, 2026
10d216e
improve hash function
finger563 Jun 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ jobs:
target: esp32s3
- path: 'components/chsc6x/example'
target: esp32s3
- path: 'components/cdr/example'
target: esp32
- path: 'components/cli/example'
target: esp32
- path: 'components/cobs/example'
Expand Down Expand Up @@ -177,6 +179,8 @@ jobs:
target: esp32s3
- path: 'components/rmt/example'
target: esp32s3
- path: 'components/rtps/example'
target: esp32
- path: 'components/rtsp/example'
target: esp32
- path: 'components/runqueue/example'
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/upload_components.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ jobs:
components/button
components/byte90
components/chsc6x
components/cdr
components/cli
components/cobs
components/codec
Expand Down Expand Up @@ -109,6 +110,7 @@ jobs:
components/qwiicnes
components/remote_debug
components/rmt
components/rtps
components/rtsp
components/runqueue
components/rx8130ce
Expand Down
3 changes: 3 additions & 0 deletions components/cdr/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
idf_component_register(
INCLUDE_DIRS "include"
SRC_DIRS "src")
34 changes: 34 additions & 0 deletions components/cdr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# CDR (Common Data Representation) Component

[![Badge](https://components.espressif.com/components/espp/cdr/badge.svg)](https://components.espressif.com/components/espp/cdr)

The `cdr` component provides a small, standalone Common Data Representation
(CDR) reader/writer utility aimed at standards-oriented protocols such as
DDS/RTPS.

This initial slice is intentionally focused on the most immediately useful
pieces for building interoperable payloads:

- encapsulation identifiers for `CDR_BE`, `CDR_LE`, `PL_CDR_BE`, and `PL_CDR_LE`
- endian-aware primitive read/write helpers
- CDR alignment and padding handling
- string serialization helpers using the standard CDR length-prefix + null terminator format
- headerless/body helpers for CDR fields embedded inside larger protocol elements
- fixed-array helpers and zero-copy payload/span views
- sequence helpers for homogeneous primitive collections
- standalone usage without depending on RTPS or DDS layers

Current scope:

- good fit for building RTPS payloads and parameter lists incrementally
- designed to stay reusable outside DDS/RTPS
- **not** yet a full DDS XTypes / XCDR2 implementation

## Example

The [example](./example) demonstrates a small round-trip using:

- a little-endian CDR encapsulation header
- primitive values
- a CDR string
- a `uint16_t` sequence
21 changes: 21 additions & 0 deletions components/cdr/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.20)

set(ENV{IDF_COMPONENT_MANAGER} "0")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

set(EXTRA_COMPONENT_DIRS
"../../../components/"
)

set(
COMPONENTS
"main esptool_py cdr logger"
CACHE STRING
"List of components to include"
)

project(cdr_example)

set(CMAKE_CXX_STANDARD 20)
30 changes: 30 additions & 0 deletions components/cdr/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# CDR Example

This example demonstrates a small CDR round-trip using the `cdr` component.

It exercises:

- a little-endian CDR encapsulation header
- primitive value serialization
- CDR string serialization
- `uint16_t` sequence serialization
- fixed-array serialization with `write_array` / `read_array`
- headerless/body CDR helpers for embedding fields inside a larger protocol value
- round-trip parsing with `CdrReader`

## How to use example

### Build and Flash

Build the project and flash it to the board, then run monitor tool to view serial output:

```bash
idf.py -p PORT flash monitor
```

Replace `PORT` with the name of the serial port to use.

## Expected Output

The example logs the encoded byte count and the decoded values. It finishes by
printing `CDR round-trip succeeded`.
2 changes: 2 additions & 0 deletions components/cdr/example/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS ".")
68 changes: 68 additions & 0 deletions components/cdr/example/main/cdr_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <algorithm>
#include <array>
#include <string>
#include <vector>

#include "cdr.hpp"
#include "logger.hpp"

extern "C" void app_main(void) {
espp::Logger logger({.tag = "cdr_example", .level = espp::Logger::Verbosity::INFO});

std::array<uint8_t, 4> input_magic{'C', 'D', 'R', '!'};
std::array<uint16_t, 3> input_values{10, 20, 30};

//! [cdr example]
espp::CdrWriter writer({
.encapsulation = espp::CdrEncapsulation::CDR_LE,
.include_encapsulation = true,
});
writer.write<uint32_t>(42);
writer.write<float>(3.25f);
writer.write_string("hello cdr");
writer.write_sequence<uint16_t>(input_values);

auto payload = writer.take_buffer();
logger.info("Serialized {} bytes of CDR data", payload.size());

auto inline_writer = espp::CdrWriter::make_body_writer(espp::CdrEncapsulation::CDR_LE);
inline_writer.write_array(input_magic);
inline_writer.write_string("embedded field");
auto inline_payload =
espp::CdrWriter::encapsulate(inline_writer.payload(), espp::CdrEncapsulation::PL_CDR_LE);

espp::CdrReader reader(payload);
espp::CdrReader inline_reader(inline_payload);
uint32_t decoded_count = 0;
float decoded_scale = 0.0f;
std::string decoded_text;
std::vector<uint16_t> decoded_values;
std::array<uint8_t, 4> decoded_magic{};
std::string decoded_inline_text;

bool ok = reader.read<uint32_t>(decoded_count) && reader.read<float>(decoded_scale) &&
reader.read_string(decoded_text) && reader.read_sequence<uint16_t>(decoded_values);
bool inline_ok = inline_reader.encapsulation() == espp::CdrEncapsulation::PL_CDR_LE &&
inline_reader.read_array(decoded_magic) &&
inline_reader.read_string(decoded_inline_text);
//! [cdr example]

if (!ok || !inline_ok) {
logger.error("Failed to decode CDR payload");
return;
}

logger.info("Decoded count={}, scale={:.2f}, text='{}', sequence size={}, embedded='{}'",
decoded_count, decoded_scale, decoded_text, decoded_values.size(),
decoded_inline_text);

if (decoded_count != 42 || decoded_scale != 3.25f || decoded_text != "hello cdr" ||
decoded_values.size() != input_values.size() ||
!std::equal(decoded_values.begin(), decoded_values.end(), input_values.begin()) ||
decoded_magic != input_magic || decoded_inline_text != "embedded field") {
logger.error("CDR round-trip mismatch");
return;
}

logger.info("CDR round-trip succeeded");
}
1 change: 1 addition & 0 deletions components/cdr/example/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Intentionally minimal; this example only exercises the CDR helpers.
21 changes: 21 additions & 0 deletions components/cdr/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## IDF Component Manager Manifest File
license: "MIT"
description: "Common Data Representation (CDR) read/write helpers for ESP-IDF and cross-platform use."
url: "https://github.com/esp-cpp/espp/tree/main/components/cdr"
repository: "git://github.com/esp-cpp/espp.git"
maintainers:
- William Emfinger <waemfinger@gmail.com>
documentation: "https://esp-cpp.github.io/espp/cdr.html"
examples:
- path: example
tags:
- cpp
- Component
- CDR
- DDS
- RTPS
- Serialization
- XCDR
dependencies:
idf:
version: '>=5.0'
Loading
Loading