diff --git a/Cargo.lock b/Cargo.lock index f2b4539..f51ea0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -281,102 +281,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8b508d585e01084059b60f06ade4cb7415cd2e4084b71dd1cb44e7d3fb9880" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" -dependencies = [ - "concurrent-queue", - "futures-lite", - "libc", - "log", - "once_cell", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "winapi", -] - -[[package]] -name = "async-lock" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-std" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52580991739c5cdb36cde8b2a516371c0a3b70dda36d916cc08b82372916808c" -dependencies = [ - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - [[package]] name = "autocfg" version = "1.1.0" @@ -404,20 +308,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blocking" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] - [[package]] name = "brotli" version = "3.3.4" @@ -439,12 +329,6 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "bumpalo" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" - [[package]] name = "bytes" version = "1.1.0" @@ -570,23 +454,12 @@ version = "0.1.0" dependencies = [ "actix-web", "askama", - "async-channel", - "async-std", "futures", "futures-timer", "paho-mqtt", "serde_json", "spaceapi", -] - -[[package]] -name = "ctor" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" -dependencies = [ - "quote", - "syn", + "tokio", ] [[package]] @@ -627,15 +500,6 @@ version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" -[[package]] -name = "fastrand" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" -dependencies = [ - "instant", -] - [[package]] name = "firestorm" version = "0.5.1" @@ -716,21 +580,6 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-macro" version = "0.3.21" @@ -799,18 +648,6 @@ dependencies = [ "wasi 0.10.2+wasi-snapshot-preview1", ] -[[package]] -name = "gloo-timers" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "h2" version = "0.3.13" @@ -895,15 +732,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "itoa" version = "1.0.2" @@ -919,24 +747,6 @@ dependencies = [ "libc", ] -[[package]] -name = "js-sys" -version = "0.3.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "language-tags" version = "0.3.2" @@ -990,7 +800,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", - "value-bag", ] [[package]] @@ -1131,12 +940,6 @@ dependencies = [ "openssl-sys", ] -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1190,19 +993,6 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" -[[package]] -name = "polling" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" -dependencies = [ - "cfg-if", - "libc", - "log", - "wepoll-ffi", - "winapi", -] - [[package]] name = "ppv-lite86" version = "0.2.16" @@ -1398,8 +1188,6 @@ dependencies = [ [[package]] name = "spaceapi" version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb00159c3cb731b45bba7ea1323b2eed08d77b851f50a8d79c6fe66bb09bce8" dependencies = [ "log", "serde", @@ -1480,14 +1268,27 @@ dependencies = [ "libc", "memchr", "mio", + "num_cpus", "once_cell", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", + "tokio-macros", "winapi", ] +[[package]] +name = "tokio-macros" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-util" version = "0.7.3" @@ -1580,16 +1381,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "value-bag" -version = "1.0.0-alpha.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" -dependencies = [ - "ctor", - "version_check", -] - [[package]] name = "vcpkg" version = "0.2.15" @@ -1602,12 +1393,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -1620,91 +1405,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" - -[[package]] -name = "web-sys" -version = "0.3.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 0fcf5d7..729bdac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,11 @@ edition = "2021" actix-web = "4.0.0" askama = "0.11.0" serde_json = "1.0.81" -spaceapi = "0.8.1" +spaceapi = { path = "/Users/fionera/src/github.com/spaceapi-community/spaceapi-rs" } paho-mqtt = "0.11" futures = "0.3" futures-timer = "3.0" -async-channel = "1.6" -async-std = "1" +tokio = { version = "1", features = ["full"] } [build-dependencies] askama = "0.11.0" diff --git a/src/main.rs b/src/main.rs index 98e4d79..8b5a9e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,44 @@ +use std::sync::{Arc, Mutex, RwLock}; use std::time::Duration; -use paho_mqtt as mqtt; + +use actix_web::{App, error, get, HttpServer, Responder, Result, web}; +use actix_web::error::ErrorInternalServerError; +use actix_web::web::Data; use futures::{executor::block_on, stream::StreamExt}; -use actix_web::{App, get, HttpServer, Responder}; -use serde_json; +use paho_mqtt as mqtt; +use tokio::spawn; + use status::*; mod status; #[get("/api/spaceapi/v13")] -async fn api_spaceapi_v13() -> impl Responder { - serde_json::to_string(&build_status_v13()) +async fn api_spaceapi_v13(info: web::Data>>) -> Result { + let info = info.read().unwrap(); + let info = SharedInfo { + power_usage: info.power_usage, + open: info.open + }; + let status = build_status_v13(info).map_err(|e| ErrorInternalServerError(e))?; + + Ok(web::Json(status)) } #[get("/api/spaceapi/v14")] -async fn api_spaceapi_v14() -> impl Responder { - serde_json::to_string(&build_status_v14()) +async fn api_spaceapi_v14(info: web::Data>>) -> Result { + let info = info.read().unwrap(); + let info = SharedInfo { + power_usage: info.power_usage, + open: info.open + }; + let status = build_status_v13(info).map_err(|e| ErrorInternalServerError(e))?; + + Ok(web::Json(status)) +} + +struct SharedInfo { + power_usage: u64, + open: bool, } const TOPICS: &[&str] = &["/status/flukso/powerinW"]; @@ -22,6 +46,11 @@ const QOS: &[i32] = &[1]; #[tokio::main] // or async fn main() -> std::io::Result<()> { + let shared_info: Arc> = Arc::new(RwLock::new(SharedInfo { + power_usage: 0, + open: false + })); + let create_opts = mqtt::CreateOptionsBuilder::new() .server_uri("mqtt.ctdo.de") .client_id("ctdo-status") @@ -29,12 +58,10 @@ async fn main() -> std::io::Result<()> { let mut cli = mqtt::AsyncClient::new(create_opts).expect("Error creating the client"); - if let Err(err) = block_on(async { + spawn(async move { // Get message stream before connecting. let mut strm = cli.get_stream(25); - // Define the set of options for the connection - let conn_opts = mqtt::ConnectOptionsBuilder::new() .keep_alive_interval(Duration::from_secs(30)) .mqtt_version(mqtt::MQTT_VERSION_3_1_1) @@ -49,23 +76,34 @@ async fn main() -> std::io::Result<()> { while let Some(msg_opt) = strm.next().await { if let Some(msg) = msg_opt { - println!("{}", msg); + match msg.topic() { + "/status/flukso/powerinW" => { + let power_usage = msg.payload_str().parse::() + .map_err(|e| { + println!("invalid power value: {}", e); + 0 + })?; + + let mut lock = shared_info.write().unwrap(); + lock.power_usage = power_usage; + } + _ => println!("{}", msg) + } } else { println!("Lost connection. Attempting reconnect."); while let Err(err) = cli.reconnect().await { println!("Error reconnecting..."); - tokio::time::delay_for(Duration::from_millis(1000)).await; + tokio::time::sleep(Duration::from_millis(1000)).await; } } } Ok::<(), mqtt::Error>(()) - }) { - panic!("{}", err); - } + }); HttpServer::new(|| { App::new() + .app_data() .service(api_spaceapi_v13) .service(api_spaceapi_v14) }) diff --git a/src/status.rs b/src/status.rs index c1d2899..737aa1e 100644 --- a/src/status.rs +++ b/src/status.rs @@ -1,31 +1,28 @@ -use spaceapi::{Contact, Feed, Feeds, Icon, IssueReportChannel, Location, State, Status, StatusBuilder}; +use std::fmt::Error; +use askama::shared::parser::Expr::Range; +use spaceapi::{Contact, Feed, Feeds, Icon, IssueReportChannel, Location, PowerConsumptionSensor, Sensors, SensorTemplate, State, Status, StatusBuilder}; +use spaceapi::sensors::PowerConsumptionSensorTemplate; +use crate::SharedInfo; - -fn fetch_room_state() -> Option { - None -} - -pub fn build_status_v13() -> Status { - build_status(StatusBuilder::v0_13) +pub fn build_status_v13(info: SharedInfo) -> Result { + build_status(StatusBuilder::v0_13, info) .add_issue_report_channel(IssueReportChannel::Ml) .add_issue_report_channel(IssueReportChannel::IssueMail) .build() - .expect("Creating status failed") } -pub fn build_status_v14() -> Status { - build_status(StatusBuilder::v14) +pub fn build_status_v14(info: SharedInfo) -> Result { + build_status(StatusBuilder::v14, info) .build() - .expect("Creating status failed") } -fn build_status(builder: fn(String) -> StatusBuilder) -> StatusBuilder { +fn build_status(builder: fn(String) -> StatusBuilder, info: SharedInfo) -> StatusBuilder { builder("Chaostreff Dortmund".into()) .logo("https://www.chaostreff-dortmund.de/presse/logo/logo_ctdo.png") .url("https://www.chaostreff-dortmund.de/") .state(State { - open: fetch_room_state(), + open: Some(info.open), icon: Some(Icon { open: "https://status.ctdo.de/img/green.png".into(), close: "https://status.ctdo.de/img/red.png".into(), @@ -38,6 +35,16 @@ fn build_status(builder: fn(String) -> StatusBuilder) -> StatusBuilder { lat: 51.527611, lon: 7.4649449, }) + + .sensors(Sensors { + power_consumption: vec![PowerConsumptionSensor{ + unit: "W".to_string(), + location: "Cellar".to_string(), + value: info.power_usage as f64, + ..PowerConsumptionSensor::default() + }], + ..Sensors::default() + }) .contact( Contact { phone: Some("+49 231 8 404 777".into()),