aranet_core/
lib.rs

1//! Core BLE library for Aranet environmental sensors.
2//!
3//! This crate provides low-level Bluetooth Low Energy (BLE) communication
4//! with Aranet sensors including the Aranet4, Aranet2, AranetRn+ (Radon), and
5//! Aranet Radiation devices.
6//!
7//! # Features
8//!
9//! - **Device discovery**: Scan for nearby Aranet devices via BLE
10//! - **Current readings**: CO₂, temperature, pressure, humidity, radon, radiation
11//! - **Historical data**: Download measurement history with timestamps
12//! - **Device settings**: Read/write measurement interval, Bluetooth range
13//! - **Auto-reconnection**: Configurable backoff and retry logic
14//! - **Real-time streaming**: Subscribe to sensor value changes
15//! - **Multi-device support**: Manage multiple sensors simultaneously
16//!
17//! # Supported Devices
18//!
19//! | Device | Sensors |
20//! |--------|---------|
21//! | Aranet4 | CO₂, Temperature, Pressure, Humidity |
22//! | Aranet2 | Temperature, Humidity |
23//! | AranetRn+ | Radon (Bq/m³), Temperature, Pressure, Humidity |
24//! | Aranet Radiation | Dose Rate (µSv/h), Total Dose (mSv) |
25//!
26//! # Platform Differences
27//!
28//! Device identification varies by platform due to differences in BLE implementations:
29//!
30//! - **macOS**: Devices are identified by a UUID assigned by CoreBluetooth. This UUID
31//!   is stable for a given device on a given Mac, but differs between Macs. The UUID
32//!   is not the same as the device's MAC address.
33//!
34//! - **Linux/Windows**: Devices are identified by their Bluetooth MAC address
35//!   (e.g., `AA:BB:CC:DD:EE:FF`). This is consistent across machines.
36//!
37//! When storing device identifiers for reconnection, be aware that:
38//! - On macOS, the UUID may change if Bluetooth is reset or the device is unpaired
39//! - Cross-platform applications should store both the device name and identifier
40//! - The [`Device::address()`] method returns the appropriate identifier for the platform
41//!
42//! # Quick Start
43//!
44//! ```no_run
45//! use aranet_core::{Device, scan};
46//!
47//! #[tokio::main]
48//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
49//!     // Scan for devices
50//!     let devices = scan::scan_for_devices().await?;
51//!     println!("Found {} devices", devices.len());
52//!
53//!     // Connect to a device
54//!     let device = Device::connect("Aranet4 12345").await?;
55//!
56//!     // Read current values
57//!     let reading = device.read_current().await?;
58//!     println!("CO2: {} ppm", reading.co2);
59//!
60//!     // Read device info
61//!     let info = device.read_device_info().await?;
62//!     println!("Serial: {}", info.serial);
63//!
64//!     Ok(())
65//! }
66//! ```
67
68pub mod advertisement;
69pub mod commands;
70pub mod device;
71pub mod error;
72pub mod events;
73pub mod guard;
74pub mod history;
75pub mod manager;
76pub mod metrics;
77pub mod mock;
78pub mod readings;
79pub mod reconnect;
80pub mod retry;
81pub mod scan;
82pub mod settings;
83pub mod streaming;
84pub mod thresholds;
85pub mod traits;
86pub mod util;
87pub mod validation;
88
89// Re-export types and uuid modules from aranet-types for backwards compatibility
90pub use aranet_types::types;
91pub use aranet_types::uuid;
92
93// Core exports
94pub use device::Device;
95pub use error::{ConnectionFailureReason, DeviceNotFoundReason, Error, Result};
96pub use history::{HistoryInfo, HistoryOptions, HistoryParam};
97pub use readings::ExtendedReading;
98pub use scan::{
99    DiscoveredDevice, FindProgress, ProgressCallback, ScanOptions, find_device_with_progress,
100    scan_with_retry,
101};
102pub use settings::{BluetoothRange, CalibrationData, DeviceSettings, MeasurementInterval};
103pub use traits::AranetDevice;
104
105/// Type alias for a shared device reference.
106///
107/// This is the recommended way to share a `Device` across multiple tasks.
108/// Since `Device` intentionally does not implement `Clone` (to prevent
109/// connection ownership ambiguity), wrapping it in `Arc` is the standard
110/// pattern for concurrent access.
111///
112/// # Example
113///
114/// ```no_run
115/// use aranet_core::{Device, SharedDevice};
116/// use std::sync::Arc;
117///
118/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
119/// let device = Device::connect("Aranet4 12345").await?;
120/// let shared: SharedDevice = Arc::new(device);
121///
122/// // Clone the Arc to share across tasks
123/// let shared_clone = Arc::clone(&shared);
124/// tokio::spawn(async move {
125///     let reading = shared_clone.read_current().await;
126///     // ...
127/// });
128/// # Ok(())
129/// # }
130/// ```
131pub type SharedDevice = std::sync::Arc<Device>;
132
133// New module exports
134pub use advertisement::{AdvertisementData, parse_advertisement, parse_advertisement_with_name};
135pub use commands::{
136    HISTORY_V1_REQUEST, HISTORY_V2_REQUEST, SET_BLUETOOTH_RANGE, SET_INTERVAL, SET_SMART_HOME,
137};
138pub use events::{DeviceEvent, EventReceiver, EventSender};
139pub use guard::{DeviceGuard, SharedDeviceGuard};
140pub use manager::{DeviceManager, ManagedDevice, ManagerConfig};
141pub use metrics::{ConnectionMetrics, OperationMetrics};
142pub use mock::{MockDevice, MockDeviceBuilder};
143pub use reconnect::{ReconnectOptions, ReconnectingDevice};
144pub use retry::{RetryConfig, with_retry};
145pub use streaming::{ReadingStream, StreamOptions, StreamOptionsBuilder};
146pub use thresholds::{Co2Level, ThresholdConfig, Thresholds};
147pub use util::{create_identifier, format_peripheral_id};
148pub use validation::{ReadingValidator, ValidationResult, ValidationWarning};
149
150// Re-export from aranet-types
151pub use aranet_types::uuid as uuids;
152pub use aranet_types::{CurrentReading, DeviceInfo, DeviceType, HistoryRecord, Status};