use std::time::Duration;
use crate::command::Command;
use crate::protocol::ResponseSpec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[repr(u8)]
pub enum StatusType {
#[default]
Abbreviated = 255,
All = 0,
DeviceParameters = 1,
Firmware = 2,
Logging = 3,
Memory = 4,
Network = 5,
Mqtt = 6,
Time = 7,
PowerThresholds = 9,
Sensors = 10,
State = 11,
Shutter = 13,
}
impl StatusType {
#[must_use]
pub const fn all_types() -> &'static [Self] {
&[
Self::Abbreviated,
Self::All,
Self::DeviceParameters,
Self::Firmware,
Self::Logging,
Self::Memory,
Self::Network,
Self::Mqtt,
Self::Time,
Self::PowerThresholds,
Self::Sensors,
Self::State,
Self::Shutter,
]
}
#[must_use]
pub const fn value(&self) -> u8 {
*self as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StatusCommand {
status_type: StatusType,
}
impl StatusCommand {
#[must_use]
pub const fn new(status_type: StatusType) -> Self {
Self { status_type }
}
#[must_use]
pub const fn abbreviated() -> Self {
Self::new(StatusType::Abbreviated)
}
#[must_use]
pub const fn all() -> Self {
Self::new(StatusType::All)
}
#[must_use]
pub const fn device_parameters() -> Self {
Self::new(StatusType::DeviceParameters)
}
#[must_use]
pub const fn firmware() -> Self {
Self::new(StatusType::Firmware)
}
#[must_use]
pub const fn logging() -> Self {
Self::new(StatusType::Logging)
}
#[must_use]
pub const fn memory() -> Self {
Self::new(StatusType::Memory)
}
#[must_use]
pub const fn network() -> Self {
Self::new(StatusType::Network)
}
#[must_use]
pub const fn mqtt() -> Self {
Self::new(StatusType::Mqtt)
}
#[must_use]
pub const fn time() -> Self {
Self::new(StatusType::Time)
}
#[must_use]
pub const fn sensors() -> Self {
Self::new(StatusType::Sensors)
}
#[must_use]
pub const fn state() -> Self {
Self::new(StatusType::State)
}
#[must_use]
pub const fn status_type(&self) -> StatusType {
self.status_type
}
}
impl Default for StatusCommand {
fn default() -> Self {
Self::abbreviated()
}
}
const MULTI_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5);
impl Command for StatusCommand {
fn name(&self) -> String {
"Status".to_string()
}
fn payload(&self) -> Option<String> {
match self.status_type {
StatusType::Abbreviated => None,
other => Some(other.value().to_string()),
}
}
fn response_spec(&self) -> ResponseSpec {
match self.status_type {
StatusType::All => ResponseSpec::status_all(MULTI_RESPONSE_TIMEOUT),
_ => ResponseSpec::Single,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn status_command_abbreviated() {
let cmd = StatusCommand::abbreviated();
assert_eq!(cmd.name(), "Status");
assert_eq!(cmd.payload(), None);
}
#[test]
fn status_command_all() {
let cmd = StatusCommand::all();
assert_eq!(cmd.payload(), Some("0".to_string()));
}
#[test]
fn status_command_network() {
let cmd = StatusCommand::network();
assert_eq!(cmd.payload(), Some("5".to_string()));
}
#[test]
fn status_command_firmware() {
let cmd = StatusCommand::firmware();
assert_eq!(cmd.payload(), Some("2".to_string()));
}
#[test]
fn status_command_http_format() {
let cmd = StatusCommand::all();
assert_eq!(cmd.to_http_command(), "Status 0");
let abbrev = StatusCommand::abbreviated();
assert_eq!(abbrev.to_http_command(), "Status");
}
#[test]
fn status_type_values() {
assert_eq!(StatusType::All.value(), 0);
assert_eq!(StatusType::DeviceParameters.value(), 1);
assert_eq!(StatusType::Network.value(), 5);
assert_eq!(StatusType::Sensors.value(), 10);
}
}