Module examples

Source
Expand description

Complete usage examples with source code

This module contains comprehensive examples demonstrating various features and use cases of mqtt-typed-client.

Β§Examples Guide

This directory contains examples demonstrating how to use the mqtt-typed-client library. Each example showcases different features and use cases.

Β§πŸ“‹ Quick Navigation

Jump directly to any example:

Β§πŸš€ Quick Start

⚠️ Important: Always run examples from the project root directory!

  1. Start local MQTT broker:

    cd dev
    docker-compose up -d
    cd ..  # Return to project root
  2. Run your first example (from project root):

    cargo run --example 000_hello_world
  3. Enable logging (optional):

    # Edit examples/.env and uncomment:
    # RUST_LOG=info
    
    # Or set temporarily:
    RUST_LOG=info cargo run --example 000_hello_world

Β§πŸ“š Examples Index

Β§000_hello_world.rs - Basic Usage

What it demonstrates:

  • Basic publish/subscribe pattern
  • Topic parameter extraction with #[mqtt_topic] macro
  • Type-safe message routing
  • Automatic serialization/deserialization

Key concepts:

  • Topic pattern: greetings/{language}/{sender}
  • BincodeSerializer for efficient binary serialization
  • Wildcard subscriptions: greetings/+/+

Β§001_ping_pong.rs - Multi-Client Communication

What it demonstrates:

  • Multiple MQTT clients in one application
  • Inter-client communication patterns
  • Game state management over MQTT
  • Concurrent async operations

Key concepts:

  • Client cloning and sharing
  • Topic-based game logic
  • Random event generation
  • Graceful shutdown handling

Β§βš™οΈ 002_configuration.rs - Advanced Configuration

What it demonstrates:

  • Custom MQTT client settings
  • Connection parameter tuning
  • Quality of Service (QoS) levels
  • Keep-alive and session management

Key concepts:

  • MqttClientConfig customization
  • Connection timeouts and retries
  • Cache size optimization
  • Credential management

Β§003_hello_world_lwt.rs - Last Will & Testament (LWT)

What it demonstrates:

  • MQTT Last Will & Testament functionality
  • Ungraceful vs graceful disconnect handling
  • Two separate client connections (subscriber/publisher)
  • LWT message configuration and triggering

Key concepts:

  • LWT configuration with typed topics
  • Unexpected disconnect simulation
  • Message differentiation (normal vs LWT)
  • Multi-terminal example usage

Usage:

# Terminal 1: Start subscriber
cargo run --example 003_hello_world_lwt

# Terminal 2: Run publisher (sends greeting then crashes)
cargo run --example 003_hello_world_lwt -- --publisher

Β§πŸ”’ 004_hello_world_tls.rs - TLS/SSL Connections

What it demonstrates:

  • Secure MQTT connections (MQTTS)
  • Custom TLS certificate handling
  • Self-signed certificate setup
  • TLS configuration for development

Key concepts:

  • rustls integration
  • Certificate validation
  • TLS transport configuration
  • Development vs production certificates

Β§πŸ”§ 005_hello_world_serializers.rs - Custom Message Serializers

What it demonstrates:

  • Using different serializers (MessagePack vs built-in Bincode)
  • Creating custom MessageSerializer trait implementation
  • Easy serializer switching with minimal code changes
  • Same MQTT logic with different data formats

Key concepts:

  • MessageSerializer trait implementation
  • serde::DeserializeOwned requirement
  • Binary vs text serialization formats
  • Custom serializer wrapper creation

Β§πŸ”„ 006_retain_and_clear.rs - MQTT Retained Messages

What it demonstrates:

  • MQTT retained message functionality with multiple clients
  • Message persistence and broker storage behavior
  • Retained message replacement and clearing
  • Different connection timing scenarios

Key concepts:

  • Retained vs non-retained messages
  • Broker message storage and delivery to new subscribers
  • clear_retained() functionality with empty payloads
  • Multi-client demonstration with timing coordination
  • Automatic empty payload filtering

Timeline demonstration:

  • t=0s: First retained message stored by broker
  • t=1s: Subscriber-1 connects β†’ receives retained message #1
  • t=5s: Second retained message replaces first in broker storage
  • t=6s: Subscriber-2 connects β†’ receives retained message #1 (timing)
  • t=10s: Non-retained message β†’ only active subscribers receive
  • t=11s: Subscriber-3 connects β†’ receives retained message #2
  • t=15s: Clear retained messages from broker storage
  • t=18s: Subscriber-4 connects β†’ receives nothing (storage empty)

Β§007_custom_patterns.rs - Custom Topic Patterns

What it demonstrates:

  • Overriding default topic patterns from #[mqtt_topic] macro
  • Environment-specific topic routing (dev/prod prefixes)
  • Pattern compatibility validation and type safety
  • Advanced subscription, publishing, and Last Will configuration

Key concepts:

  • .with_pattern() for custom subscription patterns
  • .get_publisher_to() for custom publishing patterns
  • .last_will_to() for custom Last Will patterns
  • Pattern compatibility rules (same parameters, names, order)
  • Multi-tenant and environment isolation patterns

API comparison:

β“˜
// Standard usage:
topic_client.subscribe().await?
topic_client.publish("rust", "alice", &msg).await?
GreetingTopic::last_will("rust", "client", msg)

// Custom patterns:
topic_client.subscription().with_pattern("dev/greetings/{language}/{sender}")?.subscribe().await?
topic_client.get_publisher_to("dev/greetings/{language}/{sender}", "rust", "alice")?.publish(&msg).await?
GreetingTopic::last_will_to("dev/greetings/{language}/{sender}", "rust", "client", msg)?

