Compare commits
2 Commits
430c1acdef
...
d464cf8ee6
| Author | SHA1 | Date | |
|---|---|---|---|
|
d464cf8ee6
|
|||
|
2e8e731d80
|
157
Cargo.lock
generated
157
Cargo.lock
generated
@@ -159,6 +159,12 @@ version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@@ -241,6 +247,7 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"serde_with",
|
||||
"serialport",
|
||||
"tokio",
|
||||
"tokio-serial",
|
||||
@@ -386,6 +393,41 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "4.0.2"
|
||||
@@ -403,6 +445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -428,6 +471,12 @@ version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
@@ -672,13 +721,19 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"indexmap 2.13.0",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
@@ -879,6 +934,12 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "1.1.0"
|
||||
@@ -900,6 +961,17 @@ dependencies = [
|
||||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.0"
|
||||
@@ -907,7 +979,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"hashbrown 0.16.1",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1516,6 +1590,26 @@ dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
|
||||
dependencies = [
|
||||
"ref-cast-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast-impl"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.2"
|
||||
@@ -1645,6 +1739,30 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"ref-cast",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"ref-cast",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -1760,6 +1878,37 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.13.0",
|
||||
"schemars 0.9.0",
|
||||
"schemars 1.2.1",
|
||||
"serde_core",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialport"
|
||||
version = "4.8.1"
|
||||
@@ -2131,7 +2280,7 @@ version = "0.19.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 2.13.0",
|
||||
"toml_datetime",
|
||||
"winnow 0.5.40",
|
||||
]
|
||||
@@ -2142,7 +2291,7 @@ version = "0.22.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 2.13.0",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
|
||||
@@ -34,6 +34,7 @@ gethostname = "1.1.0"
|
||||
bitflags = "2.10.0"
|
||||
influxdb2 = "0.3.9"
|
||||
chrono = "0.4.43"
|
||||
serde_with = "3.16.1"
|
||||
|
||||
[dependencies.chrony-candm]
|
||||
git = "https://github.com/aws/chrony-candm"
|
||||
|
||||
36
src/lib.rs
36
src/lib.rs
@@ -12,6 +12,7 @@ use figment::{
|
||||
use gethostname::gethostname;
|
||||
use influxdb2::models::DataPoint;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_with::{DurationSeconds, serde_as};
|
||||
use tokio::sync::broadcast::*;
|
||||
|
||||
use std::{fmt::Debug, path::Path, sync::Arc};
|
||||
@@ -40,12 +41,16 @@ impl Default for InfluxConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct ChronyConfig {
|
||||
pub enabled: bool,
|
||||
pub timeout: u64,
|
||||
pub tracking_interval: u64,
|
||||
pub sources_interval: u64,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub timeout: std::time::Duration,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub tracking_interval: std::time::Duration,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub sources_interval: std::time::Duration,
|
||||
pub measurement_prefix: String,
|
||||
pub tracking_measurement: String,
|
||||
pub sources_measurement: String,
|
||||
@@ -56,9 +61,9 @@ impl Default for ChronyConfig {
|
||||
fn default() -> Self {
|
||||
ChronyConfig {
|
||||
enabled: false,
|
||||
timeout: 5,
|
||||
tracking_interval: 60,
|
||||
sources_interval: 300,
|
||||
timeout: std::time::Duration::from_secs(5),
|
||||
tracking_interval: std::time::Duration::from_secs(60),
|
||||
sources_interval: std::time::Duration::from_secs(300),
|
||||
measurement_prefix: "chrony.".into(),
|
||||
tracking_measurement: "tracking".into(),
|
||||
sources_measurement: "sources".into(),
|
||||
@@ -88,10 +93,12 @@ pub struct HwmonSensorConfig {
|
||||
pub sensor: String,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct HwmonConfig {
|
||||
pub enabled: bool,
|
||||
pub interval: u64,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub interval: std::time::Duration,
|
||||
pub measurement: String,
|
||||
pub sensors: Map<String, HwmonSensorConfig>,
|
||||
}
|
||||
@@ -100,17 +107,19 @@ impl Default for HwmonConfig {
|
||||
fn default() -> Self {
|
||||
HwmonConfig {
|
||||
enabled: false,
|
||||
interval: 60,
|
||||
interval: std::time::Duration::from_secs(60),
|
||||
measurement: "hwmon".into(),
|
||||
sensors: map! {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct GpsdConfig {
|
||||
pub enabled: bool,
|
||||
pub interval: u64,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub interval: std::time::Duration,
|
||||
pub host: String,
|
||||
}
|
||||
|
||||
@@ -118,19 +127,23 @@ impl Default for GpsdConfig {
|
||||
fn default() -> Self {
|
||||
GpsdConfig {
|
||||
enabled: false,
|
||||
interval: 60,
|
||||
interval: std::time::Duration::from_secs(60),
|
||||
host: "localhost:2947".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct Prs10Config {
|
||||
pub enabled: bool,
|
||||
pub port: String,
|
||||
pub baud: u32,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub timeout: std::time::Duration,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub status_interval: std::time::Duration,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub stats_interval: std::time::Duration,
|
||||
}
|
||||
|
||||
@@ -217,12 +230,15 @@ pub struct SourceReport {
|
||||
pub details: Arc<dyn SourceReportDetails>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct UCCMConfig {
|
||||
pub enabled: bool,
|
||||
pub port: String,
|
||||
pub baud: u32,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub status_interval: std::time::Duration,
|
||||
#[serde_as(as = "DurationSeconds<u64>")]
|
||||
pub timeout: std::time::Duration,
|
||||
pub measurement: String,
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ impl ChronyClient {
|
||||
.expect("Unable to parse host:port:");
|
||||
let client_options = ClientOptions {
|
||||
n_tries: 3,
|
||||
timeout: Duration::from_secs(config.sources.chrony.timeout),
|
||||
timeout: config.sources.chrony.timeout,
|
||||
};
|
||||
ChronyClient {
|
||||
server,
|
||||
@@ -298,12 +298,8 @@ impl ChimemonSource for ChronyClient {
|
||||
async fn run(self, chan: ChimemonSourceChannel) {
|
||||
info!("Chrony task started");
|
||||
|
||||
let mut t_interval = tokio::time::interval(Duration::from_secs(
|
||||
self.config.sources.chrony.tracking_interval,
|
||||
));
|
||||
let mut s_interval = tokio::time::interval(Duration::from_secs(
|
||||
self.config.sources.chrony.sources_interval,
|
||||
));
|
||||
let mut t_interval = tokio::time::interval(self.config.sources.chrony.tracking_interval);
|
||||
let mut s_interval = tokio::time::interval(self.config.sources.chrony.sources_interval);
|
||||
|
||||
let t_future = async {
|
||||
let lchan = chan.clone();
|
||||
|
||||
@@ -166,7 +166,7 @@ impl ChimemonSource for GpsdSource {
|
||||
async fn run(mut self, mut chan: ChimemonSourceChannel) {
|
||||
info!("gpsd task started");
|
||||
self.conn.conn().await.unwrap();
|
||||
let mut ticker = interval(Duration::from_secs(self.config.sources.gpsd.interval));
|
||||
let mut ticker = interval(self.config.sources.gpsd.interval);
|
||||
|
||||
let mut params = WatchParams::default();
|
||||
params.json = Some(true);
|
||||
|
||||
@@ -113,8 +113,7 @@ impl HwmonSource {
|
||||
impl ChimemonSource for HwmonSource {
|
||||
async fn run(self, chan: ChimemonSourceChannel) {
|
||||
info!("hwmon task started");
|
||||
let mut interval =
|
||||
tokio::time::interval(Duration::from_secs(self.config.sources.hwmon.interval));
|
||||
let mut interval = tokio::time::interval(self.config.sources.hwmon.interval);
|
||||
loop {
|
||||
interval.tick().await;
|
||||
let mut values = Vec::new();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::any::type_name;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -225,7 +226,7 @@ pub struct Prs10Stats {
|
||||
pub ocxo_efc: u32,
|
||||
pub error_signal_volts: f64,
|
||||
pub detect_signal_volts: f64,
|
||||
pub freq_offset_ppt: u16,
|
||||
pub freq_offset_ppt: i16,
|
||||
pub mag_efc: u16,
|
||||
pub heat_volts: f64,
|
||||
pub elec_volts: f64,
|
||||
@@ -363,7 +364,10 @@ impl Prs10Monitor {
|
||||
let mut buf = Vec::new();
|
||||
let read = timeout(self.config.timeout, reader.read_until(b'\r', &mut buf)).await??;
|
||||
buf.truncate(buf.len() - 1); // strip "\r"
|
||||
debug!("response: ({read}) `{buf:?}`");
|
||||
debug!(
|
||||
"raw response: ({read}) `{}`",
|
||||
str::from_utf8(&buf).unwrap_or("<garbage>")
|
||||
);
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
@@ -391,13 +395,11 @@ impl Prs10Monitor {
|
||||
}
|
||||
|
||||
pub async fn get_analog(&mut self, id: u16) -> Result<f64, Box<dyn std::error::Error>> {
|
||||
debug!("Getting analog value {id}");
|
||||
let mut cmd = b"AD".to_vec();
|
||||
cmd.extend_from_slice(id.to_string().as_bytes());
|
||||
cmd.push(b'?');
|
||||
let resp = self.cmd_response(&cmd).await?;
|
||||
let value = str::from_utf8(&resp)?.parse::<f64>()?;
|
||||
|
||||
let value = self.get_parsed(&cmd).await?;
|
||||
debug!("Got: {value}");
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@@ -408,7 +410,11 @@ impl Prs10Monitor {
|
||||
where
|
||||
T::Err: std::error::Error + 'static,
|
||||
{
|
||||
debug!("Getting int value for command {cmd:?}");
|
||||
debug!(
|
||||
"Getting parsed <{}> value for command {}",
|
||||
type_name::<T>(),
|
||||
str::from_utf8(cmd).unwrap_or("<garbage>"),
|
||||
);
|
||||
let resp = self.cmd_response(cmd).await?;
|
||||
let val = str::from_utf8(&resp)?.parse::<T>()?;
|
||||
Ok(val)
|
||||
@@ -430,18 +436,18 @@ impl Prs10Monitor {
|
||||
}
|
||||
|
||||
pub async fn get_detected_signals(&mut self) -> Result<(f64, f64), Box<dyn std::error::Error>> {
|
||||
debug!("Getting detected signals pair");
|
||||
debug!("Getting i16,i16 -> f64,f64 detected signals pair");
|
||||
let resp = self.cmd_response(b"DS?").await?;
|
||||
let (error, signal) = resp
|
||||
.splitn(2, |c| *c == b',')
|
||||
.map(|s| str::from_utf8(s).unwrap().parse::<u16>())
|
||||
.map(|s| str::from_utf8(s).unwrap().parse::<i16>())
|
||||
.collect_tuple()
|
||||
.ok_or("Not enough values in response to DS?".to_string())?;
|
||||
Ok((error? as f64 * 0.15e-6, signal? as f64 * 0.001))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn status_poll(&mut self) -> Result<ChimemonMessage, Box<dyn std::error::Error>> {
|
||||
debug!("polling status");
|
||||
let status = self.get_status().await?;
|
||||
Ok(ChimemonMessage::SourceReport(SourceReport {
|
||||
name: "prs10".into(),
|
||||
@@ -454,14 +460,13 @@ impl Prs10Monitor {
|
||||
}))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
async fn stats_poll(&mut self) -> Result<ChimemonMessage, Box<dyn std::error::Error>> {
|
||||
const ANALOG_SCALING: [f64; 20] = [
|
||||
0.0, 10.0, 10.0, 10.0, 10.0, 1.0, 1.0, 1.0, 1.0, 4.0, 100.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
||||
4.0, 4.0, 4.0, 1.0,
|
||||
];
|
||||
|
||||
debug!("polling stats");
|
||||
|
||||
let stats_span = debug_span!("get_stats_serial");
|
||||
let stats_guard = stats_span.enter();
|
||||
let ocxo_efc = self.get_ocxo_efc().await?;
|
||||
|
||||
Reference in New Issue
Block a user