mirror of
https://codeberg.org/icewind/taspromto.git
synced 2026-06-03 08:34:21 +02:00
allow using config file instead of env
This commit is contained in:
parent
8687197051
commit
7f7ad384a8
7 changed files with 357 additions and 33 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,3 +2,4 @@
|
||||||
.env
|
.env
|
||||||
.direnv
|
.direnv
|
||||||
result
|
result
|
||||||
|
config.toml
|
||||||
197
Cargo.lock
generated
197
Cargo.lock
generated
|
|
@ -17,6 +17,55 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-stream"
|
name = "async-stream"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
|
@ -117,6 +166,46 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color-eyre"
|
name = "color-eyre"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
|
|
@ -144,6 +233,12 @@ dependencies = [
|
||||||
"tracing-error",
|
"tracing-error",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
@ -196,7 +291,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot_core",
|
"parking_lot_core",
|
||||||
|
|
@ -369,6 +464,12 @@ version = "0.14.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "headers"
|
name = "headers"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
@ -393,6 +494,12 @@ dependencies = [
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
@ -497,14 +604,20 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.2.6"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown 0.15.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
|
@ -888,6 +1001,15 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "secretfile"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "746c54b939ab8d393b536765393c0bd7634fca94eed62321ec3e3559293f6c21"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
|
|
@ -942,6 +1064,15 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
|
@ -1008,6 +1139,12 @@ dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
|
@ -1030,6 +1167,7 @@ name = "taspromto"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-stream",
|
"async-stream",
|
||||||
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
|
|
@ -1038,9 +1176,11 @@ dependencies = [
|
||||||
"jzon",
|
"jzon",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
"rumqttc",
|
"rumqttc",
|
||||||
|
"secretfile",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
"toml",
|
||||||
"warp",
|
"warp",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1164,6 +1304,40 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
|
@ -1296,6 +1470,12 @@ version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -1510,6 +1690,15 @@ version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.6.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,11 @@ color-eyre = "0.6.3"
|
||||||
async-stream = "0.3.5"
|
async-stream = "0.3.5"
|
||||||
pin-utils = "0.1.0"
|
pin-utils = "0.1.0"
|
||||||
hostname = "0.4.0"
|
hostname = "0.4.0"
|
||||||
tokio-stream = "0.1.15"
|
tokio-stream = { version = "0.1.15", features = ["net"] }
|
||||||
serde = { version = "1.0.200", features = ["derive"] }
|
serde = { version = "1.0.200", features = ["derive"] }
|
||||||
|
secretfile = "0.1.0"
|
||||||
|
toml = "0.8.19"
|
||||||
|
clap = { version = "4.5.20", features = ["derive"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
|
||||||
11
config.toml
Normal file
11
config.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
[listen]
|
||||||
|
port = 3030
|
||||||
|
|
||||||
|
[names]
|
||||||
|
mitemp = { 35f3d4 = "Bedroom" }
|
||||||
|
rftemp = { "Bresser-3CH:73:1" = "Home" }
|
||||||
|
|
||||||
|
[mqtt]
|
||||||
|
hostname = "mqtt.icewind.link"
|
||||||
|
username = "taspromto"
|
||||||
|
password = "wYTYUkP10IP3LGiMOXHGbNjKLAMe6bjI"
|
||||||
117
src/config.rs
117
src/config.rs
|
|
@ -1,23 +1,86 @@
|
||||||
use crate::device::{BDAddr, RfDeviceId};
|
use crate::device::{BDAddr, RfDeviceId};
|
||||||
use color_eyre::{eyre::WrapErr, Report, Result};
|
use color_eyre::{eyre::WrapErr, Report, Result};
|
||||||
use rumqttc::MqttOptions;
|
use rumqttc::MqttOptions;
|
||||||
|
use serde::Deserialize;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
use std::fs::read_to_string;
|
||||||
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub mqtt_host: String,
|
pub listen: ListenConfig,
|
||||||
pub mqtt_port: u16,
|
pub names: NamesConfig,
|
||||||
pub host_port: u16,
|
pub mqtt: MqttConfig,
|
||||||
pub mi_temp_names: BTreeMap<BDAddr, String>,
|
|
||||||
pub rf_temp_names: HashMap<RfDeviceId<'static>, String>,
|
|
||||||
pub mqtt_credentials: Option<Credentials>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Credentials {
|
#[derive(Debug, Deserialize)]
|
||||||
username: String,
|
#[serde(untagged)]
|
||||||
password: String,
|
pub enum ListenConfig {
|
||||||
|
Ip {
|
||||||
|
#[serde(default = "default_address")]
|
||||||
|
address: IpAddr,
|
||||||
|
port: u16,
|
||||||
|
},
|
||||||
|
Unix {
|
||||||
|
path: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_address() -> IpAddr {
|
||||||
|
Ipv4Addr::UNSPECIFIED.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct NamesConfig {
|
||||||
|
#[serde(rename = "mitemp")]
|
||||||
|
pub mi_temp: BTreeMap<BDAddr, String>,
|
||||||
|
#[serde(rename = "rftemp")]
|
||||||
|
pub rf_temp: HashMap<RfDeviceId<'static>, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct MqttConfig {
|
||||||
|
#[serde(rename = "hostname")]
|
||||||
|
host: String,
|
||||||
|
#[serde(default = "default_mqtt_port")]
|
||||||
|
port: u16,
|
||||||
|
#[serde(flatten)]
|
||||||
|
credentials: Option<Credentials>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_mqtt_port() -> u16 {
|
||||||
|
1883
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Credentials {
|
||||||
|
Raw {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
},
|
||||||
|
File {
|
||||||
|
username: String,
|
||||||
|
password_file: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Credentials {
|
||||||
|
pub fn username(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Credentials::Raw { username, .. } => username.clone(),
|
||||||
|
Credentials::File { username, .. } => username.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn password(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Credentials::Raw { password, .. } => password.clone(),
|
||||||
|
Credentials::File { password_file, .. } => secretfile::load(password_file).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
|
@ -68,32 +131,44 @@ impl Config {
|
||||||
Ok(username) => {
|
Ok(username) => {
|
||||||
let password = dotenvy::var("MQTT_PASSWORD")
|
let password = dotenvy::var("MQTT_PASSWORD")
|
||||||
.wrap_err("MQTT_USERNAME set, but MQTT_PASSWORD not set")?;
|
.wrap_err("MQTT_USERNAME set, but MQTT_PASSWORD not set")?;
|
||||||
Some(Credentials { username, password })
|
Some(Credentials::Raw { username, password })
|
||||||
}
|
}
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
mqtt_host,
|
listen: ListenConfig::Ip {
|
||||||
mqtt_port,
|
port: host_port,
|
||||||
host_port,
|
address: default_address(),
|
||||||
mi_temp_names,
|
},
|
||||||
rf_temp_names,
|
names: NamesConfig {
|
||||||
mqtt_credentials,
|
mi_temp: mi_temp_names,
|
||||||
|
rf_temp: rf_temp_names,
|
||||||
|
},
|
||||||
|
mqtt: MqttConfig {
|
||||||
|
port: mqtt_port,
|
||||||
|
host: mqtt_host,
|
||||||
|
credentials: mqtt_credentials,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Config> {
|
||||||
|
let raw = read_to_string(path)?;
|
||||||
|
Ok(toml::from_str(&raw)?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mqtt(&self) -> Result<MqttOptions> {
|
pub fn mqtt(&self) -> Result<MqttOptions> {
|
||||||
let hostname = hostname::get()?
|
let hostname = hostname::get()?
|
||||||
.into_string()
|
.into_string()
|
||||||
.map_err(|_| Report::msg("invalid hostname"))?;
|
.map_err(|_| Report::msg("invalid hostname"))?;
|
||||||
let mut mqtt_options = MqttOptions::new(
|
let mut mqtt_options = MqttOptions::new(
|
||||||
format!("taspromto-{}", hostname),
|
format!("taspromto-{}", hostname),
|
||||||
&self.mqtt_host,
|
&self.mqtt.host,
|
||||||
self.mqtt_port,
|
self.mqtt.port,
|
||||||
);
|
);
|
||||||
if let Some(credentials) = self.mqtt_credentials.as_ref() {
|
if let Some(credentials) = self.mqtt.credentials.as_ref() {
|
||||||
mqtt_options.set_credentials(&credentials.username, &credentials.password);
|
mqtt_options.set_credentials(credentials.username(), credentials.password());
|
||||||
}
|
}
|
||||||
mqtt_options.set_keep_alive(Duration::from_secs(5));
|
mqtt_options.set_keep_alive(Duration::from_secs(5));
|
||||||
Ok(mqtt_options)
|
Ok(mqtt_options)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use color_eyre::{eyre::WrapErr, Report, Result};
|
use color_eyre::{eyre::WrapErr, Report, Result};
|
||||||
use jzon::JsonValue;
|
use jzon::JsonValue;
|
||||||
use rumqttc::{AsyncClient, QoS};
|
use rumqttc::{AsyncClient, QoS};
|
||||||
|
use serde::de::Error;
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
@ -565,6 +567,16 @@ pub struct BDAddr {
|
||||||
pub address: [u8; 6usize],
|
pub address: [u8; 6usize],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for BDAddr {
|
||||||
|
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let str = <Cow<'de, str>>::deserialize(deserializer)?;
|
||||||
|
Self::from_mi_temp_mac_part(&str).map_err(D::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BDAddr {
|
impl BDAddr {
|
||||||
/// parse BDAddr from the last 6 characters of the mac address
|
/// parse BDAddr from the last 6 characters of the mac address
|
||||||
/// first 6 characters are always set to 582D34
|
/// first 6 characters are always set to 582D34
|
||||||
|
|
@ -806,6 +818,16 @@ impl RfDeviceId<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for RfDeviceId<'static> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let str = <Cow<'de, str>>::deserialize(deserializer)?;
|
||||||
|
Self::from_str(&str).map_err(D::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for RfDeviceId<'static> {
|
impl FromStr for RfDeviceId<'static> {
|
||||||
type Err = ParseIntError;
|
type Err = ParseIntError;
|
||||||
|
|
||||||
|
|
|
||||||
35
src/main.rs
35
src/main.rs
|
|
@ -3,13 +3,14 @@ mod device;
|
||||||
mod mqtt;
|
mod mqtt;
|
||||||
mod topic;
|
mod topic;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::{Config, ListenConfig};
|
||||||
use crate::device::{
|
use crate::device::{
|
||||||
format_device_state, format_dsmr_state, format_mi_temp_state, format_rf_temp_state, Device,
|
format_device_state, format_dsmr_state, format_mi_temp_state, format_rf_temp_state, Device,
|
||||||
DeviceStates,
|
DeviceStates,
|
||||||
};
|
};
|
||||||
use crate::mqtt::mqtt_stream;
|
use crate::mqtt::mqtt_stream;
|
||||||
use crate::topic::Topic;
|
use crate::topic::Topic;
|
||||||
|
use clap::Parser;
|
||||||
use color_eyre::{eyre::WrapErr, Result};
|
use color_eyre::{eyre::WrapErr, Result};
|
||||||
|
|
||||||
use pin_utils::pin_mut;
|
use pin_utils::pin_mut;
|
||||||
|
|
@ -18,14 +19,28 @@ use rumqttc::{AsyncClient, Publish, QoS};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use tokio::net::UnixListener;
|
||||||
use tokio::task::spawn;
|
use tokio::task::spawn;
|
||||||
use tokio::time::{sleep, Duration};
|
use tokio::time::{sleep, Duration};
|
||||||
|
use tokio_stream::wrappers::UnixListenerStream;
|
||||||
use tokio_stream::{Stream, StreamExt};
|
use tokio_stream::{Stream, StreamExt};
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
struct Args {
|
||||||
|
/// Config file to use, if omitted the config will be loaded from environment variables
|
||||||
|
config: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
let config = Config::from_env()?;
|
let args = Args::parse();
|
||||||
|
|
||||||
|
let config = match args.config {
|
||||||
|
Some(path) => Config::from_file(path)?,
|
||||||
|
_ => Config::from_env()?,
|
||||||
|
};
|
||||||
let mqtt_options = config.mqtt()?;
|
let mqtt_options = config.mqtt()?;
|
||||||
|
|
||||||
let device_states = <Arc<Mutex<DeviceStates>>>::default();
|
let device_states = <Arc<Mutex<DeviceStates>>>::default();
|
||||||
|
|
@ -57,9 +72,8 @@ async fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn serve(device_states: Arc<Mutex<DeviceStates>>, config: Config) {
|
async fn serve(device_states: Arc<Mutex<DeviceStates>>, config: Config) {
|
||||||
let host_port = config.host_port;
|
let mi_temp_names = config.names.mi_temp.clone();
|
||||||
let mi_temp_names = config.mi_temp_names.clone();
|
let rf_temp_names = config.names.rf_temp.clone();
|
||||||
let rf_temp_names = config.rf_temp_names.clone();
|
|
||||||
|
|
||||||
let state = warp::any().map(move || device_states.clone());
|
let state = warp::any().map(move || device_states.clone());
|
||||||
|
|
||||||
|
|
@ -83,7 +97,16 @@ async fn serve(device_states: Arc<Mutex<DeviceStates>>, config: Config) {
|
||||||
response
|
response
|
||||||
});
|
});
|
||||||
|
|
||||||
warp::serve(metrics).run(([0, 0, 0, 0], host_port)).await;
|
match config.listen {
|
||||||
|
ListenConfig::Ip { address, port } => {
|
||||||
|
warp::serve(metrics).run((address, port)).await;
|
||||||
|
}
|
||||||
|
ListenConfig::Unix { path } => {
|
||||||
|
let listener = UnixListener::bind(path).unwrap();
|
||||||
|
let incoming = UnixListenerStream::new(listener);
|
||||||
|
warp::serve(metrics).run_incoming(incoming).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn command(client: &AsyncClient, device: &Device, command: &str, body: &str) -> Result<()> {
|
async fn command(client: &AsyncClient, device: &Device, command: &str, body: &str) -> Result<()> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue