{"id":31044844,"url":"https://github.com/holovskyi/mqtt-typed-client","last_synced_at":"2026-03-27T03:42:54.412Z","repository":{"id":306645342,"uuid":"1026830603","full_name":"holovskyi/mqtt-typed-client","owner":"holovskyi","description":"Type-safe async MQTT client with automatic topic routing","archived":false,"fork":false,"pushed_at":"2025-07-27T19:00:13.000Z","size":449,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-28T22:56:47.485Z","etag":null,"topics":["async","client","iot","mqtt","mqtt-client","rust","type-safety","typed"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/holovskyi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-26T17:47:20.000Z","updated_at":"2025-07-27T19:00:17.000Z","dependencies_parsed_at":"2025-07-26T22:55:21.648Z","dependency_job_id":"21f04d3a-1a3a-4670-9b47-a2d96636bdde","html_url":"https://github.com/holovskyi/mqtt-typed-client","commit_stats":null,"previous_names":["holovskyi/mqtt-typed-client"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/holovskyi/mqtt-typed-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holovskyi%2Fmqtt-typed-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holovskyi%2Fmqtt-typed-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holovskyi%2Fmqtt-typed-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holovskyi%2Fmqtt-typed-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/holovskyi","download_url":"https://codeload.github.com/holovskyi/mqtt-typed-client/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/holovskyi%2Fmqtt-typed-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275136700,"owners_count":25411709,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","client","iot","mqtt","mqtt-client","rust","type-safety","typed"],"created_at":"2025-09-14T16:52:08.498Z","updated_at":"2026-03-27T03:42:54.362Z","avatar_url":"https://github.com/holovskyi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# 🦀 MQTT Typed Client\n\nA **type-safe async MQTT client** built on top of rumqttc\n\n**Automatic topic routing and subscription management** with **compile-time guarantees**\n\n[![CI](https://github.com/holovskyi/mqtt-typed-client/workflows/CI/badge.svg)](https://github.com/holovskyi/mqtt-typed-client/actions)\n[![Crates.io](https://img.shields.io/crates/v/mqtt-typed-client.svg)](https://crates.io/crates/mqtt-typed-client)\n[![Documentation](https://docs.rs/mqtt-typed-client/badge.svg)](https://docs.rs/mqtt-typed-client)\n[![License: MIT OR Apache-2.0](https://img.shields.io/badge/License-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE-MIT)\n[![MSRV](https://img.shields.io/badge/MSRV-1.85.1-blue.svg)](https://blog.rust-lang.org/2025/01/09/Rust-1.85.0.html)\n\n**Like this project? [⭐ Star it on GitHub!](https://github.com/holovskyi/mqtt-typed-client)**\n\u003c/div\u003e\n\n## ✨ Key Features\n\n- **Type-safe topic patterns** with named parameters and automatic parsing\n- **Zero-cost abstractions** via procedural macros with compile-time validation\n- **IDE-friendly experience** - full autocomplete for topics, parameters, and generated client methods\n- **Automatic subscription management** with intelligent routing and lifecycle handling\n- **Built-in serialization** support for 8+ formats (Bincode, JSON, MessagePack, etc.)\n- **Efficient message routing** with tree-based topic matching and internal caching\n- **Smart defaults** with full configurability when needed\n- **Memory efficient** design with proper resource management\n- **Automatic reconnection** and graceful shutdown\n\n⚠️ **MSRV**: Rust 1.85.1 (driven by default `bincode` serializer; can be lowered with alternative serializers)\n\n## 🚀 Quick Start\n\nAdd to your `Cargo.toml`:\n```toml\n[dependencies]\nmqtt-typed-client = \"0.1.0\"\n```\n\n```rust,no_run\nuse mqtt_typed_client::prelude::*;\nuse mqtt_typed_client_macros::mqtt_topic;\nuse serde::{Deserialize, Serialize};\nuse bincode::{Encode, Decode};\n\n#[derive(Serialize, Deserialize, Encode, Decode, Debug)]\nenum SensorStatus {\n    Active,\n    Inactive,\n    Maintenance,\n}\n\n#[derive(Serialize, Deserialize, Encode, Decode, Debug)]\nstruct SensorReading {\n    temperature: f64,\n    status: SensorStatus,    // enum field\n    location_note: String,   // string field for variety\n}\n\n// Define typed topic with automatic parameter extraction\n#[mqtt_topic(\"sensors/{location}/{device_id}/data\")]\nstruct SensorTopic {\n    location: String,    // String parameter\n    device_id: u32,      // Numeric parameter - automatic conversion!\n    payload: SensorReading,\n}\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    // Connect to MQTT broker\n    let (client, connection) = MqttClient::\u003cBincodeSerializer\u003e::connect(\n        \"mqtt://broker.hivemq.com:1883\"\n    ).await?;\n\n    // Get typed client for this specific topic - method generated by macro\n    // Returns a typed client for publishing and subscribing to messages \n    // with automatic parameter handling for this topic pattern\n    let topic_client = client.sensor_topic();\n    \n    // Subscribe to all matching topics: \"sensors/+/+/data\"\n    // Returns typed subscriber that automatically extracts and converts\n    // topic parameters into struct fields\n    let mut subscriber = topic_client.subscribe().await?;\n    \n    let reading = SensorReading { \n        temperature: 22.5,\n        status: SensorStatus::Active,\n        location_note: \"Kitchen sensor near window\".to_string(),\n    };\n    \n    // Publish with automatic type conversion to specific topic: \"sensors/kitchen/42/data\"\n    // Parameters are automatically converted to strings and inserted into topic pattern\n    topic_client.publish(\"kitchen\", 42u32, \u0026reading).await?;\n    //                    ^^^^^^^^  ^^^^^ \n    //                    String    u32 -\u003e automatically converts to \"42\" in topic\n    \n    // Receive with automatic parameter extraction and conversion\n    if let Some(Ok(msg)) = subscriber.receive().await {\n        println!(\"Device {} in location '{}' reported: temp={}°C, status={:?}\", \n            msg.device_id,  // u32 (converted from \"42\" in topic)\n            msg.location,   // String (extracted from topic)\n            msg.payload.temperature, msg.payload.status);\n    }\n    \n    connection.shutdown().await?;\n    Ok(())\n}\n```\n\n**Like this project? [⭐ Star it on GitHub!](https://github.com/holovskyi/mqtt-typed-client)**\n\n## 📚 Examples\n\nSee [examples/](examples/) - Complete usage examples with source code\n\n- `000_hello_world.rs` - Basic publish/subscribe with macros\n- `001_ping_pong.rs` - Multi-client communication\n- `002_configuration.rs` - Advanced client configuration\n- `003_hello_world_lwt.rs` - Last Will \u0026 Testament\n- `004_hello_world_tls.rs` - TLS/SSL connections\n- `005_hello_world_serializers.rs` - Custom serializers\n- `006_retain_and_clear.rs` - Retained messages\n- `007_custom_patterns.rs` - Custom topic patterns\n- `008_modular_example.rs` - Modular application structure\n\nRun examples:\n```bash\ncargo run --example 000_hello_world\n```\n\n## 📦 Serialization Support\n\nMultiple serialization formats are supported via feature flags:\n\n- `bincode` - Binary serialization (default, most efficient)\n- `json` - JSON serialization (default, human-readable)\n- `messagepack` - MessagePack binary format\n- `cbor` - CBOR binary format\n- `postcard` - Embedded-friendly binary format\n- `ron` - Rusty Object Notation\n- `flexbuffers` - FlatBuffers FlexBuffers\n- `protobuf` - Protocol Buffers (requires generated types)\n\nEnable additional serializers:\n```toml\n[dependencies]\nmqtt-typed-client = { version = \"0.1.0\", features = [\"messagepack\", \"cbor\"] }\n```\n\nCustom serializers can be implemented by implementing the `MessageSerializer` trait.\n\n## 🎯 Topic Pattern Matching\n\nSupports MQTT wildcard patterns with named parameters:\n\n- `{param}` - Named parameter (equivalent to `+` wildcard)\n- `{param:#}` - Multi-level named parameter (equivalent to `#` wildcard)\n\n```rust,ignore\nuse mqtt_typed_client_macros::mqtt_topic;\n\n// Traditional MQTT wildcards\n#[mqtt_topic(\"home/+/temperature\")]     // matches: home/kitchen/temperature\nstruct SimplePattern { payload: f64 }\n\n// Named parameters (recommended)\n#[mqtt_topic(\"home/{room}/temperature\")] // matches: home/kitchen/temperature  \nstruct NamedPattern { \n    room: String,        // Automatically extracted: \"kitchen\"\n    payload: f64 \n}\n\n// Multi-level parameters\n#[mqtt_topic(\"logs/{service}/{path:#}\")]  // matches: logs/api/v1/users/create\nstruct LogPattern {\n    service: String,     // \"api\"\n    path: String,        // \"v1/users/create\"  \n    payload: String     // Changed from Data to String\n}\n```\n\n## 🔧 Advanced Usage: Low-Level API\n\nFor cases where you need direct control without macros:\n\n```rust,no_run\nuse mqtt_typed_client::prelude::*;\nuse serde::{Deserialize, Serialize};\nuse bincode::{Encode, Decode};\n\n#[derive(Serialize, Deserialize, Encode, Decode, Debug)]\nstruct SensorData {\n    temperature: f64,\n    humidity: f64,\n}\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c()\u003e {\n    let (client, connection) = MqttClient::\u003cBincodeSerializer\u003e::connect(\n        \"mqtt://broker.hivemq.com:1883\"\n    ).await?;\n\n    // Direct topic operations\n    let publisher = client.get_publisher::\u003cSensorData\u003e(\"sensors/temperature\")?;\n    let mut subscriber = client.subscribe::\u003cSensorData\u003e(\"sensors/+\").await?;\n\n    let data = SensorData { temperature: 23.5, humidity: 45.0 };\n    publisher.publish(\u0026data).await?;\n\n    if let Some((topic, result)) = subscriber.receive().await {\n        match result {\n            Ok(sensor_data) =\u003e println!(\"Received from {}: {:?}\", topic.topic_path(), sensor_data),\n            Err(e) =\u003e eprintln!(\"Deserialization error: {:?}\", e),\n        }\n    }\n\n    connection.shutdown().await?;\n    Ok(())\n}\n```\n\n## 🆚 What mqtt-typed-client adds over rumqttc\n\n**Publishing:**\n```rust,ignore\n// rumqttc - manual topic construction and serialization\nlet sensor_id = \"sensor001\";\nlet data = SensorData { temperature: 23.5 };\nlet topic = format!(\"sensors/{}/temperature\", sensor_id);\nlet payload = serde_json::to_vec(\u0026data)?;\nclient.publish(topic, QoS::AtLeastOnce, false, payload).await?;\n\n// mqtt-typed-client - type-safe, automatic  \ntopic_client.publish(\u0026sensor_id, \u0026data).await?;\n```\n\n**Subscribing with routing:**\n```rust,ignore\n// rumqttc - manual pattern matching and dispatching\n// while let Ok(event) = eventloop.poll().await {\n//     if let Event::Incoming(Packet::Publish(publish)) = event {\n//         if publish.topic.starts_with(\"sensors/\") {\n//             // Manual topic parsing, manual deserialization...\n//         } else if publish.topic.starts_with(\"alerts/\") {\n//             // More manual parsing...\n//         }\n//     }\n// }\n\n// mqtt-typed-client - automatic routing to typed handlers\nlet mut sensor_sub = client.sensor_topic().subscribe().await?;\nlet mut alert_sub = client.alert_topic().subscribe().await?;\n\ntokio::select! {\n    msg = sensor_sub.receive() =\u003e { /* typed sensor data ready */ }\n    msg = alert_sub.receive() =\u003e { /* typed alert data ready */ }\n}\n```\n\n📋 **For detailed comparison see:** [docs/COMPARISON_WITH_RUMQTTC.md](docs/COMPARISON_WITH_RUMQTTC.md)\n\n## 📄 License\n\nThis project is licensed under either of\n\n * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n\nat your option.\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.\n\n## 📖 API Reference\n\nFor detailed API documentation, visit [docs.rs/mqtt-typed-client](https://docs.rs/mqtt-typed-client).\n\n## 🔗 See Also\n\n- [rumqttc](https://github.com/bytebeamio/rumqtt) - The underlying MQTT client library\n- [MQTT Protocol Specification](https://mqtt.org/) - Official MQTT documentation\n- [Rust Async Book](https://rust-lang.github.io/async-book/) - Guide to async Rust programming\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholovskyi%2Fmqtt-typed-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fholovskyi%2Fmqtt-typed-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholovskyi%2Fmqtt-typed-client/lists"}