forked from sigil-03/power
add set functionality to control outlets
This commit is contained in:
parent
987150c9b6
commit
633a57ff23
5 changed files with 42 additions and 22 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::types::Error;
|
use crate::types::{Error, PowerState};
|
||||||
|
|
||||||
pub trait Control {
|
pub trait Control {
|
||||||
async fn set_power(&self) -> Result<(), Error>;
|
async fn set_power(&self, state: PowerState) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
src/main.rs
25
src/main.rs
|
|
@ -6,26 +6,31 @@ mod system;
|
||||||
mod tasmota;
|
mod tasmota;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
pub struct PowerCommand {
|
||||||
|
index: usize,
|
||||||
|
#[command(subcommand)]
|
||||||
|
state: types::PowerState,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
Monitor,
|
Monitor,
|
||||||
#[command(subcommand)]
|
Set(PowerCommand),
|
||||||
Set(types::PowerState),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Commands {
|
impl Commands {
|
||||||
pub async fn execute(self, config_file: &str) {
|
pub async fn execute(self, config_file: &str) {
|
||||||
let handle = match self {
|
|
||||||
Self::Monitor => {
|
|
||||||
let s = system::System::new_from_file(config_file).unwrap();
|
let s = system::System::new_from_file(config_file).unwrap();
|
||||||
tokio::spawn(async move {
|
|
||||||
s.get_power().await.unwrap();
|
let handle = match self {
|
||||||
})
|
Self::Monitor => tokio::spawn(async move {
|
||||||
}
|
s.try_get_power().await.unwrap();
|
||||||
Self::Set(state) => {
|
}),
|
||||||
|
Self::Set(command) => {
|
||||||
// let c = Controller::new_from_file(config_file).unwrap();
|
// let c = Controller::new_from_file(config_file).unwrap();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
println!("SET");
|
s.try_set_power(command.index, command.state).await.unwrap();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
use crate::control::Control;
|
||||||
use crate::monitor::Monitoring;
|
use crate::monitor::Monitoring;
|
||||||
use crate::tasmota::{TasmotaInterface, TasmotaInterfaceConfig};
|
use crate::tasmota::{TasmotaInterface, TasmotaInterfaceConfig};
|
||||||
use crate::types::Error;
|
use crate::types::{self, Error};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
@ -38,7 +39,7 @@ impl System {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_power(&self) -> Result<(), Error> {
|
pub async fn try_get_power(&self) -> Result<(), Error> {
|
||||||
for component in &self.components {
|
for component in &self.components {
|
||||||
if let Ok(res) = component.get_power().await {
|
if let Ok(res) = component.get_power().await {
|
||||||
component.print();
|
component.print();
|
||||||
|
|
@ -48,4 +49,10 @@ impl System {
|
||||||
}
|
}
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{control::Control, monitor::Monitoring};
|
use crate::{
|
||||||
|
control::Control,
|
||||||
|
monitor::Monitoring,
|
||||||
|
types::{Error, PowerState},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct EnergyData {
|
pub struct EnergyData {
|
||||||
|
|
@ -70,18 +74,21 @@ impl Monitoring for TasmotaInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Control for TasmotaInterface {
|
impl Control for TasmotaInterface {
|
||||||
async fn set_power(&self) -> Result<(), Error> {
|
async fn set_power(&self, state: PowerState) -> Result<(), Error> {
|
||||||
let res = self
|
let cmd = match state {
|
||||||
|
PowerState::Off => "OFF",
|
||||||
|
PowerState::On => "ON",
|
||||||
|
};
|
||||||
|
let _res = self
|
||||||
.client
|
.client
|
||||||
.get(format!(
|
.get(format!(
|
||||||
"http://{}/cm?cmnd=Power%20TOGGLE",
|
"http://{}/cm?cmnd=Power%20{}",
|
||||||
&self.config.target
|
&self.config.target, cmd
|
||||||
))
|
))
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.text()
|
.text()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use clap::Subcommand;
|
use clap::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -13,7 +14,7 @@ pub enum Error {
|
||||||
JsonParseError(#[from] serde_json::Error),
|
JsonParseError(#[from] serde_json::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Clone)]
|
#[derive(Serialize, Deserialize, Parser, Clone)]
|
||||||
pub enum PowerState {
|
pub enum PowerState {
|
||||||
Off,
|
Off,
|
||||||
On,
|
On,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue