1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! # muse-rs
//!
//! Async Rust library and terminal UI for streaming EEG data from
//! [Interaxon Muse](https://choosemuse.com/) headsets over Bluetooth Low Energy.
//!
//! ## Supported hardware
//!
//! | Model | Firmware | EEG ch | PPG | Notes |
//! |---|---|---|---|---|
//! | Muse 1 (2014) | Classic | 4 | ✗ | baseline feature set |
//! | Muse 2 | Classic | 4 + AUX | ✓ | PPG requires `enable_ppg: true` |
//! | Muse S | Classic | 4 + AUX | ✓ | same protocol as Muse 2 |
//! | Muse S | **Athena** | **8** | **✓** | auto-detected; PPG always included with preset `p1045` |
//!
//! Athena PPG data is decoded from 20-bit LE packed samples (tag lower nibble
//! 0x4/0x5) into [`types::PpgReading`] events — 3 samples per channel
//! (ambient, infrared, red) at 64 Hz.
//!
//! Firmware is detected automatically at connect time — no configuration is
//! required. See the [README](https://github.com/eugenehp/muse-rs#firmware-variants-classic-vs-athena)
//! for a full protocol comparison.
//!
//! ## Quick start
//!
//! ```no_run
//! use muse_rs::prelude::*;
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! let client = MuseClient::new(MuseClientConfig::default());
//! let (mut rx, handle) = client.connect().await?;
//! handle.start(false, false).await?;
//!
//! while let Some(event) = rx.recv().await {
//! match event {
//! MuseEvent::Eeg(r) => println!("EEG ch{}: {:?}", r.electrode, r.samples),
//! MuseEvent::Disconnected => break,
//! _ => {}
//! }
//! }
//! Ok(())
//! }
//! ```
//!
//! ## Using as a library dependency
//!
//! Add to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! # Full build (includes the ratatui TUI feature):
//! muse-rs = "0.1.0"
//!
//! # Library only — skips ratatui / crossterm compilation:
//! muse-rs = { version = "0.1.0", default-features = false }
//! ```
//!
//! ## Module overview
//!
//! | Module | Purpose |
//! |---|---|
//! | [`prelude`] | One-line glob import of the most commonly needed types |
//! | [`muse_client`] | BLE scanning, connecting, and the [`muse_client::MuseHandle`] command API |
//! | [`types`] | All event and data types produced by the client |
//! | [`protocol`] | GATT UUIDs, sampling constants, and BLE wire-format helpers |
//! | [`parse`] | Low-level byte-to-sample decoders for EEG, IMU, PPG, and Athena packets |
// ── Prelude ───────────────────────────────────────────────────────────────────
/// Convenience re-exports for downstream crates.
///
/// A single glob import covers the entire surface area needed to scan,
/// connect, and process events from a Muse headset:
///
/// ```no_run
/// use muse_rs::prelude::*;
///
/// # #[tokio::main]
/// # async fn main() -> anyhow::Result<()> {
/// let devices = MuseClient::new(MuseClientConfig::default()).scan_all().await?;
/// let (mut rx, handle) = MuseClient::new(MuseClientConfig::default())
/// .connect_to(devices.into_iter().next().unwrap()).await?;
/// handle.start(false, false).await?;
///
/// while let Some(ev) = rx.recv().await {
/// if let MuseEvent::Eeg(r) = ev {
/// println!("{:?}", r.samples);
/// }
/// }
/// # Ok(())
/// # }
/// ```