easee_rs/
client.rs

1use std::error::Error;
2use std::sync::Arc;
3use serde::de::DeserializeOwned;
4use serde_json::{json, Value};
5use crate::response::LoginResponse;
6
7const BASE_URL: &str = "https://api.easee.com/api";
8const VERSION: &str = env!("CARGO_PKG_VERSION");
9
10#[derive(Debug, Clone)]
11pub struct Client {
12    access_token: Arc<String>,
13    client: reqwest::Client,
14}
15
16impl Client {
17    pub fn new_with_access_token(access_token: &str) -> Self {
18        Self {
19            client: reqwest::Client::new(),
20            access_token: Arc::new(access_token.to_string()),
21        }
22    }
23
24    pub async fn setup_with_username_and_password(username: &str, password: &str) -> Result<Self, Box<dyn Error + Send + Sync>> {
25        let response = Self::login(username, password).await?;
26
27        Ok(Self {
28            client: reqwest::Client::new(),
29            access_token: Arc::new(response.access_token.to_string()),
30        })
31    }
32
33    pub async fn login(username: &str, password: &str) -> Result<LoginResponse, Box<dyn Error + Send + Sync>> {
34        let client = reqwest::Client::new();
35        let payload = json!({
36            "userName": username,
37            "password": password,
38        })
39        .to_string();
40        let response = client
41            .post(format!("{}/accounts/login", BASE_URL))
42            .header("Content-Type", "application/json")
43            .header("User-Agent", format!("Flowion/EaseeClient/{}", VERSION))
44            .body(payload)
45            .send()
46            .await?;
47        if response.status().is_success() {
48            let data = response.json::<LoginResponse>().await?;
49            dbg!(&data);
50            Ok(data)
51        } else {
52            let status = response.status();
53            let text = response.text().await?;
54            Err(format!("{} - {}", status, text).into())
55        }
56    }
57
58    async fn post<T: DeserializeOwned + std::fmt::Debug>(&self, path: &str, payload: Value) -> Result<T, Box<dyn Error + Send + Sync>> {
59        let payload = payload.to_string();
60        let response = self.client
61            .post(format!("{}/{}", BASE_URL, path))
62            .header("Authorization", format!("Bearer {}", self.access_token))
63            .header("Content-Type", "application/json")
64            .header("User-Agent", format!("Flowion/EaseeClient/{}", VERSION))
65            .body(payload)
66            .send()
67            .await?;
68        if response.status().is_success() {
69            let data = response.json::<T>().await?;
70            dbg!(&data);
71            Ok(data)
72        } else {
73            let status = response.status();
74            let text = response.text().await?;
75            Err(format!("{} - {}", status, text).into())
76        }
77    }
78
79    pub async fn pair_charger(&self, serial_number: &str, pin_code: &str) -> Result<(), Box<dyn Error + Send + Sync>> {
80        self.post(&format!("chargers/{}/pair?pinCode={}", serial_number, pin_code), json!({})).await
81    }
82
83}