extract rtc module, extract tank module, fix backupview refresh, switch to embedded storage for eeprom

This commit is contained in:
2025-06-25 01:18:36 +02:00
parent 5fb8705d9a
commit 6b711e29fc
14 changed files with 851 additions and 869 deletions

View File

@@ -1,15 +1,22 @@
use anyhow::{anyhow, bail};
use bincode::config::Configuration;
use bincode::{config, Decode, Encode};
use chrono::{DateTime, Utc};
use ds323x::{DateTimeAccess, Ds323x};
use eeprom24x::{Eeprom24x, Eeprom24xTrait};
use eeprom24x::addr_size::TwoBytes;
use eeprom24x::page_size::B32;
use eeprom24x::unique_serial::No;
use eeprom24x::Storage;
use embedded_hal_bus::i2c::MutexDevice;
use embedded_storage::ReadStorage as embedded_storage_ReadStorage;
use embedded_storage::Storage as embedded_storage_Storage;
use esp_idf_hal::delay::Delay;
use esp_idf_hal::i2c::I2cDriver;
use serde::{Deserialize, Serialize};
use std::result::Result::Ok as OkStd;
const X25: crc::Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC);
const CONFIG: Configuration = config::standard();
pub trait RTCModuleInteraction {
fn get_backup_info(&mut self) -> anyhow::Result<BackupHeader>;
@@ -19,57 +26,49 @@ pub trait RTCModuleInteraction {
fn set_rtc_time(&mut self, time: &DateTime<Utc>) -> anyhow::Result<()>;
}
const BACKUP_HEADER_MAX_SIZE: usize = 64;
#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Encode, Decode)]
pub struct BackupHeader {
pub timestamp: i64,
crc16: u16,
pub size: usize,
pub size: u16,
}
pub struct DS3231Module<'a> {
pub(crate) rtc:
Ds323x<ds323x::interface::I2cInterface<MutexDevice<'a, I2cDriver<'a>>>, ds323x::ic::DS3231>,
pub(crate) eeprom: Eeprom24x<
MutexDevice<'a, I2cDriver<'a>>,
eeprom24x::page_size::B32,
eeprom24x::addr_size::TwoBytes,
eeprom24x::unique_serial::No,
>,
pub(crate) storage: Storage<MutexDevice<'a, I2cDriver<'a>>, B32, TwoBytes, No, Delay>,
}
impl RTCModuleInteraction for DS3231Module<'_> {
fn get_backup_info(&mut self) -> anyhow::Result<BackupHeader> {
let config = config::standard();
let store = bincode::encode_to_vec(&BackupHeader::default(), config)?.len();
let mut header_page_buffer = vec![0_u8; store];
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
self.eeprom
.read_data(0, &mut header_page_buffer)
self.storage
.read(0, &mut header_page_buffer)
.map_err(|err| anyhow!("Error reading eeprom header {:?}", err))?;
println!("Raw header is {:?} with size {}", header_page_buffer, store);
let (header, _len): (BackupHeader, usize) =
bincode::decode_from_slice(&header_page_buffer[..], config)?;
let (header, len): (BackupHeader, usize) =
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
println!("Raw header is {:?} with size {}", header_page_buffer, len);
anyhow::Ok(header)
}
fn get_backup_config(&mut self) -> anyhow::Result<Vec<u8>> {
let config = config::standard();
let store = bincode::encode_to_vec(&BackupHeader::default(), config)?.len();
let mut header_page_buffer = vec![0_u8; store];
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
self.eeprom
.read_data(0, &mut header_page_buffer)
self.storage
.read(0, &mut header_page_buffer)
.map_err(|err| anyhow!("Error reading eeprom header {:?}", err))?;
let (header, _header_size): (BackupHeader, usize) =
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
let (header, _len): (BackupHeader, usize) =
bincode::decode_from_slice(&header_page_buffer[..], config)?;
//skip page 0, used by the header
let data_start_address = self.eeprom.page_size() as u32;
let mut data_buffer = vec![0_u8; header.size];
self.eeprom
.read_data(data_start_address, &mut data_buffer)
let mut data_buffer = vec![0_u8; header.size as usize];
//read the specified number of bytes after the header
self.storage
.read(BACKUP_HEADER_MAX_SIZE as u32, &mut data_buffer)
.map_err(|err| anyhow!("Error reading eeprom data {:?}", err))?;
let checksum = X25.checksum(&data_buffer);
@@ -84,55 +83,31 @@ impl RTCModuleInteraction for DS3231Module<'_> {
anyhow::Ok(data_buffer)
}
fn backup_config(&mut self, bytes: &[u8]) -> anyhow::Result<()> {
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
let time = self.get_rtc_time()?.timestamp_millis();
let delay = Delay::new_default();
let checksum = X25.checksum(bytes);
let page_size = self.eeprom.page_size();
let header = BackupHeader {
crc16: checksum,
timestamp: time,
size: bytes.len(),
size: bytes.len() as u16,
};
let config = config::standard();
let encoded = bincode::encode_to_vec(&header, config)?;
if encoded.len() > page_size {
bail!(
"Size limit reached header is {}, but firest page is only {}",
encoded.len(),
page_size
)
}
let as_u8: &[u8] = &encoded;
let encoded = bincode::encode_into_slice(&header, &mut header_page_buffer, config)?;
println!(
"Raw header is {:?} with size {}",
header_page_buffer, encoded
);
self.storage
.write(0, &header_page_buffer)
.map_err(|err| anyhow!("Error writing header {:?}", err))?;
match self.eeprom.write_page(0, as_u8) {
OkStd(_) => {}
Err(err) => bail!("Error writing eeprom {:?}", err),
};
delay.delay_ms(5);
//write rest after the header
self.storage
.write(BACKUP_HEADER_MAX_SIZE as u32, &bytes)
.map_err(|err| anyhow!("Error writing body {:?}", err))?;
let to_write = bytes.chunks(page_size);
let mut lastiter = 0;
let mut current_page = 1;
for chunk in to_write {
let address = current_page * page_size as u32;
self.eeprom
.write_page(address, chunk)
.map_err(|err| anyhow!("Error writing eeprom {:?}", err))?;
current_page += 1;
let iter = (current_page % 8) as usize;
if iter != lastiter {
//todo we want to call progress here, how to do this?
//target.progress();
lastiter = iter;
}
delay.delay_ms(5);
}
anyhow::Ok(())
}