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

@@ -105,7 +105,7 @@ impl BatteryInteraction for BQ34Z100G1 {
.state_of_charge()
.map(|v| v as f32)
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -113,7 +113,7 @@ impl BatteryInteraction for BQ34Z100G1 {
self.battery_driver
.remaining_capacity()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -121,7 +121,7 @@ impl BatteryInteraction for BQ34Z100G1 {
self.battery_driver
.full_charge_capacity()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -129,13 +129,13 @@ impl BatteryInteraction for BQ34Z100G1 {
self.battery_driver
.design_capacity()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
async fn voltage_milli_volt(&mut self) -> FatResult<u16> {
self.battery_driver.voltage().map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -143,7 +143,7 @@ impl BatteryInteraction for BQ34Z100G1 {
self.battery_driver
.average_current()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -151,7 +151,7 @@ impl BatteryInteraction for BQ34Z100G1 {
self.battery_driver
.cycle_count()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -159,7 +159,7 @@ impl BatteryInteraction for BQ34Z100G1 {
self.battery_driver
.state_of_health()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -167,7 +167,7 @@ impl BatteryInteraction for BQ34Z100G1 {
self.battery_driver
.temperature()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
}
@@ -190,16 +190,16 @@ pub fn print_battery_bq34z100(
) -> FatResult<()> {
log::info!("Try communicating with battery");
let fwversion = battery_driver.fw_version().unwrap_or_else(|e| {
log::info!("Firmware {:?}", e);
log::info!("Firmware {e:?}");
0
});
log::info!("fw version is {}", fwversion);
log::info!("fw version is {fwversion}");
let design_capacity = battery_driver.design_capacity().unwrap_or_else(|e| {
log::info!("Design capacity {:?}", e);
log::info!("Design capacity {e:?}");
0
});
log::info!("Design Capacity {}", design_capacity);
log::info!("Design Capacity {design_capacity}");
if design_capacity == 1000 {
log::info!("Still stock configuring battery, readouts are likely to be wrong!");
}
@@ -219,39 +219,39 @@ pub fn print_battery_bq34z100(
cf: false,
ocv_taken: false,
});
log::info!("Flags {:?}", flags);
log::info!("Flags {flags:?}");
let chem_id = battery_driver.chem_id().unwrap_or_else(|e| {
log::info!("Chemid {:?}", e);
log::info!("Chemid {e:?}");
0
});
let bat_temp = battery_driver.internal_temperature().unwrap_or_else(|e| {
log::info!("Bat Temp {:?}", e);
log::info!("Bat Temp {e:?}");
0
});
let temp_c = Temperature::from_kelvin(bat_temp as f64 / 10_f64).as_celsius();
let voltage = battery_driver.voltage().unwrap_or_else(|e| {
log::info!("Bat volt {:?}", e);
log::info!("Bat volt {e:?}");
0
});
let current = battery_driver.current().unwrap_or_else(|e| {
log::info!("Bat current {:?}", e);
log::info!("Bat current {e:?}");
0
});
let state = battery_driver.state_of_charge().unwrap_or_else(|e| {
log::info!("Bat Soc {:?}", e);
log::info!("Bat Soc {e:?}");
0
});
let charge_voltage = battery_driver.charge_voltage().unwrap_or_else(|e| {
log::info!("Bat Charge Volt {:?}", e);
log::info!("Bat Charge Volt {e:?}");
0
});
let charge_current = battery_driver.charge_current().unwrap_or_else(|e| {
log::info!("Bat Charge Current {:?}", e);
log::info!("Bat Charge Current {e:?}");
0
});
log::info!("ChemId: {} Current voltage {} and current {} with charge {}% and temp {} CVolt: {} CCur {}", chem_id, voltage, current, state, temp_c, charge_voltage, charge_current);
log::info!("ChemId: {chem_id} Current voltage {voltage} and current {current} with charge {state}% and temp {temp_c} CVolt: {charge_voltage} CCur {charge_current}");
let _ = battery_driver.unsealed();
let _ = battery_driver.it_enable();
Ok(())

View File

@@ -155,7 +155,7 @@ impl Esp<'_> {
pub(crate) async fn delete_file(&self, filename: String) -> FatResult<()> {
let file = PathBuf::try_from(filename.as_str())?;
let access = self.fs.lock().await;
access.remove(&*file)?;
access.remove(&file)?;
Ok(())
}
pub(crate) async fn write_file(
@@ -168,7 +168,7 @@ impl Esp<'_> {
let access = self.fs.lock().await;
access.open_file_with_options_and_then(
|options| options.read(true).write(true).create(true),
&*file,
&file,
|file| {
file.seek(SeekFrom::Start(offset))?;
file.write(buf)?;
@@ -181,7 +181,7 @@ impl Esp<'_> {
pub async fn get_size(&mut self, filename: String) -> FatResult<usize> {
let file = PathBuf::try_from(filename.as_str())?;
let access = self.fs.lock().await;
let data = access.metadata(&*file)?;
let data = access.metadata(&file)?;
Ok(data.len())
}
pub(crate) async fn get_file(
@@ -198,7 +198,7 @@ impl Esp<'_> {
let offset = chunk * buf.len() as u32;
access.open_file_with_options_and_then(
|options| options.read(true),
&*file,
&file,
|file| {
let length = file.len()? as u32;
if length == 0 {
@@ -226,7 +226,7 @@ impl Esp<'_> {
self.ota_target.write(offset, buf)?;
self.ota_target.read(offset, read_back)?;
if buf != read_back {
info!("Expected {:?} but got {:?}", buf, read_back);
info!("Expected {buf:?} but got {read_back:?}");
bail!(
"Flash error, read back does not match write buffer at offset {:x}",
offset
@@ -238,10 +238,7 @@ impl Esp<'_> {
pub(crate) async fn finalize_ota(&mut self) -> Result<(), FatError> {
let current = self.ota.current_slot()?;
if self.ota.current_ota_state()? != OtaImageState::Valid {
info!(
"Validating current slot {:?} as it was able to ota",
current
);
info!("Validating current slot {current:?} as it was able to ota");
self.ota.set_current_ota_state(Valid)?;
}
@@ -250,7 +247,7 @@ impl Esp<'_> {
self.ota.set_current_ota_state(OtaImageState::New)?;
info!("switched state for new partition");
let state_new = self.ota.current_ota_state()?;
info!("state on new partition now {:?}", state_new);
info!("state on new partition now {state_new:?}");
//determine nextslot crc
self.set_restart_to_conf(true);
@@ -290,7 +287,7 @@ impl Esp<'_> {
if ntp_addrs.is_empty() {
bail!("Failed to resolve DNS");
}
info!("NTP server: {:?}", ntp_addrs);
info!("NTP server: {ntp_addrs:?}");
let mut counter = 0;
loop {
@@ -302,12 +299,12 @@ impl Esp<'_> {
match timeout {
Ok(result) => {
let time = result?;
info!("Time: {:?}", time);
info!("Time: {time:?}");
return DateTime::from_timestamp(time.seconds as i64, 0)
.context("Could not convert Sntp result");
}
Err(err) => {
warn!("sntp timeout, retry: {:?}", err);
warn!("sntp timeout, retry: {err:?}");
counter += 1;
if counter > 10 {
bail!("Failed to get time from NTP server");
@@ -426,7 +423,7 @@ impl Esp<'_> {
println!("start net task");
spawner.spawn(net_task(runner)).ok();
println!("run dhcp");
spawner.spawn(run_dhcp(stack.clone(), gw_ip_addr_str)).ok();
spawner.spawn(run_dhcp(*stack, gw_ip_addr_str)).ok();
loop {
if stack.is_link_up() {
@@ -442,7 +439,7 @@ impl Esp<'_> {
.config_v4()
.inspect(|c| println!("ipv4 config: {c:?}"));
Ok(stack.clone())
Ok(*stack)
}
pub(crate) async fn wifi(
@@ -505,12 +502,9 @@ impl Esp<'_> {
} + max_wait as u64 * 1000;
loop {
let state = esp_wifi::wifi::sta_state();
match state {
WifiState::StaStarted => {
self.controller.lock().await.connect()?;
break;
}
_ => {}
if state == WifiState::StaStarted {
self.controller.lock().await.connect()?;
break;
}
if {
let guard = TIME_ACCESS.get().await.lock().await;
@@ -527,11 +521,8 @@ impl Esp<'_> {
} + max_wait as u64 * 1000;
loop {
let state = esp_wifi::wifi::sta_state();
match state {
WifiState::StaConnected => {
break;
}
_ => {}
if state == WifiState::StaConnected {
break;
}
if {
let guard = TIME_ACCESS.get().await.lock().await;
@@ -572,7 +563,7 @@ impl Esp<'_> {
}
info!("Connected WIFI, dhcp: {:?}", stack.config_v4());
Ok(stack.clone())
Ok(*stack)
}
pub fn deep_sleep(
@@ -611,12 +602,12 @@ impl Esp<'_> {
}
let data = self.fs.lock().await.read::<4096>(&cfg)?;
let config: PlantControllerConfig = serde_json::from_slice(&data)?;
return Ok(config);
Ok(config)
}
pub(crate) async fn save_config(&mut self, config: Vec<u8>) -> FatResult<()> {
let filesystem = self.fs.lock().await;
let cfg = PathBuf::try_from(CONFIG_FILE)?;
filesystem.write(&cfg, &*config)?;
filesystem.write(&cfg, &config)?;
Ok(())
}
pub(crate) async fn list_files(&self) -> FatResult<FileList> {
@@ -690,19 +681,15 @@ impl Esp<'_> {
"",
)
.await;
for i in 0..PLANT_COUNT {
log::info!(
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
i,
LAST_WATERING_TIMESTAMP[i]
);
// is executed before main, no other code will alter these values during printing
#[allow(static_mut_refs)]
for (i, time) in LAST_WATERING_TIMESTAMP.iter().enumerate() {
log::info!("LAST_WATERING_TIMESTAMP[{i}] = UTC {time}");
}
for i in 0..PLANT_COUNT {
log::info!(
"CONSECUTIVE_WATERING_PLANT[{}] = {}",
i,
CONSECUTIVE_WATERING_PLANT[i]
);
// is executed before main, no other code will alter these values during printing
#[allow(static_mut_refs)]
for (i, item) in CONSECUTIVE_WATERING_PLANT.iter().enumerate() {
log::info!("CONSECUTIVE_WATERING_PLANT[{i}] = {item}");
}
}
}
@@ -734,9 +721,9 @@ impl Esp<'_> {
bail!("Mqtt url was empty")
}
let last_will_topic = format!("{}/state", base_topic);
let round_trip_topic = format!("{}/internal/roundtrip", base_topic);
let stay_alive_topic = format!("{}/stay_alive", base_topic);
let last_will_topic = format!("{base_topic}/state");
let round_trip_topic = format!("{base_topic}/internal/roundtrip");
let stay_alive_topic = format!("{base_topic}/stay_alive");
let mut builder: McutieBuilder<'_, String, PublishDisplay<String, &str>, 0> =
McutieBuilder::new(stack, "plant ctrl", mqtt_url);
@@ -879,8 +866,7 @@ impl Esp<'_> {
Ok(()) => {}
Err(err) => {
info!(
"Error during mqtt send on topic {} with message {:#?} error is {:?}",
subtopic, message, err
"Error during mqtt send on topic {subtopic} with message {message:#?} error is {err:?}"
);
}
};
@@ -932,7 +918,7 @@ async fn mqtt_incoming_task(
LOG_ACCESS
.lock()
.await
.log(LogMessage::UnknownTopic, 0, 0, "", &*topic)
.log(LogMessage::UnknownTopic, 0, 0, "", &topic)
.await;
}
}

View File

@@ -121,7 +121,6 @@ impl<'a> BoardInteraction<'a> for Initial<'a> {
bail!("Please configure board revision")
}
async fn general_fault(&mut self, enable: bool) {
self.general_fault.set_level(enable.into());
}

View File

@@ -24,7 +24,7 @@ impl lfs2Storage for LittleFs2Filesystem {
fn read(&mut self, off: usize, buf: &mut [u8]) -> lfs2Result<usize> {
let read_size: usize = Self::READ_SIZE;
if off % read_size != 0 {
error!("Littlefs2Filesystem read error: offset not aligned to read size offset: {} read_size: {}", off, read_size);
error!("Littlefs2Filesystem read error: offset not aligned to read size offset: {off} read_size: {read_size}");
return Err(lfs2Error::IO);
}
if buf.len() % read_size != 0 {
@@ -34,7 +34,7 @@ impl lfs2Storage for LittleFs2Filesystem {
match self.storage.read(off as u32, buf) {
Ok(..) => Ok(buf.len()),
Err(err) => {
error!("Littlefs2Filesystem read error: {:?}", err);
error!("Littlefs2Filesystem read error: {err:?}");
Err(lfs2Error::IO)
}
}
@@ -43,7 +43,7 @@ impl lfs2Storage for LittleFs2Filesystem {
fn write(&mut self, off: usize, data: &[u8]) -> lfs2Result<usize> {
let write_size: usize = Self::WRITE_SIZE;
if off % write_size != 0 {
error!("Littlefs2Filesystem write error: offset not aligned to write size offset: {} write_size: {}", off, write_size);
error!("Littlefs2Filesystem write error: offset not aligned to write size offset: {off} write_size: {write_size}");
return Err(lfs2Error::IO);
}
if data.len() % write_size != 0 {
@@ -53,7 +53,7 @@ impl lfs2Storage for LittleFs2Filesystem {
match self.storage.write(off as u32, data) {
Ok(..) => Ok(data.len()),
Err(err) => {
error!("Littlefs2Filesystem write error: {:?}", err);
error!("Littlefs2Filesystem write error: {err:?}");
Err(lfs2Error::IO)
}
}
@@ -62,25 +62,25 @@ impl lfs2Storage for LittleFs2Filesystem {
fn erase(&mut self, off: usize, len: usize) -> lfs2Result<usize> {
let block_size: usize = Self::BLOCK_SIZE;
if off % block_size != 0 {
error!("Littlefs2Filesystem erase error: offset not aligned to block size offset: {} block_size: {}", off, block_size);
error!("Littlefs2Filesystem erase error: offset not aligned to block size offset: {off} block_size: {block_size}");
return lfs2Result::Err(lfs2Error::IO);
}
if len % block_size != 0 {
error!("Littlefs2Filesystem erase error: length not aligned to block size length: {} block_size: {}", len, block_size);
error!("Littlefs2Filesystem erase error: length not aligned to block size length: {len} block_size: {block_size}");
return lfs2Result::Err(lfs2Error::IO);
}
match check_erase(self.storage, off as u32, (off+len) as u32) {
match check_erase(self.storage, off as u32, (off + len) as u32) {
Ok(_) => {}
Err(err) => {
error!("Littlefs2Filesystem check erase error: {:?}", err);
error!("Littlefs2Filesystem check erase error: {err:?}");
return lfs2Result::Err(lfs2Error::IO);
}
}
match self.storage.erase(off as u32, (off + len) as u32) {
Ok(..) => lfs2Result::Ok(len),
Err(err) => {
error!("Littlefs2Filesystem erase error: {:?}", err);
error!("Littlefs2Filesystem erase error: {err:?}");
lfs2Result::Err(lfs2Error::IO)
}
}

View File

@@ -58,9 +58,9 @@ use alloc::sync::Arc;
use async_trait::async_trait;
use bincode::{Decode, Encode};
use bq34z100::Bq34z100g1Driver;
use canapi::SensorSlot;
use chrono::{DateTime, FixedOffset, Utc};
use core::cell::RefCell;
use canapi::SensorSlot;
use ds323x::ic::DS3231;
use ds323x::interface::I2cInterface;
use ds323x::{DateTimeAccess, Ds323x};
@@ -108,7 +108,6 @@ use log::{error, info, warn};
use portable_atomic::AtomicBool;
use serde::Serialize;
pub static TIME_ACCESS: OnceLock<Mutex<CriticalSectionRawMutex, Rtc>> = OnceLock::new();
//Only support for 8 right now!
@@ -127,9 +126,9 @@ pub enum Sensor {
B,
}
impl Into<SensorSlot> for Sensor {
fn into(self) -> SensorSlot {
match self {
impl From<Sensor> for SensorSlot {
fn from(val: Sensor) -> Self {
match val {
Sensor::A => SensorSlot::A,
Sensor::B => SensorSlot::B,
}
@@ -138,6 +137,7 @@ impl Into<SensorSlot> for Sensor {
pub struct PlantHal {}
#[allow(clippy::upper_case_acronyms)]
pub struct HAL<'a> {
pub board_hal: Box<dyn BoardInteraction<'a> + Send>,
}
@@ -177,17 +177,17 @@ pub trait BoardInteraction<'a> {
let current = counter % PLANT_COUNT as u32;
for led in 0..PLANT_COUNT {
if let Err(err) = self.fault(led, current == led as u32).await {
warn!("Fault on plant {}: {:?}", led, err);
warn!("Fault on plant {led}: {err:?}");
}
}
let even = counter % 2 == 0;
let _ = self.general_fault(even.into()).await;
let _ = self.general_fault(even).await;
}
async fn clear_progress(&mut self) {
for led in 0..PLANT_COUNT {
if let Err(err) = self.fault(led, false).await {
warn!("Fault on plant {}: {:?}", led, err);
warn!("Fault on plant {led}: {err:?}");
}
}
let _ = self.general_fault(false).await;
@@ -272,11 +272,11 @@ impl PlantHal {
let timg0 = TimerGroup::new(peripherals.TIMG0);
let esp_wifi_ctrl = &*mk_static!(
EspWifiController<'static>,
init(timg0.timer0, rng.clone()).expect("Could not init wifi controller")
init(timg0.timer0, rng).expect("Could not init wifi controller")
);
let (controller, interfaces) =
esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).expect("Could not init wifi");
esp_wifi::wifi::new(esp_wifi_ctrl, peripherals.WIFI).expect("Could not init wifi");
use esp_hal::timer::systimer::SystemTimer;
esp_hal_embassy::init(systimer.alarm0);
@@ -351,9 +351,9 @@ impl PlantHal {
let running = get_current_slot_and_fix_ota_data(&mut ota, state_0, state_1)?;
let target = running.next();
info!("Currently running OTA slot: {:?}", running);
info!("Slot0 state: {:?}", state_0);
info!("Slot1 state: {:?}", state_1);
info!("Currently running OTA slot: {running:?}");
info!("Slot0 state: {state_0:?}");
info!("Slot1 state: {state_1:?}");
//obtain current_state and next_state here!
let ota_target = match target {
@@ -401,11 +401,12 @@ impl PlantHal {
log::info!("Littlefs2 filesystem is formatted");
}
Err(err) => {
error!("Littlefs2 filesystem could not be formatted: {:?}", err);
error!("Littlefs2 filesystem could not be formatted: {err:?}");
}
}
}
#[allow(clippy::arc_with_non_send_sync)]
let fs = Arc::new(Mutex::new(
lfs2Filesystem::mount(alloc, lfs2filesystem).expect("Could not mount lfs2 filesystem"),
));
@@ -498,8 +499,8 @@ impl PlantHal {
I2C_DRIVER.init(i2c_bus).expect("Could not init i2c driver");
let i2c_bus = I2C_DRIVER.get().await;
let rtc_device = I2cDevice::new(&i2c_bus);
let eeprom_device = I2cDevice::new(&i2c_bus);
let rtc_device = I2cDevice::new(i2c_bus);
let eeprom_device = I2cDevice::new(i2c_bus);
let mut rtc: Ds323x<
I2cInterface<I2cDevice<CriticalSectionRawMutex, I2c<Blocking>>>,
@@ -511,10 +512,10 @@ impl PlantHal {
let rtc_time = rtc.datetime();
match rtc_time {
Ok(tt) => {
log::info!("Rtc Module reports time at UTC {}", tt);
log::info!("Rtc Module reports time at UTC {tt}");
}
Err(err) => {
log::info!("Rtc Module could not be read {:?}", err);
log::info!("Rtc Module could not be read {err:?}");
}
}
@@ -566,7 +567,7 @@ impl PlantHal {
};
let board_hal: Box<dyn BoardInteraction + Send> = match config.hardware.board {
BoardVersion::INITIAL => {
BoardVersion::Initial => {
initial_hal::create_initial_board(free_pins, config, esp)?
}
BoardVersion::V3 => {
@@ -620,8 +621,8 @@ fn ota_state(slot: ota_slot, ota_data: &mut FlashRegion<FlashStorage>) -> OtaIma
let _ = ota_data.read(0x1000, &mut slot_buf);
}
let raw_state = u32::from_le_bytes(slot_buf[24..28].try_into().unwrap_or([0xff; 4]));
let state0 = OtaImageState::try_from(raw_state).unwrap_or(OtaImageState::Undefined);
state0
OtaImageState::try_from(raw_state).unwrap_or(OtaImageState::Undefined)
}
fn get_current_slot_and_fix_ota_data(
@@ -666,10 +667,7 @@ fn get_current_slot_and_fix_ota_data(
}
_ => {}
}
info!(
"Current slot has state {:?} other state has {:?} swapping",
state, other
);
info!("Current slot has state {state:?} other state has {other:?} swapping");
ota.set_current_slot(current.next())?;
//we actually booted other slot, than partition table assumes
return Ok(ota.current_slot()?);
@@ -699,17 +697,17 @@ pub async fn esp_set_time(time: DateTime<FixedOffset>) -> FatResult<()> {
}
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize)]
pub struct Moistures{
pub struct Moistures {
pub sensor_a_hz: [f32; PLANT_COUNT],
pub sensor_b_hz: [f32; PLANT_COUNT],
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize)]
pub struct DetectionResult {
plant: [DetectionSensorResult; crate::hal::PLANT_COUNT]
plant: [DetectionSensorResult; crate::hal::PLANT_COUNT],
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize)]
pub struct DetectionSensorResult{
pub struct DetectionSensorResult {
sensor_a: bool,
sensor_b: bool,
}
}

View File

@@ -1,5 +1,5 @@
use crate::hal::Box;
use crate::fat_error::FatResult;
use crate::hal::Box;
use async_trait::async_trait;
use bincode::config::Configuration;
use bincode::{config, Decode, Encode};
@@ -65,7 +65,7 @@ impl RTCModuleInteraction for DS3231Module {
let (header, len): (BackupHeader, usize) =
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
log::info!("Raw header is {:?} with size {}", header_page_buffer, len);
log::info!("Raw header is {header_page_buffer:?} with size {len}");
Ok(header)
}
@@ -97,7 +97,7 @@ impl RTCModuleInteraction for DS3231Module {
async fn backup_config(&mut self, offset: usize, bytes: &[u8]) -> FatResult<()> {
//skip header and write after
self.storage
.write((BACKUP_HEADER_MAX_SIZE + offset) as u32, &bytes)?;
.write((BACKUP_HEADER_MAX_SIZE + offset) as u32, bytes)?;
Ok(())
}
@@ -113,11 +113,7 @@ impl RTCModuleInteraction for DS3231Module {
};
let config = config::standard();
let encoded = bincode::encode_into_slice(&header, &mut header_page_buffer, config)?;
log::info!(
"Raw header is {:?} with size {}",
header_page_buffer,
encoded
);
log::info!("Raw header is {header_page_buffer:?} with size {encoded}");
self.storage.write(0, &header_page_buffer)?;
Ok(())
}

View File

@@ -171,10 +171,13 @@ pub(crate) fn create_v3(
}
impl V3<'_> {
async fn inner_measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result<f32, FatError> {
async fn inner_measure_moisture_hz(
&mut self,
plant: usize,
sensor: Sensor,
) -> Result<f32, FatError> {
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
for repeat in 0..REPEAT_MOIST_MEASURE {
for sample in results.iter_mut() {
self.signal_counter.pause();
self.signal_counter.clear();
//Disable all
@@ -266,7 +269,7 @@ impl V3<'_> {
&format!("{sensor:?}"),
)
.await;
results[repeat] = hz;
*sample = hz;
}
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
@@ -386,12 +389,18 @@ impl<'a> BoardInteraction<'a> for V3<'a> {
for plant in 0..PLANT_COUNT {
let a = self.inner_measure_moisture_hz(plant, Sensor::A).await;
let b = self.inner_measure_moisture_hz(plant, Sensor::B).await;
let aa = a.unwrap_or_else(|_| u32::MAX as f32);
let bb = b.unwrap_or_else(|_| u32::MAX as f32);
let aa = a.unwrap_or(u32::MAX as f32);
let bb = b.unwrap_or(u32::MAX as f32);
LOG_ACCESS
.lock()
.await
.log(LogMessage::TestSensor, aa as u32, bb as u32, &plant.to_string(), "")
.log(
LogMessage::TestSensor,
aa as u32,
bb as u32,
&plant.to_string(),
"",
)
.await;
result.sensor_a_hz[plant] = aa;
result.sensor_b_hz[plant] = bb;
@@ -399,7 +408,6 @@ impl<'a> BoardInteraction<'a> for V3<'a> {
Ok(result)
}
async fn general_fault(&mut self, enable: bool) {
hold_disable(6);
if enable {

View File

@@ -6,7 +6,10 @@ use crate::hal::esp::{hold_disable, hold_enable, Esp};
use crate::hal::rtc::RTCModuleInteraction;
use crate::hal::v4_sensor::{SensorImpl, SensorInteraction};
use crate::hal::water::TankSensor;
use crate::hal::{BoardInteraction, DetectionResult, FreePeripherals, Moistures, I2C_DRIVER, PLANT_COUNT, TIME_ACCESS};
use crate::hal::{
BoardInteraction, DetectionResult, FreePeripherals, Moistures, I2C_DRIVER, PLANT_COUNT,
TIME_ACCESS,
};
use crate::log::{LogMessage, LOG_ACCESS};
use alloc::boxed::Box;
use alloc::string::ToString;
@@ -74,35 +77,29 @@ impl<'a> Charger<'a> {
impl Charger<'_> {
pub(crate) fn power_save(&mut self) {
match self {
Charger::SolarMpptV1 { mppt_ina, .. } => {
let _ = mppt_ina
.set_configuration(Configuration {
reset: Default::default(),
bus_voltage_range: Default::default(),
shunt_voltage_range: Default::default(),
bus_resolution: Default::default(),
shunt_resolution: Default::default(),
operating_mode: OperatingMode::PowerDown,
})
.map_err(|e| {
log::info!(
"Error setting ina mppt configuration during deep sleep preparation{:?}",
e
);
});
}
_ => {}
if let Charger::SolarMpptV1 { mppt_ina, .. } = self {
let _ = mppt_ina
.set_configuration(Configuration {
reset: Default::default(),
bus_voltage_range: Default::default(),
shunt_voltage_range: Default::default(),
bus_resolution: Default::default(),
shunt_resolution: Default::default(),
operating_mode: OperatingMode::PowerDown,
})
.map_err(|e| {
log::info!(
"Error setting ina mppt configuration during deep sleep preparation{e:?}"
);
});
}
}
fn set_charge_indicator(&mut self, charging: bool) -> FatResult<()> {
match self {
Self::SolarMpptV1 {
charge_indicator, ..
} => {
charge_indicator.set_level(charging.into());
}
_ => {}
if let Self::SolarMpptV1 {
charge_indicator, ..
} = self
{
charge_indicator.set_level(charging.into());
}
Ok(())
}
@@ -244,7 +241,7 @@ pub(crate) async fn create_v4(
Some(ina)
}
Err(err) => {
log::info!("Error creating mppt ina: {:?}", err);
log::info!("Error creating mppt ina: {err:?}");
None
}
};
@@ -253,7 +250,7 @@ pub(crate) async fn create_v4(
let pump_ina = match SyncIna219::new(pump_current_dev, Address::from_pins(Pin::Gnd, Pin::Sda)) {
Ok(ina) => Some(ina),
Err(err) => {
log::info!("Error creating pump ina: {:?}", err);
log::info!("Error creating pump ina: {err:?}");
None
}
};
@@ -362,7 +359,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
let v = pump_ina
.shunt_voltage()
.map_err(|e| FatError::String {
error: alloc::format!("{:?}", e),
error: alloc::format!("{e:?}"),
})
.map(|v| {
let shunt_voltage =

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) => {

View File

@@ -137,11 +137,11 @@ impl<'a> TankSensor<'a> {
Timer::after_millis(100).await;
let mut store = [0_u16; TANK_MULTI_SAMPLE];
for multisample in 0..TANK_MULTI_SAMPLE {
for sample in store.iter_mut() {
let value = self.tank_channel.read_oneshot(&mut self.tank_pin);
//force yield
Timer::after_millis(10).await;
store[multisample] = value.unwrap();
*sample = value.unwrap();
}
self.tank_power.set_low();