Skip to content

type-one/PublishSubscribeESP32

Repository files navigation

PublishSubscribe Linux, Windows and FreeRTOS/ESP32

Agnostic, Lightweight and Portable Publish-Subscribe Helper adapted for FreeRTOS/ESP32

  • written in C++17/C++20/C++23 using templated classes
  • synchronous/asynchronous observer
  • topic subscription
  • buildable on FreeRTOS/ESP32 and Linux/Windows

Goodies:

  • simple thread-safe dictionary helper on top of std::map
  • simple thread-safe queue on top of std::queue
  • simple waitable object on top of FreeRTOS event_group or C++ std::mutex and std::condition_variable
  • simple non_copyable abstract class
  • simple periodic task helper on top of FreeRTOS task or C++ thread
  • simple worker task helper on top of FreeRTOS task or C++ thread
  • simple data processing task helper on top of FreeRTOS task or C++ thread
  • simple thread-safe ring buffer and iterable ring buffer on top of std::array
  • simple thread-safe resizeable ring buffer and iterable resizeable ring buffer on top of std::vector
  • simple single producer/single consumer lock-free ring buffer on top of std::array and scalar types/pointers
  • simple single producer/single consumer memory pipe on top of FreeRTOS memory buffer and lock-free ring buffer
  • simple chronological time list helper (thread-safe and non-thread-safe variants) on top of std::priority_queue
  • queuable commands
  • bytepack serialization in C++20 using header-only 3rd party (Faruk Eryilmaz - MIT license)
  • json serialization and deserialization using 3rd party with result-based API in this project (Dave Gamble & Dmitry Pankratov - MIT license)
  • gzip compression / decompression C++ wrapper using 3rd party (Paul Sokolovsky, Joergen Ibsen & Simon Tatham - Zlib license)
  • some logging macros
  • finite state machine based on std::variant, std::visit and overload pattern with transitions and states callbacks (based on Rainer Grimm and Bartlomiej Filipek C++ publications)
  • C++20 calendar day test
  • simple timer helper using 3rdparty (Michael Egli - MIT license) for standard implementation and using FreeRTOS timer for FreeRTOS platform
  • custom pool allocator for global new/new[]/delete/delete[]
  • tools::expected: lightweight result type for exception-free APIs, carrying either a value or a structured error
  • fixed-point arithmetic using header-only 3rd party fpm library (Mike Lankamp - MIT license)

GitHub repository

AI/Agent guidance files:

Third Parties used in the examples:

JSON integration note:

  • The project now uses the non-throwing cjsonpp API based on result values (parse_result, get, set, add, remove).
  • See main/cjsonpp/README.md for current usage examples.

Publications:

What

Test program written in C++17/C++20/C++23 to implement a simple Publish/Subscribe pattern.

The code is portable and lightweight.

C++20 is only required for the bytepack test in main.cpp C++20 enables the usage of coroutines in the async workers and enables concepts C++23 enables the usage of std::flap_map and native std::expected

Why

An attempt to write a flexible little framework that can be used on desktop PCs and embedded systems (micro-computers and micro-controllers) that are able to compile and run modern C++ code.

How

Can be compiled on FreeRTOS/ESP32, Linux and Windows, and should be easily adapted for other platforms (micro-computers, micro-controllers)

Build on FreeRTOS/ESP32

On FreeRTOS/ESP32 and Expressif-IDF SDK and Expressif Doc.

You can install the Expressif SDK easily under Linux or WSL2

git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
git checkout v5.5.4
git submodule update --init --recursive
./install.sh
cd ..

Change the version of the SDK accordingly in the git checkout command.

Assuming the ESP32 device is connected to an USB port on your PC

If you have an ESP32-S3, you can then use the following settings

source ~/esp-idf/export.sh

idf.py set-target esp32s3

idf.py build

idf.py flash monitor

Note: Ctrl-T Ctrl-X will exit the monitor.

For an ESP32 classic, just type idf.py set-target esp32 above instead.

