diff --git a/src/command_handler.rs b/src/command_handler.rs index 66e1cf9..7c9ae31 100644 --- a/src/command_handler.rs +++ b/src/command_handler.rs @@ -1,4 +1,4 @@ -use crate::{CHANNEL_CONFIG_KEY, ad7172, channels::{self, CHANNELS}, command_parser::PwmPin, config::ChannelConfig, dfu, flash_store::{FlashStore}, session::Session}; +use crate::{CHANNEL_CONFIG_KEY, ad7172, channels::{self, CHANNELS}, command_parser::{CenterPoint, PidParameter, PwmPin, ShParameter}, config::ChannelConfig, dfu, flash_store::{FlashStore}, session::Session}; use channels::Channels; use smoltcp::socket::TcpSocket; use log::{error, warn}; @@ -34,7 +34,7 @@ pub enum Handler { #[derive(Clone, Debug, PartialEq)] pub enum Error { - ParseFloat, + } fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool { @@ -65,248 +65,284 @@ fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool { impl Handler { - pub fn handle_command (command: Command, socket: &mut TcpSocket, channels: &mut Channels, session: &Session, leds: &mut Leds, store: &mut FlashStore, ipv4_config: &mut Ipv4Config) -> Result { - match command { - Command::Quit => - // socket.close(), - Ok(Handler::CloseSocket), + fn reporting(socket: &mut TcpSocket) -> Result { + send_line(socket, b"{}"); + Ok(Handler::Handled) + } - Command::Reporting(_reporting) => { - // handled by session - send_line(socket, b"{}"); - Ok(Handler::Handled) - } - Command::Show(ShowCommand::Reporting) => { - let _ = writeln!(socket, "{{ \"report\": {:?} }}", session.reporting()); - Ok(Handler::Handled) - } - Command::Show(ShowCommand::Input) => { - match channels.reports_json() { - Ok(buf) => { - send_line(socket, &buf[..]); - } - Err(e) => { - error!("unable to serialize report: {:?}", e); - let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); + fn show_report_mode(socket: &mut TcpSocket, session: &Session) -> Result { + let _ = writeln!(socket, "{{ \"report\": {:?} }}", session.reporting()); + Ok(Handler::Handled) + } - } - } - Ok(Handler::Handled) + fn show_report(socket: &mut TcpSocket, channels: &mut Channels) -> Result { + match channels.reports_json() { + Ok(buf) => { + send_line(socket, &buf[..]); } - Command::Show(ShowCommand::Pid) => { - match channels.pid_summaries_json() { - Ok(buf) => { - send_line(socket, &buf); - } - Err(e) => { - error!("unable to serialize pid summary: {:?}", e); - let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); - } - } - Ok(Handler::Handled) + Err(e) => { + error!("unable to serialize report: {:?}", e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); + } - Command::Show(ShowCommand::Pwm) => { - match channels.pwm_summaries_json() { - Ok(buf) => { - send_line(socket, &buf); - } - Err(e) => { - error!("unable to serialize pwm summary: {:?}", e); - let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); - } - } - Ok(Handler::Handled) + } + Ok(Handler::Handled) + } + + fn show_pid(socket: &mut TcpSocket, channels: &mut Channels) -> Result { + match channels.pid_summaries_json() { + Ok(buf) => { + send_line(socket, &buf); } - Command::Show(ShowCommand::SteinhartHart) => { - match channels.steinhart_hart_summaries_json() { - Ok(buf) => { - send_line(socket, &buf); - } - Err(e) => { - error!("unable to serialize steinhart-hart summaries: {:?}", e); - let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); - } - } - Ok(Handler::Handled) + Err(e) => { + error!("unable to serialize pid summary: {:?}", e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); } - Command::Show(ShowCommand::PostFilter) => { - match channels.postfilter_summaries_json() { - Ok(buf) => { - send_line(socket, &buf); - } - Err(e) => { - error!("unable to serialize postfilter summary: {:?}", e); - let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); - } - } - Ok(Handler::Handled) + } + Ok(Handler::Handled) + } + + fn show_pwm(socket: &mut TcpSocket, channels: &mut Channels) -> Result { + match channels.pwm_summaries_json() { + Ok(buf) => { + send_line(socket, &buf); } - Command::Show(ShowCommand::Ipv4) => { - let (cidr, gateway) = net::split_ipv4_config(ipv4_config.clone()); - let _ = write!(socket, "{{\"addr\":\"{}\"", cidr); - gateway.map(|gateway| write!(socket, ",\"gateway\":\"{}\"", gateway)); - let _ = writeln!(socket, "}}"); - Ok(Handler::Handled) + Err(e) => { + error!("unable to serialize pwm summary: {:?}", e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); } - Command::PwmPid { channel } => { - channels.channel_state(channel).pid_engaged = true; - leds.g3.on(); + } + Ok(Handler::Handled) + } + + fn show_steinhart_hart(socket: &mut TcpSocket, channels: &mut Channels) -> Result { + match channels.steinhart_hart_summaries_json() { + Ok(buf) => { + send_line(socket, &buf); + } + Err(e) => { + error!("unable to serialize steinhart-hart summaries: {:?}", e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); + } + } + Ok(Handler::Handled) + } + + fn show_post_filter (socket: &mut TcpSocket, channels: &mut Channels) -> Result { + match channels.postfilter_summaries_json() { + Ok(buf) => { + send_line(socket, &buf); + } + Err(e) => { + error!("unable to serialize postfilter summary: {:?}", e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); + } + } + Ok(Handler::Handled) + } + + fn show_ipv4 (socket: &mut TcpSocket, ipv4_config: &mut Ipv4Config) -> Result { + let (cidr, gateway) = net::split_ipv4_config(ipv4_config.clone()); + let _ = write!(socket, "{{\"addr\":\"{}\"", cidr); + gateway.map(|gateway| write!(socket, ",\"gateway\":\"{}\"", gateway)); + let _ = writeln!(socket, "}}"); + Ok(Handler::Handled) + } + + fn engage_pid (channels: &mut Channels, channel: usize, socket: &mut TcpSocket, leds: &mut Leds) -> Result { + channels.channel_state(channel).pid_engaged = true; + leds.g3.on(); + send_line(socket, b"{}"); + Ok(Handler::Handled) + } + + fn set_pwm (channels: &mut Channels, channel: usize, pin: PwmPin, value: f64, socket: &mut TcpSocket, leds: &mut Leds) -> Result { + match pin { + PwmPin::ISet => { + channels.channel_state(channel).pid_engaged = false; + leds.g3.off(); + let current = ElectricCurrent::new::(value); + channels.set_i(channel, current); + channels.power_up(channel); + } + PwmPin::MaxV => { + let voltage = ElectricPotential::new::(value); + channels.set_max_v(channel, voltage); + } + PwmPin::MaxIPos => { + let current = ElectricCurrent::new::(value); + channels.set_max_i_pos(channel, current); + } + PwmPin::MaxINeg => { + let current = ElectricCurrent::new::(value); + channels.set_max_i_neg(channel, current); + } + } + send_line(socket, b"{}"); + Ok(Handler::Handled) + } + + fn set_center_point(channels: &mut Channels, socket: &mut TcpSocket, channel: usize, center: CenterPoint) -> Result { + let i_tec = channels.get_i(channel); + let state = channels.channel_state(channel); + state.center = center; + if !state.pid_engaged { + channels.set_i(channel, i_tec); + } + send_line(socket, b"{}"); + Ok(Handler::Handled) + } + + fn set_pid (channels: &mut Channels, socket: &mut TcpSocket, channel: usize, parameter: PidParameter, value: f64) -> Result { + let pid = &mut channels.channel_state(channel).pid; + use command_parser::PidParameter::*; + match parameter { + Target => + pid.target = value, + KP => + pid.parameters.kp = value as f32, + KI => + pid.update_ki(value as f32), + KD => + pid.parameters.kd = value as f32, + OutputMin => + pid.parameters.output_min = value as f32, + OutputMax => + pid.parameters.output_max = value as f32, + IntegralMin => + pid.parameters.integral_min = value as f32, + IntegralMax => + pid.parameters.integral_max = value as f32, + } + send_line(socket, b"{}"); + Ok(Handler::Handled) + } + + fn set_steinhart_hart (channels: &mut Channels, socket: &mut TcpSocket, channel: usize, parameter: ShParameter, value: f64) -> Result { + let sh = &mut channels.channel_state(channel).sh; + use command_parser::ShParameter::*; + match parameter { + T0 => sh.t0 = ThermodynamicTemperature::new::(value), + B => sh.b = value, + R0 => sh.r0 = ElectricalResistance::new::(value), + } + send_line(socket, b"{}"); + Ok(Handler::Handled) + } + + fn reset_post_filter (channels: &mut Channels, socket: &mut TcpSocket, channel: usize) -> Result { + channels.adc.set_postfilter(channel as u8, None).unwrap(); + send_line(socket, b"{}"); + Ok(Handler::Handled) + } + + fn set_post_filter (channels: &mut Channels, socket: &mut TcpSocket, channel: usize, rate: f32) -> Result { + let filter = ad7172::PostFilter::closest(rate); + match filter { + Some(filter) => { + channels.adc.set_postfilter(channel as u8, Some(filter)).unwrap(); send_line(socket, b"{}"); - Ok(Handler::Handled) } - Command::Pwm { channel, pin, value } => { - match pin { - PwmPin::ISet => { - channels.channel_state(channel).pid_engaged = false; - leds.g3.off(); - let current = ElectricCurrent::new::(value); - channels.set_i(channel, current); - channels.power_up(channel); - } - PwmPin::MaxV => { - let voltage = ElectricPotential::new::(value); - channels.set_max_v(channel, voltage); - } - PwmPin::MaxIPos => { - let current = ElectricCurrent::new::(value); - channels.set_max_i_pos(channel, current); - } - PwmPin::MaxINeg => { - let current = ElectricCurrent::new::(value); - channels.set_max_i_neg(channel, current); - } - } - send_line(socket, b"{}"); - Ok(Handler::Handled) + None => { + error!("unable to choose postfilter for rate {:.3}", rate); + send_line(socket, b"{{\"error\": \"unable to choose postfilter rate\"}}"); } - Command::CenterPoint { channel, center } => { - let i_tec = channels.get_i(channel); - let state = channels.channel_state(channel); - state.center = center; - if !state.pid_engaged { - channels.set_i(channel, i_tec); - } - send_line(socket, b"{}"); - Ok(Handler::Handled) - } - Command::Pid { channel, parameter, value } => { - let pid = &mut channels.channel_state(channel).pid; - use command_parser::PidParameter::*; - match parameter { - Target => - pid.target = value, - KP => - pid.parameters.kp = value as f32, - KI => - pid.update_ki(value as f32), - KD => - pid.parameters.kd = value as f32, - OutputMin => - pid.parameters.output_min = value as f32, - OutputMax => - pid.parameters.output_max = value as f32, - IntegralMin => - pid.parameters.integral_min = value as f32, - IntegralMax => - pid.parameters.integral_max = value as f32, - } - send_line(socket, b"{}"); - Ok(Handler::Handled) - } - Command::SteinhartHart { channel, parameter, value } => { - let sh = &mut channels.channel_state(channel).sh; - use command_parser::ShParameter::*; - match parameter { - T0 => sh.t0 = ThermodynamicTemperature::new::(value), - B => sh.b = value, - R0 => sh.r0 = ElectricalResistance::new::(value), - } - send_line(socket, b"{}"); - Ok(Handler::Handled) - } - Command::PostFilter { channel, rate: None } => { - channels.adc.set_postfilter(channel as u8, None).unwrap(); - send_line(socket, b"{}"); - Ok(Handler::Handled) - } - Command::PostFilter { channel, rate: Some(rate) } => { - let filter = ad7172::PostFilter::closest(rate); - match filter { - Some(filter) => { - channels.adc.set_postfilter(channel as u8, Some(filter)).unwrap(); + } + Ok(Handler::Handled) + } + + fn load_channel (channels: &mut Channels, channel: Option, socket: &mut TcpSocket, store: &mut FlashStore) -> Result { + for c in 0..CHANNELS { + if channel.is_none() || channel == Some(c) { + match store.read_value::(CHANNEL_CONFIG_KEY[c]) { + Ok(Some(config)) => { + config.apply(channels, c); send_line(socket, b"{}"); } - None => { - error!("unable to choose postfilter for rate {:.3}", rate); - send_line(socket, b"{{\"error\": \"unable to choose postfilter rate\"}}"); + Ok(None) => { + error!("flash config not found"); + send_line(socket, b"{{\"error\": \"flash config not found\"}}"); + } + Err(e) => { + error!("unable to load config from flash: {:?}", e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); } } - Ok(Handler::Handled) } - Command::Load { channel } => { - for c in 0..CHANNELS { - if channel.is_none() || channel == Some(c) { - match store.read_value::(CHANNEL_CONFIG_KEY[c]) { - Ok(Some(config)) => { - config.apply(channels, c); - send_line(socket, b"{}"); - } - Ok(None) => { - error!("flash config not found"); - send_line(socket, b"{{\"error\": \"flash config not found\"}}"); - } - Err(e) => { - error!("unable to load config from flash: {:?}", e); - let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); - } - } + } + Ok(Handler::Handled) + } + + fn save_channel (channels: &mut Channels, channel: Option, socket: &mut TcpSocket, store: &mut FlashStore) -> Result { + for c in 0..CHANNELS { + let mut store_value_buf = [0u8; 256]; + if channel.is_none() || channel == Some(c) { + let config = ChannelConfig::new(channels, c); + match store.write_value(CHANNEL_CONFIG_KEY[c], &config, &mut store_value_buf) { + Ok(()) => { + send_line(socket, b"{}"); + } + Err(e) => { + error!("unable to save channel {} config to flash: {:?}", c, e); + let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); } } - Ok(Handler::Handled) - } - Command::Save { channel } => { - for c in 0..CHANNELS { - let mut store_value_buf = [0u8; 256]; - if channel.is_none() || channel == Some(c) { - let config = ChannelConfig::new(channels, c); - match store.write_value(CHANNEL_CONFIG_KEY[c], &config, &mut store_value_buf) { - Ok(()) => { - send_line(socket, b"{}"); - } - Err(e) => { - error!("unable to save channel {} config to flash: {:?}", c, e); - let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); - } - } - } - } - Ok(Handler::Handled) - } - Command::Ipv4(config) => { - let _ = store - .write_value("ipv4", &config, [0; 16]) - .map_err(|e| error!("unable to save ipv4 config to flash: {:?}", e)); - let new_ipv4_config = Some(config); - send_line(socket, b"{}"); - Ok(Handler::NewIPV4(new_ipv4_config.unwrap())) - } - Command::Reset => { - for i in 0..CHANNELS { - channels.power_down(i); - } - // should_reset = true; - Ok(Handler::Reset) - } - Command::Dfu => { - for i in 0..CHANNELS { - channels.power_down(i); - } - unsafe { - dfu::set_dfu_trigger(); - } - // should_reset = true; - Ok(Handler::Reset) } } + Ok(Handler::Handled) + } + + fn set_ipv4 (socket: &mut TcpSocket, config: Ipv4Config, store: &mut FlashStore) -> Result { + let _ = store + .write_value("ipv4", &config, [0; 16]) + .map_err(|e| error!("unable to save ipv4 config to flash: {:?}", e)); + let new_ipv4_config = Some(config); + send_line(socket, b"{}"); + Ok(Handler::NewIPV4(new_ipv4_config.unwrap())) + } + + fn reset (channels: &mut Channels) -> Result { + for i in 0..CHANNELS { + channels.power_down(i); + } + // should_reset = true; + Ok(Handler::Reset) + } + + fn dfu (channels: &mut Channels) -> Result { + for i in 0..CHANNELS { + channels.power_down(i); + } + unsafe { + dfu::set_dfu_trigger(); + } + // should_reset = true; + Ok(Handler::Reset) + } + + pub fn handle_command (command: Command, socket: &mut TcpSocket, channels: &mut Channels, session: &Session, leds: &mut Leds, store: &mut FlashStore, ipv4_config: &mut Ipv4Config) -> Result { + match command { + Command::Quit => Ok(Handler::CloseSocket), + Command::Reporting(_reporting) => Handler::reporting(socket), + Command::Show(ShowCommand::Reporting) => Handler::show_report_mode(socket, session), + Command::Show(ShowCommand::Input) => Handler::show_report(socket, channels), + Command::Show(ShowCommand::Pid) => Handler::show_pid(socket, channels), + Command::Show(ShowCommand::Pwm) => Handler::show_pwm(socket, channels), + Command::Show(ShowCommand::SteinhartHart) => Handler::show_steinhart_hart(socket, channels), + Command::Show(ShowCommand::PostFilter) => Handler::show_post_filter(socket, channels), + Command::Show(ShowCommand::Ipv4) => Handler::show_ipv4(socket, ipv4_config), + Command::PwmPid { channel } => Handler::engage_pid(channels, channel, socket, leds), + Command::Pwm { channel, pin, value } => Handler::set_pwm(channels, channel, pin, value, socket, leds), + Command::CenterPoint { channel, center } => Handler::set_center_point(channels, socket, channel, center), + Command::Pid { channel, parameter, value } => Handler::set_pid(channels, socket, channel, parameter, value), + Command::SteinhartHart { channel, parameter, value } => Handler::set_steinhart_hart(channels, socket, channel, parameter, value), + Command::PostFilter { channel, rate: None } => Handler::reset_post_filter(channels, socket, channel), + Command::PostFilter { channel, rate: Some(rate) } => Handler::set_post_filter(channels, socket, channel, rate), + Command::Load { channel } => Handler::load_channel(channels, channel, socket, store), + Command::Save { channel } => Handler::save_channel(channels, channel, socket, store), + Command::Ipv4(config) => Handler::set_ipv4(socket, config, store), + Command::Reset => Handler::reset(channels), + Command::Dfu => Handler::dfu(channels) + } } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index b724ed3..90fa8be 100644 --- a/src/main.rs +++ b/src/main.rs @@ -208,7 +208,6 @@ fn main() -> ! { // Do nothing and feed more data to the line reader in the next loop cycle. Ok(SessionInput::Nothing) => {} Ok(SessionInput::Command(command)) => { - // let handler = Handler::handle_command(command, &mut socket, &mut channels, session, &mut leds, store, ipv4_config); match Handler::handle_command(command, &mut socket, &mut channels, session, &mut leds, &mut store, &mut ipv4_config) { Ok(Handler::NewIPV4(ip)) => { new_ipv4_config = Some(ip);