mirror of
https://codeberg.org/icewind/taspromto.git
synced 2026-08-02 12:14:45 +02:00
cleanup rf formatting
This commit is contained in:
parent
a9a2f5270e
commit
16993948cf
4 changed files with 166 additions and 153 deletions
151
src/device/rf.rs
Normal file
151
src/device/rf.rs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Display};
|
||||
use std::num::ParseIntError;
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{Deserialize, Deserializer, de::Error};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TempState {
|
||||
pub name: String,
|
||||
pub id: RfDeviceId,
|
||||
pub temperature: f32,
|
||||
pub humidity: u8,
|
||||
}
|
||||
|
||||
impl TempState {
|
||||
pub fn new(id: RfDeviceId, name: String) -> Self {
|
||||
TempState {
|
||||
name,
|
||||
id,
|
||||
temperature: 0.0,
|
||||
humidity: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_prometheus(&self) -> impl Display + '_ {
|
||||
TempFormatter { device: self }
|
||||
}
|
||||
}
|
||||
|
||||
struct TempFormatter<'a> {
|
||||
device: &'a TempState,
|
||||
}
|
||||
|
||||
impl Display for TempFormatter<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.device.temperature > 0.0 {
|
||||
writeln!(
|
||||
f,
|
||||
"sensor_temperature{{model=\"{}\", id=\"{}\", channel=\"{}\", name=\"{}\"}} {}",
|
||||
self.device.id.name,
|
||||
self.device.id.id,
|
||||
self.device.id.channel,
|
||||
self.device.name,
|
||||
self.device.temperature
|
||||
)?;
|
||||
}
|
||||
|
||||
if self.device.humidity > 0 {
|
||||
writeln!(
|
||||
f,
|
||||
"sensor_humidity{{model=\"{}\", id=\"{}\", channel=\"{}\", name=\"{}\"}} {}",
|
||||
self.device.id.name,
|
||||
self.device.id.id,
|
||||
self.device.id.channel,
|
||||
self.device.name,
|
||||
self.device.humidity
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct RfPayload<'a> {
|
||||
pub name: &'a str,
|
||||
pub id: u16,
|
||||
pub channel: u8,
|
||||
pub battery: bool,
|
||||
pub temperature: f32,
|
||||
pub humidity: u8,
|
||||
}
|
||||
|
||||
impl<'a> RfPayload<'a> {
|
||||
pub fn device_id(&self) -> RfDeviceId {
|
||||
RfDeviceId {
|
||||
name: self.name.into(),
|
||||
id: self.id,
|
||||
channel: self.channel,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug, Default, Clone)]
|
||||
pub struct RfDeviceId {
|
||||
pub name: String,
|
||||
pub id: u16,
|
||||
pub channel: u8,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for RfDeviceId {
|
||||
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 {
|
||||
type Err = ParseIntError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut parts = s.splitn(3, ':');
|
||||
let name = parts.next().unwrap_or_default();
|
||||
let id = parts.next().unwrap_or_default().parse()?;
|
||||
let channel = parts.next().unwrap_or_default().parse()?;
|
||||
Ok(RfDeviceId {
|
||||
name: name.into(),
|
||||
id,
|
||||
channel,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_rf_payload<'a>(payload: &'a str) -> Option<RfPayload<'a>> {
|
||||
let mut parts = payload.split(";").skip(2);
|
||||
let name = parts.next()?;
|
||||
let id = parts.next()?.strip_prefix("ID=")?.parse().ok()?;
|
||||
let channel = parts.next()?.strip_prefix("CHN=")?.parse().ok()?;
|
||||
let battery = parts.next()?.strip_prefix("BAT=")? == "OK";
|
||||
let temperature = parts.next()?.strip_prefix("TEMP=")?;
|
||||
let temperature = u32::from_str_radix(temperature, 16).ok()?;
|
||||
let humidity = parts.next()?.strip_prefix("HUM=")?.parse().ok()?;
|
||||
|
||||
Some(RfPayload {
|
||||
name,
|
||||
id,
|
||||
channel,
|
||||
battery,
|
||||
temperature: temperature as f32 / 10.0,
|
||||
humidity,
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rf_payload() {
|
||||
assert_eq!(
|
||||
RfPayload {
|
||||
name: "Bresser-3CH",
|
||||
id: 49,
|
||||
channel: 1,
|
||||
battery: true,
|
||||
temperature: 16.1,
|
||||
humidity: 58
|
||||
},
|
||||
parse_rf_payload("20;1E;Bresser-3CH;ID=49;CHN=0001;BAT=OK;TEMP=00a1;HUM=58;").unwrap()
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue