chore: 📎 + fmt

This commit is contained in:
2025-10-18 20:40:38 +02:00
parent 6357ec773f
commit 1db3f7af64
26 changed files with 548 additions and 578 deletions

View File

@@ -1,14 +1,14 @@
use canapi::id::{classify, plant_id, MessageKind, IDENTIFY_CMD_OFFSET};
use crate::bail;
use crate::fat_error::{ContextExt, FatError, FatResult};
use canapi::{SensorSlot};
use crate::hal::{DetectionResult, Moistures, Sensor};
use crate::hal::Box;
use crate::hal::{DetectionResult, Moistures, Sensor};
use crate::log::{LogMessage, LOG_ACCESS};
use alloc::format;
use alloc::string::ToString;
use async_trait::async_trait;
use bincode::config;
use canapi::id::{classify, plant_id, MessageKind, IDENTIFY_CMD_OFFSET};
use canapi::SensorSlot;
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_time::{Duration, Instant, Timer, WithTimeout};
@@ -23,8 +23,6 @@ use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
const REPEAT_MOIST_MEASURE: usize = 10;
#[async_trait(?Send)]
pub trait SensorInteraction {
async fn measure_moisture_hz(&mut self) -> FatResult<Moistures>;
@@ -59,11 +57,25 @@ impl SensorInteraction for SensorImpl {
..
} => {
let mut result = Moistures::default();
for plant in 0..crate::hal::PLANT_COUNT{
result.sensor_a_hz[plant] = Self::inner_pulse(plant, Sensor::A, signal_counter, sensor_expander).await?;
info!("Sensor {} {:?}: {}", plant, Sensor::A, result.sensor_a_hz[plant]);
result.sensor_b_hz[plant] = Self::inner_pulse(plant, Sensor::B, signal_counter, sensor_expander).await?;
info!("Sensor {} {:?}: {}", plant, Sensor::B, result.sensor_b_hz[plant]);
for plant in 0..crate::hal::PLANT_COUNT {
result.sensor_a_hz[plant] =
Self::inner_pulse(plant, Sensor::A, signal_counter, sensor_expander)
.await?;
info!(
"Sensor {} {:?}: {}",
plant,
Sensor::A,
result.sensor_a_hz[plant]
);
result.sensor_b_hz[plant] =
Self::inner_pulse(plant, Sensor::B, signal_counter, sensor_expander)
.await?;
info!(
"Sensor {} {:?}: {}",
plant,
Sensor::B,
result.sensor_b_hz[plant]
);
}
Ok(result)
}
@@ -81,7 +93,7 @@ impl SensorInteraction for SensorImpl {
match rec {
Ok(_) => {}
Err(err) => {
info!("Error receiving CAN message: {:?}", err);
info!("Error receiving CAN message: {err:?}");
break;
}
}
@@ -102,8 +114,6 @@ impl SensorInteraction for SensorImpl {
}
}
impl SensorImpl {
pub async fn autodetect(&mut self) -> FatResult<DetectionResult> {
match self {
@@ -124,164 +134,176 @@ impl SensorImpl {
// Send a few test messages per potential sensor node
for plant in 0..crate::hal::PLANT_COUNT {
for sensor in [Sensor::A, Sensor::B] {
let target = StandardId::new(plant_id(IDENTIFY_CMD_OFFSET, sensor.into(), plant as u16)).context(">> Could not create address for sensor! (plant: {}) <<")?;
let target = StandardId::new(plant_id(
IDENTIFY_CMD_OFFSET,
sensor.into(),
plant as u16,
))
.context(">> Could not create address for sensor! (plant: {}) <<")?;
let can_buffer = [0_u8; 0];
if let Some(frame) = EspTwaiFrame::new(target, &can_buffer) {
// Try a few times; we intentionally ignore rx here and rely on stub logic
let resu = as_async.transmit_async(&frame).await;
match resu {
Ok(_) => {
info!(
"Sent test message to plant {} sensor {:?}",
plant, sensor
);
info!("Sent test message to plant {plant} sensor {sensor:?}");
}
Err(err) => {
info!("Error sending test message to plant {} sensor {:?}: {:?}", plant, sensor, err);
info!(
"Error sending test message to plant {plant} sensor {sensor:?}: {err:?}"
);
}
}
} else {
info!("Error building CAN frame");
}
}
}
let mut result = DetectionResult::default();
// Wait for messages to arrive
let _ = Self::wait_for_can_measurements(&mut as_async, &mut result).with_timeout(Duration::from_millis(5000)).await;
let _ = Self::wait_for_can_measurements(&mut as_async, &mut result)
.with_timeout(Duration::from_millis(5000))
.await;
let config = as_async.stop().into_blocking();
can_power.set_low();
twai_config.replace(config);
info!("Autodetection result: {:?}", result);
info!("Autodetection result: {result:?}");
Ok(result)
}
}
}
async fn wait_for_can_measurements(as_async: &mut Twai<'_, Async>, result: &mut DetectionResult) {
async fn wait_for_can_measurements(
as_async: &mut Twai<'_, Async>,
result: &mut DetectionResult,
) {
loop {
match as_async.receive_async().await {
Ok(can_frame) => {
match can_frame.id() {
Id::Standard(id) => {
info!("Received CAN message: {:?}", id);
let rawid = id.as_raw();
match classify(rawid) {
None => {}
Some(msg) => {
info!("received message of kind {:?} (plant: {}, sensor: {:?})", msg.0, msg.1, msg.2);
if msg.0 == MessageKind::MoistureData {
let plant = msg.1 as usize;
let sensor = msg.2;
match sensor {
SensorSlot::A => {
result.plant[plant].sensor_a = true;
}
SensorSlot::B => {
result.plant[plant].sensor_b = true;
}
Ok(can_frame) => match can_frame.id() {
Id::Standard(id) => {
info!("Received CAN message: {id:?}");
let rawid = id.as_raw();
match classify(rawid) {
None => {}
Some(msg) => {
info!(
"received message of kind {:?} (plant: {}, sensor: {:?})",
msg.0, msg.1, msg.2
);
if msg.0 == MessageKind::MoistureData {
let plant = msg.1 as usize;
let sensor = msg.2;
match sensor {
SensorSlot::A => {
result.plant[plant].sensor_a = true;
}
SensorSlot::B => {
result.plant[plant].sensor_b = true;
}
}
}
}
}
Id::Extended(ext) => {
warn!("Received extended ID: {:?}", ext);
}
}
}
Id::Extended(ext) => {
warn!("Received extended ID: {ext:?}");
}
},
Err(err) => {
error!("Error receiving CAN message: {:?}", err);
error!("Error receiving CAN message: {err:?}");
break;
}
}
}
}
pub async fn inner_pulse(plant: usize, sensor: Sensor, signal_counter: &mut Unit<'_, 0>, sensor_expander: &mut Pca9535Immediate<I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>>) -> FatResult<f32> {
pub async fn inner_pulse(
plant: usize,
sensor: Sensor,
signal_counter: &mut Unit<'_, 0>,
sensor_expander: &mut Pca9535Immediate<
I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>,
>,
) -> FatResult<f32> {
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
for sample in results.iter_mut() {
signal_counter.pause();
signal_counter.clear();
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
for repeat in 0..REPEAT_MOIST_MEASURE {
signal_counter.pause();
signal_counter.clear();
//Disable all
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
//Disable all
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
let sensor_channel = match sensor {
Sensor::A => plant as u32,
Sensor::B => (15 - plant) as u32,
};
let sensor_channel = match sensor {
Sensor::A => plant as u32,
Sensor::B => (15 - plant) as u32,
};
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
if is_bit_set(0) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS0)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
}
if is_bit_set(1) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS1)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
}
if is_bit_set(2) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS2)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
}
if is_bit_set(3) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS3)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
}
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
if is_bit_set(0) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS0)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
}
if is_bit_set(1) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS1)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
}
if is_bit_set(2) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS2)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
}
if is_bit_set(3) {
sensor_expander.pin_set_high(GPIOBank::Bank0, MS3)?;
} else {
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS4)?;
sensor_expander.pin_set_high(GPIOBank::Bank0, SENSOR_ON)?;
let measurement = 100; // TODO what is this scaling factor? what is its purpose?
let factor = 1000f32 / measurement as f32;
//give some time to stabilize
Timer::after_millis(10).await;
signal_counter.resume();
Timer::after_millis(measurement).await;
signal_counter.pause();
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, SENSOR_ON)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
Timer::after_millis(10).await;
let unscaled = 1337; //signal_counter.get_counter_value()? as i32;
let hz = unscaled as f32 * factor;
LOG_ACCESS
.lock()
.await
.log(
LogMessage::RawMeasure,
unscaled as u32,
hz as u32,
&plant.to_string(),
&format!("{sensor:?}"),
)
.await;
*sample = hz;
}
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
let mid = results.len() / 2;
let median = results[mid];
Ok(median)
}
sensor_expander.pin_set_low(GPIOBank::Bank0, MS4)?;
sensor_expander.pin_set_high(GPIOBank::Bank0, SENSOR_ON)?;
let measurement = 100; // TODO what is this scaling factor? what is its purpose?
let factor = 1000f32 / measurement as f32;
//give some time to stabilize
Timer::after_millis(10).await;
signal_counter.resume();
Timer::after_millis(measurement).await;
signal_counter.pause();
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, SENSOR_ON)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
Timer::after_millis(10).await;
let unscaled = 1337; //signal_counter.get_counter_value()? as i32;
let hz = unscaled as f32 * factor;
LOG_ACCESS
.lock()
.await
.log(
LogMessage::RawMeasure,
unscaled as u32,
hz as u32,
&plant.to_string(),
&format!("{sensor:?}"),
)
.await;
results[repeat] = hz;
}
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
let mid = results.len() / 2;
let median = results[mid];
Ok(median)
}
async fn inner_can(
twai: &mut Twai<'static, Blocking>,
) -> FatResult<Moistures> {
[0_u8; 8];
async fn inner_can(twai: &mut Twai<'static, Blocking>) -> FatResult<Moistures> {
config::standard();
let timeout = Instant::now()
@@ -291,7 +313,7 @@ impl SensorImpl {
let answer = twai.receive();
match answer {
Ok(answer) => {
info!("Received CAN message: {:?}", answer);
info!("Received CAN message: {answer:?}");
}
Err(error) => match error {
nb::Error::Other(error) => {