This commit is contained in:
Jacob Weaver
2024-12-13 10:23:45 -06:00
commit 6b27e84e4b
38 changed files with 2821 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
#![no_std]
use anyhow::Result;
use log::*;
use msg::{HsCmd, HsHk, HsOutData, Msg, MsgKind, TargetMsg};
use rfe::*;
extern crate alloc;
use alloc::vec::Vec;
mod watchdog;
use utils::ManualAuto;
pub use watchdog::*;
#[cfg(feature = "std")]
mod hs_std;
#[cfg(feature = "std")]
pub use hs_std::*;
#[cfg(not(any(feature = "std")))]
mod hs_stub;
#[cfg(not(any(feature = "std")))]
pub use hs_stub::*;
pub trait SystemInfoGrabber {
fn check_cpu_usage(&mut self) -> Vec<u8>;
fn check_mem_usage(&mut self) -> u8;
fn check_fs_usage(&mut self) -> Vec<u8>;
fn check_temps(&mut self) -> Vec<i8>;
}
#[derive(Debug, Default, Clone)]
pub struct HsData {
out_data: HsOutData,
hk: HsHk,
}
#[derive(Debug, Clone, Copy)]
pub struct HsConfig {
pub cpu_checks: bool,
pub mem_checks: bool,
pub fs_checks: bool,
pub temp_checks: bool,
pub watchdog_enable: bool,
pub watchdog_timeout: i32,
}
pub struct Hs<'a> {
data: HsData,
config: HsConfig,
grabber: &'a mut dyn SystemInfoGrabber,
wd: WatchdogRef<'a>,
wd_value: ManualAuto<bool>,
}
impl<'a> Hs<'a> {
pub fn new(
config: HsConfig,
grabber: &'a mut dyn SystemInfoGrabber,
mut watchdog: WatchdogRef<'a>,
) -> Self {
if config.watchdog_enable {
watchdog.enable();
} else {
watchdog.disable();
}
watchdog.set_time(config.watchdog_timeout);
Self {
data: Default::default(),
config,
grabber,
wd: watchdog,
wd_value: ManualAuto::new(config.watchdog_enable, false),
}
}
fn reset(&mut self) {
self.data = Default::default();
}
}
impl App for Hs<'_> {
fn init(&mut self, rfe: &mut Rfe) -> Result<()> {
self.reset();
rfe.subscribe(TargetMsg::new(rfe.get_instance(), MsgKind::HsCmd));
return Ok(());
}
fn run(&mut self, rfe: &mut Rfe) {
self.data.out_data.counter += 1;
while let Some(msg) = rfe.recv() {
match msg.msg {
Msg::HsCmd(cmd) => {
self.data.hk.cmd_counter += 1;
match cmd {
HsCmd::Noop => {
info!("Noop command received");
}
HsCmd::Reset => {
info!("Reset command received");
self.data = Default::default();
}
HsCmd::WatchdogEnableManual(v) => self.wd_value.manual_set(v),
HsCmd::WatchdogEnableAuto(v) => self.wd_value.auto_set(v),
HsCmd::WatchdogResumeAuto => self.wd_value.resume_auto(),
}
}
_ => {
warn!(
"HS received unexpected message: {:?} from {:?}",
msg.msg.kind(),
msg.instance
);
}
}
}
if self.wd_value.has_changed() {
if *self.wd_value.get() {
self.wd.enable();
} else {
self.wd.disable();
}
}
self.wd.feed();
if self.config.cpu_checks {
self.data.hk.cpu_usage = self.grabber.check_cpu_usage();
}
if self.config.mem_checks {
self.data.hk.mem_usage = self.grabber.check_mem_usage();
}
if self.config.fs_checks {
self.data.hk.fs_usage = self.grabber.check_fs_usage();
}
if self.config.temp_checks {
self.data.hk.temps = self.grabber.check_temps();
}
}
fn hk(&mut self, rfe: &mut Rfe) {
self.data.hk.counter = self.data.out_data.counter;
rfe.send(Msg::HsHk(self.data.hk.clone()));
}
fn out_data(&mut self, rfe: &mut Rfe) {
rfe.send(Msg::HsOutData(self.data.out_data));
}
fn get_app_rate(&self) -> Rate {
Rate::Hz1
}
}
+59
View File
@@ -0,0 +1,59 @@
use sysinfo::{Components, CpuRefreshKind, Disks, MemoryRefreshKind, RefreshKind, System};
use crate::SystemInfoGrabber;
extern crate alloc;
use alloc::vec::Vec;
pub struct StdSystemInfoGrabber {
system: System,
}
impl StdSystemInfoGrabber {
pub fn new() -> Self {
Self {
system: System::new_with_specifics(
RefreshKind::new()
.with_cpu(CpuRefreshKind::new().with_cpu_usage())
.with_memory(MemoryRefreshKind::new().with_ram()),
),
}
}
}
impl SystemInfoGrabber for StdSystemInfoGrabber {
fn check_cpu_usage(&mut self) -> Vec<u8> {
self.system.refresh_cpu_usage();
self.system
.cpus()
.iter()
.map(|x| x.cpu_usage().round() as u8)
.collect()
}
fn check_mem_usage(&mut self) -> u8 {
self.system.refresh_memory();
(self.system.used_memory() * 100 / self.system.total_memory()) as u8
}
fn check_fs_usage(&mut self) -> Vec<u8> {
let mut disks = Disks::new_with_refreshed_list();
let disks = disks.list_mut();
disks.sort_by(|x, y| x.name().cmp(y.name()));
disks
.iter()
.map(|x| ((x.total_space() - x.available_space()) * 100 / x.total_space()) as u8)
.collect()
}
fn check_temps(&mut self) -> Vec<i8> {
let mut components = Components::new_with_refreshed_list();
let components = components.list_mut();
components.sort_by(|x, y| x.label().cmp(y.label()));
components
.iter()
.map(|x| x.temperature().round() as i8)
.collect()
}
}
+84
View File
@@ -0,0 +1,84 @@
pub trait Watchdog {
fn enable(&mut self);
fn disable(&mut self);
fn set_time(&mut self, time: i32);
fn feed(&mut self);
}
#[cfg(feature = "std")]
mod watchdog_std {
use super::Watchdog;
extern crate std;
use crate::unwrap_print_err;
use anyhow::Result;
use log::*;
pub struct LinuxWatchdog {
wd: watchdog_device::Watchdog,
}
impl LinuxWatchdog {
pub fn new() -> Result<Self> {
let wd = watchdog_device::Watchdog::new()?;
wd.set_option(&watchdog_device::SetOptionFlags::DisableCard)?;
Ok(Self { wd })
}
}
impl Watchdog for LinuxWatchdog {
fn enable(&mut self) {
unwrap_print_err!(
self.wd
.set_option(&watchdog_device::SetOptionFlags::EnableCard),
"failed to enable watchdog"
);
}
fn disable(&mut self) {
unwrap_print_err!(
self.wd
.set_option(&watchdog_device::SetOptionFlags::DisableCard),
"failed to set watchdog timeout"
);
}
fn set_time(&mut self, time: i32) {
unwrap_print_err!(self.wd.set_timeout(time), "failed to set watchdog timeout");
}
fn feed(&mut self) {
unwrap_print_err!(self.wd.keep_alive(), "failed to feed watchdog");
}
}
}
#[cfg(feature = "std")]
pub use watchdog_std::*;
pub type WatchdogRef<'a> = Option<&'a mut dyn Watchdog>;
impl<'a> Watchdog for Option<&'a mut dyn Watchdog> {
fn enable(&mut self) {
if let Some(wd) = self {
wd.enable();
}
}
fn disable(&mut self) {
if let Some(wd) = self {
wd.disable();
}
}
fn set_time(&mut self, time: i32) {
if let Some(wd) = self {
wd.set_time(time);
}
}
fn feed(&mut self) {
if let Some(wd) = self {
wd.feed();
}
}
}