Migrate serialization from Bincode to Postcard
- Replaced Bincode with Postcard for serialization/deserialization across configs and save operations. - Simplified struct derives by removing `bincode`-specific traits. - Updated `Cargo.toml` and `Cargo.lock` to include `postcard` and dependencies. - Added padding stripping for deserialization and improved error handling. - Adjusted serialization logic in `savegame_manager.rs` and related modules.
This commit is contained in:
@@ -582,7 +582,15 @@ impl Esp<'_> {
|
||||
/// Retries once on flash error.
|
||||
pub(crate) async fn save_config(&mut self, config: Vec<u8>) -> FatResult<()> {
|
||||
let timestamp = self.get_time().to_rfc3339();
|
||||
self.savegame.save(config.as_slice(), ×tamp)
|
||||
self.savegame.save(config.as_slice(), ×tamp)?;
|
||||
|
||||
match self.savegame.load_latest()? {
|
||||
None => bail!("Config save verification failed: no latest save found"),
|
||||
Some(data) => {
|
||||
let _: PlantControllerConfig = serde_json::from_slice(&data)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete a specific save slot by erasing it on flash.
|
||||
|
||||
@@ -51,7 +51,6 @@ use alloc::boxed::Box;
|
||||
use alloc::format;
|
||||
use alloc::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use bincode::{Decode, Encode};
|
||||
use canapi::SensorSlot;
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use core::cell::RefCell;
|
||||
@@ -118,7 +117,7 @@ pub static I2C_DRIVER: OnceLock<
|
||||
embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<I2c<Blocking>>>,
|
||||
> = OnceLock::new();
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Encode, Decode)]
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum Sensor {
|
||||
A,
|
||||
B,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::fat_error::FatResult;
|
||||
use crate::hal::Box;
|
||||
use async_trait::async_trait;
|
||||
use bincode::{Decode, Encode};
|
||||
use chrono::{DateTime, Utc};
|
||||
use ds323x::ic::DS3231;
|
||||
use ds323x::interface::I2cInterface;
|
||||
@@ -29,7 +28,7 @@ pub trait RTCModuleInteraction {
|
||||
fn read(&mut self, offset: u32, data: &mut [u8]) -> FatResult<()>;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Encode, Decode)]
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Default)]
|
||||
pub struct BackupHeader {
|
||||
pub timestamp: i64,
|
||||
pub(crate) crc16: u16,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use alloc::string::ToString;
|
||||
use alloc::vec::Vec;
|
||||
use embedded_savegame::storage::{Flash, Storage};
|
||||
use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
|
||||
@@ -32,6 +33,19 @@ struct ParsedSave<'a> {
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
fn strip_padding(data: &[u8]) -> &[u8] {
|
||||
let mut end = data.len();
|
||||
while end > 0 {
|
||||
let b = data[end - 1];
|
||||
if b == 0x00 || b == 0xFF {
|
||||
end -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
&data[..end]
|
||||
}
|
||||
|
||||
fn parse_save(data: &[u8]) -> FatResult<ParsedSave<'_>> {
|
||||
if data.len() < SAVE_HEADER_LEN {
|
||||
return Err(FatError::String {
|
||||
@@ -60,7 +74,7 @@ fn parse_save(data: &[u8]) -> FatResult<ParsedSave<'_>> {
|
||||
|
||||
Ok(ParsedSave {
|
||||
created_at,
|
||||
data: &data[timestamp_end..],
|
||||
data: strip_padding(&data[timestamp_end..]),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -240,7 +254,7 @@ impl SavegameManager {
|
||||
saves.push(SaveInfo {
|
||||
idx,
|
||||
len: 0,
|
||||
created_at: None,
|
||||
created_at: Some(err.to_string()),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ use crate::log::{log, LogMessage};
|
||||
use alloc::boxed::Box;
|
||||
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 chrono::{DateTime, FixedOffset, Utc};
|
||||
@@ -36,7 +35,6 @@ use measurements::{Current, Voltage};
|
||||
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
||||
|
||||
pub const BACKUP_HEADER_MAX_SIZE: usize = 64;
|
||||
const CONFIG: config::Configuration = config::standard();
|
||||
|
||||
const MPPT_CURRENT_SHUNT_OHMS: f64 = 0.05_f64;
|
||||
const TWAI_BAUDRATE: twai::BaudRate = twai::BaudRate::Custom(twai::TimingConfig {
|
||||
@@ -543,7 +541,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
}
|
||||
async fn backup_config(&mut self, controller_config: &PlantControllerConfig) -> FatResult<()> {
|
||||
let mut buffer: [u8; 4096 - BACKUP_HEADER_MAX_SIZE] = [0; 4096 - BACKUP_HEADER_MAX_SIZE];
|
||||
let length = bincode::encode_into_slice(controller_config, &mut buffer, CONFIG)?;
|
||||
let length = postcard::to_slice(controller_config, &mut buffer)?.len();
|
||||
info!("Writing backup config of size {}", length);
|
||||
let mut checksum = X25.digest();
|
||||
checksum.update(&buffer[..length]);
|
||||
@@ -556,7 +554,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
size: length as u16,
|
||||
};
|
||||
info!("Header is {:?}", header);
|
||||
bincode::encode_into_slice(&header, &mut header_page_buffer, CONFIG)?;
|
||||
postcard::to_slice(&header, &mut header_page_buffer)?;
|
||||
info!("Header is serialized");
|
||||
self.get_rtc_module().write(0, &header_page_buffer)?;
|
||||
info!("Header written");
|
||||
@@ -600,7 +598,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
bail!("CRC mismatch in backup data")
|
||||
}
|
||||
info!("CRC is correct");
|
||||
let (decoded, _) = bincode::decode_from_slice(&store[..], CONFIG)?;
|
||||
let decoded = postcard::from_bytes(&store[..])?;
|
||||
info!("Backup data decoded");
|
||||
Ok(decoded)
|
||||
}
|
||||
@@ -609,8 +607,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
self.get_rtc_module().read(0, &mut header_page_buffer)?;
|
||||
info!("Read header page");
|
||||
let info: Result<(BackupHeader, usize), bincode::error::DecodeError> =
|
||||
bincode::decode_from_slice(&header_page_buffer[..], CONFIG);
|
||||
let info = postcard::take_from_bytes::<BackupHeader>(&header_page_buffer[..]);
|
||||
info!("decoding header: {:?}", info);
|
||||
let (header, _) = info.context("Could not read backup header")?;
|
||||
Ok(header)
|
||||
|
||||
Reference in New Issue
Block a user