use serde::Serialize;
use std::fmt;
pub type SenML = LimitedSenML;
#[cfg(test)]
mod tests {
use super::*;
use serde_json::Result;
#[test]
fn test_json_encode() -> Result<()> {
let datum = LimitedSenML::make_one(
"urn:dev:mac:ffffaaaa0000eeee:",
"modio.test.test",
"abc123",
1_628_546_838.0,
None,
);
let row = serde_json::to_string(&datum)?;
println!("Row is :{:?}", row);
Ok(())
}
#[test]
fn test_from_ipc() -> Result<()> {
let datum = LimitedSenML::make_one(
"urn:dev:mac:ffffaaaa0000eeee:",
"modio.test.test",
"abc123",
1_628_546_838.0,
None,
);
let res = datum.to_string();
println!("Row is :{:?}", &res);
assert_eq!(
res,
r#"{"bn":"urn:dev:mac:ffffaaaa0000eeee:","n":"modio.test.test","vs":"abc123","t":1628546838.0}"#,
);
Ok(())
}
#[test]
fn test_with_unit() -> Result<()> {
let datum = LimitedSenML::make_one(
"urn:dev:mac:ffffaaaa0000eeee:",
"modio.test.test",
"10.0",
1_628_546_838.0,
Some("cel"),
);
let res = datum.to_string();
assert_eq!(
res,
r#"{"bn":"urn:dev:mac:ffffaaaa0000eeee:","n":"modio.test.test","u":"cel","vs":"10.0","t":1628546838.0}"#,
);
Ok(())
}
}
#[derive(Debug, Serialize)]
pub struct LimitedSenML {
#[serde(skip_serializing_if = "Option::is_none")]
bn: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
n: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
u: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
s: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
vs: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
t: Option<f64>,
}
impl LimitedSenML {
pub fn make_one(bn: &str, n: &str, vs: &str, t: f64, u: Option<&str>) -> LimitedSenML {
LimitedSenML {
bn: Some(bn.to_string()),
n: Some(n.to_string()),
vs: Some(vs.to_string()),
t: Some(t),
u: u.map(String::from),
s: None,
}
}
pub fn make_topic(&self, prefix: &str) -> String {
if let Some(name) = &self.n {
let name = name.replace('.', "/");
format!("{}/metric/{}", &prefix, name)
} else {
prefix.to_string()
}
}
}
impl fmt::Display for LimitedSenML {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = serde_json::to_string(&self).map_err(|_| std::fmt::Error::default())?;
write!(f, "{}", s)
}
}
#[cfg(test)]
mod test_prefix {
use super::LimitedSenML;
use std::error::Error;
#[test]
fn test_no_name() -> Result<(), Box<dyn Error>> {
let prefix = "modio/modio-localhost";
let datum = LimitedSenML {
bn: Some("urn:dev:mac:ffffaaaa0000eeee:".to_string()),
n: None,
vs: None,
t: None,
u: None,
s: None,
};
let res = datum.make_topic(prefix);
assert_eq!(res, "modio/modio-localhost");
Ok(())
}
#[test]
fn test_name_splits() -> Result<(), Box<dyn Error>> {
let prefix = "modio/modio-localhost";
let datum = LimitedSenML {
bn: Some("urn:dev:mac:ffffaaaa0000eeee:".to_string()),
n: Some("28.000000000000".to_string()),
vs: Some("21".to_string()),
t: Some(1_636_722_945.0),
u: None,
s: None,
};
let res = datum.make_topic(prefix);
assert_eq!(res, "modio/modio-localhost/metric/28/000000000000");
Ok(())
}
}