use core::cmp::Ordering;
use core::fmt::{Debug, Display};
use core::ops::Add;
use heapless::{LinearMap, Vec};
use serde::{de, Deserialize, Serialize, Serializer};
use crate::nodes::SystemNodeId;
use crate::properties::{MeasurementsVec, CLUSTER_NODE_COUNT, MEASUREMENTS_MAX_COUNT};
use crate::rules::measurements::ClusterType::{HUMIDITY, TEMPERATURE};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
pub enum ClusterType {
TEMPERATURE,
HUMIDITY,
}
impl Display for ClusterType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
TEMPERATURE => f.write_str("TEMPERATURE"),
HUMIDITY => f.write_str("HUMIDITY"),
}
}
}
impl From<char> for ClusterType {
fn from(input: char) -> Self {
match input {
'T' => TEMPERATURE,
'H' => HUMIDITY,
_ => panic!("Unexpected Sensor Type."),
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Measurement {
pub typed: ClusterType,
pub value: i32,
}
impl Add for Measurement {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
typed: self.typed,
value: self.value + rhs.value,
}
}
}
impl PartialEq<i32> for Measurement {
fn eq(&self, other: &i32) -> bool {
&self.value == other
}
}
impl PartialOrd<i32> for Measurement {
fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
Some(self.value.cmp(other))
}
}
impl Ord for Measurement {
fn cmp(&self, other: &Self) -> Ordering {
self.value.cmp(&other.value)
}
}
impl PartialOrd for Measurement {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Debug for Measurement {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let sensor_type = if self.typed == ClusterType::TEMPERATURE {
"T"
} else {
"H"
};
write!(f, "{:}: {:?}", sensor_type, self.value)
}
}
impl Measurement {
pub fn new(sensor_type: ClusterType, value: i32) -> Self {
Self { typed: sensor_type, value }
}
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Serialize, Deserialize)]
pub struct SystemState {
#[serde(serialize_with = "serialize", deserialize_with = "deserialize")]
pub measurements: LinearMap<SystemNodeId, NodeMeasurementsVec, CLUSTER_NODE_COUNT>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Serialize, Deserialize)]
pub struct NodeMeasurementsVec {
measurements: Vec<Measurement, MEASUREMENTS_MAX_COUNT>,
}
impl From<LinearMap<SystemNodeId, NodeMeasurementsVec, CLUSTER_NODE_COUNT>> for SystemState {
fn from(
measurements: LinearMap<SystemNodeId, NodeMeasurementsVec, CLUSTER_NODE_COUNT>,
) -> Self {
Self { measurements }
}
}
impl NodeMeasurementsVec {
pub fn new() -> Self {
Self {
measurements: Vec::new(),
}
}
pub fn from(measurement: Measurement) -> Self {
Self {
measurements: Vec::from_slice(&[measurement]).unwrap(),
}
}
pub fn pop(&mut self) -> Option<Measurement> {
self.measurements.pop()
}
pub fn push(&mut self, measurement: Measurement) {
if self.measurements.push(measurement).is_err() {
self.measurements.remove(0);
self.measurements.push(measurement).unwrap();
}
}
pub fn last(&self) -> Option<Measurement> {
self.measurements.last().copied()
}
pub fn is_empty(&self) -> bool {
self.measurements.is_empty()
}
pub fn len(&self) -> usize { self.measurements.len() }
pub fn is_full(&self) -> bool { self.measurements.len() == MEASUREMENTS_MAX_COUNT }
}
impl SystemState {
pub fn raw(self) -> LinearMap<SystemNodeId, NodeMeasurementsVec, CLUSTER_NODE_COUNT> {
self.measurements
}
pub fn new(id: SystemNodeId, measurement: Measurement) -> Self {
let mut state = LinearMap::new();
state
.insert(id, NodeMeasurementsVec::from(measurement))
.unwrap();
Self {
measurements: state,
}
}
pub fn update(&mut self, id: SystemNodeId, measurement: Measurement) {
match self.measurements.get_mut(&id) {
Some(measurements) => {
measurements.push(measurement);
}
None => {
self.measurements
.insert(id, NodeMeasurementsVec::from(measurement))
.unwrap();
}
}
}
pub fn last_measurements(&self) -> MeasurementsVec {
let mut measurements = MeasurementsVec::new();
for (_, node_measurements) in self.measurements.clone().iter() {
if let Some(it) = node_measurements.last() {
measurements.push(it).unwrap()
}
}
measurements
}
pub fn extend(&mut self, rhs: Self) {
for (id, node_measurements) in rhs.measurements.into_iter() {
for measurement in node_measurements.measurements.clone().into_iter() {
self.update(*id, measurement)
}
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Serialize, Deserialize)]
struct InnerSystemState {
state: Vec<Inner, CLUSTER_NODE_COUNT>,
}
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
struct Inner {
id: SystemNodeId,
value: NodeMeasurementsVec,
}
fn deserialize<'de, D>(
deserializer: D,
) -> Result<LinearMap<SystemNodeId, NodeMeasurementsVec, CLUSTER_NODE_COUNT>, D::Error>
where
D: de::Deserializer<'de>,
{
let inner = <Vec<Inner, CLUSTER_NODE_COUNT>>::deserialize(deserializer)?;
let mut system_state: LinearMap<SystemNodeId, NodeMeasurementsVec, CLUSTER_NODE_COUNT> =
LinearMap::new();
for Inner { id, value } in inner.into_iter() {
system_state
.insert(id, value)
.expect("Couldn't insert value into state.");
}
Ok(system_state)
}
fn serialize<S>(
map: &LinearMap<SystemNodeId, NodeMeasurementsVec, CLUSTER_NODE_COUNT>,
ser: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut vec: Vec<Inner, CLUSTER_NODE_COUNT> = Vec::new();
for (key, value) in map {
let inner = Inner {
id: *key,
value: value.clone(),
};
vec.push(inner).expect("Couldn't pusshe value into vec");
}
vec.serialize(ser)
}
#[cfg(test)]
mod measurement_test {
use crate::rules::measurements::Measurement;
use crate::rules::measurements::ClusterType::TEMPERATURE;
#[test]
fn can_get_max_measurements_of_same_type() {
assert!(Measurement::new(TEMPERATURE, 2) > Measurement::new(TEMPERATURE, 1));
}
#[test]
fn can_cmp_measurement_with_i32() {
let measurement = Measurement::new(TEMPERATURE, 2);
assert!(measurement > 1_i32);
}
}