PluginBench
Skill
Review
Audit score 70

domain-iot

actionbook/rust-skills

Design IoT apps with offline-first, power-efficient, and secure patterns in Rust.

What is domain-iot?

This skill provides domain constraints and design patterns for building reliable IoT applications. Use it when architecting sensor networks, gateways, or edge devices that must handle unreliable networks, power limits, and security requirements.

  • Map IoT constraints (network unreliability, power limits, resource scarcity) to Rust design patterns
  • Implement offline-first architectures with local buffering and store-and-forward messaging
  • Build secure MQTT clients with TLS, QoS levels, and retry logic
  • Apply power-management patterns including sleep modes and efficient algorithms
  • Design OTA update mechanisms with rollback capability
  • Avoid common mistakes like missing retry logic, unencrypted comms, and always-on radios

How to install domain-iot

npx skills add https://github.com/actionbook/rust-skills --skill domain-iot
Prerequisites
  • Familiarity with async Rust (tokio or embassy)
  • Basic understanding of MQTT or pub/sub messaging
  • Knowledge of embedded systems constraints (power, memory, network)
Claude Code
Cursor
Windsurf
Cline

How to use domain-iot

  1. 1.Review the domain constraints table to understand your IoT scenario's key challenges
  2. 2.Select the appropriate stack: tokio+std for gateways, embassy+no_std for MCUs, or hybrid
  3. 3.Implement the MQTT client pattern provided, adapting broker address and topics to your setup
  4. 4.Add local buffering and retry logic using exponential backoff for network resilience
  5. 5.Configure TLS and signed messages for encrypted communication
  6. 6.Test power consumption and adjust sleep intervals based on your device's battery life requirements

Use cases

Good for
  • Building a battery-powered sensor node that buffers readings locally and syncs when network returns
  • Creating a smart-home gateway that processes commands locally and handles broker disconnections gracefully
  • Designing firmware updates for remote devices with signed packages and rollback support
  • Implementing a telemetry pipeline that minimizes power consumption on MCUs using embassy
  • Setting up MQTT pub/sub architecture for device-to-cloud communication with QoS guarantees
Who it's for
  • IoT/embedded systems engineers
  • Backend engineers building device platforms
  • Hardware teams integrating Rust firmware
  • Edge computing architects
  • Smart-home or industrial automation developers

domain-iot FAQ

When should I use rumqttc vs paho-mqtt?

Use rumqttc for async Rust with tokio on Linux gateways; use paho-mqtt for blocking code or when C library bindings are preferred. For embedded no_std, neither is suitable—use embassy patterns instead.

How do I handle network outages without losing data?

Implement store-and-forward: buffer sensor readings locally (in flash or RAM), then flush to the broker when connectivity returns. Use QoS 1 or 2 for guaranteed delivery.

What's the difference between no_std and std IoT code?

no_std (embassy) runs on MCUs with minimal memory; std (tokio) runs on Linux gateways. Hybrid architectures split workloads: edge compute on MCU, aggregation on gateway.

How do I minimize battery drain?

Use sleep modes between sensor reads, keep the radio off except during transmit/receive windows, and use efficient algorithms. Avoid always-on polling; prefer interrupt-driven or timer-based wake events.

Should all MQTT communication use TLS?

Yes, for any device accessible over untrusted networks. TLS prevents eavesdropping and man-in-the-middle attacks. For local-only networks, evaluate risk vs. performance trade-off.

Full instructions (SKILL.md)

Source of truth, from actionbook/rust-skills.


name: domain-iot description: "Use when building IoT apps. Keywords: IoT, Internet of Things, sensor, MQTT, device, edge computing, telemetry, actuator, smart home, gateway, protocol, 物联网, 传感器, 边缘计算, 智能家居" user-invocable: false

IoT Domain

Layer 3: Domain Constraints

Domain Constraints → Design Implications

Domain RuleDesign ConstraintRust Implication
Unreliable networkOffline-firstLocal buffering
Power constraintsEfficient codeSleep modes, minimal alloc
Resource limitsSmall footprintno_std where needed
SecurityEncrypted commsTLS, signed firmware
ReliabilitySelf-recoveryWatchdog, error handling
OTA updatesSafe upgradesRollback capability

Critical Constraints

Network Unreliability

RULE: Network can fail at any time
WHY: Wireless, remote locations
RUST: Local queue, retry with backoff

Power Management

RULE: Minimize power consumption
WHY: Battery life, energy costs
RUST: Sleep modes, efficient algorithms

Device Security

RULE: All communication encrypted
WHY: Physical access possible
RUST: TLS, signed messages

Trace Down ↓

From constraints to design (Layer 2):

"Need offline-first design"
    ↓ m12-lifecycle: Local buffer with persistence
    ↓ m13-domain-error: Retry with backoff

"Need power efficiency"
    ↓ domain-embedded: no_std patterns
    ↓ m10-performance: Minimal allocations

"Need reliable messaging"
    ↓ m07-concurrency: Async with timeout
    ↓ MQTT: QoS levels

Environment Comparison

EnvironmentStackCrates
Linux gatewaytokio + stdrumqttc, reqwest
MCU deviceembassy + no_stdembedded-hal
HybridSplit workloadsBoth

Key Crates

PurposeCrate
MQTT (std)rumqttc, paho-mqtt
Embeddedembedded-hal, embassy
Async (std)tokio
Async (no_std)embassy
Logging (no_std)defmt
Logging (std)tracing

Design Patterns

PatternPurposeImplementation
Pub/SubDevice commsMQTT topics
Edge computeLocal processingFilter before upload
OTA updatesFirmware upgradeSigned + rollback
Power mgmtBattery lifeSleep + wake events
Store & forwardNetwork reliabilityLocal queue

Code Pattern: MQTT Client

use rumqttc::{AsyncClient, MqttOptions, QoS};

async fn run_mqtt() -> anyhow::Result<()> {
    let mut options = MqttOptions::new("device-1", "broker.example.com", 1883);
    options.set_keep_alive(Duration::from_secs(30));

    let (client, mut eventloop) = AsyncClient::new(options, 10);

    // Subscribe to commands
    client.subscribe("devices/device-1/commands", QoS::AtLeastOnce).await?;

    // Publish telemetry
    tokio::spawn(async move {
        loop {
            let data = read_sensor().await;
            client.publish("devices/device-1/telemetry", QoS::AtLeastOnce, false, data).await.ok();
            tokio::time::sleep(Duration::from_secs(60)).await;
        }
    });

    // Process events
    loop {
        match eventloop.poll().await {
            Ok(event) => handle_event(event).await,
            Err(e) => {
                tracing::error!("MQTT error: {}", e);
                tokio::time::sleep(Duration::from_secs(5)).await;
            }
        }
    }
}

Common Mistakes

MistakeDomain ViolationFix
No retry logicLost dataExponential backoff
Always-on radioBattery drainSleep between sends
Unencrypted MQTTSecurity riskTLS
No local bufferNetwork outage = data lossPersist locally

Trace to Layer 1

ConstraintLayer 2 PatternLayer 1 Implementation
Offline-firstStore & forwardLocal queue + flush
Power efficiencySleep patternsTimer-based wake
Network reliabilityRetrytokio-retry, backoff
SecurityTLSrustls, native-tls

Related Skills

WhenSee
Embedded patternsdomain-embedded
Async patternsm07-concurrency
Error recoverym13-domain-error
Performancem10-performance