If you have an ESP32-C5, type idf.py set-target esp32c5 and use a SDK that supports the Risc-V toolchain (ex. 5.5.1 or above).

If you develop under Windows/WSL2, this tool is useful to bind the serial port: usbipd-win.

Use then Powershell as admin and type

usbipd list

to get the list of USB devices.

Then bind and attach the USB device by typing the commands below with the proper BUSID:

usbipd bind --busid=<BUSID>
usbipd attach --wsl --busid=<BUSID>

Note: Under WSL2, if you get usbipd: error: Loading vhci_hcd failed. when launching usbipd attach --wsl --busid=<BUSID>, run sudo modprobe vhci_hcd in your Linux shell and retry.

Be sure to chmod 666 your /dev/ttyUSB0 or /dev/ttyACM0 if you got a flashing error.

Build on Linux and Windows

You need to go in the main sub-folder to find the proper cmake file for your system

cd main

rename CMakeLists.txt to CMakeLists.copy 

rename CMakeLists_PC.txt to CMakeLists.txt

Then

On Linux, just use cmake . -B build and then go to build and run make (or ninja)

On Windows, just use cmake-gui to generate a Visual Studio solution

Linux desktop build modes (speed vs analysis)

The desktop CMake files provide two build modes:

  • fast local build (default): clang-tidy disabled
  • analysis build: clang-tidy enabled explicitly

Fast local build (recommended for day-to-day dev):

cd main
cmake -S . -B build -G Ninja
cmake --build build -j

Analysis build (slower, static analysis enabled):

cd main
cmake -S . -B build_tidy -G Ninja -DENABLE_CLANG_TIDY=ON
cmake --build build_tidy -j

ccache is used as compiler launcher when available on Linux. To verify cache activity:

ccache -s

Useful maintenance commands:

ccache -z   # reset stats
ccache -s   # inspect hit/miss ratio after a build

Memory usage

If you build on Linux you can use valgrind to profile the memory usage (with or without custom allocator enabled):

valgrind --tool=massif ./publish_subscribe

massif-visualizer ./massif.out.xxxxxx

The purpose of the custom allocator is to pre-allocate tiny blocks and reuse them over the time to prevent memory fragmentation and to minimize the need to allocate new blocks from the heap.

Indeed heavy and high frequency usage of dynamic heap allocation for events/messages can cause memory fragmentation, in particular on platforms with a limited amount of memory available such as the ESP32.

More info on:

Valgrind and Massiv Valgrind manual About custom allocators

Components In main/

The main/ folder combines first-party framework code and bundled third-party dependencies used by the project.

  • bytepack/: third-party binary serialization library used for compact payload encoding/decoding in examples and tests.
  • CException/: third-party lightweight C-style exception support used by some vendor-side integrations.
  • cJSON/: third-party C JSON parser/printer backend used as the low-level JSON engine.
  • cjsonpp/: C++ wrapper over cJSON adapted in this repository to use result-based (exception-free) error handling.
  • cpptime/: portable timer component (CppTime::Timer) used for one-shot and periodic timeout scheduling on desktop builds.
  • fpm/: third-party header-only fixed-point arithmetic library used where deterministic fixed-point math is preferred.
  • portable_concurrency/: future/promise/executor-style asynchronous framework integrated with this project (result-oriented adaptation).
  • tools/: core first-party abstraction layer (tasks, synchronization primitives, observer/pub-sub helpers, containers, logging, utilities) with FreeRTOS and desktop backends.
  • uzlib/: third-party compression/decompression backend used by the gzip wrapper.
  • examples/: runnable sample scenarios that demonstrate framework usage patterns and integrations.
  • tests/: unit tests and validation coverage for framework modules and adapters.

Author

Laurent Lardinois / Type One (TFL-TDV)

LinkedIn profile

Demozoo profile

About

FreeRTOS/ESP32 C++17/C++23 Agnostic Publish-Subscribe Helper (with sync/async observer and topic subscription)

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages