use super::{Address, GeoLocation, JobMode, OpMode, Operator, TextID, TextName, ID, R32};
use chrono::{DateTime, FixedOffset};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::convert::TryInto;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Controller<'a> {
pub controller_id: ID,
pub display_name: TextName<'a>,
pub controller_type: TextID<'a>,
pub version: TextID<'a>,
pub model: TextID<'a>,
#[serde(rename = "IP")]
pub address: Address<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(flatten)]
pub geo_location: Option<GeoLocation>,
pub op_mode: OpMode,
pub job_mode: JobMode,
#[serde(skip_serializing_if = "IndexMap::is_empty")]
#[serde(default)]
pub last_cycle_data: IndexMap<TextID<'a>, R32>,
#[serde(skip_serializing_if = "IndexMap::is_empty")]
#[serde(default)]
pub variables: IndexMap<TextID<'a>, R32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_connection_time: Option<DateTime<FixedOffset>>,
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub operator: Option<Operator<'a>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(borrow)]
pub job_card_id: Option<Box<Cow<'a, str>>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(borrow)]
pub mold_id: Option<Box<Cow<'a, str>>>,
}
impl Default for Controller<'_> {
fn default() -> Self {
Controller {
controller_id: ID::from_u32(1),
display_name: "Unknown".try_into().unwrap(),
controller_type: "Unknown".try_into().unwrap(),
version: "Unknown".try_into().unwrap(),
model: "Unknown".try_into().unwrap(),
address: Address::Unknown,
geo_location: None,
op_mode: OpMode::Unknown,
job_mode: JobMode::Unknown,
job_card_id: None,
last_cycle_data: Default::default(),
variables: Default::default(),
last_connection_time: None,
operator: None,
mold_id: None,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use std::result::Result;
#[test]
fn test_controller_to_json() -> Result<(), String> {
let c = Controller {
op_mode: OpMode::Automatic,
job_mode: JobMode::ID02,
operator: Some(Operator::try_new_with_name(ID::from_u32(123), "John")?),
geo_location: Some(GeoLocation::new(88.0, 123.0)?),
..Default::default()
};
let serialized = serde_json::to_string(&c).map_err(|x| x.to_string())?;
assert_eq!(
r#"{"controllerId":1,"displayName":"Unknown","controllerType":"Unknown","version":"Unknown","model":"Unknown","IP":"0.0.0.0:0","geoLatitude":88.0,"geoLongitude":123.0,"opMode":"Automatic","jobMode":"ID02","operatorId":123,"operatorName":"John"}"#,
serialized
);
Ok(())
}
#[test]
fn test_controller_from_json() -> Result<(), String> {
let c: Controller = serde_json::from_str(r#"{"controllerId":1,"geoLatitude":88,"geoLongitude":-123,"displayName":"Hello","controllerType":"Unknown","version":"Unknown","model":"Unknown","IP":"127.0.0.1:123","opMode":"Automatic","jobMode":"ID02","operatorId":123,"operatorName":"John"}"#).map_err(|x| x.to_string())?;
assert_eq!(
r#"Controller { controller_id: 1, display_name: "Hello", controller_type: "Unknown", version: "Unknown", model: "Unknown", address: IPv4(127.0.0.1, 123), geo_location: Some((88,-123)), op_mode: Automatic, job_mode: ID02, last_cycle_data: {}, variables: {}, last_connection_time: None, operator: Some(Operator { operator_id: 123, operator_name: Some("John") }), job_card_id: None, mold_id: None }"#,
format!("{:?}", &c)
);
Ok(())
}
}