kirdy/src/net/cmd_handler.rs

446 lines
16 KiB
Rust

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<LdCmdEnum>,
thermostat_cmd: Option<ThermostatCmdEnum>,
device_cmd: Option<DeviceCmd>,
data_bool: Option<bool>,
data_f32: Option<f32>,
data_f64: Option<f64>,
}
#[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::<milliampere>(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::<milliampere>(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::<microampere>(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::<milliampere>(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::<milliwatt>(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::<volt>(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::<ampere>(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::<milliampere>(val));
}
None => {
info!("Wrong Data type is received")
}
}
}
Some(ThermostatCmdEnum::SetTecIOut) => {
match cmd.json.data_f64 {
Some(val) => {
tec.set_i(ElectricCurrent::new::<milliampere>(val));
}
None => {
info!("Wrong Data type is received")
}
}
}
Some(ThermostatCmdEnum::SetTemperatureSetpoint) => {
match cmd.json.data_f64 {
Some(val) => {
tec.set_temperature_setpoint(ThermodynamicTemperature::new::<degree_celsius>(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::<degree_celsius>(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::<degree_celsius>(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::<degree_celsius>(val));
}
None => {
info!("Wrong Data type is received")
}
}
}
Some(ThermostatCmdEnum::SetShR0) => {
match cmd.json.data_f64 {
Some(val) => {
tec.set_sh_r0(ElectricalResistance::new::<ohm>(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)
}