diff --git a/src/control.rs b/src/control.rs index 2ecde08..7b9ae29 100644 --- a/src/control.rs +++ b/src/control.rs @@ -1,5 +1,5 @@ -use crate::types::Error; +use crate::types::{Error, PowerState}; pub trait Control { - async fn set_power(&self) -> Result<(), Error>; + async fn set_power(&self, state: PowerState) -> Result<(), Error>; } diff --git a/src/main.rs b/src/main.rs index 42e68a9..a85d5e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,26 +6,31 @@ mod system; mod tasmota; mod types; +#[derive(Parser)] +pub struct PowerCommand { + index: usize, + #[command(subcommand)] + state: types::PowerState, +} + #[derive(Subcommand)] pub enum Commands { Monitor, - #[command(subcommand)] - Set(types::PowerState), + Set(PowerCommand), } impl Commands { pub async fn execute(self, config_file: &str) { + let s = system::System::new_from_file(config_file).unwrap(); + let handle = match self { - Self::Monitor => { - let s = system::System::new_from_file(config_file).unwrap(); - tokio::spawn(async move { - s.get_power().await.unwrap(); - }) - } - Self::Set(state) => { + Self::Monitor => tokio::spawn(async move { + s.try_get_power().await.unwrap(); + }), + Self::Set(command) => { // let c = Controller::new_from_file(config_file).unwrap(); tokio::spawn(async move { - println!("SET"); + s.try_set_power(command.index, command.state).await.unwrap(); }) } }; diff --git a/src/system.rs b/src/system.rs index 61b7791..b5ffa8c 100644 --- a/src/system.rs +++ b/src/system.rs @@ -1,6 +1,7 @@ +use crate::control::Control; use crate::monitor::Monitoring; use crate::tasmota::{TasmotaInterface, TasmotaInterfaceConfig}; -use crate::types::Error; +use crate::types::{self, Error}; use reqwest::Client; use serde::Deserialize; use std::fs; @@ -38,7 +39,7 @@ impl System { v } - pub async fn get_power(&self) -> Result<(), Error> { + pub async fn try_get_power(&self) -> Result<(), Error> { for component in &self.components { if let Ok(res) = component.get_power().await { component.print(); @@ -48,4 +49,10 @@ impl System { } Ok(()) } + + pub async fn try_set_power(&self, index: usize, state: types::PowerState) -> Result<(), Error> { + //TODO: check bounds + self.components[index].set_power(state).await?; + Ok(()) + } } diff --git a/src/tasmota.rs b/src/tasmota.rs index 769eaf2..b8bae8a 100644 --- a/src/tasmota.rs +++ b/src/tasmota.rs @@ -1,7 +1,11 @@ use reqwest::Client; use serde::Deserialize; -use crate::{control::Control, monitor::Monitoring}; +use crate::{ + control::Control, + monitor::Monitoring, + types::{Error, PowerState}, +}; #[derive(Deserialize)] pub struct EnergyData { @@ -70,18 +74,21 @@ impl Monitoring for TasmotaInterface { } impl Control for TasmotaInterface { - async fn set_power(&self) -> Result<(), Error> { - let res = self + async fn set_power(&self, state: PowerState) -> Result<(), Error> { + let cmd = match state { + PowerState::Off => "OFF", + PowerState::On => "ON", + }; + let _res = self .client .get(format!( - "http://{}/cm?cmnd=Power%20TOGGLE", - &self.config.target + "http://{}/cm?cmnd=Power%20{}", + &self.config.target, cmd )) .send() .await? .text() .await?; - Ok(()) } } diff --git a/src/types.rs b/src/types.rs index 889bcb6..d25711e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,4 +1,5 @@ -use clap::Subcommand; +use clap::Parser; +use serde::{Deserialize, Serialize}; use thiserror::Error; #[derive(Error, Debug)] @@ -13,7 +14,7 @@ pub enum Error { JsonParseError(#[from] serde_json::Error), } -#[derive(Subcommand, Clone)] +#[derive(Serialize, Deserialize, Parser, Clone)] pub enum PowerState { Off, On,