make async can useable
This commit is contained in:
@@ -11,7 +11,7 @@ use esp_hal::Blocking;
|
||||
use measurements::Temperature;
|
||||
use serde::Serialize;
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
pub trait BatteryInteraction {
|
||||
async fn state_charge_percent(&mut self) -> FatResult<f32>;
|
||||
async fn remaining_milli_ampere_hour(&mut self) -> FatResult<u16>;
|
||||
@@ -51,7 +51,7 @@ pub enum BatteryState {
|
||||
|
||||
/// If no battery monitor is installed this implementation will be used
|
||||
pub struct NoBatteryMonitor {}
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl BatteryInteraction for NoBatteryMonitor {
|
||||
async fn state_charge_percent(&mut self) -> FatResult<f32> {
|
||||
// No monitor configured: assume full battery for lightstate logic
|
||||
@@ -105,7 +105,7 @@ pub struct BQ34Z100G1 {
|
||||
pub battery_driver: Bq34z100g1Driver<I2cDev, Delay>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl BatteryInteraction for BQ34Z100G1 {
|
||||
async fn state_charge_percent(&mut self) -> FatResult<f32> {
|
||||
self.battery_driver
|
||||
|
@@ -1,6 +1,6 @@
|
||||
use crate::bail;
|
||||
use crate::config::{NetworkConfig, PlantControllerConfig};
|
||||
use crate::hal::{get_current_slot_and_fix_ota_data, PLANT_COUNT, TIME_ACCESS};
|
||||
use crate::hal::{PLANT_COUNT, TIME_ACCESS};
|
||||
use crate::log::{LogMessage, LOG_ACCESS};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Serialize;
|
||||
|
@@ -24,7 +24,7 @@ pub struct Initial<'a> {
|
||||
|
||||
pub(crate) struct NoRTC {}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl RTCModuleInteraction for NoRTC {
|
||||
async fn get_backup_info(&mut self) -> Result<BackupHeader, FatError> {
|
||||
bail!("Please configure board revision")
|
||||
@@ -68,7 +68,7 @@ pub(crate) fn create_initial_board(
|
||||
Ok(Box::new(v))
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl<'a> BoardInteraction<'a> for Initial<'a> {
|
||||
fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError> {
|
||||
bail!("Please configure board revision")
|
||||
|
@@ -130,7 +130,7 @@ pub struct HAL<'a> {
|
||||
pub board_hal: Box<dyn BoardInteraction<'a> + Send>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
pub trait BoardInteraction<'a> {
|
||||
fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError>;
|
||||
fn get_esp(&mut self) -> &mut Esp<'a>;
|
||||
|
@@ -21,7 +21,7 @@ use serde::{Deserialize, Serialize};
|
||||
pub const X25: crc::Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC);
|
||||
const CONFIG: Configuration = config::standard();
|
||||
//
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
pub trait RTCModuleInteraction {
|
||||
async fn get_backup_info(&mut self) -> FatResult<BackupHeader>;
|
||||
async fn get_backup_config(&mut self, chunk: usize) -> FatResult<([u8; 32], usize, u16)>;
|
||||
@@ -55,7 +55,7 @@ pub struct DS3231Module {
|
||||
>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl RTCModuleInteraction for DS3231Module {
|
||||
async fn get_backup_info(&mut self) -> FatResult<BackupHeader> {
|
||||
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
|
@@ -170,7 +170,7 @@ pub(crate) fn create_v3(
|
||||
}))
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl<'a> BoardInteraction<'a> for V3<'a> {
|
||||
fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError> {
|
||||
Ok(&mut self.tank_sensor)
|
||||
|
@@ -297,7 +297,7 @@ pub(crate) async fn create_v4(
|
||||
Ok(Box::new(v))
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError> {
|
||||
Ok(&mut self.tank_sensor)
|
||||
@@ -461,7 +461,6 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
|
||||
async fn detect_sensors(&mut self) -> Result<alloc::string::String, FatError> {
|
||||
// Delegate to sensor autodetect and build JSON
|
||||
use alloc::string::ToString;
|
||||
let detected = self.sensor.autodetect().await?;
|
||||
// Build JSON manually to avoid exposing internal types
|
||||
let mut s = alloc::string::String::from("{\"plants\":[");
|
||||
|
@@ -9,24 +9,21 @@ use alloc::string::ToString;
|
||||
use async_trait::async_trait;
|
||||
use bincode::config;
|
||||
use bincode::error::DecodeError;
|
||||
use core::mem;
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use embassy_time::{Instant, Timer, WithTimeout};
|
||||
use embedded_can::nb::Can;
|
||||
use embedded_can::Frame;
|
||||
use esp_hal::gpio::Output;
|
||||
use esp_hal::i2c::master::I2c;
|
||||
use esp_hal::pcnt::unit::Unit;
|
||||
use esp_hal::twai::{EspTwaiError, EspTwaiFrame, StandardId, Twai, TwaiConfiguration};
|
||||
use esp_hal::Blocking;
|
||||
use esp_hal::twai::{EspTwaiFrame, StandardId, Twai, TwaiConfiguration};
|
||||
use esp_hal::{Async, Blocking};
|
||||
use log::info;
|
||||
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
||||
|
||||
const REPEAT_MOIST_MEASURE: usize = 10;
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
pub trait SensorInteraction {
|
||||
async fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> FatResult<f32>;
|
||||
}
|
||||
@@ -50,7 +47,7 @@ pub enum SensorImpl {
|
||||
},
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait(?Send)]
|
||||
impl SensorInteraction for SensorImpl {
|
||||
async fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> FatResult<f32> {
|
||||
match self {
|
||||
@@ -180,8 +177,10 @@ impl SensorImpl {
|
||||
} => {
|
||||
// Power on CAN transceiver and start controller
|
||||
can_power.set_high();
|
||||
let config = twai_config.take().expect("twai config not set");
|
||||
let mut twai = config.start();
|
||||
let mut config = twai_config.take().expect("twai config not set");
|
||||
let mut as_async = config.into_async().start();
|
||||
Timer::after_millis(10).await;
|
||||
|
||||
|
||||
// Give CAN some time to stabilize
|
||||
Timer::after_millis(10).await;
|
||||
@@ -197,7 +196,7 @@ impl SensorImpl {
|
||||
{
|
||||
if let Some(frame) = EspTwaiFrame::new(address, &can_buffer) {
|
||||
// Try a few times; we intentionally ignore rx here and rely on stub logic
|
||||
let resu = twai.transmit(&frame);
|
||||
let resu = as_async.transmit_async(&frame).await;
|
||||
match resu {
|
||||
Ok(_) => {
|
||||
info!(
|
||||
@@ -217,22 +216,23 @@ impl SensorImpl {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Poll for messages for ~100 ms
|
||||
let detect_timeout = Instant::now()
|
||||
.checked_add(embassy_time::Duration::from_millis(100))
|
||||
.unwrap();
|
||||
|
||||
loop {
|
||||
let rec = twai
|
||||
.receive()
|
||||
.with_timeout(embassy_time::Duration::from_millis(100))
|
||||
.await;
|
||||
match rec {
|
||||
Ok(msg) => match msg {
|
||||
Ok(or) => {
|
||||
info!("Received CAN message: {:?}", or);
|
||||
}
|
||||
Err(err) => {
|
||||
info!("Error receiving CAN message: {:?}", err);
|
||||
match as_async.receive() {
|
||||
Ok(or) => {
|
||||
info!("Received CAN message: {:?}", or);
|
||||
}
|
||||
Err(nb::Error::WouldBlock) => {
|
||||
if Instant::now() > detect_timeout {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
Timer::after_millis(10).await;
|
||||
}
|
||||
Err(nb::Error::Other(err)) => {
|
||||
info!("Error receiving CAN message: {:?}", err);
|
||||
break;
|
||||
}
|
||||
@@ -242,6 +242,7 @@ impl SensorImpl {
|
||||
// Wait for acknowledgements on the bus (stub: just wait 5 seconds)
|
||||
Timer::after_millis(5_000).await;
|
||||
// Stop CAN and power down
|
||||
let config = as_async.stop().into_blocking();
|
||||
can_power.set_low();
|
||||
twai_config.replace(config);
|
||||
|
||||
|
Reference in New Issue
Block a user