use alloc::{rc::Rc, string::String};
use core::fmt::Debug;
use datex_core::{network::com_hub::ComHub, runtime::Runtime};
use embassy_executor::Spawner;
use embassy_net::Stack;
use sntpc::NtpTimestampGenerator;
use crate::setup::{network::init_network, network_time::get_network_time};
pub struct CommonContext {
pub spawner: Spawner,
pub stack: Option<Stack<'static>>,
}
impl Debug for CommonContext {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("CommonContext").finish()
}
}
#[derive(Debug, Clone)]
pub struct WifiCredentials {
pub ssid: String,
pub password: String,
pub auth_method: Option<String>,
}
pub trait WifiInitializer {
#[cfg(feature = "wifi")]
async fn init_wifi_stack(
self,
spawner: &Spawner,
credentials: WifiCredentials,
) -> Stack<'static>;
}
pub trait SetupInitializer {
fn register_com_interface_factories(
&self,
stack: &Option<Stack<'static>>,
com_hub: Rc<ComHub>,
);
fn get_timestamp_generator(&self) -> impl NtpTimestampGenerator + Copy;
async fn set_current_time(&self, current_time: u64);
}
pub struct GlobalInitializer;
impl GlobalInitializer {
pub async fn init_datex_runtime(
runtime: Runtime,
wifi_credentials: Option<WifiCredentials>,
wifi_initializer: impl WifiInitializer,
setup_initializer: impl SetupInitializer,
spawner: Spawner,
) -> CommonContext {
let (current_time_us, maybe_wifi_stack) = match wifi_credentials {
Some(wifi_credentials) => {
#[cfg(feature = "wifi")]
{
let wifi_stack = wifi_initializer
.init_wifi_stack(&spawner, wifi_credentials)
.await;
let timestamp_generator =
setup_initializer.get_timestamp_generator();
(
Self::init_network_stack(
timestamp_generator,
wifi_stack,
)
.await,
Some(wifi_stack),
)
}
#[cfg(not(feature = "wifi"))]
{
panic!(
"Cannot initialize DATEX runtime with WIFI, 'wifi' feature is disabled"
)
}
}
None => (0, None),
};
setup_initializer.set_current_time(current_time_us).await;
setup_initializer.register_com_interface_factories(
&maybe_wifi_stack,
runtime.com_hub(),
);
CommonContext {
stack: maybe_wifi_stack,
spawner,
}
}
async fn init_network_stack(
timestamp_generator: impl NtpTimestampGenerator + Copy,
stack: Stack<'_>,
) -> u64 {
init_network(&stack).await;
get_network_time(stack, timestamp_generator).await.unwrap()
}
}