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}