use std::str::FromStr;
use serde::{Deserialize, Serialize};
use crate::models::scheduler as api_scheduler;
#[derive(Deserialize)]
pub struct WorkMode {
#[serde(rename = "enumList")]
pub enum_list: Vec<String>,
pub unit: String,
pub precision: f64,
}
#[derive(Deserialize)]
pub struct Range {
pub min: f64,
pub max: f64,
}
#[derive(Deserialize)]
pub struct Structure {
pub unit: String,
pub precision: f64,
pub range: Range,
}
#[derive(Deserialize)]
pub struct Properties {
#[serde(rename = "startminute")]
pub start_minute: Structure,
#[serde(rename = "fdpwr")]
pub fd_pwr: Structure,
#[serde(rename = "endhour")]
pub end_hour: Structure,
#[serde(rename = "endminute")]
pub end_minute: Structure,
#[serde(rename = "fdsoc")]
pub fd_soc: Structure,
#[serde(rename = "starthour")]
pub start_hour: Structure,
#[serde(rename = "workmode")]
pub work_mode: WorkMode,
#[serde(rename = "minsocongrid")]
pub min_soc_on_grid: Structure,
#[serde(rename = "maxsoc")]
pub max_soc: Structure,
}
#[derive(Deserialize, Serialize)]
pub struct ExtraParam {
#[serde(rename = "fdPwr", skip_serializing_if = "Option::is_none")]
pub fd_pwr: Option<f64>,
#[serde(rename = "minSocOnGrid", skip_serializing_if = "Option::is_none")]
pub min_soc_on_grid: Option<f64>,
#[serde(rename = "fdSoc", skip_serializing_if = "Option::is_none")]
pub fd_soc: Option<f64>,
#[serde(rename = "maxSoc", skip_serializing_if = "Option::is_none")]
pub max_soc: Option<f64>,
#[serde(rename = "importLimit", skip_serializing_if = "Option::is_none")]
pub import_limit: Option<f64>,
#[serde(rename = "exportLimit", skip_serializing_if = "Option::is_none")]
pub export_limit: Option<f64>,
#[serde(rename = "pvLimit", skip_serializing_if = "Option::is_none")]
pub pv_limit: Option<f64>,
#[serde(rename = "reactivePower", skip_serializing_if = "Option::is_none")]
pub reactive_power: Option<f64>,
}
impl ExtraParam {
pub fn is_empty(&self) -> bool {
self.fd_pwr.is_none()
&& self.min_soc_on_grid.is_none()
&& self.fd_soc.is_none()
&& self.max_soc.is_none()
&& self.import_limit.is_none()
&& self.export_limit.is_none()
&& self.pv_limit.is_none()
&& self.reactive_power.is_none()
}
}
fn extra_param_is_none_or_empty(v: &Option<ExtraParam>) -> bool {
v.as_ref().is_none_or(ExtraParam::is_empty)
}
#[derive(Deserialize, Serialize)]
pub struct Group {
#[serde(rename = "startHour")]
pub start_hour: i64,
#[serde(rename = "startMinute")]
pub start_minute: i64,
#[serde(rename = "endHour")]
pub end_hour: i64,
#[serde(rename = "endMinute")]
pub end_minute: i64,
#[serde(rename = "workMode")]
pub work_mode: String,
#[serde(rename = "extraParam", skip_serializing_if = "extra_param_is_none_or_empty")]
pub extra_param: Option<ExtraParam>,
}
#[derive(Deserialize)]
pub struct TimeSegmentsInfo {
pub enable: i64,
#[serde(rename = "maxGroupCount")]
pub max_group_count: i64,
pub groups: Vec<Group>,
pub properties: Properties,
}
#[derive(Deserialize)]
pub struct SchedulerTimeSegmentsResult {
pub result: TimeSegmentsInfo,
}
impl From<&api_scheduler::ExtraParam> for ExtraParam {
fn from(value: &api_scheduler::ExtraParam) -> Self {
Self {
fd_pwr: value.fd_pwr,
min_soc_on_grid: value.min_soc_on_grid,
fd_soc: value.fd_soc,
max_soc: value.max_soc,
import_limit: value.import_limit,
export_limit: value.export_limit,
pv_limit: value.pv_limit,
reactive_power: value.reactive_power,
}
}
}
impl From<&api_scheduler::Group> for Group {
fn from(value: &api_scheduler::Group) -> Self {
Self {
start_hour: value.start_hour,
start_minute: value.start_minute,
end_hour: value.end_hour,
end_minute: value.end_minute,
work_mode: value.work_mode.as_str().to_string(),
extra_param: value.extra_param.as_ref().map(Into::into),
}
}
}
impl From<ExtraParam> for api_scheduler::ExtraParam {
fn from(value: ExtraParam) -> Self {
Self {
fd_pwr: value.fd_pwr,
min_soc_on_grid: value.min_soc_on_grid,
fd_soc: value.fd_soc,
max_soc: value.max_soc,
import_limit: value.import_limit,
export_limit: value.export_limit,
pv_limit: value.pv_limit,
reactive_power: value.reactive_power,
}
}
}
impl From<Group> for api_scheduler::Group {
fn from(value: Group) -> Self {
Self {
start_hour: value.start_hour,
start_minute: value.start_minute,
end_hour: value.end_hour,
end_minute: value.end_minute,
work_mode: crate::FoxWorkModes::from_str(&value.work_mode)
.unwrap_or(crate::FoxWorkModes::Unknown),
extra_param: value.extra_param.map(Into::into),
}
}
}
impl From<Structure> for api_scheduler::MetaData {
fn from(value: Structure) -> Self {
Self {
unit: value.unit,
precision: value.precision,
range: value.range.into(),
}
}
}
impl From<Range> for api_scheduler::Range {
fn from(value: Range) -> Self {
Self {
min: value.min,
max: value.max,
}
}
}
impl From<WorkMode> for api_scheduler::WorkMode {
fn from(value: WorkMode) -> Self {
Self {
enum_list: value
.enum_list
.into_iter()
.map(|mode| crate::FoxWorkModes::from_str(&mode).unwrap_or(crate::FoxWorkModes::Unknown))
.collect(),
unit: value.unit,
precision: value.precision,
}
}
}
impl From<Properties> for api_scheduler::Properties {
fn from(value: Properties) -> Self {
Self {
start_minute: value.start_minute.into(),
fd_pwr: value.fd_pwr.into(),
end_hour: value.end_hour.into(),
end_minute: value.end_minute.into(),
fd_soc: value.fd_soc.into(),
start_hour: value.start_hour.into(),
work_mode: value.work_mode.into(),
min_soc_on_grid: value.min_soc_on_grid.into(),
max_soc: value.max_soc.into(),
}
}
}
impl From<TimeSegmentsInfo> for api_scheduler::TimeSegmentsData {
fn from(value: TimeSegmentsInfo) -> Self {
Self {
enable: value.enable,
max_group_count: value.max_group_count,
groups: value.groups.into_iter().map(Into::into).collect(),
properties: value.properties.into(),
}
}
}
impl From<SchedulerTimeSegmentsResult> for api_scheduler::TimeSegmentsData {
fn from(value: SchedulerTimeSegmentsResult) -> Self {
value.result.into()
}
}
#[derive(Serialize)]
pub struct SchedulerTimeSegmentsRequest {
#[serde(rename = "deviceSN")]
pub device_sn: String,
#[serde(rename = "isDefault")]
pub is_default: bool,
pub groups: Vec<Group>,
}