1
0
Fork 0
forked from sigil-03/power

Merge pull request #1 from sigil-03/tasmota-refactor

move tasmota interface support into separate module
This commit is contained in:
sigil-03 2025-04-06 14:11:12 -06:00 committed by GitHub
commit fd120be85e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 75 additions and 20 deletions

View file

@ -17,7 +17,6 @@ impl Commands {
tokio::spawn(async move { tokio::spawn(async move {
m.get_power().await.unwrap(); m.get_power().await.unwrap();
}) })
// println!("[TODO] Power: ----W")
} }
}; };
handle.await.unwrap(); handle.await.unwrap();

View file

@ -1,4 +1,4 @@
use crate::tasmota::{PowerStatusData, StatusResponse}; use crate::tasmota::{PowerStatusData, StatusResponse, TasmotaInterface, TasmotaInterfaceConfig};
use reqwest::Client; use reqwest::Client;
use serde::Deserialize; use serde::Deserialize;
use std::fs; use std::fs;
@ -16,20 +16,24 @@ pub enum Error {
JsonParseError(#[from] serde_json::Error), JsonParseError(#[from] serde_json::Error),
} }
pub trait Monitoring {
async fn get_power(&self) -> Result<isize, Error>;
}
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct MonitorConfig { pub struct MonitorConfig {
target: Vec<String>, targets: Vec<TasmotaInterfaceConfig>,
} }
impl MonitorConfig { impl MonitorConfig {
fn print(&self) { fn print(&self) {
for t in &self.target { for t in &self.targets {
println!("* {}", t); t.print();
} }
} }
} }
pub struct Monitor { pub struct Monitor {
config: MonitorConfig, targets: Vec<TasmotaInterface>,
client: Client, client: Client,
} }
@ -37,26 +41,28 @@ impl Monitor {
pub fn new_from_file(config_file: &str) -> Result<Self, Error> { pub fn new_from_file(config_file: &str) -> Result<Self, Error> {
let config_str = fs::read_to_string(config_file)?; let config_str = fs::read_to_string(config_file)?;
let config: MonitorConfig = toml::from_str(&config_str)?; let config: MonitorConfig = toml::from_str(&config_str)?;
// config.print();
Ok(Self { Ok(Self {
config, targets: Monitor::load_targets(&config.targets),
client: Client::new(), client: Client::new(),
}) })
} }
pub async fn get_power(&self) -> Result<(), Error> { pub fn load_targets(targets: &Vec<TasmotaInterfaceConfig>) -> Vec<TasmotaInterface> {
let ip = &self.config.target[0]; let mut v = Vec::new();
let res = self for target in targets {
.client v.push(TasmotaInterface::new(target.clone()));
.get(format!("http://{ip}/cm?cmnd=Status%208")) }
.send() v
.await? }
.text()
.await?;
// println!("body = {res:?}"); pub async fn get_power(&self) -> Result<(), Error> {
let data: StatusResponse = serde_json::from_str(&res)?; for target in &self.targets {
println!("POWER: {}W", data.status.energy.power); if let Ok(res) = target.get_power().await {
target.print();
println!("* POWER: {}W", res);
println!("------------------")
}
}
Ok(()) Ok(())
} }
} }

View file

@ -1,5 +1,9 @@
use reqwest::Client;
use serde::Deserialize; use serde::Deserialize;
use crate::monitor::Error;
use crate::monitor::Monitoring;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct EnergyData { pub struct EnergyData {
#[serde(rename = "Power")] #[serde(rename = "Power")]
@ -19,3 +23,49 @@ pub struct StatusResponse {
#[serde(rename = "StatusSNS")] #[serde(rename = "StatusSNS")]
pub status: PowerStatusData, pub status: PowerStatusData,
} }
#[derive(Deserialize, Clone)]
pub struct TasmotaInterfaceConfig {
name: String,
target: String,
}
impl TasmotaInterfaceConfig {
pub fn print(&self) {
println!("{}", self.name);
println!("* {}", self.target);
}
}
pub struct TasmotaInterface {
config: TasmotaInterfaceConfig,
client: Client,
}
impl TasmotaInterface {
pub fn new(config: TasmotaInterfaceConfig) -> Self {
Self {
config,
client: Client::new(),
}
}
pub fn print(&self) {
println!("{}", self.config.name)
}
}
// Monitoring
impl Monitoring for TasmotaInterface {
async fn get_power(&self) -> Result<isize, Error> {
let res = self
.client
.get(format!("http://{}/cm?cmnd=Status%208", &self.config.target))
.send()
.await?
.text()
.await?;
let data: StatusResponse = serde_json::from_str(&res)?;
Ok(data.status.energy.power)
}
}