Skip to content

Commit

Permalink
sample: make sampling and summaries work with any Sensor implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
alevinval committed Jun 30, 2024
1 parent 4909909 commit 456f222
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 33 deletions.
10 changes: 7 additions & 3 deletions ble-client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ use btleplug::{
platform::{self, Adapter, Manager},
};
use chrono::Local;
use humidity_core::{sample::Summary, serde, shared};
use humidity_core::{
sample::Summary,
sensors::{Hygrometer, Sensor},
serde, shared,
};
use std::{error::Error, time::Duration};
use tokio::{
fs::OpenOptions,
Expand Down Expand Up @@ -50,8 +54,8 @@ async fn collect_data(device: impl Peripheral) -> Result<(), Box<dyn Error>> {
device.disconnect().await?;
println!("disconnected, elapsed: {:?}", since_connecting.elapsed());

let summary = serde::deserialize::<Summary>(&single_read).unwrap();
println!("latest sample: {summary:?} dryness: {}", summary.dryness());
let summary: Summary<Hygrometer> = serde::deserialize(&single_read).unwrap();
println!("latest sample: {summary:?} dryness: {}", summary.sensor.percentage(summary.avg));

let mut open = OpenOptions::new();
let mut output = open.write(true).append(true).open("data.csv").await?;
Expand Down
15 changes: 5 additions & 10 deletions humidity-core/src/sample/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,20 @@
//!
//! Establish a common ground to work with the results of a sampling operation.
//! Uses [`Summary`] to hold the results of a sampling operation.
//!
//! ## TODO
//!
//! - For the moment, only works with [`Hygrometer`] as sensor, should be
//! reworked to work with any [`crate::sensors::Sensor`].
pub use summary::Summary;

use crate::sensors::Hygrometer;
use crate::sensors;

mod summary;

pub fn perform_sampling(
pub fn perform_sampling<SENSOR: sensors::Sensor>(
n: u8,
toggle_sensor: &mut impl FnMut(),
warmup_delay: &mut impl FnMut(),
adc_read: &mut impl FnMut() -> u16,
hygrometer: Hygrometer,
) -> Summary {
sensor: SENSOR,
) -> Summary<SENSOR> {
let mut sum = 0u32;
let mut min = u16::MAX;
let mut max = u16::MIN;
Expand All @@ -43,5 +38,5 @@ pub fn perform_sampling(
toggle_sensor();

let avg = sum.div_ceil(n as u32) as u16;
Summary { n, avg, min, max, hygrometer }
Summary::<SENSOR> { n, avg, min, max, sensor }
}
40 changes: 23 additions & 17 deletions humidity-core/src/sample/summary.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use crate::{
sensors::{Hygrometer, Sensor},
sensors::{self},
serde::{self, Deserializable, Serializable},
};

/// Summarizes the results of a sampling operation.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Summary {
pub struct Summary<SENSOR>
where
SENSOR: sensors::Sensor,
{
/// Number of samples.
pub n: u8,
/// Average reading across all samples.
Expand All @@ -14,50 +17,53 @@ pub struct Summary {
pub min: u16,
/// Maximum reading across all samples.
pub max: u16,
/// Hygrometer model.
pub hygrometer: Hygrometer,
/// Sensor model.
pub sensor: SENSOR,
}

impl Summary {
pub fn dryness(&self) -> f32 {
self.hygrometer.percentage(self.avg)
}
}

impl Serializable for Summary {
impl<S> Serializable for Summary<S>
where
S: sensors::Sensor,
{
fn serialize(&self, ser: &mut serde::Serializer) -> Result<usize, serde::Error> {
let mut n = ser.write_u8(self.n)?;
n += ser.write_u16(self.avg)?;
n += ser.write_u16(self.min)?;
n += ser.write_u16(self.max)?;
n += self.hygrometer.serialize(ser)?;
n += self.sensor.serialize(ser)?;
Ok(n)
}
}

impl Deserializable for Summary {
impl<S> Deserializable for Summary<S>
where
S: sensors::Sensor,
{
fn deserialize(de: &mut serde::Deserializer) -> Result<Self, serde::Error> {
let n = de.read_u8()?;
let avg = de.read_u16()?;
let min = de.read_u16()?;
let max = de.read_u16()?;
let hygrometer = Hygrometer::deserialize(de)?;
Ok(Self { n, avg, min, max, hygrometer })
let sensor = S::deserialize(de)?;
Ok(Self { n, avg, min, max, sensor })
}
}

#[cfg(test)]
mod test {
use sensors::Hygrometer;

use super::*;

#[test]
fn sample_result_serde() {
let input = Summary { n: 1, avg: 990, min: 813, max: 1238, hygrometer: Hygrometer::YL69 };
let input =
Summary::<Hygrometer> { n: 1, avg: 990, min: 813, max: 1238, sensor: Hygrometer::YL69 };

let mut buffer = [0u8; 60];
let n = serde::serialize(&input, &mut buffer).unwrap();

let output = serde::deserialize::<Summary>(&buffer[..n]).unwrap();
let output = serde::deserialize::<Summary<Hygrometer>>(&buffer[..n]).unwrap();
assert_eq!(input, output);
}
}
4 changes: 3 additions & 1 deletion humidity-core/src/sensors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
pub use hygrometer::Hygrometer;

use crate::serde;

mod hygrometer;

/// Defines common behaviour for all sensors, such as getting the calibrated low
/// and high values, and provides a function to compute where a value
/// fits within the calibrated boundaries.
pub trait Sensor {
pub trait Sensor: serde::Serializable + serde::Deserializable {
/// Returns the calibrated low reading.
fn low(&self) -> u16;
/// Returns the calibrated high reading.
Expand Down
2 changes: 1 addition & 1 deletion humidity-monitor-c6/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use humidity_core::{
mod blessed;

#[ram(rtc_fast)]
static mut SAMPLE_HISTORY: Historical<128, Summary> = Historical::new();
static mut SAMPLE_HISTORY: Historical<128, Summary<Hygrometer>> = Historical::new();

const MEASURE_DELAY: u64 = MicrosDurationU64::minutes(15).to_millis();
const HYGROMETER_WARMUP: u32 = MillisDurationU32::millis(1000).to_millis();
Expand Down
2 changes: 1 addition & 1 deletion humidity-monitor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use humidity_core::{
};

#[ram(rtc_fast)]
static mut SAMPLE_HISTORY: Historical<128, Summary> = Historical::new();
static mut SAMPLE_HISTORY: Historical<128, Summary<Hygrometer>> = Historical::new();

const MEASURE_DELAY: u64 = MicrosDurationU64::minutes(15).to_millis();
const HYGROMETER_WARMUP: u32 = MillisDurationU32::millis(1000).to_millis();
Expand Down

0 comments on commit 456f222

Please sign in to comment.