use crate::capabilities::Capabilities;
use crate::command::StatusCommand;
use crate::device::Device;
use crate::error::Error;
use crate::protocol::{HttpClient, HttpConfig, Protocol};
use crate::response::StatusResponse;
use crate::state::DeviceState;
#[derive(Debug)]
pub struct HttpDeviceBuilder {
config: HttpConfig,
capabilities: Option<Capabilities>,
}
impl HttpDeviceBuilder {
pub(crate) fn new(config: HttpConfig) -> Self {
Self {
config,
capabilities: None,
}
}
#[must_use]
pub fn with_credentials(
mut self,
username: impl Into<String>,
password: impl Into<String>,
) -> Self {
let host = self.config.host().to_string();
let port = self.config.port();
let timeout = self.config.timeout();
let use_https = self.config.use_https();
let mut new_config = HttpConfig::new(host)
.with_port(port)
.with_timeout(timeout)
.with_credentials(username, password);
if use_https {
new_config = new_config.with_https();
}
self.config = new_config;
self
}
#[must_use]
pub fn with_capabilities(mut self, capabilities: Capabilities) -> Self {
self.capabilities = Some(capabilities);
self
}
#[must_use]
pub fn capabilities(&self) -> Option<&Capabilities> {
self.capabilities.as_ref()
}
pub async fn build(self) -> Result<(Device<HttpClient>, DeviceState), Error> {
let client = self.config.into_client().map_err(Error::Protocol)?;
let capabilities = if let Some(caps) = self.capabilities {
caps
} else {
let cmd = StatusCommand::all();
let response = client.send_command(&cmd).await.map_err(Error::Protocol)?;
let status: StatusResponse = response.parse().map_err(Error::Parse)?;
Capabilities::from_status(&status)
};
let device = Device::new(client, capabilities);
let initial_state = device.query_state().await?;
Ok((device, initial_state))
}
pub async fn build_without_probe(self) -> Result<(Device<HttpClient>, DeviceState), Error> {
let client = self.config.into_client().map_err(Error::Protocol)?;
let capabilities = self.capabilities.unwrap_or_default();
let device = Device::new(client, capabilities);
let initial_state = device.query_state().await?;
Ok((device, initial_state))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builder_new() {
let config = HttpConfig::new("192.168.1.100");
let builder = HttpDeviceBuilder::new(config);
assert!(builder.capabilities.is_none());
}
#[test]
fn builder_with_capabilities() {
let config = HttpConfig::new("192.168.1.100");
let builder =
HttpDeviceBuilder::new(config).with_capabilities(Capabilities::rgbcct_light());
assert!(builder.capabilities.is_some());
}
#[test]
fn builder_capabilities_accessor() {
let config = HttpConfig::new("192.168.1.100");
let builder = HttpDeviceBuilder::new(config);
assert!(builder.capabilities().is_none());
let builder = builder.with_capabilities(Capabilities::basic());
assert!(builder.capabilities().is_some());
}
}