Β§008_modular_example.rs - Modular Project Architecture

What it demonstrates:

  • Organizing MQTT applications with multiple modules
  • Separating topic definitions from business logic
  • Clean import patterns and code organization
  • Multiple subscription strategies (wildcard vs. filtered)
  • Production-ready error handling and graceful shutdown

Key concepts:

  • Modular topic definitions in separate files
  • Type-safe MQTT operations with custom data structures
  • Subscription patterns: wildcard (sensors/+/+/+/data) vs. specific filters
  • Publisher/subscriber coordination with proper timing
  • Structured logging and timeout handling

Project structure:

modular_example/
β”œβ”€β”€ mod.rs          # Module exports
β”œβ”€β”€ topics.rs       # Topic definitions and data structures  
└── runner.rs       # Business logic and execution flow

Topic pattern: sensors/{location}/{sensor_type}/{device_id}/data

  • Publishing: client.temperature_topic().get_publisher("Home", "floor", 37)
  • Wildcard subscription: Receives from all sensors
  • Filtered subscription: Only specific device with caching
  • Data flow: Real sensor data β†’ MQTT β†’ Multiple typed subscribers

Β§100_all_serializers_demo.rs - Complete Serializer Test Suite

What it demonstrates:

  • Full publish/subscribe cycle testing for all 8 available serializers
  • Serialization and deserialization verification
  • Connection testing for schema-based serializers (Protobuf)
  • Comprehensive coverage of the entire serialization architecture

Available serializers tested:

  • Serde-compatible: JSON, MessagePack, CBOR, Postcard, RON, Flexbuffers
  • Bincode: Native Rust binary format
  • Schema-based: Protobuf (connection-only, requires generated types)

Key concepts:

  • Complete serialization ecosystem demonstration
  • Feature flag system (requires –all-features)
  • Real-world publish/subscribe verification
  • Error handling and diagnostics

Usage:

# Requires all serializer features to be enabled
cargo run --example 100_all_serializers_demo --all-features

Β§πŸ› οΈ Configuration

Examples use configuration files for easy setup:

Β§.env File (committed, safe defaults)

# MQTT Broker
MQTT_BROKER=mqtt://localhost:1883

# Tracing (uncomment to enable)
# RUST_LOG=info     # Recommended for learning
# RUST_LOG=debug    # Shows all MQTT traffic

Β§.env.local File (ignored by git, for secrets)

# Create this file for sensitive configuration
MQTT_USERNAME=your_username
MQTT_PASSWORD=your_password

Β§Environment Variables

You can override any setting:

MQTT_BROKER="mqtt://broker.hivemq.com:1883" cargo run --example 000_hello_world

Β§πŸ”§ Troubleshooting

§⚠️ Wrong Working Directory

Error: No such file or directory: examples/.env or config not loading

# Solution: Make sure you're in the project root directory
pwd  # Should show: /path/to/mqtt-typed-client
ls   # Should show: Cargo.toml, examples/, dev/, etc.

# If you're in examples/ directory:
cd ..

# Then run examples:
cargo run --example 000_hello_world

Β§Connection Issues

Error: Connection failed to mqtt://localhost:1883

# Solution: Start the local broker
cd dev && docker-compose up -d

Error: TLS handshake failed

# Solutions:
1. Check if TLS broker is running: docker-compose ps
2. Use plain MQTT: MQTT_BROKER="mqtt://localhost:1883"
3. Try public broker: MQTT_BROKER="mqtt://broker.hivemq.com:1883"

Β§No Logging Output

# Enable logging by uncommenting in examples/.env:
RUST_LOG=info

# Or set temporarily:
RUST_LOG=debug cargo run --example 000_hello_world

Β§Port Conflicts

# If ports 1883/8883 are in use, modify dev/docker-compose.yml
# Or use external broker:
MQTT_BROKER="mqtt://broker.hivemq.com:1883" cargo run --example 000_hello_world

§🧩 Code Structure

All examples use the shared helper modules:

β“˜
mod shared;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize tracing from .env configuration
    shared::tracing::setup(None);
    
    // Connect with automatic URL and client_id generation
    let connection_url = shared::config::build_url("example_name");
    let (client, connection) = MqttClient::<BincodeSerializer>::connect(&connection_url)
        .await
        .inspect_err(|e| {
            shared::config::print_connection_error(&connection_url, e);
        })?;
    
    // Your example code here...
    
    connection.shutdown().await?;
    Ok(())
}

Β§πŸš€ Creating New Examples

⚠️ Remember: Examples must be run from project root directory!

  1. Copy template from 000_hello_world.rs
  2. Update client_id prefix in build_url("your_example_name")
  3. Add your MQTT logic
  4. Test from project root: cargo run --example your_example_name
  5. Update this README with your example

Β§πŸ“– Additional Resources


Happy coding! πŸ¦€ If you run into issues, check the troubleshooting section above or create an issue on GitHub.

ModulesΒ§

example_000_hello_world
Hello World Example
example_001_ping_pong
Ping Pong Example
example_002_configuration
Configuration Example
example_003_hello_world_lwt
Last Will & Testament Example
example_004_hello_world_tls
TLS/SSL Connections Example
example_005_hello_world_serializers
Custom Serializers Example
example_006_retain_and_clear
Retained Messages Example
example_007_custom_patterns
Custom Topic Patterns Example
example_008_modular_example
Modular Application Structure Example
example_100_all_serializers_demo
Complete Serializer Test Suite