use std::collections::HashMap;
use base64::{prelude::BASE64_STANDARD, Engine};
use crate::{
errors::WardError,
http::{self, Response},
};
pub struct Camera {
pub ip: String,
pub port: u16,
pub username: String,
pub password: String,
pub description: String,
pub alarm_out: u8,
}
pub trait CameraFeatures {
fn new(
ip: String,
port: Option<u16>,
username: String,
password: String,
description: String,
alarm_out: Option<u8>,
) -> Self;
fn send_request(&self, path: &str) -> Result<Response, WardError>;
}
impl CameraFeatures for Camera {
fn new(
ip: String,
port: Option<u16>,
username: String,
password: String,
description: String,
alrm_out: Option<u8>,
) -> Self {
Camera {
ip,
port: port.unwrap_or(80),
username,
password,
description,
alarm_out: alrm_out.unwrap_or(1),
}
}
fn send_request(&self, path: &str) -> Result<Response, WardError> {
let host = format!("{}:{}", &self.ip, &self.port);
let path = format!("/cgi-bin{}", path.replace(" ", "%20"));
let auth = BASE64_STANDARD.encode(format!("{}:{}", &self.username, &self.password));
let mut headers = HashMap::new();
headers.insert("Host", &self.ip);
let header = format!(
"GET {path} HTTP/1.1\n{}\nAuthorization: Basic {auth}\n\n",
headers
.iter()
.map(|(i, x)| format!("{}: {}", i, x))
.collect::<Vec<_>>()
.join("\n")
);
let raw_response = http::send_request(&host, header.as_bytes())?;
let response = http::Response::from_str(&raw_response).unwrap();
Ok(response)
}
}