2021-04-29 17:54:16 +08:00
|
|
|
///! Stabilizer network management module
|
|
|
|
///!
|
|
|
|
///! # Design
|
|
|
|
///! The stabilizer network architecture supports numerous layers to permit transmission of
|
|
|
|
///! telemetry (via MQTT), configuration of run-time settings (via MQTT + Miniconf), and live data
|
|
|
|
///! streaming over raw UDP/TCP sockets. This module encompasses the main processing routines
|
|
|
|
///! related to Stabilizer networking operations.
|
2021-05-29 00:34:25 +08:00
|
|
|
use heapless::String;
|
2021-05-05 22:16:54 +08:00
|
|
|
use miniconf::Miniconf;
|
|
|
|
use serde::Serialize;
|
2021-04-13 21:38:30 +08:00
|
|
|
|
2021-05-06 18:33:07 +08:00
|
|
|
use core::fmt::Write;
|
|
|
|
|
2021-04-29 17:54:16 +08:00
|
|
|
mod messages;
|
2021-05-05 22:50:51 +08:00
|
|
|
mod miniconf_client;
|
|
|
|
mod network_processor;
|
2021-05-06 18:35:04 +08:00
|
|
|
mod shared;
|
2021-05-05 21:39:33 +08:00
|
|
|
mod telemetry;
|
|
|
|
|
2021-05-05 22:16:54 +08:00
|
|
|
use crate::hardware::{CycleCounter, EthernetPhy, NetworkStack};
|
2021-05-04 19:13:44 +08:00
|
|
|
use messages::{MqttMessage, SettingsResponse};
|
2021-05-05 01:52:41 +08:00
|
|
|
|
2021-05-05 22:50:51 +08:00
|
|
|
pub use miniconf_client::MiniconfClient;
|
|
|
|
pub use network_processor::NetworkProcessor;
|
2021-05-06 18:35:04 +08:00
|
|
|
pub use shared::NetworkManager;
|
2021-05-05 22:16:54 +08:00
|
|
|
pub use telemetry::{Telemetry, TelemetryBuffer, TelemetryClient};
|
2021-05-05 01:52:41 +08:00
|
|
|
|
|
|
|
pub type NetworkReference = shared::NetworkStackProxy<'static, NetworkStack>;
|
2021-03-18 03:16:13 +08:00
|
|
|
|
2021-05-05 21:39:33 +08:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
2021-05-05 01:52:41 +08:00
|
|
|
pub enum UpdateState {
|
|
|
|
NoChange,
|
|
|
|
Updated,
|
2021-03-18 03:16:13 +08:00
|
|
|
}
|
|
|
|
|
2021-05-26 19:05:54 +08:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
|
|
|
pub enum NetworkState {
|
|
|
|
SettingsChanged,
|
|
|
|
Updated,
|
|
|
|
NoChange,
|
|
|
|
}
|
2021-05-06 18:33:07 +08:00
|
|
|
/// A structure of Stabilizer's default network users.
|
2021-05-05 22:16:54 +08:00
|
|
|
pub struct NetworkUsers<S: Default + Clone + Miniconf, T: Serialize> {
|
2021-05-05 21:39:33 +08:00
|
|
|
pub miniconf: MiniconfClient<S>,
|
|
|
|
pub processor: NetworkProcessor,
|
2021-05-05 22:16:54 +08:00
|
|
|
pub telemetry: TelemetryClient<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S, T> NetworkUsers<S, T>
|
|
|
|
where
|
|
|
|
S: Default + Clone + Miniconf,
|
|
|
|
T: Serialize,
|
|
|
|
{
|
2021-05-06 18:33:07 +08:00
|
|
|
/// Construct Stabilizer's default network users.
|
|
|
|
///
|
|
|
|
/// # Args
|
|
|
|
/// * `stack` - The network stack that will be used to share with all network users.
|
|
|
|
/// * `phy` - The ethernet PHY connecting the network.
|
|
|
|
/// * `cycle_counter` - The clock used for measuring time in the network.
|
|
|
|
/// * `app` - The name of the application.
|
|
|
|
/// * `mac` - The MAC address of the network.
|
|
|
|
///
|
|
|
|
/// # Returns
|
|
|
|
/// A new struct of network users.
|
2021-05-05 22:16:54 +08:00
|
|
|
pub fn new(
|
|
|
|
stack: NetworkStack,
|
|
|
|
phy: EthernetPhy,
|
|
|
|
cycle_counter: CycleCounter,
|
|
|
|
app: &str,
|
|
|
|
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
|
|
|
|
) -> Self {
|
|
|
|
let stack_manager =
|
|
|
|
cortex_m::singleton!(: NetworkManager = NetworkManager::new(stack))
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let processor = NetworkProcessor::new(
|
|
|
|
stack_manager.acquire_stack(),
|
|
|
|
phy,
|
|
|
|
cycle_counter,
|
|
|
|
);
|
|
|
|
|
|
|
|
let prefix = get_device_prefix(app, mac);
|
|
|
|
|
|
|
|
let settings = MiniconfClient::new(
|
|
|
|
stack_manager.acquire_stack(),
|
|
|
|
&get_client_id(app, "settings", mac),
|
|
|
|
&prefix,
|
|
|
|
);
|
|
|
|
|
|
|
|
let telemetry = TelemetryClient::new(
|
|
|
|
stack_manager.acquire_stack(),
|
|
|
|
&get_client_id(app, "tlm", mac),
|
|
|
|
&prefix,
|
|
|
|
);
|
|
|
|
|
|
|
|
NetworkUsers {
|
|
|
|
miniconf: settings,
|
|
|
|
processor,
|
|
|
|
telemetry,
|
|
|
|
}
|
|
|
|
}
|
2021-05-05 22:46:53 +08:00
|
|
|
|
2021-05-06 18:33:07 +08:00
|
|
|
/// Update and process all of the network users state.
|
|
|
|
///
|
|
|
|
/// # Returns
|
|
|
|
/// An indication if any of the network users indicated a state change.
|
2021-05-26 19:05:54 +08:00
|
|
|
pub fn update(&mut self) -> NetworkState {
|
2021-05-05 22:46:53 +08:00
|
|
|
// Poll for incoming data.
|
2021-05-26 19:05:54 +08:00
|
|
|
let poll_result = match self.processor.update() {
|
|
|
|
UpdateState::NoChange => NetworkState::NoChange,
|
|
|
|
UpdateState::Updated => NetworkState::Updated,
|
|
|
|
};
|
2021-05-05 22:46:53 +08:00
|
|
|
|
|
|
|
// Update the MQTT clients.
|
|
|
|
self.telemetry.update();
|
|
|
|
|
|
|
|
match self.miniconf.update() {
|
2021-05-26 19:05:54 +08:00
|
|
|
UpdateState::Updated => NetworkState::SettingsChanged,
|
2021-05-05 22:46:53 +08:00
|
|
|
UpdateState::NoChange => poll_result,
|
|
|
|
}
|
|
|
|
}
|
2021-05-05 22:16:54 +08:00
|
|
|
}
|
|
|
|
|
2021-05-06 18:33:07 +08:00
|
|
|
/// Get an MQTT client ID for a client.
|
|
|
|
///
|
|
|
|
/// # Args
|
|
|
|
/// * `app` - The name of the application
|
|
|
|
/// * `client` - The unique tag of the client
|
|
|
|
/// * `mac` - The MAC address of the device.
|
|
|
|
///
|
|
|
|
/// # Returns
|
|
|
|
/// A client ID that may be used for MQTT client identification.
|
2021-05-05 22:16:54 +08:00
|
|
|
fn get_client_id(
|
|
|
|
app: &str,
|
|
|
|
client: &str,
|
|
|
|
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
|
2021-05-29 00:34:25 +08:00
|
|
|
) -> String<64> {
|
2021-05-05 22:16:54 +08:00
|
|
|
let mut identifier = String::new();
|
2021-05-10 16:57:50 +08:00
|
|
|
write!(&mut identifier, "{}-{}-{}", app, mac, client).unwrap();
|
2021-05-05 22:16:54 +08:00
|
|
|
identifier
|
2021-05-05 21:39:33 +08:00
|
|
|
}
|
|
|
|
|
2021-04-13 21:38:30 +08:00
|
|
|
/// Get the MQTT prefix of a device.
|
|
|
|
///
|
|
|
|
/// # Args
|
|
|
|
/// * `app` - The name of the application that is executing.
|
|
|
|
/// * `mac` - The ethernet MAC address of the device.
|
|
|
|
///
|
|
|
|
/// # Returns
|
|
|
|
/// The MQTT prefix used for this device.
|
|
|
|
pub fn get_device_prefix(
|
|
|
|
app: &str,
|
|
|
|
mac: smoltcp_nal::smoltcp::wire::EthernetAddress,
|
2021-05-29 00:34:25 +08:00
|
|
|
) -> String<128> {
|
2021-04-13 21:38:30 +08:00
|
|
|
// Note(unwrap): The mac address + binary name must be short enough to fit into this string. If
|
|
|
|
// they are defined too long, this will panic and the device will fail to boot.
|
2021-05-29 00:34:25 +08:00
|
|
|
let mut prefix: String<128> = String::new();
|
2021-05-10 16:57:50 +08:00
|
|
|
write!(&mut prefix, "dt/sinara/{}/{}", app, mac).unwrap();
|
2021-04-13 21:38:30 +08:00
|
|
|
|
|
|
|
prefix
|
|
|
|
}
|