changed decom to output json

This commit is contained in:
2025-04-07 22:32:22 -05:00
parent bfe3333d65
commit d7d8c0789a
21 changed files with 1165 additions and 951 deletions
+4
View File
@@ -9,6 +9,9 @@ members = [
"builds/ground", "builds/ground",
"builds/rp_pico_example", "builds/rp_pico_example",
"rfe", "rfe",
"rfe/macros",
"rfe/reflect",
"rfe/reflect/reflect_macros",
"tools/decom", "tools/decom",
] ]
resolver = "2" resolver = "2"
@@ -25,3 +28,4 @@ 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" mio-serial = "=5.0.5"
reflect = { path = "rfe/reflect" }
+177
View File
@@ -0,0 +1,177 @@
# Rust Flight Executive (RFE)
RFE is a framework for building real-time embedded applications in Rust, inspired by concepts from NASA's Core Flight Executive (cFE). Rather than being a direct port of cFE to Rust, RFE is designed as an alternative that embraces Rust's idioms and strengths. Unlike cFE which primarily targets computer systems, RFE extends support to microcontrollers and other resource-constrained embedded devices. It provides a message-passing architecture for inter-application communication, time management, and scheduling at different rates. I/O operations are handled either by the standard library (when the `std` feature is enabled) or by board support packages like `rp2040-hal` for embedded platforms. These board support packages can be used generically through the traits defined in the `embedded-hal` crate, allowing for portable code across different embedded platforms.
## Overview
RFE is a framework that enables the development of modular, reusable flight software applications in Rust. While it shares some architectural concepts with NASA's cFE, RFE makes different design choices that are more ergonomic and better aligned with Rust's safety features, performance characteristics, and modern development ecosystem. By supporting both standard computers and microcontrollers, RFE offers greater flexibility for embedded systems development across a wide range of hardware platforms.
## Features
- **Message-passing architecture** for inter-application communication
- **Time management** for both system and monotonic time
- **Scheduling of applications** at different rates (1Hz to 100Hz)
- **Platform abstraction** through feature flags:
- `std`: Standard library support (Unix, Windows)
- `rp2040`: Raspberry Pi Pico support
- More platform abstractions planned for future releases
- Support for custom platforms by implementing a few simple traits
- **Runtime reflection**:
- `reflect`: Runtime type information that can be used for dynamic command generation and telemetry processing
- **Connectors**: A trait-based system for communication between instances, with built-in implementations (TCP, UDP, Memory) and support for custom user-defined connectors
- **Core applications**:
- Data Storage (DS): For telemetry storage
- Health & Safety (HS): For system monitoring
- Telemetry Output (TO): For telemetry management
- Example app: Demonstrating application development
## Architecture
RFE follows a modular architecture where applications communicate through a message bus. The core components include:
- **RfeInstance**: The main framework instance that manages applications and scheduling. An instance is intended as a runner for apps - multiple apps can be added to a single instance, but thread/task priority is given to each instance rather than to individual apps. For each app to have its own task priority, you will need a separate instance for each app.
- **App trait**: Interface that all applications must implement
- **Rfe**: Interface for applications to interact with the framework
- **Connectors**: A trait-based interface for communication between different RFE instances, allowing users to implement custom message transport mechanisms. Instances can communicate with each other through these connectors.
## Getting Started
### Prerequisites
- Rust toolchain (latest stable recommended)
- For RP2040 development: `thumbv6m-none-eabi` target
### Building
```bash
# For standard desktop build
cargo build --package example_build
# For Raspberry Pi Pico
cargo build --package rp_pico_example --target thumbv6m-none-eabi
```
### Creating an Application
Applications in RFE must implement the `App` trait:
```rust
use rfe::*;
use anyhow::Result;
struct MyApp;
impl App for MyApp {
fn init(&mut self, rfe: &mut Rfe) -> Result<()> {
// Initialize the application
// Set up message subscriptions
rfe.subscribe(TargetMsg::new(rfe.get_instance(), MsgKind::YourMsgKind));
Ok(())
}
fn run(&mut self, rfe: &mut Rfe) {
// Run the application logic
// Process received messages
while let Some(msg) = rfe.recv() {
// Handle message
}
}
fn hk(&mut self, rfe: &mut Rfe) {
// Generate housekeeping data
rfe.send(Msg::YourHkMsg(self.your_hk_data.clone()));
}
fn out_data(&mut self, rfe: &mut Rfe) {
// Generate output data
rfe.send(Msg::YourOutDataMsg(self.your_out_data.clone()));
}
fn get_app_rate(&self) -> Rate {
// Set the intended rate at which your app runs
Rate::Hz10 // Run at 10Hz
}
}
```
### Running an RFE Instance
```rust
use rfe::*;
use rfe::connector::MemConnector;
use std::thread;
use std::sync::Arc;
// Create a shared memory connector for inter-instance communication
let (connector1, connector2) = Arc::new(MemConnector::new());
// First instance (you can set the priority of the thread you run the instance in)
thread::spawn(move || {
// Create a time driver for the first instance
let time_driver = StdTimeDriver::new();
// Create the first RFE instance
let mut instance1 = RfeInstance::new(Instance::Main, &time_driver);
// Add the memory connector to the instance
instance1.add_connector(connector1);
// Add applications to the first instance
let mut my_app1 = MyApp::new();
instance1.add_app("my_app1", &mut my_app1).unwrap();
// Run the first instance
instance1.start();
});
// Second instance
let time_driver2 = StdTimeDriver::new();
let mut instance2 = RfeInstance::new(Instance::Secondary, &time_driver2);
// Add the memory connector to the second instance
instance2.add_connector(connector_clone);
// Add applications to the second instance
let mut my_app2 = AnotherApp::new();
instance2.add_app("my_app2", &mut my_app2).unwrap();
// Run the second instance
instance2.start();
```
In this example:
- Two RFE instances are created, each with its own application
- The first instance runs in a separate thread. You can set the priority of this thread
- The second instance runs in the main thread
- A shared `MemConnector` allows the instances to communicate with each other
- Each app can send messages that will be routed to the appropriate instance
## Project Structure
- `rfe/`: Core framework implementation
- `apps/`: Application implementations
- `ds/`: Data Storage application
- `hs/`: Health & Safety application
- `to/`: Telemetry Output application
- `example/`: Example application
- `builds/`: Example builds for different platforms
- `example_build/`: Standard desktop build
- `rp_pico_example/`: Raspberry Pi Pico build
- `ground/`: Ground system with GUI
- `tools/`: Development tools
- `decom/`: Telemetry decommutation tool
## Platform Support
RFE supports multiple platforms through feature flags:
- **Standard Desktop** (`std` feature): Unix, Windows
- **Raspberry Pi Pico** (`rp2040` feature): Embedded ARM Cortex-M0+
- Users can add support for any platform by implementing just a few key traits (primarily the `TimeDriver` trait)
- Board support packages utilize the `embedded-hal` traits for generic, portable hardware abstraction
- Platform-specific functionality can be easily integrated through Rust's trait system
- Additional platform support is planned for future releases
The `reflect` feature can be enabled on any platform to provide runtime type information.
+11 -4
View File
@@ -89,14 +89,16 @@ mod watchdog_rp2040 {
pub struct Rp2040Watchdog { pub struct Rp2040Watchdog {
wd: Watchdog, wd: Watchdog,
time: u32, timeout: u32,
enabled: bool,
} }
impl Rp2040Watchdog { impl Rp2040Watchdog {
pub fn new(wd: Watchdog) -> Self { pub fn new(wd: Watchdog) -> Self {
Self { Self {
wd, wd,
time: 3 * 1000000, timeout: 3 * 1000000,
enabled: false,
} }
} }
} }
@@ -105,16 +107,21 @@ mod watchdog_rp2040 {
fn enable(&mut self) { fn enable(&mut self) {
self.wd self.wd
.start(rp2040_hal::fugit::Duration::<u32, 1, 1000000>::from_ticks( .start(rp2040_hal::fugit::Duration::<u32, 1, 1000000>::from_ticks(
self.time, self.timeout,
)); ));
self.enabled = true;
} }
fn disable(&mut self) { fn disable(&mut self) {
self.wd.disable(); self.wd.disable();
self.enabled = false;
} }
fn set_timeout(&mut self, time: i32) { fn set_timeout(&mut self, time: i32) {
self.time = time as u32 * 1000000; self.timeout = time as u32 * 1000000;
if self.enabled {
self.enable();
}
} }
fn feed(&mut self) { fn feed(&mut self) {
+2 -2
View File
@@ -12,8 +12,8 @@ use connector::{Connector, UdpConnector};
use egui::{Layout, Ui}; use egui::{Layout, Ui};
use log::*; use log::*;
use msg::Msg; use msg::Msg;
use reflect::*;
use rfe::macros::Reflect; use rfe::reflect::*;
use rfe::*; use rfe::*;
extern crate alloc; extern crate alloc;
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;
+6 -1
View File
@@ -7,7 +7,8 @@ edition = "2021"
default = [] default = []
std = ["dep:mio", "dep:mio-serial"] std = ["dep:mio", "dep:mio-serial"]
rp2040 = ["dep:rp2040-hal", "dep:rp2040-pac"] rp2040 = ["dep:rp2040-hal", "dep:rp2040-pac"]
reflect = [] reflect = ["dep:reflect"]
serde = ["dep:serde"]
[dependencies] [dependencies]
bincode.workspace = true bincode.workspace = true
@@ -19,3 +20,7 @@ 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 } mio-serial = { workspace = true, optional = true }
serde = { version = "1.0.219", default-features = false, features = [
"derive",
], optional = true }
reflect = { workspace = true, optional = true }
+13 -188
View File
@@ -71,7 +71,8 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
let expanded = quote! { let expanded = quote! {
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[cfg_attr(feature = "reflect", derive(reflect::Reflect))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum #kind_name { pub enum #kind_name {
#[default] #[default]
#(#kind_enum_arms)* #(#kind_enum_arms)*
@@ -103,195 +104,19 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
TokenStream::from(expanded) TokenStream::from(expanded)
} }
#[proc_macro_attribute]
#[proc_macro_derive(Reflect)] pub fn msg(_attrs: TokenStream, input: TokenStream) -> TokenStream {
pub fn reflect_derive(input: TokenStream) -> TokenStream { // Parse the input tokens into a syntax tree
let input = parse_macro_input!(input as DeriveInput); let input = parse_macro_input!(input as DeriveInput);
let name = input.ident; // Create a new version of the input with the additional derives
let name_s = name.to_string(); let output = quote! {
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
let expanded = match input.data { #[cfg_attr(feature = "reflect", derive(reflect::Reflect))]
Data::Struct(data_struct) => { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
let fields = data_struct.fields; #input
let field_arms = fields.iter().map(|field| {
let field_ident = field.clone().ident.unwrap();
let field_name = field_ident.to_string();
quote! { {
fields.push((#field_name, &mut self.#field_ident as &mut dyn rfe::reflect::Reflect));
} }
});
quote! {
impl rfe::reflect::Reflect for #name {
fn reflect_type(&self) -> rfe::reflect::ReflectType {
rfe::reflect::ReflectType::Structure
}
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()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn rfe::reflect::Reflect)> {
None
}
fn as_vec(&mut self) -> Option<alloc::vec::Vec<&mut dyn rfe::reflect::Reflect>> {
None
}
}
}
}
Data::Enum(data_enum) => {
let variants = data_enum.variants;
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_s = variant_name.to_string();
match &variant.fields {
Fields::Unit => {
quote! {
Self::#variant_name => None,
}
}
Fields::Unnamed(_) => {
quote! {
Self::#variant_name(v) => Some((#variant_name_s, v)),
}
}
Fields::Named(_) => {
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! {
impl rfe::reflect::Reflect for #name {
fn reflect_type(&self) -> rfe::reflect::ReflectType {
rfe::reflect::ReflectType::Enumeration
}
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 {
#(#unwrap_arms)*
}
}
fn as_vec(&mut self) -> Option<alloc::vec::Vec<&mut dyn rfe::reflect::Reflect>> {
None
}
}
}
}
Data::Union(_data_union) => {
return syn::Error::new_spanned(name, "Reflect not implemented for unions")
.to_compile_error()
.into();
}
}; };
TokenStream::from(expanded) // Return the modified token stream
output.into()
} }
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "reflect"
version = "0.1.0"
edition = "2024"
[lib]
path = "src/reflect.rs"
name = "reflect"
[dependencies]
hashbrown.workspace = true
reflect_macros.path = "reflect_macros"
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "reflect_macros"
version = "0.1.0"
edition = "2024"
[lib]
path = "src/reflect_macros.rs"
proc-macro = true
[dependencies]
proc-macro2 = "1.0.89"
quote = "1.0.37"
syn = { version = "2.0.87", features = ["full"] }
@@ -0,0 +1,196 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::Fields;
use syn::{parse_macro_input, Data, DeriveInput};
#[proc_macro_derive(Reflect)]
pub fn reflect_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
let name_s = name.to_string();
let expanded = match input.data {
Data::Struct(data_struct) => {
let fields = data_struct.fields;
let field_arms = fields.iter().map(|field| {
let field_ident = field.clone().ident.unwrap();
let field_name = field_ident.to_string();
quote! { {
fields.push((#field_name, &mut self.#field_ident as &mut dyn reflect::Reflect));
} }
});
quote! {
impl reflect::Reflect for #name {
fn reflect_type(&self) -> reflect::ReflectType {
reflect::ReflectType::Structure
}
fn type_name(&self) -> &str {
#name_s
}
fn fields(&mut self) -> alloc::vec::Vec<(&str, &mut dyn reflect::Reflect)> {
let mut fields = alloc::vec::Vec::new();
#(#field_arms)*
fields
}
fn set_value(&mut self, value: reflect::ReflectValue) {
}
fn get_value(&self) -> reflect::ReflectValue {
reflect::ReflectValue::None
}
fn variants(&self) -> alloc::vec::Vec<(&'static str, alloc::boxed::Box<dyn reflect::Reflect>)> {
alloc::vec::Vec::new()
}
fn convert_variant(&mut self, _i: usize) {}
fn unwrap_variant(&mut self) -> Option<(&str, &mut dyn reflect::Reflect)> {
None
}
fn as_vec(&mut self) -> Option<alloc::vec::Vec<&mut dyn reflect::Reflect>> {
None
}
}
}
}
Data::Enum(data_enum) => {
let variants = data_enum.variants;
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_s = variant_name.to_string();
match &variant.fields {
Fields::Unit => {
quote! {
Self::#variant_name => None,
}
}
Fields::Unnamed(_) => {
quote! {
Self::#variant_name(v) => Some((#variant_name_s, v)),
}
}
Fields::Named(_) => {
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 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 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! {
impl reflect::Reflect for #name {
fn reflect_type(&self) -> reflect::ReflectType {
reflect::ReflectType::Enumeration
}
fn type_name(&self) -> &str {
#name_s
}
fn fields(&mut self) -> alloc::vec::Vec<(&str, &mut dyn reflect::Reflect)> {
alloc::vec::Vec::new()
}
fn set_value(&mut self, value: reflect::ReflectValue) {
}
fn get_value(&self) -> reflect::ReflectValue {
reflect::ReflectValue::None
}
fn variants(&self) -> alloc::vec::Vec<(&'static str, alloc::boxed::Box<dyn 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 reflect::Reflect)> {
match self {
#(#unwrap_arms)*
}
}
fn as_vec(&mut self) -> Option<alloc::vec::Vec<&mut dyn reflect::Reflect>> {
None
}
}
}
}
Data::Union(_data_union) => {
return syn::Error::new_spanned(name, "Reflect not implemented for unions")
.to_compile_error()
.into();
}
};
TokenStream::from(expanded)
}
+650
View File
@@ -0,0 +1,650 @@
extern crate alloc;
use core::mem::zeroed;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use hashbrown::HashMap;
pub use reflect_macros::Reflect;
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);
}
}
}
+1 -1
View File
@@ -65,7 +65,7 @@ pub use rfe::*;
/// Reflection module for runtime type information /// Reflection module for runtime type information
#[cfg(feature = "reflect")] #[cfg(feature = "reflect")]
pub mod reflect; pub use reflect;
/// Macros for RFE /// Macros for RFE
pub use macros; pub use macros;
+8 -11
View File
@@ -3,14 +3,12 @@ use bincode::{Decode, Encode};
extern crate alloc; extern crate alloc;
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use macros::msg;
use super::{TlmSetId, TlmSetItem}; use super::{TlmSetId, TlmSetItem};
use crate as rfe;
#[cfg(feature = "reflect")]
use crate::macros::Reflect;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Eq, Hash)]
pub struct DsTlmSet { pub struct DsTlmSet {
pub items: Vec<TlmSetItem>, pub items: Vec<TlmSetItem>,
pub id: TlmSetId, pub id: TlmSetId,
@@ -18,23 +16,22 @@ pub struct DsTlmSet {
pub path: String, pub path: String,
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
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)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
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, Default, Clone, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum DsCmd { pub enum DsCmd {
#[default] #[default]
Noop, Noop,
+7 -9
View File
@@ -1,25 +1,23 @@
extern crate alloc; extern crate alloc;
use crate as rfe;
#[cfg(feature = "reflect")]
use crate::macros::Reflect;
use crate::utils::PerfData; use crate::utils::PerfData;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
use macros::msg;
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
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)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
pub struct ExampleOutData { pub struct ExampleOutData {
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
pub enum ExampleCmd { pub enum ExampleCmd {
#[default] #[default]
Noop, Noop,
+6 -9
View File
@@ -1,14 +1,11 @@
use crate::utils::PerfData; use crate::utils::PerfData;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
use macros::msg;
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)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct HsHk { pub struct HsHk {
pub perf: PerfData, pub perf: PerfData,
pub counter: u32, pub counter: u32,
@@ -22,14 +19,14 @@ pub struct HsHk {
pub fs_usage_enabled: bool, pub fs_usage_enabled: bool,
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
pub struct HsOutData { pub struct HsOutData {
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
pub enum HsCmd { pub enum HsCmd {
#[default] #[default]
Noop, Noop,
+12 -18
View File
@@ -3,7 +3,7 @@ extern crate alloc;
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
use macros::Kind; use macros::{msg, Kind};
mod example; mod example;
pub use example::*; pub use example::*;
@@ -14,13 +14,10 @@ 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;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq, Hash)]
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,
@@ -33,8 +30,8 @@ impl TargetMsg {
} }
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq, Hash)]
pub enum Instance { pub enum Instance {
#[default] #[default]
None, None,
@@ -44,8 +41,8 @@ pub enum Instance {
Example2, Example2,
} }
#[derive(Debug, Default, Clone, PartialEq, Kind, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Kind)]
pub enum Msg { pub enum Msg {
#[default] #[default]
None, None,
@@ -67,8 +64,7 @@ pub enum Msg {
ToCmd(ToCmd), ToCmd(ToCmd),
} }
#[derive(Debug, Clone, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct MsgPacket { pub struct MsgPacket {
pub instance: Instance, pub instance: Instance,
pub msg: Msg, pub msg: Msg,
@@ -93,22 +89,20 @@ impl MsgPacket {
} }
} }
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct SubList { pub struct SubList {
pub subs: Vec<TargetMsg>, pub subs: Vec<TargetMsg>,
} }
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)] #[msg]
#[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, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq, Hash)]
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 /// decimation 0 means sends every msg, decimation 1 means sends every other, etc
+9 -11
View File
@@ -1,36 +1,34 @@
use crate::utils::PerfData; use crate::utils::PerfData;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
use macros::msg;
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, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Eq, Hash)]
pub struct ToTlmSet { pub struct ToTlmSet {
pub items: Vec<TlmSetItem>, pub items: Vec<TlmSetItem>,
pub id: TlmSetId, pub id: TlmSetId,
pub enabled: bool, pub enabled: bool,
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
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)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Copy, Eq)]
pub struct ToOutData { pub struct ToOutData {
pub counter: u32, pub counter: u32,
} }
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)] #[msg]
#[cfg_attr(feature = "reflect", derive(Reflect))] #[derive(Eq)]
pub enum ToCmd { pub enum ToCmd {
#[default] #[default]
Noop, Noop,
-649
View File
@@ -1,649 +0,0 @@
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);
}
}
}
+9 -9
View File
@@ -415,17 +415,17 @@ impl<'a> RfeInstance<'a> {
// Run applications and collect messages // Run applications and collect messages
for app in self.app_list.values_mut() { for app in self.app_list.values_mut() {
// Check if the application should run at this tick // Check if the application should run at this tick
if self.should_run_at_rate(app.app_rate) { if Self::should_run_at_rate(self.sch_counter, app.app_rate) {
app.app.run(&mut app.rfe); app.app.run(&mut app.rfe);
} }
// Check if housekeeping should run at this tick // Check if housekeeping should run at this tick
if self.should_run_at_rate(app.hk_rate) { if Self::should_run_at_rate(self.sch_counter, app.hk_rate) {
app.app.hk(&mut app.rfe); app.app.hk(&mut app.rfe);
} }
// Check if output data should run at this tick // Check if output data should run at this tick
if self.should_run_at_rate(app.out_data_rate) { if Self::should_run_at_rate(self.sch_counter, app.out_data_rate) {
app.app.out_data(&mut app.rfe); app.app.out_data(&mut app.rfe);
} }
@@ -568,14 +568,14 @@ impl<'a> RfeInstance<'a> {
/// # Returns /// # Returns
/// * `true` - If the task should run at this tick /// * `true` - If the task should run at this tick
/// * `false` - If the task should not run at this tick /// * `false` - If the task should not run at this tick
fn should_run_at_rate(&self, rate: Rate) -> bool { fn should_run_at_rate(sch_counter: u64, rate: Rate) -> bool {
match rate { match rate {
Rate::Hz100 => true, Rate::Hz100 => true,
Rate::Hz50 => self.sch_counter % 2 == 0, Rate::Hz50 => sch_counter % 2 == 0,
Rate::Hz20 => self.sch_counter % 5 == 0, Rate::Hz20 => sch_counter % 5 == 0,
Rate::Hz10 => self.sch_counter % 10 == 0, Rate::Hz10 => sch_counter % 10 == 0,
Rate::Hz5 => self.sch_counter % 20 == 0, Rate::Hz5 => sch_counter % 20 == 0,
Rate::Hz1 => self.sch_counter % 100 == 0, Rate::Hz1 => sch_counter % 100 == 0,
} }
} }
+4 -8
View File
@@ -1,16 +1,12 @@
use crate::time::Timestamp;
use crate::Rfe; use crate::Rfe;
use crate::time::Timestamp;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
use macros::msg;
extern crate alloc; extern crate alloc;
use crate as rfe; #[msg]
#[cfg(feature = "reflect")] #[derive(Copy, Eq, Hash)]
use crate::macros::Reflect;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "reflect", derive(Reflect))]
pub struct PerfData { pub struct PerfData {
enter_time: Timestamp, enter_time: Timestamp,
elapsed: u32, elapsed: u32,
+3 -1
View File
@@ -11,5 +11,7 @@ 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 = ["reflect"] } rfe = { path = "../../rfe", features = ["serde"] }
bincode = { workspace = true, features = ["std"] } bincode = { workspace = true, features = ["std"] }
serde_json = "1.0.140"
clap = { version = "4.5.35", features = ["derive"] }
+20 -29
View File
@@ -1,7 +1,6 @@
#![feature(bufreader_peek)] #![feature(bufreader_peek)]
use std::{ use std::{
collections::HashMap, collections::HashMap,
env::args,
fs::{read_dir, OpenOptions}, fs::{read_dir, OpenOptions},
io::{BufReader, Write}, io::{BufReader, Write},
path::PathBuf, path::PathBuf,
@@ -15,6 +14,17 @@ use log::*;
use rfe::{msg::MsgPacket, BINCODE_CONFIG}; use rfe::{msg::MsgPacket, BINCODE_CONFIG};
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;
use clap::Parser;
// Decom DS recorded data files
#[derive(Parser, Debug)]
struct CliArgs {
/// The path to the file or folder containing the DS data
path: String,
/// The path to the folder to output the decommed data
out_dir: String,
}
fn decom_file(file_path: String, out_dir: String) -> Result<()> { fn decom_file(file_path: String, out_dir: String) -> Result<()> {
info!("decomming {file_path}"); info!("decomming {file_path}");
let f = OpenOptions::new().read(true).open(file_path)?; let f = OpenOptions::new().read(true).open(file_path)?;
@@ -29,40 +39,25 @@ fn decom_file(file_path: String, out_dir: String) -> Result<()> {
}; };
if !files.contains_key(&msg.msg.kind()) { if !files.contains_key(&msg.msg.kind()) {
let path = PathBuf::from_str(&out_dir)? let path = PathBuf::from_str(&out_dir)?
.join(format!("{:?}.csv", msg.msg.kind()).to_lowercase()); .join(format!("{:?}.json", msg.msg.kind()).to_lowercase());
let exists = path.exists(); let w = OpenOptions::new()
let mut w = OpenOptions::new()
.write(true) .write(true)
.create(true) .create(true)
.append(true) .append(true)
.open(path)?; .open(path)?;
if !exists {
let values = msg.to_csv_clean();
let mut line = values
.iter()
.map(|x| x.split_once(" = ").expect("unexpected csv data").0)
.collect::<Vec<&str>>()
.join(",");
line += "\n";
w.write(line.as_bytes())?;
}
files.insert(msg.msg.kind(), w); files.insert(msg.msg.kind(), w);
} }
if let Some(w) = files.get_mut(&msg.msg.kind()) { if let Some(w) = files.get_mut(&msg.msg.kind()) {
let values = msg.to_csv_clean(); let values = serde_json::to_string(&msg)?;
let mut line = values
.iter() w.write(values.as_bytes())?;
.map(|x| x.split_once(" = ").expect("unexpected csv data").1) w.write("\n".as_bytes())?;
.collect::<Vec<&str>>()
.join(",");
line += "\n";
w.write(line.as_bytes())?;
} }
} }
} }
return Ok(()); return Ok(());
} }
@@ -99,13 +94,9 @@ fn decom_task(folder: String, out_dir: String) -> Result<()> {
fn main() -> Result<()> { fn main() -> Result<()> {
SimpleLogger::new().init().unwrap(); SimpleLogger::new().init().unwrap();
let args = CliArgs::parse();
info!("started decom"); info!("started decom");
decom_task(args.path, args.out_dir)?;
let args = args().skip(1).collect::<Vec<String>>();
let folder = args[0].clone();
let out_dir = args[1].clone();
decom_task(folder, out_dir)?;
info!("finished decom"); info!("finished decom");
return Ok(()); return Ok(());