use std::collections::HashMap;
use serde::Deserialize;
use serde::Serialize;
use serde;
use chrono::prelude::*;
use chrono::TimeZone;
use statrs::statistics::Distribution;
use statrs::statistics::Statistics;
use statrs::statistics::Data;
use chrono::prelude::*;
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct BasicResult {
pub success: bool,
pub message: String
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct KeycloakToken {
pub access_token: String,
pub expires_in: i32,
pub refresh_expires_in: i32,
pub refresh_token: String,
pub token_type: String,
pub session_state: String,
pub scope: String,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Contact {
pub administrativeArea: String,
pub city: String,
pub country: String,
pub deliveryPoint: String,
pub email: String,
pub fax: String,
pub individualName: String,
pub organizationName: String,
pub postalcode: String,
pub role: String,
pub voice: String,
pub web: String
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Item {
pub name: String,
pub definition: String,
pub value: String
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GOparams {
pub request: String,
pub service: String,
pub version: String,
pub observedProperty: String,
pub procedure: String,
pub qualityIndex: String,
pub responseFormat: String,
pub offering: String,
pub eventTime: String
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct ItemSmall {
pub name: String
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct NumCoords([f64; 3]);
#[derive(Clone, Debug, Serialize, Deserialize)]
struct StringCoords([String; 3]);
#[derive(Clone, Debug, Serialize, Deserialize)]
enum Coords {
NumCoords,
StringCoords,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Point {
pub r#type: String,
pub coordinates: [f64; 3]
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Crs {
pub r#type: String,
pub properties: ItemSmall
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Location {
pub r#type: String,
pub geometry: Point,
pub crs: Crs,
pub properties: ItemSmall
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Output {
pub name: String,
pub definition: String,
pub uom: String,
pub description: String,
pub constraint: HashMap<String, StringVec>
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum StringVec {
A(Vec<String>),
B(String)
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct SimpleOutput {
pub name: String,
pub definition: String,
pub uom: String
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct MinimalOutput {
pub name: String,
pub definition: String
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum OutputGen {
A(Output),
B(SimpleOutput),
C(MinimalOutput),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Procedure {
pub system_id: String,
pub assignedSensorId: String,
pub system: String,
pub description: String,
pub keywords: String,
pub identification: Vec<Item>,
pub classification: Vec<Item>,
pub characteristics: String,
pub contacts: Vec<Contact>,
pub documentation: Vec<String>,
pub capabilities: Vec<String>,
pub location: Location,
pub interfaces: String,
pub inputs: Vec<String>,
pub outputs: Vec<Output>,
pub history: Vec<String>,
pub mqtt: String
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProcedureItem {
pub id: i32,
pub name: String,
pub description: String,
pub assignedid: String,
pub sensortype: String,
pub samplingTime: SamplingTimeItem,
pub observedproperties: Vec<SimpleOutput>,
pub offerings: Vec<String>
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct DataResult {
pub success: bool,
pub message: String,
pub data: Procedure,
pub total: i32
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct DataResultGO {
pub success: bool,
pub message: String,
pub data: Vec<ObservationType>,
pub total: i32
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct ObservationCollection {
pub description: String,
pub name: String,
pub member: Vec<ObservationTypeGO>
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct ResultGO {
pub ObservationCollection: ObservationCollection,
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct DataResultGetProcedures {
pub success: bool,
pub message: String,
pub data: Vec<ProcedureItem>,
pub total: i32
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ValueIO {
V(f64),
I(i64),
DT(DateTime<FixedOffset>)
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum SamplingTimeType {
V(SamplingTime),
Empty {},
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct SamplingTime {
pub beginPosition: String,
pub endPosition: String,
pub duration: String
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct SamplingTimeItem {
pub beginposition: String,
pub endposition: String
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DataArrayElement {
pub elementCount: String,
pub field: Vec<OutputGen>,
pub values: Vec<Vec<ValueIO>>
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DataArrayElementGO {
pub elementCount: String,
pub field: Vec<OutputGen>,
pub values: Vec<Vec<ValueIO>>
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Phenomenon {
pub id: String,
pub dimension: String,
pub name: String
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ObservedProperty {
pub CompositePhenomenon: Phenomenon,
pub component: Vec<String>
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FeatureOfInterest {
pub name: String,
pub geom: String
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ObservationType {
pub name: String,
pub samplingTime: SamplingTimeType,
pub procedure: String,
pub observedProperty: ObservedProperty,
pub featureOfInterest: FeatureOfInterest,
pub result: ResultElement
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ObservationTypeGO {
pub name: String,
pub samplingTime: SamplingTimeType,
pub procedure: String,
pub observedProperty: ObservedProperty,
pub featureOfInterest: FeatureOfInterest,
pub result: ResultElementGO
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ResultElement {
pub DataArray: DataArrayElement
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ResultElementGO {
pub DataArray: DataArrayElementGO
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct InsertObservation {
pub AssignedSensorId: String,
pub ForceInsert: String,
pub Observation: ObservationType
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RecordMaintenance {
pub begin: DateTime<FixedOffset>,
pub end: DateTime<FixedOffset>
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RecordCalibration {
pub begin: DateTime<FixedOffset>,
pub end: DateTime<FixedOffset>,
pub coeff: f64,
pub procedure: String,
}
pub async fn get_token(oauth_params: &HashMap<&str, &str>, url: &str) -> Result<KeycloakToken, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.post(url)
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded"
)
.form(&oauth_params)
.send()
.await?;
let t = res
.text()
.await?;
let token: KeycloakToken = serde_json::from_str(&t).unwrap();
return Ok(token)
}
pub async fn refresh_token(oauth_params: &HashMap<&str, &str>, url: &str) -> Result<KeycloakToken, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.post(url)
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded"
)
.form(&oauth_params)
.send()
.await?;
let t = res
.text()
.await?;
let token: KeycloakToken = serde_json::from_str(&t).unwrap();
return Ok(token)
}
pub async fn describe_sensor(url: &str, auth: &str, name: &str) -> Result<Procedure, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.get(format!("{}/procedures/{}", url, name))
.header(
reqwest::header::AUTHORIZATION,
auth
)
.send()
.await?;
let t = res
.text()
.await?;
let proc: DataResult = serde_json::from_str(&t).unwrap();
return Ok(proc.data)
}
pub async fn get_observation_last(
url: &str,
offering: &str,
procedure: &str,
auth: &str
) -> Result<Vec<ObservationType>, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.get(
format!(
"{}/operations/getobservation/offerings/{}/procedures/{}/observedproperties/:/eventtime/last",
url,
offering,
procedure
)
)
.header(
reqwest::header::AUTHORIZATION,
auth
)
.header(
reqwest::header::CONTENT_TYPE,
"application/json"
)
.send()
.await?;
let t = res
.text()
.await?;
let go: DataResultGO = serde_json::from_str(&t).unwrap();
return Ok(go.data)
}
pub async fn get_observation(
url: &str,
service: &str,
params: GOparams,
auth: &str
) -> Result<ResultGO, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
println!("{:?}", params);
let res = client_1
.get(
format!(
"{}/{}",
url,
service
)
)
.header(
reqwest::header::AUTHORIZATION,
auth
)
.header(
reqwest::header::CONTENT_TYPE,
"application/json"
)
.query(¶ms)
.send()
.await?;
let t = res
.text()
.await?;
let go: ResultGO = serde_json::from_str(&t).unwrap();
return Ok(go)
}
pub async fn get_string_observations(
url: &str, auth: &str
) -> Result<String, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.get(url)
.header(
reqwest::header::AUTHORIZATION,
auth
)
.send()
.await?;
let t = res
.text()
.await?;
Ok(t)
}
pub async fn insert_observation(
url: String,
auth: String,
body: InsertObservation
) -> Result<String, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.post(url)
.header(
reqwest::header::AUTHORIZATION,
auth
)
.json(&body)
.send()
.await?;
let t = res
.text()
.await?;
return Ok(t.to_string())
}
pub async fn register_sensor(
url: &str,
auth: &str,
body: Procedure
) -> Result<BasicResult, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.post(
format!(
"{}/procedures",
url
)
)
.header(
reqwest::header::AUTHORIZATION,
auth
)
.json(&body)
.send()
.await?;
let t = res
.text()
.await?;
let rs: BasicResult = serde_json::from_str(&t).unwrap();
Ok(rs)
}
pub async fn fast_insert(
url: String,
user: &str,
password: &str,
body: String
) -> Result<String, Box<dyn std::error::Error>> {
let client_1 = reqwest::Client::new();
let res = client_1
.post(url)
.basic_auth(
user,
Some(password)
)
.body(body)
.send()
.await?;
let t = res
.text()
.await?;
return Ok(t.to_string())
}
pub async fn get_procedures(
url: &str,
auth: &str
) -> Result<Vec<ProcedureItem>, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let res = client
.get(format!("{}{}", url, "/procedures/operations/getlist"))
.header(
reqwest::header::AUTHORIZATION,
auth
)
.send()
.await?;
let t = res
.text()
.await?;
let go: DataResultGetProcedures = serde_json::from_str(&t).unwrap();
Ok(go.data)
}
pub async fn linear_equation_find_y(xs: [f64; 2], ys: [f64; 2], x: f64) -> Result<f64, Box<dyn std::error::Error>> {
let my = ys[1]-ys[0];
let mx = xs[1]-xs[0];
let mx2 = x-xs[0];
let y = ((mx2/mx)*(my))+ys[0];
Ok(y)
}
pub async fn oxygen_conc_saturation(
temp: f64,
sal: f64
) -> Result<f64, Box<dyn std::error::Error>> {
let t = temp + 273.15;
let c = -173.4292 +
(249.6339*(100.0/t)) +
(143.3483*(t/100.0).ln())
- 21.8492*(t/100.0)
+ (sal * (
-0.033096 + (0.014259*(t/100.0))
- (0.0017*(t/100.0).powf(2.0))
));
let oxygen_sat = c.powf(1.423);
Ok(oxygen_sat)
}
pub async fn oxygen_saturation_corrected(
oxygen_saturation: f64,
pressure: f64
) -> Result<f64, Box<dyn std::error::Error>> {
let cf = ((pressure * 0.0987)-0.0112)/100.0;
let os = oxygen_saturation * cf;
Ok(os)
}
pub async fn step_test(x: Vec<f64>) -> Result<bool, Box<dyn std::error::Error>> {
if x.len() == 3 {
let sum_abs_val = (x[1] - x[0]).abs() + (x[1] - x[2]).abs();
let s_data = Data::new(x);
let four_std = 4.0_f64*s_data.std_dev().unwrap();
if sum_abs_val <= four_std {
Ok(true)
} else {
Ok(false)
}
} else {
Ok(false)
}
}