diff --git a/micro-rdk-ffi/src/ffi/runtime.rs b/micro-rdk-ffi/src/ffi/runtime.rs index 0f38e9d13..375170fbb 100644 --- a/micro-rdk-ffi/src/ffi/runtime.rs +++ b/micro-rdk-ffi/src/ffi/runtime.rs @@ -261,6 +261,8 @@ pub unsafe extern "C" fn viam_server_start(ctx: *mut viam_server_context) -> via } }; + use micro_rdk::common::entry::serve_with_network; + #[cfg(has_robot_config)] { use micro_rdk::common::credentials_storage::RAMStorage; @@ -271,38 +273,23 @@ pub unsafe extern "C" fn viam_server_start(ctx: *mut viam_server_context) -> via ROBOT_SECRET.expect("Provided build-time configuration failed to set `ROBOT_SECRET`"), ); log::info!("Robot configuration information was provided at build time - bypassing Viam provisioning flow"); - #[cfg(target_os = "espidf")] - use micro_rdk::esp32::entry::serve_web_with_external_network; - #[cfg(not(target_os = "espidf"))] - use micro_rdk::native::entry::serve_web_with_external_network; - serve_web_with_external_network(None, repr, max_connection, ram_storage, network); + serve_with_network(None, repr, max_connection, ram_storage, network); } #[cfg(not(has_robot_config))] { #[cfg(not(target_os = "espidf"))] - { - use micro_rdk::common::credentials_storage::RAMStorage; - let storage = RAMStorage::default(); - micro_rdk::native::entry::serve_web_with_external_network( - Some(ctx.provisioning_info), - repr, - max_connection, - storage, - network, - ) - } + let storage = micro_rdk::common::credentials_storage::RAMStorage::default(); #[cfg(target_os = "espidf")] - { - let storage = micro_rdk::esp32::nvs_storage::NVSStorage::new("nvs").unwrap(); - micro_rdk::esp32::entry::serve_web_with_external_network( - Some(ctx.provisioning_info), - repr, - max_connection, - storage, - network, - ) - } + let storage = micro_rdk::esp32::nvs_storage::NVSStorage::new("nvs").unwrap(); + + serve_with_network( + Some(ctx.provisioning_info), + repr, + max_connection, + storage, + network, + ) } viam_code::VIAM_OK diff --git a/micro-rdk-server/esp32/main.rs b/micro-rdk-server/esp32/main.rs index d07e2ca4e..299fffe15 100644 --- a/micro-rdk-server/esp32/main.rs +++ b/micro-rdk-server/esp32/main.rs @@ -21,7 +21,7 @@ mod esp32 { registry::ComponentRegistry, }, esp32::{ - entry::serve_web, + entry::serve, esp_idf_svc::{ self, sys::{g_wifi_feature_caps, CONFIG_FEATURE_CACHE_TX_BUF_BIT}, @@ -34,7 +34,7 @@ mod esp32 { pub static g_spiram_ok: bool; } - fn register_examples(r: &mut ComponentRegistry) { + fn register_example_modules(r: &mut ComponentRegistry) { if let Err(e) = micro_rdk_modular_driver_example::free_heap_sensor::register_models(r) { log::error!("failed to register `free_heap_sensor`: {}", e); } @@ -66,14 +66,15 @@ mod esp32 { eth_configure(&sys_loop, eth).unwrap() }; - let mut r = Box::::default(); - register_examples(&mut r); - let repr = RobotRepresentation::WithRegistry(r); + let mut registry = Box::::default(); + register_example_modules(&mut registry); + let repr = RobotRepresentation::WithRegistry(registry); let storage = NVSStorage::new("nvs").unwrap(); // At runtime, if the program does not detect credentials or configs in storage, // it will try to load statically compiled values. + if !storage.has_wifi_credentials() { // check if any were statically compiled if SSID.is_some() && PASS.is_some() { @@ -117,7 +118,7 @@ mod esp32 { info.set_manufacturer("viam".to_owned()); info.set_model("test-esp32".to_owned()); - serve_web(Some(info), repr, max_connections, storage); + serve(Some(info), repr, max_connections, storage); } } diff --git a/micro-rdk-server/native/main.rs b/micro-rdk-server/native/main.rs index f469b2a97..f6521fd94 100755 --- a/micro-rdk-server/native/main.rs +++ b/micro-rdk-server/native/main.rs @@ -3,14 +3,12 @@ mod native { const ROBOT_ID: Option<&str> = option_env!("MICRO_RDK_ROBOT_ID"); const ROBOT_SECRET: Option<&str> = option_env!("MICRO_RDK_ROBOT_SECRET"); - use micro_rdk::{ - common::{ - conn::network::ExternallyManagedNetwork, - credentials_storage::{RAMStorage, RobotConfigurationStorage, RobotCredentials}, - entry::RobotRepresentation, - provisioning::server::ProvisioningInfo, - }, - native::entry::serve_web_with_external_network, + use micro_rdk::common::{ + conn::network::ExternallyManagedNetwork, + credentials_storage::{RAMStorage, RobotConfigurationStorage, RobotCredentials}, + entry::{serve_with_network, RobotRepresentation}, + provisioning::server::ProvisioningInfo, + registry::ComponentRegistry, }; pub(crate) fn main_native() { @@ -18,31 +16,42 @@ mod native { .format_timestamp(Some(env_logger::TimestampPrecision::Millis)) .init(); - let repr = RobotRepresentation::WithRegistry(Box::default()); - let network = match local_ip_address::local_ip().expect("error parsing local IP") { std::net::IpAddr::V4(ip) => ExternallyManagedNetwork::new(ip), _ => panic!("oops expected ipv4"), }; + let registry = Box::::default(); + let repr = RobotRepresentation::WithRegistry(registry); + let storage = RAMStorage::new(); - if ROBOT_ID.is_some() && ROBOT_SECRET.is_some() { - if let Err(e) = storage.store_robot_credentials( - RobotCredentials::new( - ROBOT_ID.unwrap().to_string(), - ROBOT_SECRET.unwrap().to_string(), - ) - .into(), - ) { - log::error!("Failed to store RobotCredentials: {}", e); + + // At runtime, if the program does not detect credentials or configs in storage, + // it will try to load statically compiled values. + + if !storage.has_robot_configuration() { + // check if any were statically compiled + if ROBOT_ID.is_some() && ROBOT_SECRET.is_some() { + log::info!("Storing static values from build time robot configuration"); + storage + .store_robot_credentials( + RobotCredentials::new( + ROBOT_ID.unwrap().to_string(), + ROBOT_SECRET.unwrap().to_string(), + ) + .into(), + ) + .expect("Failed to store robot credentials"); } } + let max_connections = 3; + let mut info = ProvisioningInfo::default(); info.set_manufacturer("viam".to_owned()); info.set_model("test-esp32".to_owned()); - serve_web_with_external_network(Some(info), repr, 3, storage, network); + serve_with_network(Some(info), repr, max_connections, storage, network); } } diff --git a/micro-rdk/src/common/entry.rs b/micro-rdk/src/common/entry.rs index 94cca25f5..8ae47f9cb 100644 --- a/micro-rdk/src/common/entry.rs +++ b/micro-rdk/src/common/entry.rs @@ -75,7 +75,7 @@ pub async fn validate_robot_credentials( builder.build().await.map_err(|e| e.into()) } -pub async fn serve_web_inner( +pub async fn serve_inner( storage: S, repr: RobotRepresentation, exec: Executor, @@ -235,7 +235,7 @@ pub async fn serve_web_inner( server.serve(robot).await; } -pub async fn serve_async_with_external_network( +pub async fn async_serve_with_network( exec: Executor, info: Option, storage: S, @@ -356,7 +356,7 @@ where let _ = last_error.insert(e); } }; - serve_web_inner( + serve_inner( storage, repr, exec, @@ -368,3 +368,54 @@ where .await; Ok(()) } + +pub fn serve_with_network( + info: Option, + repr: RobotRepresentation, + max_webrtc_connection: usize, + storage: S, + network: impl Network, +) where + S: RobotConfigurationStorage + WifiCredentialStorage + Clone + 'static, + ::Error: Debug, + ServerError: From<::Error>, + ::Error: Sync + Send + 'static, +{ + let exec = Executor::new(); + + #[cfg(feature = "esp32")] + { + // set the TWDT to expire after 5 minutes + crate::esp32::esp_idf_svc::sys::esp!(unsafe { + crate::esp32::esp_idf_svc::sys::esp_task_wdt_init(300, true) + }) + .unwrap(); + + // Register the current task on the TWDT. The TWDT runs in the IDLE Task. + crate::esp32::esp_idf_svc::sys::esp!(unsafe { + crate::esp32::esp_idf_svc::sys::esp_task_wdt_add( + crate::esp32::esp_idf_svc::sys::xTaskGetCurrentTaskHandle(), + ) + }) + .unwrap(); + + exec.spawn(async { + loop { + Timer::after(Duration::from_secs(150)).await; + unsafe { crate::esp32::esp_idf_svc::sys::esp_task_wdt_reset() }; + } + }) + .detach(); + } + + let _ = exec.block_on(Box::pin(async_serve_with_network( + exec.clone(), + info, + storage, + repr, + network, + max_webrtc_connection, + ))); + + unreachable!() +} diff --git a/micro-rdk/src/esp32/entry.rs b/micro-rdk/src/esp32/entry.rs index 5bdbd0a14..cc16a5ea3 100755 --- a/micro-rdk/src/esp32/entry.rs +++ b/micro-rdk/src/esp32/entry.rs @@ -9,8 +9,8 @@ use crate::{ app_client::AppClientError, conn::network::Network, credentials_storage::{RobotConfigurationStorage, WifiCredentialStorage}, + entry::validate_robot_credentials, entry::RobotRepresentation, - entry::{serve_async_with_external_network, validate_robot_credentials}, exec::Executor, grpc::ServerError, grpc_client::GrpcClientError, @@ -32,7 +32,7 @@ use crate::{ // 4) Robot Credentials + WiFi without external network // The function attempts to connect to the configured Wifi network if any, it then checks the robot credentials. If Wifi credentials are absent it starts provisioning mode // If they are invalid or absent it will start the provisioning server. Once provision is done it invokes the main server. -async fn serve_async( +async fn async_serve( exec: Executor, info: Option, storage: S, @@ -194,7 +194,7 @@ where } }; - crate::common::entry::serve_web_inner( + crate::common::entry::serve_inner( storage, repr, exec, @@ -207,7 +207,7 @@ where Ok(()) } -pub fn serve_web( +pub fn serve( info: Option, repr: RobotRepresentation, max_webrtc_connection: usize, @@ -244,7 +244,7 @@ pub fn serve_web( }) .detach(); - let _ = cloned_exec.block_on(Box::pin(serve_async( + let _ = cloned_exec.block_on(Box::pin(async_serve( exec, info, storage, @@ -254,53 +254,3 @@ pub fn serve_web( unreachable!() } - -pub fn serve_web_with_external_network( - info: Option, - repr: RobotRepresentation, - max_webrtc_connection: usize, - storage: S, - network: impl Network, -) where - S: RobotConfigurationStorage + WifiCredentialStorage + Clone + 'static, - ::Error: Debug, - ServerError: From<::Error>, - ::Error: Sync + Send + 'static, -{ - // set the TWDT to expire after 5 minutes - crate::esp32::esp_idf_svc::sys::esp!(unsafe { - crate::esp32::esp_idf_svc::sys::esp_task_wdt_init(300, true) - }) - .unwrap(); - - // Register the current task on the TWDT. The TWDT runs in the IDLE Task. - crate::esp32::esp_idf_svc::sys::esp!(unsafe { - crate::esp32::esp_idf_svc::sys::esp_task_wdt_add( - crate::esp32::esp_idf_svc::sys::xTaskGetCurrentTaskHandle(), - ) - }) - .unwrap(); - - let exec = Executor::new(); - let cloned_exec = exec.clone(); - - cloned_exec - .spawn(async { - loop { - Timer::after(Duration::from_secs(150)).await; - unsafe { crate::esp32::esp_idf_svc::sys::esp_task_wdt_reset() }; - } - }) - .detach(); - - let _ = cloned_exec.block_on(Box::pin(serve_async_with_external_network( - exec, - info, - storage, - repr, - network, - max_webrtc_connection, - ))); - - unreachable!() -} diff --git a/micro-rdk/src/native/entry.rs b/micro-rdk/src/native/entry.rs index 0d50692a6..7797caa91 100755 --- a/micro-rdk/src/native/entry.rs +++ b/micro-rdk/src/native/entry.rs @@ -1,41 +1,3 @@ -#![allow(dead_code)] - -use std::fmt::Debug; - -use crate::common::{ - conn::network::Network, - credentials_storage::{RobotConfigurationStorage, WifiCredentialStorage}, - entry::{serve_async_with_external_network, RobotRepresentation}, - exec::Executor, - grpc::ServerError, - provisioning::server::ProvisioningInfo, -}; - -pub fn serve_web_with_external_network( - info: Option, - repr: RobotRepresentation, - max_webrtc_connection: usize, - storage: S, - network: impl Network, -) where - S: RobotConfigurationStorage + WifiCredentialStorage + Clone + 'static, - ::Error: Debug, - ServerError: From<::Error>, - ::Error: Sync + Send + 'static, -{ - let exec = Executor::new(); - let cloned_exec = exec.clone(); - - let _ = cloned_exec.block_on(Box::pin(serve_async_with_external_network( - exec, - info, - storage, - repr, - network, - max_webrtc_connection, - ))); -} - #[cfg(test)] mod tests { use crate::common::app_client::AppClientBuilder; diff --git a/templates/project/src/main.rs b/templates/project/src/main.rs index f2bca0915..c173bc5e4 100644 --- a/templates/project/src/main.rs +++ b/templates/project/src/main.rs @@ -13,15 +13,19 @@ use micro_rdk::{ registry::{ComponentRegistry, RegistryError}, }, esp32::{ - entry::serve_web, + entry::serve, esp_idf_svc::{ - log::EspLogger, - sys::{self, esp, g_wifi_feature_caps, CONFIG_FEATURE_CACHE_TX_BUF_BIT}, + self, + sys::{g_wifi_feature_caps, CONFIG_FEATURE_CACHE_TX_BUF_BIT}, }, nvs_storage::NVSStorage, }, }; +extern "C" { + pub static g_spiram_ok: bool; +} + macro_rules! generate_register_modules { ($($module:ident),*) => { #[allow(unused_variables)] @@ -37,29 +41,28 @@ macro_rules! generate_register_modules { include!(concat!(env!("OUT_DIR"), "/modules.rs")); -extern "C" { - pub static g_spiram_ok: bool; -} - fn main() { - sys::link_patches(); - EspLogger::initialize_default(); + esp_idf_svc::sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); - esp!(unsafe { sys::esp_vfs_eventfd_register(&sys::esp_vfs_eventfd_config_t { max_fds: 5 },) }) - .unwrap(); + esp_idf_svc::sys::esp!(unsafe { + esp_idf_svc::sys::esp_vfs_eventfd_register(&esp_idf_svc::sys::esp_vfs_eventfd_config_t { + max_fds: 5, + }) + }) + .unwrap(); - let max_connections = unsafe { - if !g_spiram_ok { - log::info!("spiram not initialized disabling cache feature of the wifi driver"); - g_wifi_feature_caps &= !(CONFIG_FEATURE_CACHE_TX_BUF_BIT as u64); - 1 - } else { - 3 - } - }; + let mut registry = Box::::default(); + if let Err(e) = register_modules(&mut registry) { + log::error!("couldn't register modules {:?}", e); + } + let repr = RobotRepresentation::WithRegistry(registry); let storage = NVSStorage::new("nvs").unwrap(); + // At runtime, if the program does not detect credentials or configs in storage, + // it will try to load statically compiled values. + if !storage.has_wifi_credentials() { // check if any were statically compiled if SSID.is_some() && PASS.is_some() { @@ -89,14 +92,19 @@ fn main() { } } + let max_connections = unsafe { + if !g_spiram_ok { + log::info!("spiram not initialized disabling cache feature of the wifi driver"); + g_wifi_feature_caps &= !(CONFIG_FEATURE_CACHE_TX_BUF_BIT as u64); + 1 + } else { + 3 + } + }; + let mut info = ProvisioningInfo::default(); info.set_manufacturer("viam".to_owned()); info.set_model("esp32".to_owned()); - let mut registry = Box::::default(); - if let Err(e) = register_modules(&mut registry) { - log::error!("couldn't register modules {:?}", e); - } - let repr = RobotRepresentation::WithRegistry(registry); - serve_web(Some(info), repr, max_connections, storage); + serve(Some(info), repr, max_connections, storage); }