Expand description
The goal of postcard-rpc
is to make it easier for a
host PC to talk to a constrained device, like a microcontroller.
See the repo for examples
§Architecture overview
┌──────────┐ ┌─────────┐ ┌───────────┐
│ Endpoint │ │ Publish │ │ Subscribe │
└──────────┘ └─────────┘ └───────────┘
│ ▲ message│ │ ▲
┌────────┐ rqst│ │resp │ subscribe│ │messages
┌─┤ CLIENT ├─────┼─────┼──────────────┼────────────────┼────────┼──┐
│ └────────┘ ▼ │ ▼ ▼ │ │
│ ┌─────────────────────────────────────────────────────┐ │ │
│ │ HostClient │ │ │
│ └─────────────────────────────────────────────────────┘ │ │
│ │ │ ▲ │ | │
│ │ │ │ │ │ │
│ │ │ │ ▼ │ │
│ │ │ ┌──────────────┬──────────────┐│
│ │ └─────▶│ Pending Resp │ Subscription ││
│ │ └──────────────┴──────────────┘│
│ │ ▲ ▲ │
│ │ └───────┬──────┘ │
│ ▼ │ │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ ││ Task: out_worker │ │ Task: in_worker ▲│ │
│ ├┼───────────────────┤ ├───────────────────┼┤ │
│ │▼ Trait: WireTx │ │ Trait: WireRx ││ │
└──────┴────────────────────┴────────────┴────────────────────┴────┘
│ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ▲
│ The Server + Client WireRx │
│ │ and WireTx traits can be │ │
│ impl'd for any wire │
│ │ transport like USB, TCP, │ │
│ I2C, UART, etc. │
▼ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │
┌─────┬────────────────────┬────────────┬────────────────────┬─────┐
│ ││ Trait: WireRx │ │ Trait: WireTx ▲│ │
│ ├┼───────────────────┤ ├───────────────────┼┤ │
│ ││ Server │ ┌───▶│ Sender ││ │
│ ├┼───────────────────┤ │ └────────────────────┘ │
│ │▼ Macro: Dispatch │ │ ▲ │
│ └────────────────────┘ │ │ │
│ ┌─────────┐ │ ┌──────────┐ │ ┌───────────┐ │ ┌───────────┐ │
│ │ Topic │ │ │ Endpoint │ │ │ Publisher │ │ │ Publisher │ │
│ │ fn │◀┼▶│ async fn │────┤ │ Task │─┼─│ Task │ │
│ │ Handler │ │ │ Handler │ │ └───────────┘ │ └───────────┘ │
│ └─────────┘ │ └──────────┘ │ │ │
│ ┌─────────┐ │ ┌──────────┐ │ ┌───────────┐ │ ┌───────────┐ │
│ │ Topic │ │ │ Endpoint │ │ │ Publisher │ │ │ Publisher │ │
│ │async fn │◀┴▶│ task │────┘ │ Task │─┴─│ Task │ │
│ │ Handler │ │ Handler │ └───────────┘ └───────────┘ │
│ └─────────┘ └──────────┘ │
│ ┌────────┐ │
└─┤ SERVER ├───────────────────────────────────────────────────────┘
└────────┘
§Defining a schema
Typically, you will define your “wire types” in a shared schema crate. This crate essentially defines the protocol used between two or more devices.
A schema consists of a couple of necessary items:
§Wire types
We will need to define all of the types that we will use within our protocol. We specify normal Rust types, which will need to implement or derive three important traits:
serde
’sSerialize
trait - which defines how we can convert a type into bytes on the wireserde
’sDeserialize
trait - which defines how we can convert bytes on the wire into a typepostcard_schema
’sSchema
trait - which generates a reflection-style schema value for a given type.
§Endpoints
Now that we have some basic types that will be used on the wire, we need to start building our protocol. The first thing we can build are Endpoints, which represent a bidirectional “Request”/“Response” relationship. One of our devices will act as a Client (who makes a request, and receives a response), and the other device will act as a Server (who receives a request, and sends a response). Every request should be followed (eventually) by exactly one response.
An endpoint consists of:
- The type of the Request
- The type of the Response
- A string “path”, like an HTTP URI that uniquely identifies the endpoint.
§Topics
Sometimes, you would just like to send data in a single direction, with no response. This could be for reasons like asynchronous logging, blindly sending sensor data periodically, or any other reason you can think of.
Topics have no “client” or “server” role, either device may decide to send a message on a given topic.
A topic consists of:
- The type of the Message
- A string “path”, like an HTTP URI that uniquely identifies the topic.
Modules§
- Accumulator tools
- URI and Schema Hashing
- Postcard-RPC Header Format
- A postcard-rpc host client
- Definitions of a postcard-rpc Server
- These are items you can use for your error path and error key.
- Test utilities for doctests and integration tests
- Create unique type lists at compile time
Macros§
- Define Dispatch Macro
- Endpoint macro
- Endpoints macro
merge_unique_types
collects all unique, non-primitive types contained by the given comma separated types. It can be used with any types that implement theSchema
trait, and returns a&'static [&'static NamedType]
.- Topic macro
- Topics macro
unique_types
collects all unique, non-primitive types contained by the given single type. It can be used with any type that implements theSchema
trait, and returns a&'static [&'static NamedType]
.
Structs§
- An overview of all topics (in and out) and endpoints
- An overview of a list of endpoints
- The
Key
uniquely identifies what “kind” of message this is. - A compacted 2-byte key
- A compacted 2-byte key
- A compacted 4-byte key
- An overview of a list of topics
Traits§
- A marker trait denoting a single endpoint
- A marker trait denoting a single topic