Skip to content

Commit

Permalink
Merge branch 'main' into RSDK-9344-compress-robot-config
Browse files Browse the repository at this point in the history
  • Loading branch information
acmorrow committed Dec 19, 2024
2 parents a232c3b + 3339b17 commit c937107
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 8 deletions.
24 changes: 19 additions & 5 deletions micro-rdk/src/common/conn/viam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::future::Future;
use crate::common::app_client::{
AppClient, AppClientBuilder, AppClientError, PeriodicAppClientTask,
};
use crate::common::credentials_storage::TlsCertificate;
use crate::common::credentials_storage::{StorageDiagnostic, TlsCertificate};
use crate::common::webrtc::signaling_server::SignalingServer;
use std::marker::PhantomData;
use std::net::{SocketAddr, TcpListener};
Expand Down Expand Up @@ -91,23 +91,33 @@ impl From<&proto::app::v1::CloudConfig> for RobotCloudConfig {

#[cfg(not(feature = "ota"))]
pub trait ViamServerStorage:
RobotConfigurationStorage + WifiCredentialStorage + Clone + 'static
RobotConfigurationStorage + WifiCredentialStorage + StorageDiagnostic + Clone + 'static
{
}
#[cfg(not(feature = "ota"))]
impl<T> ViamServerStorage for T where
T: RobotConfigurationStorage + WifiCredentialStorage + Clone + 'static
T: RobotConfigurationStorage + WifiCredentialStorage + StorageDiagnostic + Clone + 'static
{
}

#[cfg(feature = "ota")]
pub trait ViamServerStorage:
RobotConfigurationStorage + WifiCredentialStorage + OtaMetadataStorage + Clone + 'static
RobotConfigurationStorage
+ WifiCredentialStorage
+ OtaMetadataStorage
+ StorageDiagnostic
+ Clone
+ 'static
{
}
#[cfg(feature = "ota")]
impl<T> ViamServerStorage for T where
T: RobotConfigurationStorage + WifiCredentialStorage + OtaMetadataStorage + Clone + 'static
T: RobotConfigurationStorage
+ WifiCredentialStorage
+ OtaMetadataStorage
+ StorageDiagnostic
+ Clone
+ 'static
{
}

Expand Down Expand Up @@ -454,6 +464,7 @@ where
}

pub(crate) async fn run(&mut self) -> ! {
self.storage.log_space_diagnostic();
// The first step is to check whether or not credentials are populated in
// storage. If not, we should go straight to provisioning.
//
Expand Down Expand Up @@ -643,6 +654,7 @@ where
})
.ok()
} else {
log::info!("Failed to obtain certificates from app, will attempt to load any stored certificates");
Some(self.storage.get_tls_certificate().ok())
}
.flatten();
Expand All @@ -664,6 +676,8 @@ where
}
}

self.storage.log_space_diagnostic();

let (tx, rx) = async_channel::bounded(1);

let mut inner = RobotServer {
Expand Down
8 changes: 8 additions & 0 deletions micro-rdk/src/common/credentials_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ pub trait OtaMetadataStorage {
fn reset_ota_metadata(&self) -> Result<(), Self::Error>;
}

pub trait StorageDiagnostic {
fn log_space_diagnostic(&self);
}

#[derive(Default)]
struct RAMCredentialStorageInner {
robot_creds: Option<RobotCredentials>,
Expand Down Expand Up @@ -300,6 +304,10 @@ impl WifiCredentialStorage for RAMStorage {
}
}

impl StorageDiagnostic for RAMStorage {
fn log_space_diagnostic(&self) {}
}

impl From<Infallible> for ServerError {
fn from(_: Infallible) -> Self {
unreachable!()
Expand Down
47 changes: 44 additions & 3 deletions micro-rdk/src/esp32/nvs_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,24 @@ use prost::{DecodeError, Message};
use snap::{read::FrameDecoder, write::FrameEncoder};
use std::{
cell::RefCell,
ffi::CString,
io::{Read, Write},
num::NonZeroI32,
rc::Rc,
};
use thiserror::Error;

use crate::{
common::{
credentials_storage::{
RobotConfigurationStorage, RobotCredentials, TlsCertificate, WifiCredentialStorage,
WifiCredentials,
RobotConfigurationStorage, RobotCredentials, StorageDiagnostic, TlsCertificate,
WifiCredentialStorage, WifiCredentials,
},
grpc::{GrpcError, ServerError},
},
esp32::esp_idf_svc::{
nvs::{EspCustomNvs, EspCustomNvsPartition, EspNvs},
sys::EspError,
sys::{esp, nvs_get_stats, nvs_stats_t, EspError, ESP_ERR_INVALID_ARG},
},
proto::{app::v1::RobotConfig, provisioning::v1::CloudConfig},
};
Expand Down Expand Up @@ -48,6 +50,7 @@ pub struct NVSStorage {
// esp-idf-svc partition driver ensures that only one handle of a type can be created
// so inner mutability can be achieves safely with RefCell
nvs: Rc<RefCell<EspCustomNvs>>,
partition_name: CString,
}

impl NVSStorage {
Expand All @@ -58,6 +61,9 @@ impl NVSStorage {

Ok(Self {
nvs: Rc::new(nvs.into()),
partition_name: CString::new(partition_name).map_err(|_| {
EspError::from_non_zero(NonZeroI32::new(ESP_ERR_INVALID_ARG).unwrap())
})?,
})
}

Expand Down Expand Up @@ -133,6 +139,41 @@ impl NVSStorage {
}
}

const BYTES_PER_ENTRY: usize = 32;

impl StorageDiagnostic for NVSStorage {
fn log_space_diagnostic(&self) {
let mut stats: nvs_stats_t = Default::default();
if let Err(err) =
esp!(unsafe { nvs_get_stats(self.partition_name.as_ptr(), &mut stats as *mut _) })
{
log::error!("could not acquire NVS stats: {:?}", err);
return;
}

let used_entries = stats.used_entries;
let used_space = used_entries * BYTES_PER_ENTRY;
let total_space = stats.total_entries * BYTES_PER_ENTRY;

// From experimentation we have found that NVS requires 4000 bytes of
// unused space for reasons unknown. The percentage portion of the calculation (0.976)
// comes from the blob size restriction as stated in the ESP32 documentation
// on NVS
let total_usable_space = (0.976 * (total_space as f64)) - 4000.0;
let fraction_used = (used_space as f64) / total_usable_space;
log::log!(
if fraction_used > 0.9 {
log::Level::Warn
} else {
log::Level::Info
},
"NVS stats: {:?} bytes used of {:?} available",
used_space,
total_space
);
}
}

const NVS_ROBOT_SECRET_KEY: &str = "ROBOT_SECRET";
const NVS_ROBOT_ID_KEY: &str = "ROBOT_ID";
const NVS_ROBOT_APP_ADDRESS: &str = "ROBOT_APP_ADDR";
Expand Down

0 comments on commit c937107

Please sign in to comment.