divoom 0.1.42

Rust API for controlling divoom devices, like pixoo.
Documentation
use crate::{DivoomAPIError, DivoomAPIResult, DivoomServerErrorInfo};
use log::debug;
use reqwest::RequestBuilder;
use serde::de::DeserializeOwned;
use std::time::Duration;

pub struct DivoomRestAPIClient {
    pub server_url_base: String,
    pub http_client: reqwest::Client,
    pub timeout: Duration,
}

impl DivoomRestAPIClient {
    pub fn new(server_url_base: String, timeout: Option<Duration>) -> DivoomRestAPIClient {
        DivoomRestAPIClient {
            server_url_base,
            http_client: reqwest::Client::new(),
            timeout: timeout.unwrap_or(Duration::from_secs(2)),
        }
    }

    pub async fn send_request<TResp: DeserializeOwned>(
        &self,
        url_path: &str,
    ) -> DivoomAPIResult<TResp> {
        let url = format!("{}{}", self.server_url_base, url_path);
        debug!(
            "Sending request without body: Url = \"{}\", Timeout = {:?}",
            url, self.timeout
        );

        let request = self.http_client.post(url).timeout(self.timeout);
        let response = self.send_request_with_request_builder(request).await?;
        Ok(response)
    }

    pub async fn send_request_with_body<TResp: DeserializeOwned>(
        &self,
        url_path: &str,
        body: String,
    ) -> DivoomAPIResult<TResp> {
        let url = format!("{}{}", self.server_url_base, url_path);
        debug!(
            "Sending request: Url = \"{}\", Body = \"{}\", Timeout = {:?}",
            url, body, self.timeout
        );

        let request = self.http_client.post(url).body(body).timeout(self.timeout);
        let response = self.send_request_with_request_builder(request).await?;
        Ok(response)
    }

    pub async fn send_raw_request_with_body(
        &self,
        url_path: &str,
        body: String,
    ) -> DivoomAPIResult<String> {
        let url = format!("{}{}", self.server_url_base, url_path);
        debug!(
            "Sending request: Url = \"{}\", Body = \"{}\", Timeout = {:?}",
            url, body, self.timeout
        );

        let request = self.http_client.post(url).body(body).timeout(self.timeout);
        let response = self.send_raw_request_with_request_builder(request).await?;
        Ok(response)
    }

    async fn send_request_with_request_builder<T: DeserializeOwned>(
        &self,
        request: RequestBuilder,
    ) -> DivoomAPIResult<T> {
        let response_text = self.send_raw_request_with_request_builder(request).await?;
        let parsed_response = serde_json::from_str::<T>(&response_text)?;
        Ok(parsed_response)
    }

    async fn send_raw_request_with_request_builder(
        &self,
        request: RequestBuilder,
    ) -> DivoomAPIResult<String> {
        let response = request.send().await?;
        debug!(
            "Response header received: StatusCode = {}",
            response.status().as_u16()
        );

        if response.status() != reqwest::StatusCode::OK {
            return Err(DivoomAPIError::ServerError(DivoomServerErrorInfo {
                http_status_code: response.status().as_u16(),
                error_code: 0,
                error_message: "".into(),
            }));
        }

        let response_text = response.text().await?;
        debug!("Response received: Body = \"{}\"", response_text);

        Ok(response_text)
    }
}