use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum HeadsetModel {
EpocX,
EpocPlus,
EpocFlex,
EpocStd,
Insight,
Insight2,
MN8,
Xtrodes,
}
impl std::fmt::Display for HeadsetModel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name())
}
}
impl HeadsetModel {
pub fn from_str(s: &str) -> Option<Self> {
match s {
"EPOC X" | "epoc_x" | "EPOC_X" => Some(HeadsetModel::EpocX),
"EPOC+" | "epoc_plus" | "EPOC_PLUS" => Some(HeadsetModel::EpocPlus),
"EPOC Flex" | "epoc_flex" | "EPOC_FLEX" => Some(HeadsetModel::EpocFlex),
"EPOC" | "epoc_std" | "EPOC_STD" => Some(HeadsetModel::EpocStd),
"Insight" | "insight" => Some(HeadsetModel::Insight),
"Insight 2" | "insight_2" | "INSIGHT_2" => Some(HeadsetModel::Insight2),
"MN8" | "mn8" => Some(HeadsetModel::MN8),
"Xtrodes" | "xtrodes" => Some(HeadsetModel::Xtrodes),
_ => None,
}
}
pub fn name(&self) -> &str {
match self {
HeadsetModel::EpocX => "EPOC X",
HeadsetModel::EpocPlus => "EPOC+",
HeadsetModel::EpocFlex => "EPOC Flex",
HeadsetModel::EpocStd => "EPOC",
HeadsetModel::Insight => "Insight",
HeadsetModel::Insight2 => "Insight 2",
HeadsetModel::MN8 => "MN8",
HeadsetModel::Xtrodes => "Xtrodes",
}
}
pub fn channel_count(&self) -> usize {
match self {
HeadsetModel::EpocX | HeadsetModel::EpocPlus | HeadsetModel::EpocStd => 14,
HeadsetModel::EpocFlex => 32,
HeadsetModel::Insight | HeadsetModel::Insight2 => 5,
HeadsetModel::MN8 => 2,
HeadsetModel::Xtrodes => 8,
}
}
pub fn channels(&self) -> Vec<&'static str> {
match self {
HeadsetModel::EpocX | HeadsetModel::EpocPlus | HeadsetModel::EpocStd => vec![
"AF3", "F7", "F3", "FC5", "T7", "P7", "O1", "O2", "P8", "T8", "FC6", "F4", "F8", "AF4",
],
HeadsetModel::EpocFlex => vec![
"Fp1", "Fpz", "Fp2", "AF7", "AF3", "AFz", "AF4", "AF8",
"F7", "F5", "F3", "F1", "Fz", "F2", "F4", "F6", "F8",
"FT7", "FC5", "FC3", "FC1", "FCz", "FC2", "FC4", "FC6", "FT8",
"T7", "C5", "C3", "C1", "Cz", "C2", "C4", "C6", "T8",
],
HeadsetModel::Insight | HeadsetModel::Insight2 => {
vec!["AF3", "AF4", "T7", "T8", "Pz"]
}
HeadsetModel::MN8 => vec!["TP9", "TP10"],
_ => vec![],
}
}
pub fn sampling_rate(&self) -> u32 {
match self {
HeadsetModel::EpocX | HeadsetModel::EpocPlus => 256,
HeadsetModel::EpocStd => 128,
HeadsetModel::EpocFlex => 256,
HeadsetModel::Insight => 128,
HeadsetModel::Insight2 => 256,
HeadsetModel::MN8 => 256,
HeadsetModel::Xtrodes => 250,
}
}
pub fn eeg_physical_range(&self) -> (f64, f64) {
match self {
HeadsetModel::EpocX | HeadsetModel::EpocPlus | HeadsetModel::EpocStd => {
(-8399.0, 8399.0)
}
HeadsetModel::EpocFlex => (-8399.0, 8399.0),
HeadsetModel::Insight | HeadsetModel::Insight2 => (-4199.5, 4199.5),
HeadsetModel::MN8 => (-4199.5, 4199.5),
HeadsetModel::Xtrodes => (-32767.0, 32767.0),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DecryptedData {
pub counter: u32,
pub eeg_uv: Vec<f64>,
pub eeg_adc: Vec<i32>,
pub contact_quality: Vec<u8>,
pub signal_quality: u8,
pub motion: Option<Vec<f64>>,
pub battery_percent: u8,
pub timestamp: f64,
pub receive_time: f64,
}
impl DecryptedData {
pub fn new(
counter: u32,
eeg_uv: Vec<f64>,
eeg_adc: Vec<i32>,
contact_quality: Vec<u8>,
signal_quality: u8,
battery_percent: u8,
) -> Self {
Self {
counter,
eeg_uv,
eeg_adc,
contact_quality,
signal_quality,
motion: None,
battery_percent,
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs_f64(),
receive_time: 0.0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatteryInfo {
pub percent: u8,
pub voltage_mv: u16,
pub is_low: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeviceState {
Disconnected,
Connecting,
Connected,
Streaming,
Disconnecting,
}
impl std::fmt::Display for DeviceState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Disconnected => write!(f, "Disconnected"),
Self::Connecting => write!(f, "Connecting"),
Self::Connected => write!(f, "Connected"),
Self::Streaming => write!(f, "Streaming"),
Self::Disconnecting => write!(f, "Disconnecting"),
}
}
}