Initial commit

This commit is contained in:
Maxime Augier 2024-08-07 19:59:20 +02:00
commit 14164037d3
4 changed files with 1294 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

1168
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

19
Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "easee-controller"
version = "0.1.0"
edition = "2021"
description = "Software load-balancer and control endpoint for Easee chargers"
authors = ["Maxime Augier <max@xolus.net>"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.86"
clap = { version = "4.5.11", features = ["derive", "env"] }
easee = { path = "../easee", features = ["tungstenite"] }
humantime = "2.1.0"
serde_json = "1.0.121"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
tungstenite = { version = "0.23.0", optional = true, features = ["rustls-tls-native-roots"] }

106
src/main.rs Normal file
View File

@ -0,0 +1,106 @@
use clap::ValueEnum;
use clap::{Parser, Subcommand};
use anyhow::Result;
use easee::api;
use easee::stream;
use tracing::info;
#[derive(Debug,Clone,ValueEnum)]
enum Command {
Start,
Stop,
Pause,
Resume,
}
#[derive(Debug,Clone,Subcommand)]
enum Mode {
Status { id: Option<String> },
Ongoing,
Latest,
Stream,
Command { id: String, command: Command }
}
#[derive(Debug,Parser)]
struct CLI {
#[arg(short,long,env)]
username: String,
#[arg(short,long,env)]
password: String,
#[command(subcommand)]
mode: Mode,
}
fn main() -> Result<()> {
tracing::subscriber::set_global_default(tracing_subscriber::FmtSubscriber::new())
.expect("Tracing subscriber failed");
let args = CLI::parse();
let mut ctx = api::Context::from_login(&args.username, &args.password)?;
info!("Logged in");
let sites = ctx.sites()?;
let chargers = ctx.chargers()?;
info!("{} sites and {} chargers available", sites.len(), chargers.len());
match args.mode {
Mode::Status { id } => {
for c in &chargers {
if id.as_deref().map(|id| id == &c.id).unwrap_or(true) {
println!("{}: {:?}", c.id, c.state(&mut ctx));
}
}
Ok(())
},
Mode::Ongoing => {
for c in &chargers {
println!("{}: {:?}", c.id, c.ongoing_session(&mut ctx));
}
Ok(())
},
Mode::Latest => {
for c in &chargers {
println!("{:?}", c.latest_session(&mut ctx));
}
Ok(())
},
Mode::Stream => {
let mut stream = stream::Stream::open(&mut ctx)?;
for c in &chargers {
stream.subscribe(&c.id)?;
}
let mut stream = easee::signalr::Stream::from_ws(stream);
loop {
println!("{:?}", stream.recv()?);
}
},
Mode::Command { id, command } => {
for c in &chargers {
if c.id == id {
match command {
Command::Start => c.start(&mut ctx)?,
Command::Stop => c.stop(&mut ctx)?,
Command::Pause => c.pause(&mut ctx)?,
Command::Resume => c.resume(&mut ctx)?,
}
return Ok(())
}
}
eprintln!("Charger not found.");
Ok(())
},
}
}