rpictrl/src/main.rs

101 lines
2.3 KiB
Rust

use std::sync::Arc;
use ntex::{
http::StatusCode,
web::{self, App, HttpServer, Responder, types::State},
};
mod error;
type Result<T> = core::result::Result<T, error::ErrorWrapper>;
#[derive(Debug, Clone)]
struct Config {
doas: Option<Arc<String>>,
}
#[ntex::main]
async fn main() -> std::io::Result<()> {
let bind = std::env::var("BIND").unwrap_or("127.0.0.1:5544".to_owned());
let cfg = Config {
doas: std::env::var("DOAS").map(Arc::new).ok(),
};
HttpServer::new(move || {
App::new()
.service(root)
.service(poweroff)
.service(ping)
.service(clients)
.service(temp)
.state(cfg.clone())
})
.bind(bind)?
.run()
.await
}
#[web::get("/")]
async fn root() -> impl Responder {
include_bytes!("../static/index.html")
.with_header("content-type", "text/html")
.with_status(StatusCode::OK)
}
#[web::get("/off")]
async fn poweroff(cfg: State<Config>) -> Result<impl Responder> {
const EXE: &str = "/sbin/poweroff";
let mut cmd = if let Some(doas) = &cfg.doas {
let mut cmd = tokio::process::Command::new(&**doas);
cmd.arg(EXE);
cmd
} else {
tokio::process::Command::new(EXE)
};
cmd.kill_on_drop(false).spawn()?;
Ok("OK")
}
#[web::get("/ping")]
async fn ping() -> Result<impl Responder> {
let out = tokio::process::Command::new("/bin/ping")
.arg("-c")
.arg("4")
.arg("1.1.1.1")
.output()
.await?;
Ok(format!(
"exited with {}\n\nstdout:\n{}\n----\n\nstderr:\n{}",
out.status,
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr),
))
}
#[web::get("/ips")]
async fn clients() -> Result<impl Responder> {
tokio::fs::read_to_string("/var/lib/misc/dnsmasq.leases")
.await
.map_err(Into::into)
}
#[web::get("/temp")]
async fn temp(cfg: State<Config>) -> Result<impl Responder> {
const EXE: &str = "/usr/bin/vcgencmd";
let mut cmd = if let Some(doas) = &cfg.doas {
let mut cmd = tokio::process::Command::new(&**doas);
cmd.arg(EXE);
cmd
} else {
tokio::process::Command::new(EXE)
};
let out = cmd.arg("measure_temp").output().await?;
Ok(String::from_utf8(out.stdout)?)
}