main refactor: refine command handler

pull/60/head
topquark12 2021-06-02 17:39:03 +08:00
parent 6473b27539
commit 31f7e7eead
2 changed files with 261 additions and 226 deletions

View File

@ -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 channels::Channels;
use smoltcp::socket::TcpSocket; use smoltcp::socket::TcpSocket;
use log::{error, warn}; use log::{error, warn};
@ -34,7 +34,7 @@ pub enum Handler {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum Error { pub enum Error {
ParseFloat,
} }
fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool { fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool {
@ -65,248 +65,284 @@ fn send_line(socket: &mut TcpSocket, data: &[u8]) -> bool {
impl Handler { 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<Self, Error> { fn reporting(socket: &mut TcpSocket) -> Result<Handler, Error> {
match command { send_line(socket, b"{}");
Command::Quit => Ok(Handler::Handled)
// socket.close(), }
Ok(Handler::CloseSocket),
Command::Reporting(_reporting) => { fn show_report_mode(socket: &mut TcpSocket, session: &Session) -> Result<Handler, Error> {
// handled by session let _ = writeln!(socket, "{{ \"report\": {:?} }}", session.reporting());
send_line(socket, b"{}"); Ok(Handler::Handled)
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(socket: &mut TcpSocket, channels: &mut Channels) -> Result<Handler, Error> {
} match channels.reports_json() {
Ok(Handler::Handled) Ok(buf) => {
send_line(socket, &buf[..]);
} }
Command::Show(ShowCommand::Pid) => { Err(e) => {
match channels.pid_summaries_json() { error!("unable to serialize report: {:?}", e);
Ok(buf) => { let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
send_line(socket, &buf);
}
Err(e) => {
error!("unable to serialize pid summary: {:?}", e);
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
}
}
Ok(Handler::Handled)
} }
Command::Show(ShowCommand::Pwm) => { }
match channels.pwm_summaries_json() { Ok(Handler::Handled)
Ok(buf) => { }
send_line(socket, &buf);
} fn show_pid(socket: &mut TcpSocket, channels: &mut Channels) -> Result<Handler, Error> {
Err(e) => { match channels.pid_summaries_json() {
error!("unable to serialize pwm summary: {:?}", e); Ok(buf) => {
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); send_line(socket, &buf);
}
}
Ok(Handler::Handled)
} }
Command::Show(ShowCommand::SteinhartHart) => { Err(e) => {
match channels.steinhart_hart_summaries_json() { error!("unable to serialize pid summary: {:?}", e);
Ok(buf) => { let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
send_line(socket, &buf);
}
Err(e) => {
error!("unable to serialize steinhart-hart summaries: {:?}", e);
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
}
}
Ok(Handler::Handled)
} }
Command::Show(ShowCommand::PostFilter) => { }
match channels.postfilter_summaries_json() { Ok(Handler::Handled)
Ok(buf) => { }
send_line(socket, &buf);
} fn show_pwm(socket: &mut TcpSocket, channels: &mut Channels) -> Result<Handler, Error> {
Err(e) => { match channels.pwm_summaries_json() {
error!("unable to serialize postfilter summary: {:?}", e); Ok(buf) => {
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e); send_line(socket, &buf);
}
}
Ok(Handler::Handled)
} }
Command::Show(ShowCommand::Ipv4) => { Err(e) => {
let (cidr, gateway) = net::split_ipv4_config(ipv4_config.clone()); error!("unable to serialize pwm summary: {:?}", e);
let _ = write!(socket, "{{\"addr\":\"{}\"", cidr); let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", e);
gateway.map(|gateway| write!(socket, ",\"gateway\":\"{}\"", gateway));
let _ = writeln!(socket, "}}");
Ok(Handler::Handled)
} }
Command::PwmPid { channel } => { }
channels.channel_state(channel).pid_engaged = true; Ok(Handler::Handled)
leds.g3.on(); }
fn show_steinhart_hart(socket: &mut TcpSocket, channels: &mut Channels) -> Result<Handler, Error> {
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<Handler, Error> {
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<Handler, Error> {
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<Handler, Error> {
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<Handler, Error> {
match pin {
PwmPin::ISet => {
channels.channel_state(channel).pid_engaged = false;
leds.g3.off();
let current = ElectricCurrent::new::<ampere>(value);
channels.set_i(channel, current);
channels.power_up(channel);
}
PwmPin::MaxV => {
let voltage = ElectricPotential::new::<volt>(value);
channels.set_max_v(channel, voltage);
}
PwmPin::MaxIPos => {
let current = ElectricCurrent::new::<ampere>(value);
channels.set_max_i_pos(channel, current);
}
PwmPin::MaxINeg => {
let current = ElectricCurrent::new::<ampere>(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<Handler, Error> {
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<Handler, Error> {
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<Handler, Error> {
let sh = &mut channels.channel_state(channel).sh;
use command_parser::ShParameter::*;
match parameter {
T0 => sh.t0 = ThermodynamicTemperature::new::<degree_celsius>(value),
B => sh.b = value,
R0 => sh.r0 = ElectricalResistance::new::<ohm>(value),
}
send_line(socket, b"{}");
Ok(Handler::Handled)
}
fn reset_post_filter (channels: &mut Channels, socket: &mut TcpSocket, channel: usize) -> Result<Handler, Error> {
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<Handler, Error> {
let filter = ad7172::PostFilter::closest(rate);
match filter {
Some(filter) => {
channels.adc.set_postfilter(channel as u8, Some(filter)).unwrap();
send_line(socket, b"{}"); send_line(socket, b"{}");
Ok(Handler::Handled)
} }
Command::Pwm { channel, pin, value } => { None => {
match pin { error!("unable to choose postfilter for rate {:.3}", rate);
PwmPin::ISet => { send_line(socket, b"{{\"error\": \"unable to choose postfilter rate\"}}");
channels.channel_state(channel).pid_engaged = false;
leds.g3.off();
let current = ElectricCurrent::new::<ampere>(value);
channels.set_i(channel, current);
channels.power_up(channel);
}
PwmPin::MaxV => {
let voltage = ElectricPotential::new::<volt>(value);
channels.set_max_v(channel, voltage);
}
PwmPin::MaxIPos => {
let current = ElectricCurrent::new::<ampere>(value);
channels.set_max_i_pos(channel, current);
}
PwmPin::MaxINeg => {
let current = ElectricCurrent::new::<ampere>(value);
channels.set_max_i_neg(channel, current);
}
}
send_line(socket, b"{}");
Ok(Handler::Handled)
} }
Command::CenterPoint { channel, center } => { }
let i_tec = channels.get_i(channel); Ok(Handler::Handled)
let state = channels.channel_state(channel); }
state.center = center;
if !state.pid_engaged { fn load_channel (channels: &mut Channels, channel: Option<usize>, socket: &mut TcpSocket, store: &mut FlashStore) -> Result<Handler, Error> {
channels.set_i(channel, i_tec); for c in 0..CHANNELS {
} if channel.is_none() || channel == Some(c) {
send_line(socket, b"{}"); match store.read_value::<ChannelConfig>(CHANNEL_CONFIG_KEY[c]) {
Ok(Handler::Handled) Ok(Some(config)) => {
} config.apply(channels, c);
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::<degree_celsius>(value),
B => sh.b = value,
R0 => sh.r0 = ElectricalResistance::new::<ohm>(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();
send_line(socket, b"{}"); send_line(socket, b"{}");
} }
None => { Ok(None) => {
error!("unable to choose postfilter for rate {:.3}", rate); error!("flash config not found");
send_line(socket, b"{{\"error\": \"unable to choose postfilter rate\"}}"); 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 { Ok(Handler::Handled)
if channel.is_none() || channel == Some(c) { }
match store.read_value::<ChannelConfig>(CHANNEL_CONFIG_KEY[c]) {
Ok(Some(config)) => { fn save_channel (channels: &mut Channels, channel: Option<usize>, socket: &mut TcpSocket, store: &mut FlashStore) -> Result<Handler, Error> {
config.apply(channels, c); for c in 0..CHANNELS {
send_line(socket, b"{}"); let mut store_value_buf = [0u8; 256];
} if channel.is_none() || channel == Some(c) {
Ok(None) => { let config = ChannelConfig::new(channels, c);
error!("flash config not found"); match store.write_value(CHANNEL_CONFIG_KEY[c], &config, &mut store_value_buf) {
send_line(socket, b"{{\"error\": \"flash config not found\"}}"); Ok(()) => {
} send_line(socket, b"{}");
Err(e) => { }
error!("unable to load config from flash: {:?}", e); Err(e) => {
let _ = writeln!(socket, "{{\"error\":\"{:?}\"}}", 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<Handler, Error> {
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<Handler, Error> {
for i in 0..CHANNELS {
channels.power_down(i);
}
// should_reset = true;
Ok(Handler::Reset)
}
fn dfu (channels: &mut Channels) -> Result<Handler, Error> {
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<Self, Error> {
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)
}
} }
} }

View File

@ -208,7 +208,6 @@ fn main() -> ! {
// Do nothing and feed more data to the line reader in the next loop cycle. // Do nothing and feed more data to the line reader in the next loop cycle.
Ok(SessionInput::Nothing) => {} Ok(SessionInput::Nothing) => {}
Ok(SessionInput::Command(command)) => { 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) { match Handler::handle_command(command, &mut socket, &mut channels, session, &mut leds, &mut store, &mut ipv4_config) {
Ok(Handler::NewIPV4(ip)) => { Ok(Handler::NewIPV4(ip)) => {
new_ipv4_config = Some(ip); new_ipv4_config = Some(ip);