use reqwest::{Client, StatusCode};
use url::Url;
use uuid::Uuid;
use crate::error::Error;
use crate::types::electricity::{
CommandControl, CommandRegular, LocationId, ReasonNegative, ReferenceId,
StateNegative, StatePositive, StateUnknown, PreliminaryStatePositive,
};
#[derive(Clone, Debug)]
pub struct ControlMeasuresClient {
inner: Client,
base_url: Url,
}
impl ControlMeasuresClient {
pub fn new(base_url: Url, client: Client) -> Self {
Self { inner: client, base_url }
}
pub fn new_insecure(base_url: Url) -> Result<Self, Error> {
let client = Client::builder()
.build()
.map_err(|e| Error::Transport(e.to_string()))?;
Ok(Self::new(base_url, client))
}
pub async fn send_konfiguration(
&self,
transaction_id: Uuid,
creation_date_time: &str,
location_id: &LocationId,
command: &CommandControl,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/konfiguration/")?;
let command_json = serde_json::to_string(command)?;
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&[("locationId", location_id.to_string())])
.query(&[("commandControl", command_json)]);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
pub async fn send_initial_zustand(
&self,
transaction_id: Uuid,
creation_date_time: &str,
location_id: &LocationId,
command: &CommandRegular,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/initialZustand/")?;
let command_json = serde_json::to_string(command)?;
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&[("locationId", location_id.to_string())])
.query(&[("commandRegular", command_json)]);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
pub async fn send_vorlaeufigepositiveantwort(
&self,
transaction_id: Uuid,
creation_date_time: &str,
reference_id: ReferenceId,
location_id: &LocationId,
state: PreliminaryStatePositive,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/vorlaeufigePositiveAntwort/")?;
let payload = serde_json::json!({ "preliminaryStatePositive": state });
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&[
("referenceId", reference_id.to_string()),
("locationId", location_id.to_string()),
("preliminaryResultPositive", payload.to_string()),
]);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
pub async fn send_vorlaeufige_negative_antwort(
&self,
transaction_id: Uuid,
creation_date_time: &str,
reference_id: ReferenceId,
location_id: &LocationId,
state: StateNegative,
reason: ReasonNegative,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/vorlaeufigeNegativeAntwort/")?;
let payload =
serde_json::json!({ "stateNegative": state, "reasonNegative": reason });
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&[
("referenceId", reference_id.to_string()),
("locationId", location_id.to_string()),
("resultNegative", payload.to_string()),
]);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
pub async fn send_positive_antwort(
&self,
transaction_id: Uuid,
creation_date_time: &str,
reference_id: ReferenceId,
location_id: &LocationId,
state: StatePositive,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/positiveAntwort/")?;
let payload = serde_json::json!({ "statePositive": state });
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&[
("referenceId", reference_id.to_string()),
("locationId", location_id.to_string()),
("resultPositive", payload.to_string()),
]);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
pub async fn send_negative_antwort(
&self,
transaction_id: Uuid,
creation_date_time: &str,
reference_id: ReferenceId,
location_id: &LocationId,
state: StateNegative,
reason: ReasonNegative,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/negativeAntwort/")?;
let payload =
serde_json::json!({ "stateNegative": state, "reasonNegative": reason });
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&[
("referenceId", reference_id.to_string()),
("locationId", location_id.to_string()),
("resultNegative", payload.to_string()),
]);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
pub async fn send_information_anweisung(
&self,
transaction_id: Uuid,
creation_date_time: &str,
reference_id: ReferenceId,
location_id: &LocationId,
state: StateUnknown,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/informationAnweisung/")?;
let payload = serde_json::json!({ "stateUnknown": state });
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&[
("referenceId", reference_id.to_string()),
("locationId", location_id.to_string()),
("stateUnknown", payload.to_string()),
]);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
pub async fn send_information(
&self,
transaction_id: Uuid,
creation_date_time: &str,
location_id: &LocationId,
partner_id: i64,
command_control: Option<&CommandControl>,
command_regular: Option<&CommandRegular>,
initial_transaction_id: Option<Uuid>,
) -> Result<(), Error> {
let url = self.url("[Post]/steuerbefehl/information/")?;
let mut query: Vec<(String, String)> = vec![
("locationId".into(), location_id.to_string()),
("partnerId".into(), partner_id.to_string()),
];
if let Some(cc) = command_control {
query.push(("commandControl".into(), serde_json::to_string(cc)?));
}
if let Some(cr) = command_regular {
query.push(("commandRegular".into(), serde_json::to_string(cr)?));
}
let mut req = self
.inner
.post(url)
.header("transactionId", transaction_id.to_string())
.header("creationDateTime", creation_date_time)
.query(&query);
if let Some(itid) = initial_transaction_id {
req = req.header("initialTransactionId", itid.to_string());
}
check_accepted(req.send().await?).await
}
fn url(&self, path: &str) -> Result<Url, Error> {
self.base_url.join(path).map_err(Error::Url)
}
}
async fn check_accepted(resp: reqwest::Response) -> Result<(), Error> {
match resp.status() {
StatusCode::ACCEPTED => Ok(()),
s => Err(Error::Http {
status: s.as_u16(),
body: resp.text().await.unwrap_or_default(),
}),
}
}