Skip to main content

idun_rs/
lib.rs

1//! # idun-rs
2//!
3//! Async Rust library and terminal UI for streaming EEG, IMU, and impedance
4//! data from [IDUN Guardian](https://idun.tech/) earbuds over Bluetooth Low
5//! Energy.
6//!
7//! ## Supported hardware
8//!
9//! | Model | BLE name | EEG | Impedance | IMU | Notes |
10//! |---|---|---|---|---|---|
11//! | Guardian Earbud 2.1a | `IGEB` | ✓ | ✓ | ✓ | Original model |
12//! | Guardian Earbud 3.0a | `IGE-XXXXXX` | ✓ | ✓ | ✓ | Newer hardware |
13//!
14//! ## IDUN Cloud API token (optional)
15//!
16//! The Guardian's BLE wire format is proprietary. For authoritative EEG
17//! decoding you can use the IDUN Cloud WebSocket API as a fallback:
18//!
19//! 1. Get an API token from <https://idun.tech/>
20//! 2. Export it: `export IDUN_API_TOKEN="your_token"`
21//! 3. Pass `--cloud` to the CLI or use [`cloud::CloudDecoder`] in code
22//!
23//! Local experimental decoding (`--decode` / `local-decode` feature) works
24//! without any API token but may not be fully accurate.
25//!
26//! ## Quick start
27//!
28//! ```no_run
29//! use idun_rs::prelude::*;
30//!
31//! #[tokio::main]
32//! async fn main() -> anyhow::Result<()> {
33//!     let client = GuardianClient::new(GuardianClientConfig::default());
34//!     let (mut rx, handle) = client.connect().await?;
35//!     handle.start_recording().await?;
36//!
37//!     while let Some(event) = rx.recv().await {
38//!         match event {
39//!             GuardianEvent::Eeg(r) => println!("EEG idx={} ts={:.0}ms", r.index, r.timestamp),
40//!             GuardianEvent::Disconnected => break,
41//!             _ => {}
42//!         }
43//!     }
44//!     Ok(())
45//! }
46//! ```
47//!
48//! ## Module overview
49//!
50//! | Module | Purpose |
51//! |---|---|
52//! | [`prelude`] | One-line glob import of the most commonly needed types |
53//! | [`guardian_client`] | BLE scanning, connecting, and the [`GuardianHandle`](guardian_client::GuardianHandle) command API |
54//! | [`types`] | All event and data types ([`GuardianEvent`](types::GuardianEvent), [`EegReading`](types::EegReading), etc.) |
55//! | [`protocol`] | GATT UUIDs, commands, config bytes, sampling constants |
56//! | [`parse`] | Binary decoders for EEG, IMU, and impedance packets |
57//! | [`cloud`] | IDUN Cloud WebSocket client for server-side EEG decoding (requires `IDUN_API_TOKEN`) |
58
59pub mod cloud;
60pub mod guardian_client;
61pub mod parse;
62pub mod protocol;
63pub mod types;
64
65/// Convenience re-exports for downstream crates.
66pub mod prelude {
67    pub use crate::cloud::{CloudDecoder, CloudDecodedEeg};
68    pub use crate::guardian_client::{
69        GuardianClient, GuardianClientConfig, GuardianDevice, GuardianHandle,
70    };
71    pub use crate::types::{
72        AccelerometerReading, BatteryReading, DecodeSource, DeviceInfo, EegReading,
73        GuardianEvent, GyroscopeReading, ImpedanceReading, XyzSample,
74    };
75    pub use crate::protocol::{
76        EEG_CHANNEL_NAME, EEG_SAMPLE_RATE, EEG_SAMPLES_PER_PACKET,
77    };
78    pub use crate::parse::{parse_eeg_packet, parse_impedance};
79    #[cfg(feature = "local-decode")]
80    pub use crate::parse::{
81        compute_rms, try_decode_eeg_12bit, try_decode_imu_i16le,
82    };
83}