add set functionality to control outlets

This commit is contained in:
sigil-03 2025-04-06 15:21:38 -06:00
parent 987150c9b6
commit 633a57ff23
5 changed files with 42 additions and 22 deletions

View file

@ -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>;
}

View file

@ -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();
})
}
};

View file

@ -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(())
}
}

View file

@ -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(())
}
}

View file

@ -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,