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