Apoidea's Embedded MQTT library
A small MQTT 3.1.1 client written in C99 for embedded/bare-metal targets, with no dynamic allocation and a cooperative, user-driven polling model.
- Handle-centric, no hidden state.
aemlib_client_tis a plain, non-opaque struct the caller owns and can allocate statically. - No dynamic allocation. The caller provides all buffers (TX/RX) up front; the library only ever references them.
- Cooperative polling. Nothing happens except inside
aemlib_poll(). Safe to call from a bare-metal loop or an RTOS task on a timer tick. - Pluggable everything. Transport, time, and storage are plain structs of function pointers plus a
void *ctx— swap in a real socket, a virtual/loopback transport, or a fake for tests without touching the client.
MQTT 3.1.1, QoS 0 only, for now. Working:
- Connect handshake with real CONNACK wait + timeout
- Publish / subscribe (QoS 0)
- Inbound PUBLISH delivered via an
on_messagecallback - Keepalive (PINGREQ)
- Clean disconnect
Planned features
- QoS 1 (packet IDs, retries, PUBACK)
- Offline/persistent queue are not implemented yet (the interface for it is defined and reserved however).
Requires CMake 3.20+ and a C99 compiler. A dev preset (Ninja, -Wall -Wextra) is provided:
cmake --preset dev
cmake --build --preset dev
ctest --preset dev --output-on-failureOr without presets:
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failureBuild options (both default ON): AEMLIB_BUILD_TESTS, AEMLIB_BUILD_EXAMPLES.
smoke_test: Includes<aemlib/aemlib.h>to test for API compatibility. Wired intoctest.pubsub_demo: A real client talking to a tiny fake broker over the virtual transport; proves connect → subscribe → publish → receive end to end. Wired intoctest.mqtt_broker_demo: Connects to a real public broker (test.mosquitto.org:1883) over a POSIX TCP transport. Built by default but not part ofctest(not hermetic).
Unit tests use Unity, fetched via CMake FetchContent. Run everything with ctest --preset dev.