use ratatui::style::Color;
use std::borrow::Cow;
pub const COLORS: &[Color] = &[
Color::Cyan,
Color::Magenta,
Color::Yellow,
Color::Green,
Color::Red,
Color::Blue,
Color::White,
Color::LightCyan,
Color::LightMagenta,
Color::LightYellow,
Color::LightGreen,
Color::LightRed,
Color::LightBlue,
];
pub fn get_color_for_index(index: usize) -> Color {
COLORS[index % COLORS.len()]
}
#[derive(Debug, Clone)]
pub struct SensorData {
pub name: String,
pub data: Vec<(f64, f64)>,
pub color: Color,
pub min_value: f64,
pub max_value: f64,
pub current_value: f64,
}
impl SensorData {
pub fn new(name: String, color: Color) -> Self {
SensorData {
name,
data: Vec::new(),
color,
min_value: f64::INFINITY,
max_value: f64::NEG_INFINITY,
current_value: 0.0,
}
}
pub fn add_point(&mut self, x: f64, y: f64, max_points: usize) {
self.data.push((x, y));
self.current_value = y;
if y < self.min_value {
self.min_value = y;
}
if y > self.max_value {
self.max_value = y;
}
if self.data.len() > max_points {
self.data.remove(0);
}
}
pub fn has_data(&self) -> bool {
!self.data.is_empty()
}
}
pub fn parse_sensor_data<'a>(line: &'a str) -> Vec<(Cow<'a, str>, f64)> {
let mut results = Vec::new();
let line = line.trim();
if line.contains(',') {
let parts: Vec<&str> = line.split(',').collect();
let mut found_any = false;
for (i, part) in parts.iter().enumerate() {
let part = part.trim();
if let Some(pos) = part.find(':') {
let (name, val_str) = part.split_at(pos);
if let Ok(val) = val_str[1..].trim().parse::<f64>() {
results.push((Cow::Owned(name.trim().to_string()), val));
found_any = true;
continue;
}
}
if let Some(pos) = part.find('=') {
let (name, val_str) = part.split_at(pos);
if let Ok(val) = val_str[1..].trim().parse::<f64>() {
results.push((Cow::Owned(name.trim().to_string()), val));
found_any = true;
continue;
}
}
if let Ok(val) = part.parse::<f64>() {
results.push((Cow::Owned(format!("Channel {}", i)), val));
found_any = true;
}
}
if found_any {
return results;
}
}
if let Some(pos) = line.find(':') {
let (name, val_str) = line.split_at(pos);
if let Ok(val) = val_str[1..].trim().parse::<f64>() {
results.push((Cow::Borrowed(name.trim()), val));
return results;
}
}
if let Some(pos) = line.find('=') {
let (name, val_str) = line.split_at(pos);
if let Ok(val) = val_str[1..].trim().parse::<f64>() {
results.push((Cow::Borrowed(name.trim()), val));
return results;
}
}
let words: Vec<&str> = line.split_whitespace().collect();
let numeric: Vec<f64> = words.iter().filter_map(|w| w.parse::<f64>().ok()).collect();
if numeric.len() > 1 {
for (i, v) in numeric.iter().enumerate() {
results.push((Cow::Owned(format!("Channel {}", i)), *v));
}
return results;
}
if let Ok(value) = line.parse::<f64>() {
results.push((Cow::Borrowed("Value"), value));
return results;
}
for word in &words {
let cleaned = word.trim_matches(|c: char| !c.is_ascii_digit() && c != '.' && c != '-');
if let Ok(value) = cleaned.parse::<f64>() {
let ll = line.to_lowercase();
let sensor_name: &'static str = if ll.contains("temp") {
"Temperature"
} else if ll.contains("humid") {
"Humidity"
} else if ll.contains("pressure") {
"Pressure"
} else if ll.contains("mag") {
"Magnetometer"
} else if ll.contains("gyro") {
"Gyroscope"
} else if ll.contains("accel") {
"Accelerometer"
} else {
"Sensor"
};
results.push((Cow::Borrowed(sensor_name), value));
break; }
}
results
}