BTP — Binary Telemetry Protocol¶
BTP moves telemetry, logs, commands and terminal traffic between an embedded producer and a consumer, across links with opposite characteristics: a low-bandwidth radio with short datagrams and high loss, and a local bus with more bandwidth and a byte-stream shape. Every message carries an identity and an instant created at the source, and no intermediary rewrites either.
This repository is three things at once — the wire specification, the C++11 library that implements it, and the binary vectors that prove an implementation is correct. They ship as one version.
Current state¶
| Component | State |
|---|---|
Wire version == 0x01 |
Specified, implemented, covered by test-vectors/v1/. |
Wire version == 0x02 (AEAD payload) |
Specified, implemented in btp::aead with two ciphers, covered by test-vectors/v2/. |
COMMAND / CONTROL payload layout |
Specified, implemented in btp::messages, covered by test-vectors/v2/messages/. |
TELEMETRY sample body |
Specified, implemented in btp::telemetry (PACKED_LE / TLV_LE against a schema), covered by test-vectors/v2/telemetry/. |
| Command deduplication | Specified, implemented in btp::session (btp::DedupCache), covered by tests/test_session.cpp (behaviour, no vector tree). |
| The session lifecycle and inactivity watchdog, both sides | Implemented in btp::session (btp::Session, the responder; btp::SessionInitiator, the peer that connects out), covered by tests/test_session.cpp (behaviour, no vector tree). |
| Identity, sequencing and the transmit pipeline | Implemented in btp::endpoint (btp::Endpoint), covered by tests/test_endpoint.cpp (orchestration over the codec, no vector tree). |
| The decode + CRC + reassembly receive path | Implemented in btp::receiver (btp::Receiver), covered by tests/test_receiver.cpp (orchestration over the codec, no vector tree). |
The MANIFEST_DATA schema catalogue |
Implemented in btp::catalog (btp::Catalog), covered by tests/test_catalog.cpp (behaviour, no vector tree). |
Subscriptions (SUBSCRIBE / SUBSCRIBE_RESULT / UNSUBSCRIBE) |
Implemented in btp::subscription (btp::SubscriptionTable / btp::SubscriptionClient), covered by tests/test_subscription.cpp (behaviour, no vector tree). |
| Endpoint + receiver + session + catalogue + subscriptions, wired into one object | Implemented in btp::node (btp::Node, btp::StaticNode / btp::SizedNode), covered by tests/test_node.cpp (orchestration, no vector tree). |
| Version | 2.45.0 — one number, in include/btp/version.hpp; CMakeLists.txt parses it and library.json is checked against it. |
| Branches | main carries the newest major (introduced wire 0x02); 1.x keeps the wire 0x01 line alive. |
BTP is one SemVer line, MAJOR.MINOR.PATCH. MAJOR is also the newest
wire-version byte and the maintenance-branch name (MAJOR.x); the git tag is
vMAJOR.MINOR.PATCH. Versioning and branches
has the rule in full; released versions are on the
releases page.
Where to start¶
Deciding whether BTP fits your problem — read Why BTP exists. It is the only chapter that stands on its own, and it answers what the design buys, what it costs, and where it does not belong.
Integrating BTP into a project — read The model, then The datagram, then Using the library. Come back for the payload chapters when you need a specific channel.
Reimplementing BTP on another platform — read The datagram and
Getting it across the link in full, then the
payload chapters for the channels you need, then
the conformance vectors — the frame vectors
and, for the COMMAND / CONTROL payloads, test-vectors/v2/messages/. Your
implementation is not finished when you believe you understood the prose; it is
finished when it produces and consumes the same octets as the vectors.
The chapters¶
| Chapter | What it covers |
|---|---|
| Why BTP exists | The problem, what the design buys, what it costs, where it fits. |
| The model | Roles, the five logical channels, identity, time, delivery. |
| The datagram | The 36-octet header octet by octet, flags, CRC, validation. |
| Getting it across the link | Fragmentation, reassembly, and TransportLimits -- the five ready-made presets (ESP-NOW, Serial, USB HID, BLE, TCP), or a caller's own. |
| Encryption | Wire v2 AEAD: ciphers, nonce, the canonicalized AAD, and the limits. |
| Telemetry payloads | Topics, schemas, encodings, and how a client binds a field. |
| Commands and discovery | Requests, results, deduplication, the manifest, subscriptions, status. |
| Session and terminal | HELLO, session lifetime, the opaque terminal, priority under load. |
| Using the library | The API, btp::messages, btp::telemetry, btp::node, guarantees, build, vectors, versioning, known limits. |
Scope¶
This book covers what two implementations must agree on: the wire format, the shared library and the conformance vectors.
Deliberately out of scope: the internals of any particular consumer, toolchain tutorials, and the provisioning of identity and keys — a real operational requirement that stays off the wire, as Encryption explains.