use core::{fmt::Debug, marker::PhantomData}; use miniconf::{JsonCoreSlash, Tree}; use serde::{Deserialize, Serialize}; use uom::si::{ electric_current::{ampere, microampere, milliampere, ElectricCurrent}, electric_potential::{volt, ElectricPotential}, electrical_resistance::{ohm, ElectricalResistance}, power::{milliwatt, Power}, thermodynamic_temperature::{degree_celsius, ThermodynamicTemperature} }; use crate::{laser_diode::{laser_diode::{ LdDrive, StatusReport as LdStatusReport}, pd_responsitivity::ResponsitivityUnit }, net::net, thermostat::thermostat::StatusReport as TecStatusReport }; use crate::thermostat::thermostat::Thermostat; use crate::thermostat::pid_state::PidSettings::*; use crate::device::dfu; use log::info; use crate::DeviceSettings; #[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)] enum DeviceCmd { #[default] Reserved, ReportStatus, Dfu, } #[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)] enum LdCmdEnum { #[default] Reserved, // LD Drive Related PowerUp, PowerDown, LdTermsShort, LdTermsOpen, SetI, SetISoftLimit, // PD Mon Related SetPdResponsitivity, SetPdDarkCurrent, SetPdILimit, SetLdPwrLimit, ClearAlarmStatus, // Report Related GetModInTermStatus, GetLdStatus, GetAlramStatus, } #[derive(Deserialize, Serialize, Copy, Clone, Default, Debug)] enum ThermostatCmdEnum { #[default] Reserved, PowerUp, PowerDown, // TEC SetTecMaxV, SetTecMaxIPos, SetTecMaxINeg, SetTecIOut, // Constant Current Mode SetTemperatureSetpoint, // PID SetPidEngage, SetPidDisEngage, SetPidKp, SetPidKi, SetPidKd, SetPidOutMin, SetPidOutMax, SetPidUpdateInterval, // Update Interval is set based on the sampling rate of ADC // TempMon SetTempMonUpperLimit, SetTempMonLowerLimit, ClearAlarm, // Steinhart-Hart Equation SetShT0, SetShR0, SetShBeta, // Report Related GetTecStatus, GetPidStatus, GetShParams, } #[derive(Deserialize, Serialize, Copy, Clone, Debug, Default, Tree)] pub struct CmdJsonObj{ laser_diode_cmd: Option, thermostat_cmd: Option, device_cmd: Option, data_bool: Option, data_f32: Option, data_f64: Option, } #[derive(Deserialize, Serialize, Copy, Clone, Debug, Default, Tree)] pub struct Cmd { json: CmdJsonObj } #[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)] pub struct TecStatusReportStruct { json: TecStatusReport } #[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)] pub struct LaserStatusReportStruct { json: LdStatusReport } pub fn send_ld_readings(buffer: &mut [u8], laser: &mut LdDrive){ let status_report = LaserStatusReportStruct { json: laser.get_status_report() }; let num_bytes = status_report.get_json("/json", buffer).unwrap(); net::eth_send(buffer, num_bytes); } pub fn send_tec_readings(buffer: &mut [u8], tec: &mut Thermostat){ let status_report = TecStatusReportStruct { json: tec.get_status_report() }; let num_bytes = status_report.get_json("/json", buffer).unwrap(); net::eth_send(buffer, num_bytes); } pub fn execute_cmd(buffer: &mut [u8], buffer_size: usize, mut laser: LdDrive, mut tec: Thermostat, mut device_settings: DeviceSettings)->(LdDrive, Thermostat, bool, DeviceSettings){ let mut should_reset = false; let mut cmd = Cmd { json: CmdJsonObj::default() }; match cmd.set_json("/json", &buffer[0..buffer_size]){ Ok(_) => { info!("############ Laser Diode Command Received {:?}", cmd.json.laser_diode_cmd); info!("############ Thermostat Command Received {:?}", cmd.json.thermostat_cmd); info!("############ Device Command Received {:?}", cmd.json.device_cmd); match cmd.json.device_cmd { Some(DeviceCmd::Dfu) => { unsafe { dfu::set_dfu_trigger(); } should_reset = true; } Some(DeviceCmd::ReportStatus) => { match cmd.json.data_bool{ Some(val) => { device_settings.report_readings = val; } None => { info!("Wrong Data type is received") } } } None => { /* Do Nothing */} _ => { info!("Unimplemented Command") } } match cmd.json.laser_diode_cmd { Some(LdCmdEnum::PowerUp) => { laser.power_up() } Some(LdCmdEnum::PowerDown) => { laser.power_down() } Some(LdCmdEnum::LdTermsShort) => { laser.ld_short(); } Some(LdCmdEnum::LdTermsOpen) => { laser.ld_open(); } Some(LdCmdEnum::SetI) => { match cmd.json.data_f64 { Some(val) => { laser.ld_set_i(ElectricCurrent::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(LdCmdEnum::SetISoftLimit) => { match cmd.json.data_f64 { Some(val) => { laser.set_ld_drive_current_limit(ElectricCurrent::new::(val)) } None => { info!("Wrong Data type is received") } } } Some(LdCmdEnum::SetPdResponsitivity) => { match cmd.json.data_f64 { Some(val) => { laser.set_pd_responsitivity(ResponsitivityUnit {dimension: PhantomData, units: PhantomData, value: val}) } None => { info!("Wrong Data type is received") } } } Some(LdCmdEnum::SetPdDarkCurrent) => { match cmd.json.data_f64 { Some(val) => { laser.set_pd_dark_current(ElectricCurrent::new::(val)) } None => { info!("Wrong Data type is received") } } } Some(LdCmdEnum::SetPdILimit) => { match cmd.json.data_f64 { Some(val) => { laser.set_pd_i_limit(ElectricCurrent::new::(val)) } None => { info!("Wrong Data type is received") } } } Some(LdCmdEnum::SetLdPwrLimit) => { match cmd.json.data_f64 { Some(val) => { laser.set_ld_power_limit(Power::new::(val)) } None => { info!("Wrong Data type is received") } } } Some(LdCmdEnum::ClearAlarmStatus) => { laser.pd_mon_clear_alarm() } Some(LdCmdEnum::GetModInTermStatus) => { info!("Not supported Yet") } Some(LdCmdEnum::GetLdStatus) => { send_ld_readings(buffer, &mut laser); } Some(LdCmdEnum::GetAlramStatus) => { info!("Not supported Yet") } None => { /* Do Nothing*/ } _ => { info!("Unimplemented Command") } } match cmd.json.thermostat_cmd { Some(ThermostatCmdEnum::PowerUp) => { tec.power_up() } Some(ThermostatCmdEnum::PowerDown) => { tec.power_down() } Some(ThermostatCmdEnum::SetTecMaxV) => { match cmd.json.data_f64 { Some(val) => { tec.set_max_v(ElectricPotential::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetTecMaxIPos) => { match cmd.json.data_f64 { Some(val) => { tec.set_max_i_pos(ElectricCurrent::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetTecMaxINeg) => { match cmd.json.data_f64 { Some(val) => { tec.set_max_i_pos(ElectricCurrent::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetTecIOut) => { match cmd.json.data_f64 { Some(val) => { tec.set_i(ElectricCurrent::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetTemperatureSetpoint) => { match cmd.json.data_f64 { Some(val) => { tec.set_temperature_setpoint(ThermodynamicTemperature::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetPidEngage) => { tec.set_pid_engaged(true); } Some(ThermostatCmdEnum::SetPidDisEngage) => { tec.set_pid_engaged(false); } Some(ThermostatCmdEnum::SetPidKp) => { match cmd.json.data_f64 { Some(val) => { tec.set_pid(Kp, val); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetPidKi) => { match cmd.json.data_f64 { Some(val) => { tec.set_pid(Ki, val); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetPidKd) => { match cmd.json.data_f64 { Some(val) => { tec.set_pid(Kd, val); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetPidOutMin) => { match cmd.json.data_f64 { Some(val) => { tec.set_pid(Min, val); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetPidOutMax) => { match cmd.json.data_f64 { Some(val) => { tec.set_pid(Max, val); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetPidUpdateInterval) => { info!("Not supported Yet") } Some(ThermostatCmdEnum::SetTempMonUpperLimit) => { match cmd.json.data_f64 { Some(val) => { tec.set_temp_mon_upper_limit(ThermodynamicTemperature::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetTempMonLowerLimit) => { match cmd.json.data_f64 { Some(val) => { tec.set_temp_mon_lower_limit(ThermodynamicTemperature::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::ClearAlarm) => { tec.clear_temp_mon_alarm(); } Some(ThermostatCmdEnum::SetShT0) => { match cmd.json.data_f64 { Some(val) => { tec.set_sh_t0(ThermodynamicTemperature::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetShR0) => { match cmd.json.data_f64 { Some(val) => { tec.set_sh_r0(ElectricalResistance::new::(val)); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::SetShBeta) => { match cmd.json.data_f64 { Some(val) => { tec.set_sh_beta(val); } None => { info!("Wrong Data type is received") } } } Some(ThermostatCmdEnum::GetTecStatus) => { send_tec_readings(buffer, &mut tec); } Some(ThermostatCmdEnum::GetPidStatus) => { info!("Not supported Yet") } Some(ThermostatCmdEnum::GetShParams) => { info!("Not supported Yet") } None => { /* Do Nothing*/ } _ => { info!("Unimplemented Command") } } } Err(err) => { info!("Invalid Command: {:?}", err); } } (laser, tec, should_reset, device_settings) }