get log to work, make time accessible
This commit is contained in:
@@ -1,47 +1,122 @@
|
||||
use crate::vec;
|
||||
use alloc::string::ToString;
|
||||
use alloc::vec::Vec;
|
||||
use bytemuck::{AnyBitPattern, Contiguous, Pod, Zeroable};
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::lazy_lock::LazyLock;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use embassy_time::Instant;
|
||||
use esp_println::println;
|
||||
use esp_hal::Persistable;
|
||||
use log::info;
|
||||
use serde::Serialize;
|
||||
use strum_macros::IntoStaticStr;
|
||||
|
||||
use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
|
||||
use unit_enum::UnitEnum;
|
||||
use crate::hal::TIME_ACCESS;
|
||||
|
||||
#[esp_hal::ram(rtc_fast, persistent)]
|
||||
static mut LOG_ARRAY: LogArray = LogArray {
|
||||
buffer: [LogEntryInner { timestamp: 0, message_id: 0, a: 0, b: 0, txt_short: [0;TXT_SHORT_LENGTH], txt_long: [0;TXT_LONG_LENGTH] }; 256],
|
||||
head: 0,
|
||||
};
|
||||
pub static LOG_ACCESS: Mutex<CriticalSectionRawMutex, LogArray> = Mutex::new(unsafe { LOG_ARRAY });
|
||||
|
||||
const TXT_SHORT_LENGTH: usize = 8;
|
||||
const TXT_LONG_LENGTH: usize = 32;
|
||||
|
||||
const BUFFER_SIZE: usize = 220;
|
||||
|
||||
#[link_section = ".rtc.data"]
|
||||
static mut BUFFER: ConstGenericRingBuffer<LogEntry, BUFFER_SIZE> =
|
||||
ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
||||
#[allow(static_mut_refs)]
|
||||
static BUFFER_ACCESS: LazyLock<
|
||||
Mutex<CriticalSectionRawMutex, &mut ConstGenericRingBuffer<LogEntry, BUFFER_SIZE>>,
|
||||
> = LazyLock::new(|| unsafe { Mutex::new(&mut BUFFER) });
|
||||
#[derive(Debug, Clone, Copy, AnyBitPattern)]
|
||||
#[repr(C)]
|
||||
pub struct LogArray{
|
||||
buffer: [LogEntryInner; (u8::MAX_VALUE as usize) +1],
|
||||
head: u8
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
unsafe impl Persistable for LogArray {}
|
||||
unsafe impl Zeroable for LogEntryInner {}
|
||||
|
||||
unsafe impl Pod for LogEntryInner{}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct LogEntryInner {
|
||||
pub timestamp: u64,
|
||||
pub message_id: u16,
|
||||
pub a: u32,
|
||||
pub b: u32,
|
||||
pub txt_short: [u8; TXT_SHORT_LENGTH],
|
||||
pub txt_long: [u8; TXT_LONG_LENGTH],
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LogEntry {
|
||||
pub timestamp: u64,
|
||||
pub message_id: u16,
|
||||
pub a: u32,
|
||||
pub b: u32,
|
||||
pub txt_short: heapless::String<TXT_SHORT_LENGTH>,
|
||||
pub txt_long: heapless::String<TXT_LONG_LENGTH>,
|
||||
pub txt_short: alloc::string::String,
|
||||
pub txt_long: alloc::string::String,
|
||||
}
|
||||
|
||||
pub async fn init() {
|
||||
unsafe {
|
||||
BUFFER = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
||||
};
|
||||
let mut access = BUFFER_ACCESS.get().lock().await;
|
||||
access.drain().for_each(|_| {});
|
||||
impl From<LogEntryInner> for LogEntry {
|
||||
fn from(value: LogEntryInner) -> Self {
|
||||
LogEntry{
|
||||
timestamp: value.timestamp,
|
||||
message_id: value.message_id,
|
||||
a: value.a,
|
||||
b: value.b,
|
||||
txt_short: alloc::string::String::from_utf8_lossy_owned(value.txt_short.to_vec()),
|
||||
txt_long: alloc::string::String::from_utf8_lossy_owned(value.txt_long.to_vec()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LogArray {
|
||||
pub fn get(&mut self) -> Vec<LogEntry> {
|
||||
let mut rv: Vec<LogEntry> = Vec::new();
|
||||
let mut index = self.head.wrapping_sub(1);
|
||||
for _ in 0..self.buffer.len() {
|
||||
let entry = self.buffer[index as usize];
|
||||
if (entry.message_id as usize) != LogMessage::Empty.ordinal() {
|
||||
rv.push(entry.into());
|
||||
}
|
||||
index = index.wrapping_sub(1);
|
||||
}
|
||||
rv
|
||||
}
|
||||
|
||||
pub async fn log(
|
||||
&mut self,
|
||||
message_key: LogMessage,
|
||||
number_a: u32,
|
||||
number_b: u32,
|
||||
txt_short: &str,
|
||||
txt_long: &str,
|
||||
) {
|
||||
let mut txt_short_stack: heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
|
||||
let mut txt_long_stack: heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
|
||||
|
||||
limit_length(txt_short, &mut txt_short_stack);
|
||||
limit_length(txt_long, &mut txt_long_stack);
|
||||
|
||||
let time = TIME_ACCESS.get().await.current_time_us()/1000;
|
||||
|
||||
let ordinal = message_key.ordinal() as u16;
|
||||
let template: &str = message_key.into();
|
||||
let mut template_string = template.to_string();
|
||||
template_string = template_string.replace("${number_a}", number_a.to_string().as_str());
|
||||
template_string = template_string.replace("${number_b}", number_b.to_string().as_str());
|
||||
template_string = template_string.replace("${txt_long}", txt_long);
|
||||
template_string = template_string.replace("${txt_short}", txt_short);
|
||||
|
||||
info!("{}", template_string);
|
||||
|
||||
let to_modify = &mut self.buffer[self.head as usize];
|
||||
to_modify.timestamp = time;
|
||||
to_modify.message_id = ordinal;
|
||||
to_modify.a = number_a;
|
||||
to_modify.b = number_b;
|
||||
to_modify.txt_short.clone_from_slice(&txt_short_stack.as_bytes());
|
||||
to_modify.txt_long.clone_from_slice(&txt_long_stack.as_bytes());
|
||||
self.head = self.head.wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn limit_length<const LIMIT: usize>(input: &str, target: &mut heapless::String<LIMIT>) {
|
||||
@@ -60,60 +135,19 @@ fn limit_length<const LIMIT: usize>(input: &str, target: &mut heapless::String<L
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_log() -> Vec<LogEntry> {
|
||||
let buffer = BUFFER_ACCESS.get().lock().await;
|
||||
let mut read_copy = Vec::new();
|
||||
for entry in buffer.iter() {
|
||||
let copy = entry.clone();
|
||||
read_copy.push(copy);
|
||||
while target.len() < LIMIT {
|
||||
target.push(' ').unwrap();
|
||||
}
|
||||
drop(buffer);
|
||||
read_copy
|
||||
}
|
||||
|
||||
pub async fn log(
|
||||
message_key: LogMessage,
|
||||
number_a: u32,
|
||||
number_b: u32,
|
||||
txt_short: &str,
|
||||
txt_long: &str,
|
||||
) {
|
||||
let mut txt_short_stack: heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
|
||||
let mut txt_long_stack: heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
|
||||
|
||||
limit_length(txt_short, &mut txt_short_stack);
|
||||
limit_length(txt_long, &mut txt_long_stack);
|
||||
|
||||
//TODO
|
||||
let time = Instant::now().as_secs();
|
||||
// let time = EspSystemTime {}.now().as_millis() as u64;
|
||||
//
|
||||
let ordinal = message_key.ordinal() as u16;
|
||||
let template: &str = message_key.into();
|
||||
let mut template_string = template.to_string();
|
||||
template_string = template_string.replace("${number_a}", number_a.to_string().as_str());
|
||||
template_string = template_string.replace("${number_b}", number_b.to_string().as_str());
|
||||
template_string = template_string.replace("${txt_long}", txt_long);
|
||||
template_string = template_string.replace("${txt_short}", txt_short);
|
||||
|
||||
info!("LOG: {} : {}", time, template_string);
|
||||
|
||||
let entry = LogEntry {
|
||||
timestamp: time,
|
||||
message_id: ordinal,
|
||||
a: number_a,
|
||||
b: number_b,
|
||||
txt_short: txt_short_stack,
|
||||
txt_long: txt_long_stack,
|
||||
};
|
||||
|
||||
let mut buffer = BUFFER_ACCESS.get().lock().await;
|
||||
buffer.push(entry);
|
||||
}
|
||||
#[derive(IntoStaticStr, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone, UnitEnum)]
|
||||
pub enum LogMessage {
|
||||
#[strum(
|
||||
serialize = ""
|
||||
)]
|
||||
Empty,
|
||||
#[strum(
|
||||
serialize = "Reset due to ${txt_long} requires rtc clear ${number_a} and force config mode ${number_b}"
|
||||
)]
|
||||
|
||||
Reference in New Issue
Block a user