MQTT Typed Client
A type-safe async MQTT client built on top of rumqttc
Automatic topic routing and subscription management with compile-time guarantees
The problem
Raw MQTT topics are stringly-typed. You hand-build them with format!(), split
them with split('/'), and deserialize payloads by hand — and the compiler
can't help when you swap two segments or typo a prefix:
// rumqttc: easy to get wrong, fails silently at runtime
let topic = format!; // swapped order? compiler shrugs
let payload = to_vec?;
client.publish.await?;
With mqtt-typed-client the topic is a type. One derive turns the pattern into
a checked API — wrong order, wrong parameter type, or a typo won't compile:
// generated, type-checked: device_id must be u32, order is fixed
client.sensor_topic.publish.await?;
Key Features
- Topics as types — named parameters parsed/validated at compile time
- Typed parameters —
{device_id}can beu32,Uuid, or your own enum, not justString - Automatic routing — one broker stream fanned out to typed subscribers, no manual
if topic.starts_with(...) - Pluggable serialization — Bincode, JSON, MessagePack, CBOR and more behind one trait
- Reconnect that keeps subscriptions — automatic resubscribe on reconnect (happy path), graceful shutdown, LWT
MSRV: Rust 1.85.1 (driven by default bincode serializer; can be lowered with alternative serializers)
Quick Start
Add the crate and the few deps the derive example needs:
[]
= "0.3.0"
= { = "1", = ["full"] }
= { = "1", = ["derive"] }
= "2"
serdeis needed for theSerialize/Deserializederives andbincodefor the default serializer'sEncode/Decode. Switch serializers (e.g.json) and the derive requirements change accordingly.
use *;
use ;
use ;
// Define typed topic with automatic parameter extraction
async
Examples
See examples/ - Complete usage examples with source code
000_hello_world.rs- Basic publish/subscribe with macros001_ping_pong.rs- Multi-client communication002_configuration.rs- Advanced client configuration003_hello_world_lwt.rs- Last Will & Testament004_hello_world_tls.rs- TLS/SSL connections005_hello_world_serializers.rs- Custom serializers006_retain_and_clear.rs- Retained messages007_custom_patterns.rs- Custom topic patterns008_modular_example.rs- Modular application structure102_multi_serializer_macro.rs- Per-topic custom serializers
Run examples:
Serialization Support
Multiple serialization formats are supported via feature flags:
bincode- Binary serialization (default, most efficient)json- JSON serialization (default, human-readable)messagepack- MessagePack binary formatcbor- CBOR binary formatpostcard- Embedded-friendly binary formatron- Rusty Object Notationflexbuffers- FlatBuffers FlexBuffersprotobuf- Protocol Buffers (requires generated types)
Enable additional serializers:
[]
= { = "0.3.0", = ["messagepack", "cbor"] }
Custom serializers can be implemented by implementing the MessageSerializer trait.
Per-Topic Serializer Override
By default every topic uses the client's serializer. You can override it for a specific topic type — handy for legacy formats or gradual migrations:
use mqtt_topic;
// This topic always uses JSON, regardless of the client's default serializer.
Limitations:
- Using a custom serializer disables the generated
TypedClientextension for that topic (typed clients require a generic serializer parameter, while a custom serializer is a concrete type). - Only a simple type path is accepted. For a generic serializer, declare a type
alias first:
type MySer = MySerializer<Foo>;then useserializer = MySer.
Topic Pattern Matching
Supports MQTT wildcard patterns with named parameters:
{param}- Named parameter (equivalent to+wildcard){param:#}- Multi-level named parameter (equivalent to#wildcard)
use mqtt_topic;
// Traditional MQTT wildcards
// matches: home/kitchen/temperature
// Named parameters (recommended)
// matches: home/kitchen/temperature
// Multi-level parameters
// matches: logs/api/v1/users/create
TLS and Transport
Transport security and extras are opt-in via feature flags:
| Feature | Effect |
|---|---|
tls-rustls (default) |
TLS via rustls with the aws-lc-rs provider |
tls-rustls-no-provider |
rustls without a bundled crypto provider — bring your own (e.g. ring) and avoid the aws-lc build |
tls-native |
Compile in the platform's native-tls (reachable via the backend escape hatch for now) |
websocket |
MQTT over WebSocket |
proxy |
Connect through an HTTP/HTTPS proxy |
(The 0.2 rumqttc-* feature names still work as deprecated aliases and will be
removed in 0.4 — except rumqttc-url, which is gone: URL parsing is built in.)
For custom TLS setups you can build the rustls config yourself. The crate
re-exports the backend's rustls (version-matched, so you don't add a
separate rustls dependency that could drift out of sync):
use ;
#
See examples/004_hello_world_tls.rs for a complete TLS example,
including loading a CA certificate from a PEM file.
Advanced Usage: Low-Level API
For cases where you need direct control without macros:
use *;
use ;
use ;
async
What mqtt-typed-client adds over rumqttc
Publishing:
// rumqttc - manual topic construction and serialization
let sensor_id = "sensor001";
let data = SensorData ;
let topic = format!;
let payload = to_vec?;
client.publish.await?;
// mqtt-typed-client - type-safe, automatic
topic_client.publish.await?;
Subscribing with routing:
// rumqttc - manual pattern matching and dispatching
// while let Ok(event) = eventloop.poll().await {
// if let Event::Incoming(Packet::Publish(publish)) = event {
// if publish.topic.starts_with("sensors/") {
// // Manual topic parsing, manual deserialization...
// } else if publish.topic.starts_with("alerts/") {
// // More manual parsing...
// }
// }
// }
// mqtt-typed-client - automatic routing to typed handlers
let mut sensor_sub = client.sensor_topic.subscribe.await?;
let mut alert_sub = client.alert_topic.subscribe.await?;
select!
For a detailed comparison see: docs/COMPARISON_WITH_RUMQTTC.md
Alternatives
- rumqttc — the async MQTT client this crate builds on. Use it directly when you want full manual control over topics, serialization, and the event loop.
- paho-mqtt — Rust bindings to the Eclipse Paho C client; a fit when you need that mature C library or its feature set.
- ntex-mqtt — MQTT client and server built on the ntex framework; worth a look if you're already in that ecosystem or need a broker.
Reach for mqtt-typed-client when you want typed topic routing and automatic
(de)serialization on top of rumqttc, without hand-writing the dispatch layer.
License
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
API Reference
For detailed API documentation, visit docs.rs/mqtt-typed-client.
See Also
- rumqttc - The underlying MQTT client library
- MQTT Protocol Specification - Official MQTT documentation
- Rust Async Book - Guide to async Rust programming