use std::str::FromStr;
use super::{
UPSState,
UPSStateParameters,
UPSMode,
MainsState,
Error};
fn _parse_voltage(line: &str) -> Result<u16, Error>{
line.parse::<u16>()
.map_err(|err| Error::CanNotParseVoltage{
line: line.to_owned(),
err})
}
fn _parse_frequency(line: &str) -> Result<u8, Error>{
line.parse::<u8>()
.map_err(|err| Error::CanNotParseFrequency{
line: line.to_owned(),
err})
}
fn _parse_load_percent(line: &str) -> Result<u8, Error>{
line
.parse::<u8>()
.map_err(|err| Error::CanNotParseLoadPercent{
line: line.to_owned(),
err})
}
fn _parse_temperature(line: &str) -> Result<i8, Error>{
line
.parse::<i8>()
.map_err(|err| Error::CanNotParseTemperature{
line: line.to_owned(),
err})
}
fn _parse_battery_charge_percent(line: &str) -> Result<u8, Error>{
let charge_percent =
line
.parse::<u8>()
.map_err(|err| Error::CanNotParseChargePercent{
line: line.to_owned(),
err})?;
if charge_percent>100 {
Err(Error::ChargePercentOutOfRange{
charge_percent})
}
else {
Ok(charge_percent)
}
}
fn _parse_ups_mode(line: &str) -> Result<UPSMode, Error>{
match line{
"1" => Ok(UPSMode::Normal),
"2" => Ok(UPSMode::BuckingVoltage),
"3" => Ok(UPSMode::BoostingVoltage),
"4" => Ok(UPSMode::Bypass),
"5" => Ok(UPSMode::OnLine),
_ => Err(Error::CanNotParseUPSMode{
line:line.to_owned()})
}
}
fn _parse_mains_state(line: &str) -> Result<MainsState, Error>{
match line{
"1" => Ok(MainsState::Ok),
"2" => Ok(MainsState::Warning),
"3" => Ok(MainsState::Failure),
_ => Err(Error::CanNotParseMainsState{
line:line.to_owned()})
}
}
const VIN_LINE_IDX: usize = 0;
const VOUT_LINE_IDX: usize = 1;
const LOAD_LEVEL_LINE_IDX: usize = 2;
const FREQ_LINE_IDX: usize = 3;
const TEMP_OR_FREQ_LINE_IDX: usize = 4;
const CHG_PERCENT_LINE_IDX: usize = 5;
const UPS_MODE_LINE_IDX: usize = 6;
const MAINS_STATE_LINE_IDX: usize = 7;
const CONNECTION_STATUS_LINE_IDX: usize = 8;
const TEMP_FREQ_MODE_LINE_IDX: usize = 9;
fn _parse_state_parameters(lines: &[&str]) -> Result<UPSStateParameters, Error> {
let (frequency, temperature) =
match lines[TEMP_FREQ_MODE_LINE_IDX] {
"1" => (_parse_frequency(
lines[TEMP_OR_FREQ_LINE_IDX])?,
None),
_ => (_parse_frequency(
lines[FREQ_LINE_IDX])?,
Some(_parse_temperature(
lines[TEMP_OR_FREQ_LINE_IDX])?))
};
Ok(UPSStateParameters::new(
_parse_ups_mode(lines[UPS_MODE_LINE_IDX])?,
_parse_mains_state(lines[MAINS_STATE_LINE_IDX])?,
_parse_voltage(lines[VIN_LINE_IDX])?,
_parse_voltage(lines[VOUT_LINE_IDX])?,
_parse_load_percent(lines[LOAD_LEVEL_LINE_IDX])?,
frequency,
_parse_battery_charge_percent(lines[CHG_PERCENT_LINE_IDX])?,
temperature))
}
impl FromStr for UPSState {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let lines: Vec<&str> = s.lines().take(10).collect();
if lines.len() < 10 {
return Err(Error::UPSStateStringTooShort{ups_state: s.to_owned()})
}
let connection_status: &str = lines[CONNECTION_STATUS_LINE_IDX];
match connection_status {
"1" => Ok(UPSState::Connected(
_parse_state_parameters(&lines)?)),
"2" => Ok(UPSState::Connecting),
"3" => Ok(UPSState::Disconnecting),
"4" => Ok(UPSState::Disconnected),
_ => Err(Error::CanNotParseUPSConnectionStatus{
line:connection_status.to_owned()})
}
}
}