pub use heapless;
pub use miniconf;
pub use serde;
pub mod data_stream;
pub mod network_processor;
pub mod telemetry;
use crate::hardware::{
metadata::ApplicationMetadata, EthernetPhy, NetworkManager, NetworkStack,
SystemTimer,
};
use crate::settings::NetSettings;
use data_stream::{DataStream, FrameGenerator, StreamTarget};
use network_processor::NetworkProcessor;
use telemetry::TelemetryClient;
use core::fmt::Write;
use heapless::String;
use miniconf::{TreeDeserializeOwned, TreeKey, TreeSerialize};
use miniconf_mqtt::minimq;
pub type NetworkReference =
smoltcp_nal::shared::NetworkStackProxy<'static, NetworkStack>;
pub struct MqttStorage {
telemetry: [u8; 2048],
settings: [u8; 1024],
}
impl Default for MqttStorage {
fn default() -> Self {
Self {
telemetry: [0u8; 2048],
settings: [0u8; 1024],
}
}
}
pub enum UpdateState {
NoChange,
Updated,
}
pub enum NetworkState {
SettingsChanged,
Updated,
NoChange,
}
pub struct NetworkUsers<S, const Y: usize>
where
S: Default + TreeDeserializeOwned + TreeSerialize + Clone,
{
pub miniconf: miniconf_mqtt::MqttClient<
'static,
S,
NetworkReference,
SystemTimer,
minimq::broker::NamedBroker<NetworkReference>,
Y,
>,
pub processor: NetworkProcessor,
stream: DataStream,
generator: Option<FrameGenerator>,
pub telemetry: TelemetryClient,
}
impl<S, const Y: usize> NetworkUsers<S, Y>
where
S: Default + TreeDeserializeOwned + TreeSerialize + TreeKey + Clone,
{
pub fn new(
stack: NetworkStack,
phy: EthernetPhy,
clock: SystemTimer,
app: &str,
net_settings: &NetSettings,
metadata: &'static ApplicationMetadata,
) -> Self {
let stack_manager =
cortex_m::singleton!(: NetworkManager = NetworkManager::new(stack))
.unwrap();
let processor =
NetworkProcessor::new(stack_manager.acquire_stack(), phy);
let prefix = cortex_m::singleton!(: String<128> = get_device_prefix(app, &net_settings.id)).unwrap();
let store =
cortex_m::singleton!(: MqttStorage = MqttStorage::default())
.unwrap();
let named_broker = minimq::broker::NamedBroker::new(
&net_settings.broker,
stack_manager.acquire_stack(),
)
.unwrap();
let settings = miniconf_mqtt::MqttClient::<_, _, _, _, Y>::new(
stack_manager.acquire_stack(),
prefix.as_str(),
clock,
minimq::ConfigBuilder::new(named_broker, &mut store.settings)
.client_id(&get_client_id(&net_settings.id, "settings"))
.unwrap(),
)
.unwrap();
let named_broker = minimq::broker::NamedBroker::new(
&net_settings.broker,
stack_manager.acquire_stack(),
)
.unwrap();
let mqtt = minimq::Minimq::new(
stack_manager.acquire_stack(),
clock,
minimq::ConfigBuilder::new(named_broker, &mut store.telemetry)
.rx_buffer(minimq::config::BufferConfig::Maximum(100))
.client_id(&get_client_id(&net_settings.id, "tlm"))
.unwrap(),
);
let telemetry = TelemetryClient::new(mqtt, prefix, metadata);
let (generator, stream) =
data_stream::setup_streaming(stack_manager.acquire_stack());
NetworkUsers {
miniconf: settings,
processor,
telemetry,
stream,
generator: Some(generator),
}
}
pub fn configure_streaming(
&mut self,
format: impl Into<u8>,
) -> FrameGenerator {
let mut generator = self.generator.take().unwrap();
generator.configure(format);
generator
}
pub fn direct_stream(&mut self, remote: StreamTarget) {
if self.generator.is_none() {
self.stream.set_remote(remote);
}
}
pub fn update(&mut self, settings: &mut S) -> NetworkState {
self.telemetry.update();
if self.generator.is_none() {
self.stream.process();
}
let poll_result = match self.processor.update() {
UpdateState::NoChange => NetworkState::NoChange,
UpdateState::Updated => NetworkState::Updated,
};
let res = self.miniconf.update(settings);
match res {
Ok(true) => NetworkState::SettingsChanged,
_ => poll_result,
}
}
}
fn get_client_id(id: &str, mode: &str) -> String<64> {
let mut identifier = String::new();
write!(&mut identifier, "{id}-{mode}").unwrap();
identifier
}
pub fn get_device_prefix(app: &str, id: &str) -> String<128> {
let mut prefix: String<128> = String::new();
write!(&mut prefix, "dt/sinara/{app}/{id}").unwrap();
prefix
}