#[mqtt_topic]
Expand description
Generate a typed MQTT subscriber and/or publisher from a struct and topic pattern
This macro analyzes the annotated struct and generates:
FromMqttMessage
trait implementation for message conversion (if subscriber enabled)- Helper constants (
TOPIC_PATTERN
,MQTT_PATTERN
) - Async
subscribe()
method for easy subscription (if subscriber enabled) publish()
andget_publisher()
methods for publishing (if publisher enabled)
§Arguments
The macro takes a topic pattern string and optional mode flags:
#[mqtt_topic("pattern")]
- Generate both subscriber and publisher (default)#[mqtt_topic("pattern", subscriber)]
- Generate only subscriber#[mqtt_topic("pattern", publisher)]
- Generate only publisher#[mqtt_topic("pattern", subscriber, publisher)]
- Generate both (explicit)
The pattern can include:
- Literal segments:
sensors
,data
,status
- Named wildcards:
{sensor_id}
,{room}
,{device_type}
- Anonymous wildcards:
+
(single level),#
(multi-level, subscriber-only)
§Struct Requirements
The annotated struct must:
- Be a struct with named fields
- Only contain fields that correspond to:
- Topic parameters (matching
{param}
names in the pattern) payload
field (optional, for message data)topic
field (optional, must beArc<TopicMatch>
)
- Topic parameters (matching
§Generated Code
For a struct annotated with #[mqtt_topic("sensors/{id}/data")]
:
ⓘ
// Subscriber functionality (if enabled)
impl<DE> FromMqttMessage<PayloadType, DE> for YourStruct {
fn from_mqtt_message(
topic: Arc<TopicMatch>,
payload: PayloadType,
) -> Result<Self, MessageConversionError<DE>> {
// Parameter extraction and struct construction
}
}
impl YourStruct {
pub const TOPIC_PATTERN: &'static str = "sensors/{id}/data";
pub const MQTT_PATTERN: &'static str = "sensors/+/data";
// Subscriber methods (if enabled)
pub async fn subscribe<F>(client: &MqttClient<F>) -> Result<...> {
// Subscription logic
}
// Publisher methods (if enabled)
pub async fn publish<F>(client: &MqttClient<F>, id: ParamType, data: &PayloadType) -> Result<...> {
// Publishing logic
}
pub fn get_publisher<F>(client: &MqttClient<F>, id: ParamType) -> Result<...> {
// Publisher creation
}
}
§Examples
§Basic Usage (Both Modes)
ⓘ
#[derive(Debug)]
#[mqtt_topic("sensors/{sensor_id}/temperature")]
struct TemperatureReading {
sensor_id: u32,
payload: f64,
}
§Subscriber Only
ⓘ
#[derive(Debug)]
#[mqtt_topic("devices/{device_id}/status/#", subscriber)]
struct DeviceStatus {
device_id: String,
payload: Vec<u8>,
topic: Arc<TopicMatch>, // Access to full topic match
}
§Publisher Only
ⓘ
#[derive(Debug)]
#[mqtt_topic("commands/{service}/{action}", publisher)]
struct Command {
service: String,
action: String,
payload: String,
}
§Multiple Parameters
ⓘ
#[derive(Debug)]
#[mqtt_topic("buildings/{building}/floors/{floor}/rooms/{room}/sensors/{sensor_id}")]
struct SensorReading {
building: String,
floor: u32,
room: String,
sensor_id: u32,
payload: Vec<u8>,
}
§No Payload
ⓘ
#[derive(Debug)]
#[mqtt_topic("heartbeat/{service_name}")]
struct Heartbeat {
service_name: String,
// No payload field - will default to Vec<u8>
}
§Error Handling
The macro performs compile-time validation and will produce helpful error messages for common issues:
- Unknown fields that don’t match topic parameters
- Invalid topic patterns (e.g.,
#
not at the end) - Incorrect type for
topic
field - Non-struct types or structs without named fields
- Publisher mode with
#
wildcards (not supported)
§Runtime Behavior
§Subscriber
When messages are received:
- Topic is matched against the pattern
- Named parameters are extracted and parsed to their field types
- Payload is deserialized to the payload field type
- Struct is constructed with all extracted values
§Publisher
When publishing messages:
- Topic parameters are provided as method arguments
- Topic string is constructed from the pattern
- Payload is serialized and published
If parameter parsing fails (e.g., non-numeric string for u32
field),
a MessageConversionError
is returned.