Compare commits

..
11 Commits
Author SHA1 Message Date
Jacob Weaver e645bbcc08 ui stuff 2024-12-19 12:12:55 -06:00
Jacob Weaver 70b2f1386d made serial config pub 2024-12-19 10:10:12 -06:00
Jacob Weaver 27559a8d31 added serial 2024-12-19 09:52:40 -06:00
jcweaver997 f59b164095 reflect 2024-12-18 22:13:41 -06:00
Jacob Weaver e9a4f3de75 reflect do vec 2024-12-18 16:16:26 -06:00
Jacob Weaver fbd47eba43 reflect do vec 2024-12-18 16:15:55 -06:00
Jacob Weaver 1a511523f4 reflect 2024-12-18 15:44:02 -06:00
Jacob Weaver c9ad723e79 start reflect 2024-12-17 16:13:03 -06:00
Jacob Weaver 5401d624bd added example app to rp pico 2024-12-17 11:12:30 -06:00
Jacob Weaver a243b860d2 Merge remote-tracking branch 'origin/main' 2024-12-17 11:02:53 -06:00
Jacob Weaver ffe33fec50 fix watchdog 2024-12-17 11:02:10 -06:00
22 changed files with 1164 additions and 284 deletions
+1
View File
@@ -24,3 +24,4 @@ bincode = { version = "2.0.0-rc.3", default-features = false, features = [
simple_logger = "5.0.0" simple_logger = "5.0.0"
rp2040-hal = "0.10.2" rp2040-hal = "0.10.2"
rp2040-pac = "0.6.0" rp2040-pac = "0.6.0"
mio-serial = "=5.0.5"
+2
View File
@@ -41,7 +41,9 @@ impl App for Example {
ExampleCmd::Noop => info!("NOOP command received"), ExampleCmd::Noop => info!("NOOP command received"),
ExampleCmd::Reset => { ExampleCmd::Reset => {
info!("RESET command received"); info!("RESET command received");
let perf = self.data.hk.perf;
self.data = Default::default(); self.data = Default::default();
self.data.hk.perf = perf;
} }
}, },
_ => { _ => {
+1 -1
View File
@@ -96,7 +96,7 @@ mod watchdog_rp2040 {
pub fn new(wd: Watchdog) -> Self { pub fn new(wd: Watchdog) -> Self {
Self { Self {
wd, wd,
time: 10 * 1000000, time: 3 * 1000000,
} }
} }
} }
+3 -1
View File
@@ -5,7 +5,9 @@ edition = "2021"
[dependencies] [dependencies]
rfe.path = "../../rfe" rfe.path = "../../rfe"
rfe.features = ["std"] rfe.features = ["std", "reflect"]
anyhow.workspace = true anyhow.workspace = true
simple_logger = "5.0.0" simple_logger = "5.0.0"
log.workspace = true log.workspace = true
egui = "0.30.0"
eframe = "0.30.0"
+198 -11
View File
@@ -1,30 +1,217 @@
#![feature(thread_sleep_until)] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
use std::{ use std::{
thread::sleep_until, collections::HashMap,
thread::{sleep, spawn},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use anyhow::anyhow;
use anyhow::Result; use anyhow::Result;
use connector::{Connector, UdpConnector}; use connector::{Connector, UdpConnector};
use egui::{Layout, Ui};
use log::*; use log::*;
use msg::Msg;
use reflect::*;
use rfe::macros::Reflect;
use rfe::*; use rfe::*;
extern crate alloc;
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;
#[derive(Debug, Default, Reflect)]
struct TestStruct {
counter: i8,
}
#[derive(Debug, Default, Reflect)]
enum EnumTest {
#[default]
None,
Test(TestStruct),
}
fn main() -> Result<()> { fn main() -> Result<()> {
SimpleLogger::new().init().unwrap(); SimpleLogger::new()
.with_level(LevelFilter::Debug)
.init()
.unwrap();
let mut udp = UdpConnector::new("127.0.0.1", 7011, "127.0.0.1", 7010)?; spawn(|| {
let mut udp = UdpConnector::new("127.0.0.1", 7011, "127.0.0.1", 7010).unwrap();
let mut next_time = Instant::now() + Duration::from_millis(10); let mut next_time = Instant::now() + Duration::from_millis(10);
loop { loop {
sleep_until(next_time); sleep(next_time - Instant::now());
while let Some(msgs) = udp.recv() { while let Some(msgs) = udp.recv() {
for msg in msgs { for msg in msgs {
info!("got msg {:?}", msg); info!("got msg {:?}", msg);
}
} }
next_time += Duration::from_millis(10);
}
});
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([560.0, 480.0]),
..Default::default()
};
eframe::run_native(
"RFE Ground",
options,
Box::new(|_cc| Ok(Box::<MyApp>::default())),
)
.or(Err(anyhow!("eframe failed")))?;
return Ok(());
}
struct MyApp {
command: Msg,
values: HashMap<String, String>,
}
impl Default for MyApp {
fn default() -> Self {
Self {
command: Msg::None,
values: HashMap::new(),
} }
next_time += Duration::from_millis(10); }
}
fn build_command_ui_value_number(ui: &mut Ui, name: &str, cmd: &mut dyn Reflect) {
let mut r = cmd.get_value().str();
ui.with_layout(
Layout::left_to_right(egui::Align::Min)
.with_main_wrap(true)
.with_main_justify(false),
|ui| {
ui.label(name);
ui.text_edit_singleline(&mut r);
cmd.set_value(ReflectValue::Str(r));
},
);
}
fn build_command_ui(ui: &mut Ui, name: &str, cmd: &mut dyn Reflect) {
// ui.separator();
match cmd.reflect_type() {
ReflectType::Value => match cmd.get_value() {
ReflectValue::None => {}
ReflectValue::U8(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::U16(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::U32(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::U64(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::I8(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::I16(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::I32(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::I64(_) => build_command_ui_value_number(ui, name, cmd),
ReflectValue::Vec(_vec) => {
ui.with_layout(Layout::top_down(egui::Align::Min), |ui| {
ui.with_layout(
Layout::left_to_right(egui::Align::Min).with_main_wrap(true),
|ui| {
ui.label(name);
if ui.button("+").clicked() {
cmd.vec_add();
}
if ui.button("-").clicked() {
cmd.vec_remove();
}
},
);
if let Some(v) = cmd.as_vec() {
ui.with_layout(
Layout::left_to_right(egui::Align::Min).with_main_wrap(true),
|ui| {
for (i, cmd) in v.into_iter().enumerate() {
build_command_ui(ui, &format!("[{i}]"), cmd);
}
},
);
}
});
}
ReflectValue::Str(_) => {}
ReflectValue::Bool(_) => {}
},
ReflectType::Enumeration => {
// variants
ui.with_layout(
Layout::left_to_right(egui::Align::Min)
.with_main_wrap(true)
.with_main_justify(false),
|ui| {
for (i, (name, _v)) in cmd.variants().into_iter().enumerate() {
if ui.button(name).clicked() {
cmd.convert_variant(i);
}
}
},
);
// values
if let Some((name, cmd)) = cmd.unwrap_variant() {
build_command_ui(ui, name, cmd);
}
}
ReflectType::Structure => {
ui.with_layout(
Layout::left_to_right(egui::Align::Min)
.with_main_wrap(true)
.with_main_justify(false),
|ui| {
for (name, cmd) in cmd.fields().into_iter() {
build_command_ui(ui, name, cmd);
}
},
);
}
}
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading(format!("Command: {:?}", self.command));
if ui.button("X").clicked() {
self.command = Msg::None;
}
build_command_ui(ui, "Msg", &mut self.command);
// if self
// .command_path
// .as_bytes()
// .iter()
// .filter(|x| **x == b'.')
// .count()
// >= 2
// {
// for item in &self.tree.get_add_path(&self.command_path).children {
// for c in &item.children {
// if c.is_last() {
// if !self.values.contains_key(&c.name) {
// self.values.insert(c.name.clone(), String::new());
// }
// let sref = self.values.get_mut(&c.name).unwrap();
// ui.horizontal(|ui| {
// ui.label(format!("{} : {}", item.name, c.name.clone()));
// ui.text_edit_singleline(sref);
// });
// }
// }
// }
// if ui.button("send").clicked() {
// info!("sending {}", self.command_path);
// }
// } else {
// for item in &self.tree.get_add_path(&self.command_path).children {
// if ui.button(item.name.clone()).clicked() {
// self.command_path = format!("{}.{}", self.command_path, item.name);
// }
// }
// }
});
} }
} }
File diff suppressed because one or more lines are too long
+1
View File
@@ -8,6 +8,7 @@ embassy-usb-logger = { git = "https://github.com/embassy-rs/embassy.git" }
rfe = { path = "../../rfe", default-features = false, features = ["rp2040"] } rfe = { path = "../../rfe", default-features = false, features = ["rp2040"] }
to = { path = "../../apps/to", default-features = false } to = { path = "../../apps/to", default-features = false }
hs = { path = "../../apps/hs", default-features = false, features = ["rp2040"] } hs = { path = "../../apps/hs", default-features = false, features = ["rp2040"] }
example = { path = "../../apps/example" }
anyhow.workspace = true anyhow.workspace = true
anyhow.default_features = false anyhow.default_features = false
embedded-alloc = "0.6.0" embedded-alloc = "0.6.0"
+14 -16
View File
@@ -15,10 +15,11 @@ mod app {
usb::{self, Driver}, usb::{self, Driver},
}; };
use embedded_hal::digital::v2::OutputPin; use embedded_hal::digital::v2::OutputPin;
use example::Example;
use fugit::Duration; use fugit::Duration;
use hs::{Hs, HsConfig, Rp2040Watchdog, StubSystemInfoGrabber}; use hs::{Hs, HsConfig, Rp2040Watchdog, StubSystemInfoGrabber};
use log::info; use log::info;
use msg::{ExampleHk, Instance, MsgKind, MsgPacket, TargetMsg, TlmSetItem, ToTlmSet}; use msg::{Instance, MsgKind, MsgPacket, TargetMsg, TlmSetItem, ToTlmSet};
use rfe::{connector::Connector, Rate, *}; use rfe::{connector::Connector, Rate, *};
use rp_pico::hal::{ use rp_pico::hal::{
clocks, clocks,
@@ -69,19 +70,13 @@ mod app {
self.counter += 1; self.counter += 1;
self.on = !self.on; self.on = !self.on;
if self.on { if self.on {
info!("led on!");
self.led_pin.set_high().ok(); self.led_pin.set_high().ok();
} else { } else {
info!("led off!");
self.led_pin.set_low().ok(); self.led_pin.set_low().ok();
} }
} }
fn hk(&mut self, rfe: &mut Rfe) { fn hk(&mut self, _rfe: &mut Rfe) {}
rfe.send(msg::Msg::ExampleHk(ExampleHk {
counter: self.counter,
}));
}
fn out_data(&mut self, _rfe: &mut Rfe) {} fn out_data(&mut self, _rfe: &mut Rfe) {}
@@ -108,7 +103,7 @@ mod app {
fn init(mut ctx: init::Context) -> (Shared, Local) { fn init(mut ctx: init::Context) -> (Shared, Local) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
// Configure the clocks, watchdog - The default is to generate a 125 MHz system clock // Configure the clocks, watchdog - The default is to generate a 125 MHz system clock
Mono::start(ctx.device.TIMER, &mut ctx.device.RESETS); // default rp2040 clock-rate is 125MHz
let mut watchdog = Watchdog::new(ctx.device.WATCHDOG); let mut watchdog = Watchdog::new(ctx.device.WATCHDOG);
let clocks = clocks::init_clocks_and_plls( let clocks = clocks::init_clocks_and_plls(
XOSC_CRYSTAL_FREQ, XOSC_CRYSTAL_FREQ,
@@ -121,6 +116,11 @@ mod app {
) )
.ok() .ok()
.unwrap(); .unwrap();
let time_driver = Rp2040TimeDriver::new(ctx.device.TIMER, &mut ctx.device.RESETS, &clocks);
Mono::start(
unsafe { rp_pico::pac::TIMER::steal() },
&mut ctx.device.RESETS,
); // default rp2040 clock-rate is 125MHz
{ {
const HEAP_SIZE: usize = 1024 * 16; const HEAP_SIZE: usize = 1024 * 16;
@@ -141,12 +141,6 @@ mod app {
.into_pull_type::<PullNone>() .into_pull_type::<PullNone>()
.into_push_pull_output(); .into_push_pull_output();
let time_driver = Rp2040TimeDriver::new(
unsafe { rp_pico::pac::TIMER::steal() },
&mut ctx.device.RESETS,
&clocks,
);
// Spawn heartbeat task // Spawn heartbeat task
blink_instance::spawn().ok(); blink_instance::spawn().ok();
usb_logger::spawn().ok(); usb_logger::spawn().ok();
@@ -199,7 +193,9 @@ mod app {
}, },
); );
let mut to = To::new(&mut log_connector, tlmsets); let mut to = To::new(&mut log_connector, tlmsets);
let mut example = Example::new();
let mut wd = Rp2040Watchdog::new(ctx.local.wd.take().unwrap()); let mut wd = Rp2040Watchdog::new(ctx.local.wd.take().unwrap());
let mut grabber = StubSystemInfoGrabber::new(); let mut grabber = StubSystemInfoGrabber::new();
let mut hs = Hs::new( let mut hs = Hs::new(
HsConfig { HsConfig {
@@ -208,16 +204,18 @@ mod app {
mem_checks: false, mem_checks: false,
temp_checks: false, temp_checks: false,
watchdog_enable: true, watchdog_enable: true,
watchdog_timeout: 10, watchdog_timeout: 3,
}, },
&mut grabber, &mut grabber,
Some(&mut wd), Some(&mut wd),
); );
let time_driver = ctx.local.time_driver.take().unwrap(); let time_driver = ctx.local.time_driver.take().unwrap();
let mut instance = RfeInstance::new(Instance::Example, &time_driver); let mut instance = RfeInstance::new(Instance::Example, &time_driver);
instance.add_app("blink_app", &mut blink_app).unwrap(); instance.add_app("blink_app", &mut blink_app).unwrap();
instance.add_app("to", &mut to).unwrap(); instance.add_app("to", &mut to).unwrap();
instance.add_app("hs", &mut hs).unwrap(); instance.add_app("hs", &mut hs).unwrap();
instance.add_app("example", &mut example).unwrap();
let mut next_time = Mono::now() + Duration::<u64, 1, 1000000>::from_ticks(10000); let mut next_time = Mono::now() + Duration::<u64, 1, 1000000>::from_ticks(10000);
+3 -2
View File
@@ -5,9 +5,9 @@ edition = "2021"
[features] [features]
default = [] default = []
std = ["dep:mio"] std = ["dep:mio", "dep:mio-serial"]
rp2040 = ["dep:rp2040-hal", "dep:rp2040-pac"] rp2040 = ["dep:rp2040-hal", "dep:rp2040-pac"]
to_csv = [] reflect = []
[dependencies] [dependencies]
bincode.workspace = true bincode.workspace = true
@@ -18,3 +18,4 @@ mio = { version = "1.0.2", features = ["net", "os-poll"], optional = true }
rp2040-hal = { workspace = true, optional = true } rp2040-hal = { workspace = true, optional = true }
rp2040-pac = { workspace = true, optional = true } rp2040-pac = { workspace = true, optional = true }
macros.path = "macros" macros.path = "macros"
mio-serial = { workspace = true, optional = true }
+168 -40
View File
@@ -31,6 +31,25 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
} }
}); });
let kind_to_default_arms = variants.iter().map(|variant| {
let variant_name = &variant.ident;
match &variant.fields {
Fields::Unit => {
quote! {
#kind_name::#variant_name => #name::#variant_name,
}
}
Fields::Unnamed(_) => {
quote! {
#kind_name::#variant_name => #name::#variant_name(Default::default()),
}
}
Fields::Named(_) => {
panic!("Named fields not supported by Kind");
}
}
});
let kind_arms = variants.iter().map(|variant| { let kind_arms = variants.iter().map(|variant| {
let variant_name = &variant.ident; let variant_name = &variant.ident;
match &variant.fields { match &variant.fields {
@@ -51,9 +70,10 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
}); });
let expanded = quote! { let expanded = quote! {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum #kind_name { pub enum #kind_name {
#[default]
#(#kind_enum_arms)* #(#kind_enum_arms)*
} }
@@ -63,6 +83,12 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
#(#kind_enum_vec_arms)* #(#kind_enum_vec_arms)*
] ]
} }
pub fn to_default(&self) -> #name {
match self {
#(#kind_to_default_arms)*
}
}
} }
impl #name { impl #name {
@@ -77,8 +103,9 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
TokenStream::from(expanded) TokenStream::from(expanded)
} }
#[proc_macro_derive(ToCsv)]
pub fn to_csv_derive(input: TokenStream) -> TokenStream { #[proc_macro_derive(Reflect)]
pub fn reflect_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
let name = input.ident; let name = input.ident;
@@ -88,82 +115,183 @@ pub fn to_csv_derive(input: TokenStream) -> TokenStream {
Data::Struct(data_struct) => { Data::Struct(data_struct) => {
let fields = data_struct.fields; let fields = data_struct.fields;
let arms = fields.iter().map(|field| { let field_arms = fields.iter().map(|field| {
let field_ident = field.clone().ident.unwrap(); let field_ident = field.clone().ident.unwrap();
let field_name = field_ident.to_string(); let field_name = field_ident.to_string();
quote! { { quote! { {
let mut field_csvs: alloc::vec::Vec<String> = (&self.#field_ident as &dyn ToCsv).to_csv(); fields.push((#field_name, &mut self.#field_ident as &mut dyn rfe::reflect::Reflect));
for entry in &mut field_csvs {
*entry = format!("{}.{}", #field_name, &entry);
}
values.extend(field_csvs);
} } } }
}); });
quote! { quote! {
impl ToCsv for #name { impl rfe::reflect::Reflect for #name {
fn to_csv(&self) -> alloc::vec::Vec<String> { fn reflect_type(&self) -> rfe::reflect::ReflectType {
extern crate alloc; rfe::reflect::ReflectType::Structure
use alloc::format; }
fn type_name(&self) -> &str {
#name_s
}
fn fields(&mut self) -> alloc::vec::Vec<(&str, &mut dyn rfe::reflect::Reflect)> {
let mut fields = alloc::vec::Vec::new();
#(#field_arms)*
fields
}
fn set_value(&mut self, value: rfe::reflect::ReflectValue) {
}
fn get_value(&self) -> rfe::reflect::ReflectValue {
rfe::reflect::ReflectValue::None
}
fn variants(&self) -> alloc::vec::Vec<(&'static str, alloc::boxed::Box<dyn rfe::reflect::Reflect>)> {
alloc::vec::Vec::new()
}
let mut values:alloc::vec::Vec<String> = alloc::vec::Vec::new(); fn convert_variant(&mut self, _i: usize) {}
#(#arms)*
for value in &mut values { fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn rfe::reflect::Reflect)> {
*value = format!("{}", value); None
} }
return values;
fn as_vec(&mut self) -> Option<alloc::vec::Vec<&mut dyn rfe::reflect::Reflect>> {
None
} }
} }
} }
} }
Data::Enum(data_enum) => { Data::Enum(data_enum) => {
let variants = data_enum.variants; let variants = data_enum.variants;
let arms = variants.iter().map(|variant| { let convert_arms = variants.iter().enumerate().map(|(i, variant)| {
let variant_name = &variant.ident;
match &variant.fields {
Fields::Unit => {
quote! {
if _i == #i {
*self = Self::#variant_name;
}
}
}
Fields::Unnamed(_) => {
quote! {
if _i == #i {
*self = Self::#variant_name(Default::default());
}
}
}
Fields::Named(_) => {
panic!("Named fields not supported by Reflect");
}
}
});
let unwrap_arms = variants.iter().enumerate().map(|(_i, variant)| {
let variant_name = &variant.ident; let variant_name = &variant.ident;
let variant_name_s = variant_name.to_string(); let variant_name_s = variant_name.to_string();
match &variant.fields { match &variant.fields {
Fields::Unit => { Fields::Unit => {
quote! { Self::#variant_name => values.push(format!(" = {}::{}", #name_s, #variant_name_s)), } quote! {
// quote! { Self::#variant_name => {}, } Self::#variant_name => None,
}
} }
Fields::Unnamed(_) => { Fields::Unnamed(_) => {
quote! {Self::#variant_name(l) => { quote! {
let mut field_csvs: alloc::vec::Vec<String> = (l as &dyn ToCsv).to_csv(); Self::#variant_name(v) => Some((#variant_name_s, v)),
for entry in &mut field_csvs { }
*entry = format!("{}.{}", #variant_name_s, &entry);
}
values.extend(field_csvs);
},}
} }
Fields::Named(_) => { Fields::Named(_) => {
panic!("Named fields not supported by ToCsv"); panic!("Named fields not supported by Reflect");
}
}
});
let variant_arms = variants.iter().map(|variant| {
let variant_name = &variant.ident;
let variant_name_s = variant_name.to_string();
match &variant.fields {
Fields::Unit => {
quote! {
{
let name: &'static str = #variant_name_s;
let value: alloc::boxed::Box<dyn rfe::reflect::Reflect> = alloc::boxed::Box::new(Self::#variant_name);
variants.push((name, value));
}
}
}
Fields::Unnamed(_) => {
quote! {
{
let name: &'static str = #variant_name_s;
let value: alloc::boxed::Box<dyn rfe::reflect::Reflect> = alloc::boxed::Box::new(Self::#variant_name(Default::default()));
variants.push((name, value));
}
}
}
Fields::Named(_) => {
panic!("Named fields not supported by Reflect");
} }
} }
}); });
quote! { quote! {
impl ToCsv for #name { impl rfe::reflect::Reflect for #name {
fn to_csv(&self) -> alloc::vec::Vec<String> { fn reflect_type(&self) -> rfe::reflect::ReflectType {
extern crate alloc; rfe::reflect::ReflectType::Enumeration
use alloc::format; }
let mut values: alloc::vec::Vec<String> = alloc::vec::Vec::new();
fn type_name(&self) -> &str {
#name_s
}
fn fields(&mut self) -> alloc::vec::Vec<(&str, &mut dyn rfe::reflect::Reflect)> {
alloc::vec::Vec::new()
}
fn set_value(&mut self, value: rfe::reflect::ReflectValue) {
}
fn get_value(&self) -> rfe::reflect::ReflectValue {
rfe::reflect::ReflectValue::None
}
fn variants(&self) -> alloc::vec::Vec<(&'static str, alloc::boxed::Box<dyn rfe::reflect::Reflect>)> {
let mut variants = alloc::vec::Vec::new();
#(#variant_arms)*
variants
}
fn convert_variant(&mut self, _i: usize) {
#(#convert_arms)*
}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn rfe::reflect::Reflect)> {
match self { match self {
#(#arms)* #(#unwrap_arms)*
} }
return values; }
fn as_vec(&mut self) -> Option<alloc::vec::Vec<&mut dyn rfe::reflect::Reflect>> {
None
} }
} }
} }
} }
Data::Union(_data_union) => { Data::Union(_data_union) => {
return syn::Error::new_spanned(name, "ToCsv not implemented for unions") return syn::Error::new_spanned(name, "Reflect not implemented for unions")
.to_compile_error() .to_compile_error()
.into(); .into();
} }
}; };
TokenStream::from(expanded) TokenStream::from(expanded)
} }
+4 -2
View File
@@ -10,9 +10,11 @@ pub mod msg;
mod rfe; mod rfe;
pub use rfe::*; pub use rfe::*;
#[cfg(feature = "to_csv")] #[cfg(feature = "reflect")]
pub mod to_csv; pub mod reflect;
pub use macros;
pub mod serial;
pub mod time; pub mod time;
pub mod utils; pub mod utils;
+10 -10
View File
@@ -1,17 +1,16 @@
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
use crate::utils::PerfData; use crate::utils::PerfData;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
extern crate alloc; extern crate alloc;
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use super::{TlmSetId, TlmSetItem}; use super::{TlmSetId, TlmSetItem};
use crate as rfe;
#[cfg(feature = "reflect")]
use crate::macros::Reflect;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct DsTlmSet { pub struct DsTlmSet {
pub items: Vec<TlmSetItem>, pub items: Vec<TlmSetItem>,
pub id: TlmSetId, pub id: TlmSetId,
@@ -20,23 +19,24 @@ pub struct DsTlmSet {
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct DsHk { pub struct DsHk {
pub perf: PerfData, pub perf: PerfData,
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct DsOutData { pub struct DsOutData {
pub counter: u32, pub counter: u32,
pub bytes_written: u32, pub bytes_written: u32,
pub bytes_written_this_cycle: u32, pub bytes_written_this_cycle: u32,
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum DsCmd { pub enum DsCmd {
#[default]
Noop, Noop,
Reset, Reset,
CloseAll, CloseAll,
+8 -8
View File
@@ -1,27 +1,27 @@
extern crate alloc; extern crate alloc;
#[cfg(feature = "to_csv")] use crate as rfe;
use crate::to_csv::ToCsv; #[cfg(feature = "reflect")]
use crate::macros::Reflect;
use crate::utils::PerfData; use crate::utils::PerfData;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct ExampleHk { pub struct ExampleHk {
pub perf: PerfData, pub perf: PerfData,
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct ExampleOutData { pub struct ExampleOutData {
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum ExampleCmd { pub enum ExampleCmd {
#[default]
Noop, Noop,
Reset, Reset,
} }
+9 -8
View File
@@ -1,14 +1,14 @@
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
use crate::utils::PerfData; use crate::utils::PerfData;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
extern crate alloc; extern crate alloc;
use crate as rfe;
#[cfg(feature = "reflect")]
use crate::macros::Reflect;
use alloc::vec::Vec; use alloc::vec::Vec;
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct HsHk { pub struct HsHk {
pub perf: PerfData, pub perf: PerfData,
pub counter: u32, pub counter: u32,
@@ -23,14 +23,15 @@ pub struct HsHk {
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct HsOutData { pub struct HsOutData {
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum HsCmd { pub enum HsCmd {
#[default]
Noop, Noop,
Reset, Reset,
WatchdogEnableManual(bool), WatchdogEnableManual(bool),
+20 -17
View File
@@ -14,14 +14,13 @@ pub use to::*;
mod ds; mod ds;
pub use ds::*; pub use ds::*;
use crate as rfe;
#[cfg(feature = "reflect")]
use crate::macros::Reflect;
use crate::time::Timestamp; use crate::time::Timestamp;
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
#[cfg(feature = "to_csv")]
use macros::ToCsv;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct TargetMsg { pub struct TargetMsg {
// instance is FROM for tlm, is TO for cmds // instance is FROM for tlm, is TO for cmds
pub instance: Instance, pub instance: Instance,
@@ -34,18 +33,21 @@ impl TargetMsg {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum Instance { pub enum Instance {
#[default]
None,
All, All,
Other, Other,
Example, Example,
Example2, Example2,
} }
#[derive(Debug, Clone, PartialEq, Kind, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Kind, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum Msg { pub enum Msg {
#[default]
None, None,
SubRequest, SubRequest,
SubList(SubList), SubList(SubList),
@@ -66,7 +68,7 @@ pub enum Msg {
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct MsgPacket { pub struct MsgPacket {
pub instance: Instance, pub instance: Instance,
pub msg: Msg, pub msg: Msg,
@@ -91,24 +93,25 @@ impl MsgPacket {
} }
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct SubList { pub struct SubList {
pub subs: Vec<TargetMsg>, pub subs: Vec<TargetMsg>,
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct ReinitAppCmd { pub struct ReinitAppCmd {
app_name: String, app_name: String,
} }
pub type TlmSetId = u16; pub type TlmSetId = u16;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct TlmSetItem { pub struct TlmSetItem {
pub target: TargetMsg, pub target: TargetMsg,
/// decimation 0 means sends every msg, decimation 1 means sends every other, etc
pub decimation: u16, pub decimation: u16,
pub counter: u16, pub counter: u16,
} }
+10 -10
View File
@@ -1,16 +1,15 @@
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
use crate::utils::PerfData; use crate::utils::PerfData;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
extern crate alloc; extern crate alloc;
use crate as rfe;
#[cfg(feature = "reflect")]
use crate::macros::Reflect;
use alloc::vec::Vec; use alloc::vec::Vec;
use super::{TlmSetId, TlmSetItem}; use super::{TlmSetId, TlmSetItem};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct ToTlmSet { pub struct ToTlmSet {
pub items: Vec<TlmSetItem>, pub items: Vec<TlmSetItem>,
pub id: TlmSetId, pub id: TlmSetId,
@@ -18,21 +17,22 @@ pub struct ToTlmSet {
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct ToHk { pub struct ToHk {
pub perf: PerfData, pub perf: PerfData,
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct ToOutData { pub struct ToOutData {
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum ToCmd { pub enum ToCmd {
#[default]
Noop, Noop,
Reset, Reset,
AddTlmSet(ToTlmSet), AddTlmSet(ToTlmSet),
+649
View File
@@ -0,0 +1,649 @@
extern crate alloc;
use core::mem::zeroed;
use std::string::ToString;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use hashbrown::HashMap;
pub trait Reflect: std::fmt::Debug {
fn reflect_type(&self) -> ReflectType;
fn type_name(&self) -> &str;
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)>;
fn set_value(&mut self, value: ReflectValue);
fn get_value(&self) -> ReflectValue;
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)>;
fn convert_variant(&mut self, i: usize);
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)>;
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>>;
fn vec_add(&mut self) {}
fn vec_remove(&mut self) {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReflectType {
Value,
Enumeration,
Structure,
}
pub enum ReflectValue {
None,
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
Vec(Vec<ReflectValue>),
Str(String),
Bool(bool),
}
impl ReflectValue {
pub fn signed(&self) -> i64 {
match self {
ReflectValue::None => 0,
ReflectValue::U8(v) => *v as i64,
ReflectValue::U16(v) => *v as i64,
ReflectValue::U32(v) => *v as i64,
ReflectValue::U64(v) => *v as i64,
ReflectValue::I8(v) => *v as i64,
ReflectValue::I16(v) => *v as i64,
ReflectValue::I32(v) => *v as i64,
ReflectValue::I64(v) => *v as i64,
ReflectValue::Vec(_) => 0,
ReflectValue::Str(s) => {
if let Ok(v) = s.parse() {
v
} else {
0
}
}
ReflectValue::Bool(b) => {
if *b {
1
} else {
0
}
}
}
}
pub fn unsigned(&self) -> u64 {
match self {
ReflectValue::None => 0,
ReflectValue::U8(v) => *v as u64,
ReflectValue::U16(v) => *v as u64,
ReflectValue::U32(v) => *v as u64,
ReflectValue::U64(v) => *v as u64,
ReflectValue::I8(v) => *v as u64,
ReflectValue::I16(v) => *v as u64,
ReflectValue::I32(v) => *v as u64,
ReflectValue::I64(v) => *v as u64,
ReflectValue::Vec(_) => 0,
ReflectValue::Str(s) => {
if let Ok(v) = s.parse() {
v
} else {
0
}
}
ReflectValue::Bool(b) => {
if *b {
1
} else {
0
}
}
}
}
pub fn str(self) -> String {
match self {
ReflectValue::Str(s) => s,
ReflectValue::None => "".to_string(),
ReflectValue::U8(v) => v.to_string(),
ReflectValue::U16(v) => v.to_string(),
ReflectValue::U32(v) => v.to_string(),
ReflectValue::U64(v) => v.to_string(),
ReflectValue::I8(v) => v.to_string(),
ReflectValue::I16(v) => v.to_string(),
ReflectValue::I32(v) => v.to_string(),
ReflectValue::I64(v) => v.to_string(),
ReflectValue::Vec(_v) => "".to_string(),
ReflectValue::Bool(v) => v.to_string(),
}
}
pub fn bool(&self) -> bool {
match self {
ReflectValue::None => false,
ReflectValue::U8(v) => *v == 0,
ReflectValue::U16(v) => *v == 0,
ReflectValue::U32(v) => *v == 0,
ReflectValue::U64(v) => *v == 0,
ReflectValue::I8(v) => *v == 0,
ReflectValue::I16(v) => *v == 0,
ReflectValue::I32(v) => *v == 0,
ReflectValue::I64(v) => *v == 0,
ReflectValue::Vec(_) => false,
ReflectValue::Str(_) => false,
ReflectValue::Bool(b) => *b,
}
}
pub fn vec(self) -> Vec<ReflectValue> {
if let ReflectValue::Vec(v) = self {
v
} else {
Vec::new()
}
}
}
pub fn path_set(reflect: &mut dyn Reflect, path: &str, value: ReflectValue) {
let mut next = reflect;
for p in path.split(".") {
let mut index = None;
for (i, f) in next.fields().iter().enumerate() {
if f.0 == p {
index = Some(i);
}
}
if let Some(i) = index {
next = next.fields().remove(i).1;
} else {
return;
}
}
next.set_value(value);
}
pub fn path_get<'a>(reflect: &'a mut dyn Reflect, path: &str) -> Option<&'a mut dyn Reflect> {
let mut next = reflect;
for p in path.split(".") {
let mut index = None;
for (i, f) in next.fields().iter().enumerate() {
if f.0 == p {
index = Some(i);
}
}
if let Some(i) = index {
next = next.fields().remove(i).1;
} else {
return None;
}
}
Some(next)
}
fn _flatten<'a>(reflect: &'a mut dyn Reflect) -> HashMap<String, &'a mut dyn Reflect> {
let mut list = HashMap::new();
match reflect.reflect_type() {
ReflectType::Value => match reflect.get_value() {
ReflectValue::Vec(_) => {
for (i, r) in reflect.as_vec().unwrap().into_iter().enumerate() {
let map = _flatten(r);
for (sn, v) in map {
list.insert(alloc::format!("[{i}].{}", sn), v);
}
}
}
_ => {
list.insert("".to_string(), reflect);
}
},
ReflectType::Enumeration => {
if let Some((name, r)) = reflect.unwrap_variant() {
let map = _flatten(r);
for (sn, v) in map {
list.insert(alloc::format!("{}.{}", name, sn), v);
}
}
}
ReflectType::Structure => {
for (name, r) in reflect.fields() {
let map = _flatten(r);
for (sn, v) in map {
list.insert(alloc::format!("{}.{}", name, sn), v);
}
}
}
}
list
}
pub fn flatten<'a>(reflect: &'a mut dyn Reflect) -> HashMap<String, &'a mut dyn Reflect> {
_flatten(reflect)
.into_iter()
.map(|(k, v)| (k[..k.len() - 1].to_string().replace(".[", "["), v))
.collect()
}
impl Reflect for u8 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"u8"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.unsigned() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::U8(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for u16 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"u16"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.unsigned() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::U16(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for u32 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"u32"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.unsigned() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::U32(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for u64 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"u64"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.unsigned() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::U64(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for i8 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"i8"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.signed() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::I8(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for i16 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"i16"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.signed() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::I16(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for i32 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"i32"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.signed() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::I32(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for i64 {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"i64"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.signed() as Self;
}
fn get_value(&self) -> ReflectValue {
ReflectValue::I64(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for String {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"str"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.str();
}
fn get_value(&self) -> ReflectValue {
ReflectValue::Str(self.to_string())
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl Reflect for bool {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"bool"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
*self = value.bool();
}
fn get_value(&self) -> ReflectValue {
ReflectValue::Bool(*self)
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec(&mut self) -> Option<Vec<&mut dyn Reflect>> {
None
}
}
impl<T: Reflect + Default> Reflect for Vec<T> {
fn reflect_type(&self) -> ReflectType {
ReflectType::Value
}
fn type_name(&self) -> &str {
"vec[]"
}
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
Vec::new()
}
fn set_value(&mut self, value: ReflectValue) {
if let ReflectValue::Vec(v) = value {
*self = v
.into_iter()
.map(|x| {
let mut t: T = unsafe { zeroed() };
t.set_value(x);
t
})
.collect();
}
}
fn get_value(&self) -> ReflectValue {
ReflectValue::Vec(self.iter().map(|x| x.get_value()).collect())
}
fn variants(&self) -> Vec<(&'static str, Box<dyn Reflect>)> {
Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn Reflect)> {
None
}
fn as_vec<'a>(&'a mut self) -> Option<Vec<&'a mut dyn Reflect>> {
Some(
self.iter_mut()
.map(|x| {
let v: &mut dyn Reflect = x;
v
})
.collect(),
)
}
fn vec_add(&mut self) {
self.push(Default::default());
}
fn vec_remove(&mut self) {
if self.len() > 0 {
self.remove(self.len() - 1);
}
}
}
+55
View File
@@ -0,0 +1,55 @@
use anyhow::Result;
pub trait SerialPort {
fn open(&mut self) -> Result<()>;
fn write(&mut self, bytes: &[u8]) -> Result<usize>;
fn read(&mut self, bytes: &mut [u8]) -> Result<usize>;
}
#[cfg(feature = "std")]
mod serial_std {
use std::io::{Read, Write};
use anyhow::anyhow;
use mio_serial::{SerialPortBuilder, SerialPortBuilderExt, SerialStream};
pub struct StdSerialPort {
pub config: SerialPortBuilder,
serial: Option<SerialStream>,
}
impl StdSerialPort {
pub fn new(config: SerialPortBuilder) -> Self {
Self {
config,
serial: None,
}
}
}
impl super::SerialPort for StdSerialPort {
fn open(&mut self) -> anyhow::Result<()> {
self.serial = None;
self.serial = Some(self.config.clone().open_native_async()?);
return Ok(());
}
fn write(&mut self, bytes: &[u8]) -> anyhow::Result<usize> {
Ok(self
.serial
.as_mut()
.ok_or(anyhow!("port not open"))?
.write(bytes)?)
}
fn read(&mut self, bytes: &mut [u8]) -> anyhow::Result<usize> {
Ok(self
.serial
.as_mut()
.ok_or(anyhow!("port not open"))?
.read(bytes)?)
}
}
}
#[cfg(feature = "std")]
pub use serial_std::*;
-151
View File
@@ -1,151 +0,0 @@
extern crate alloc;
use alloc::format;
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
pub trait ToCsv {
fn to_csv(&self) -> Vec<String>;
}
pub trait ToCsvClean {
fn to_csv_clean(&self) -> Vec<String>;
}
impl ToCsv for u8 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for i8 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for u16 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for i16 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for u32 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for i32 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for u64 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for i64 {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for &str {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for String {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl ToCsv for bool {
fn to_csv(&self) -> Vec<String> {
vec![format!(" = {}", self)]
}
}
impl<T: ToCsv> ToCsv for Vec<T> {
fn to_csv(&self) -> Vec<String> {
self.iter()
.enumerate()
.map(|(i, x)| {
x.to_csv()
.iter()
.map(|a| format!("[{}].{}", i, a))
.collect::<Vec<String>>()
})
.flatten()
.collect()
}
}
impl<T: ToCsv, const N: usize> ToCsv for [T; N] {
fn to_csv(&self) -> Vec<String> {
self.iter()
.enumerate()
.map(|(i, x)| {
x.to_csv()
.iter()
.map(|a| format!("[{}].{}", i, a))
.collect::<Vec<String>>()
})
.flatten()
.collect()
}
}
impl<T1: ToCsv, T2: ToCsv> ToCsv for (T1, T2) {
fn to_csv(&self) -> Vec<String> {
let mut csvs = Vec::new();
csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
csvs
}
}
impl<T1: ToCsv, T2: ToCsv, T3: ToCsv> ToCsv for (T1, T2, T3) {
fn to_csv(&self) -> Vec<String> {
let mut csvs = Vec::new();
csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
csvs.extend(self.2.to_csv().iter().map(|x| format!("[2].{}", x)));
csvs
}
}
impl<T1: ToCsv, T2: ToCsv, T3: ToCsv, T4: ToCsv> ToCsv for (T1, T2, T3, T4) {
fn to_csv(&self) -> Vec<String> {
let mut csvs = Vec::new();
csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
csvs.extend(self.2.to_csv().iter().map(|x| format!("[2].{}", x)));
csvs.extend(self.3.to_csv().iter().map(|x| format!("[3].{}", x)));
csvs
}
}
impl<T: ToCsv> ToCsvClean for T {
fn to_csv_clean(&self) -> Vec<String> {
self.to_csv().iter().map(|x| to_csv_clean(x)).collect()
}
}
fn to_csv_clean(s: &String) -> String {
let s = s.replace(".[", "[");
let s = s.replace(". =", " =");
s
}
+6 -5
View File
@@ -3,13 +3,14 @@ use crate::Rfe;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
extern crate alloc; extern crate alloc;
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv; use crate as rfe;
#[cfg(feature = "to_csv")] #[cfg(feature = "reflect")]
use macros::ToCsv; use crate::macros::Reflect;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))] #[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct PerfData { pub struct PerfData {
enter_time: Timestamp, enter_time: Timestamp,
elapsed: u32, elapsed: u32,
+1 -1
View File
@@ -11,5 +11,5 @@ path = "src/decom.rs"
anyhow.workspace = true anyhow.workspace = true
log.workspace = true log.workspace = true
simple_logger.workspace = true simple_logger.workspace = true
rfe = { path = "../../rfe", features = ["to_csv"] } rfe = { path = "../../rfe", features = ["reflect"] }
bincode = { workspace = true, features = ["std"] } bincode = { workspace = true, features = ["std"] }
-1
View File
@@ -12,7 +12,6 @@ use std::{
use anyhow::Result; use anyhow::Result;
use bincode::decode_from_std_read; use bincode::decode_from_std_read;
use log::*; use log::*;
use rfe::ToCsvClean;
use rfe::{msg::MsgPacket, BINCODE_CONFIG}; use rfe::{msg::MsgPacket, BINCODE_CONFIG};
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;