Module error

Source
Expand description

Error types for aranet-core.

This module defines all error types that can occur when communicating with Aranet devices via Bluetooth Low Energy.

§Error Recovery Strategies

Different errors require different recovery approaches. This guide helps you choose the right strategy for each error type.

§Retry vs Reconnect

Error TypeStrategyRationale
Error::TimeoutRetry (2-3 times)Transient BLE congestion
Error::BluetoothRetry, then reconnectMay be transient or connection lost
Error::NotConnectedReconnectConnection was lost
Error::ConnectionFailedRetry with backoffDevice may be temporarily busy
Error::WriteFailedRetry (1-2 times)BLE write can fail transiently
Error::InvalidDataDo not retryData corruption, report to user
Error::DeviceNotFoundDo not retryDevice not in range or wrong name
Error::CharacteristicNotFoundDo not retryFirmware incompatibility
Error::InvalidConfigDo not retryFix configuration and restart
OperationRecommended TimeoutNotes
Device scan10-30 secondsAranet4 advertises every ~4s
Connection10-15 secondsMay take longer if device is busy
Read current5 secondsUsually completes in <1s
Read device info5 secondsMultiple characteristic reads
History download2-5 minutesDepends on record count
Write settings5 secondsIncludes verification read

§Using RetryConfig

For transient failures, use crate::RetryConfig with crate::with_retry:

use aranet_core::{RetryConfig, with_retry};

// Default: 3 retries with exponential backoff (100ms -> 200ms -> 400ms)
let config = RetryConfig::default();

// For unreliable connections: 5 retries, more aggressive
let aggressive = RetryConfig::aggressive();

// Wrap your operation
let reading = with_retry(&config, "read_current", || async {
    device.read_current().await
}).await?;

§Using ReconnectingDevice

For long-running applications, use crate::ReconnectingDevice which automatically handles reconnection:

use aranet_core::{ReconnectingDevice, ReconnectOptions};

// Default: 5 attempts with exponential backoff (1s -> 2s -> 4s -> 8s -> 16s)
let options = ReconnectOptions::default();

// For always-on services: unlimited retries
let unlimited = ReconnectOptions::unlimited();

// Connect with auto-reconnect
let device = ReconnectingDevice::connect("Aranet4 12345", options).await?;

// Operations automatically reconnect if connection is lost
let reading = device.read_current().await?;

§Error Classification

The retry module internally classifies errors as retryable or not. The following errors are considered retryable:

The following errors should NOT be retried:

§Example: Robust Reading Loop

use aranet_core::{Device, Error, RetryConfig, with_retry};
use std::time::Duration;

async fn read_with_recovery(device: &Device) -> Result<CurrentReading, Error> {
    let config = RetryConfig::new(3);

    with_retry(&config, "read_current", || async {
        device.read_current().await
    }).await
}

// For long-running monitoring
async fn monitoring_loop(identifier: &str) {
    let options = ReconnectOptions::default()
        .max_attempts(10)
        .initial_delay(Duration::from_secs(2));

    let device = ReconnectingDevice::connect(identifier, options).await?;

    loop {
        match device.read_current().await {
            Ok(reading) => println!("CO2: {} ppm", reading.co2),
            Err(Error::Cancelled) => break, // Graceful shutdown
            Err(e) => eprintln!("Error (will retry): {}", e),
        }
        tokio::time::sleep(Duration::from_secs(60)).await;
    }
}

Enums§

ConnectionFailureReason
Structured reasons for connection failures.
DeviceNotFoundReason
Reason why a device was not found.
Error
Errors that can occur when communicating with Aranet devices.

Type Aliases§

Result
Result type alias using aranet-core’s Error type.