use serde::{Serialize, Serializer};
use super::records::RECORD_VERSION;
pub const READINGS_SUBJECT: &str = "console.readings";
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum TargetKind {
Device,
Station,
Line,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Origin {
Server,
Participant(String),
}
impl Serialize for Origin {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Server => serializer.serialize_str("server"),
Self::Participant(id) => serializer.serialize_str(id),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct ReadingValue(f64);
impl ReadingValue {
#[must_use]
pub fn new(value: f64) -> Option<Self> {
value.is_finite().then_some(Self(value + 0.0))
}
#[must_use]
pub const fn get(self) -> f64 {
self.0
}
}
impl PartialEq for ReadingValue {
fn eq(&self, other: &Self) -> bool {
self.0.to_bits() == other.0.to_bits()
}
}
impl Eq for ReadingValue {}
impl Serialize for ReadingValue {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_f64(self.0)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct Source {
pub id: String,
pub label: String,
pub unit: String,
pub target: TargetKind,
pub from: Origin,
#[serde(skip_serializing_if = "Option::is_none")]
pub range: Option<[ReadingValue; 2]>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct Reading {
pub source: String,
pub target: String,
pub value: ReadingValue,
pub at: u64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct ReadingsRecord {
v: u64,
#[serde(rename = "type")]
record_type: &'static str,
pub rev: u64,
pub topology_rev: u64,
pub sources: Vec<Source>,
pub readings: Vec<Reading>,
}
impl ReadingsRecord {
#[must_use]
pub const fn new(
rev: u64,
topology_rev: u64,
sources: Vec<Source>,
readings: Vec<Reading>,
) -> Self {
Self {
v: RECORD_VERSION,
record_type: "readings",
rev,
topology_rev,
sources,
readings,
}
}
}