These sections explain some concepts of Drogue Device.

Actor System

An actor system is a framework that allows for isolating state within narrow contexts, making it easier to reason about system. Within a actor system, the primary component is an Actor, which represents the boundary of state usage. Each actor has exclusive access to its own state and only communicates with other actors through message-passing.

Actor model example

Drogue Actor Model

Drogue Device Actor Model


Each actor is single-threaded, able to process a single message at a time, allowing for lock-free processing of each event. As embedded processors are globally single-threaded, supporting multiple actors requires the usage of async and .await within the Rust ecosystem. Each actor can therefore process each message either synchronously if its logic is non-blocking or using an async block if complex processing is required.

Each event is fully processed, in the order in which it is received, before the next event is considered.

While processing an event, an actor may send a message to another actor, which itself is an asynchronous action, allowing the system to continue to make progress with actors that are able to.


All messages are sent using async channels attached to each actor. The channel depth is configurable based on const generics.


Each actor within the system has its own unique Address which is used to communicate with the actor (through it’s FIFO). There is an async request(msg) method on each address to send a message asynchronously to the actor, which may only be used from another async context, as the sender must .await the response. There is also a sync notify(msg) method on each address to send a message without awaiting a response.

Specifically, the Address for a given actor may expose additional async methods or wrap an Address to facility fluent APIs for communicating with the underlying actor. For instance, the Socket type wraps an Address for actors that implement the TcpSocket trait.


Each actor is wrapped in a state object which is executed by the embassy runtime. When each state is mount(…​)`ed into the system, its `Address<…​> is made available.

Each Actor in the system defines the configuration it expects to get handed in its mount() implementation.

Bootstrap & Mounting

A top-level Device struct created by the application writer, maintain members for each actor. A static instance of DeviceContext is created to hold a static reference to the Device struct.

The application entry point is specified using a function marked with #[embassy::main], and it will be passed a Spawner that is used when mounting actors and packages.


In some cases, it may be desirable to have two or more actors involve in a single semantic component or package. The Package trait may be implemented for any type.