Adding refactor for telemetry

master
Ryan Summers 2021-05-05 15:39:33 +02:00
parent 06b328ff52
commit 4a656eedd2
6 changed files with 122 additions and 78 deletions

View File

@ -13,7 +13,10 @@ use hardware::{
DigitalInput1, InputPin, SystemTimer, AFE0, AFE1,
};
use net::{UpdateState, MiniconfClient, NetworkProcessor};
use net::{
MiniconfClient, NetworkManager, NetworkProcessor, NetworkUsers,
TelemetryBuffer, UpdateState,
};
const SCALE: f32 = i16::MAX as _;
@ -49,11 +52,6 @@ impl Default for Settings {
}
}
struct NetworkUsers {
miniconf: MiniconfClient<Settings>,
processor: NetworkProcessor,
}
#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true, monotonic = stabilizer::hardware::SystemTimer)]
const APP: () = {
struct Resources {
@ -61,9 +59,10 @@ const APP: () = {
digital_inputs: (DigitalInput0, DigitalInput1),
adcs: (Adc0Input, Adc1Input),
dacs: (Dac0Output, Dac1Output),
network: NetworkUsers,
network: NetworkUsers<Settings>,
settings: Settings,
telemetry: TelemetryBuffer,
#[init([[[0.; 5]; IIR_CASCADE_LENGTH]; 2])]
iir_state: [[iir::Vec5; IIR_CASCADE_LENGTH]; 2],
@ -75,7 +74,8 @@ const APP: () = {
let (mut stabilizer, _pounder) = hardware::setup(c.core, c.device);
let network = {
let stack_manager = cortex_m::singleton!(: NetworkManager = NetworkManager::new(stabilizer.net.stack)).unwrap();
let stack = stabilizer.net.stack;
let stack_manager = cortex_m::singleton!(: NetworkManager = NetworkManager::new(stack)).unwrap();
let processor = NetworkProcessor::new(
stack_manager.acquire_stack(),
@ -83,7 +83,7 @@ const APP: () = {
stabilizer.cycle_counter,
);
let settings = MqttInterface::new(
let settings = MiniconfClient::new(
stack_manager.acquire_stack(),
"",
&net::get_device_prefix(
@ -113,7 +113,6 @@ const APP: () = {
// Start sampling ADCs.
stabilizer.adc_dac_timer.start();
init::LateResources {
afes: stabilizer.afes,
adcs: stabilizer.adcs,
@ -193,12 +192,19 @@ const APP: () = {
fn idle(mut c: idle::Context) -> ! {
loop {
// Update the smoltcp network stack.
let poll_result = c.resources.network.lock(|network| network.processor.poll());
let poll_result = c
.resources
.network
.lock(|network| network.processor.update());
// Service the MQTT configuration client.
if c.resources.miniconf_client.lock(|client| client.update()) == UpdateStatus::Updated {
if c.resources
.network
.lock(|network| network.miniconf.update())
== UpdateState::Updated
{
c.spawn.settings_update().unwrap()
} else if poll_result == UpdateStatus::NoChange {
} else if poll_result == UpdateState::NoChange {
cortex_m::asm::wfi();
}
}
@ -217,10 +223,10 @@ const APP: () = {
#[task(priority = 1, resources=[network, settings, telemetry], schedule=[telemetry])]
fn telemetry(mut c: telemetry::Context) {
let telemetry =
let _telemetry =
c.resources.telemetry.lock(|telemetry| telemetry.clone());
let gains = c.resources.settings.lock(|settings| settings.afe.clone());
let _gains = c.resources.settings.lock(|settings| settings.afe.clone());
// TODO: Publish telemetry through the telemetry client here.
//c.resources

View File

@ -18,7 +18,9 @@ use stabilizer::hardware::{
};
use miniconf::Miniconf;
use stabilizer::net::{Action, MqttInterface};
use stabilizer::net::{
MiniconfClient, NetworkManager, NetworkProcessor, NetworkUsers, UpdateState,
};
#[derive(Copy, Clone, Debug, Deserialize, Miniconf)]
enum Conf {
@ -64,7 +66,7 @@ const APP: () = {
afes: (AFE0, AFE1),
adcs: (Adc0Input, Adc1Input),
dacs: (Dac0Output, Dac1Output),
mqtt: MqttInterface<Settings>,
network: NetworkUsers<Settings>,
settings: Settings,
telemetry: net::TelemetryBuffer,
digital_inputs: (DigitalInput0, DigitalInput1),
@ -79,16 +81,32 @@ const APP: () = {
// Configure the microcontroller
let (mut stabilizer, _pounder) = setup(c.core, c.device);
let mqtt = MqttInterface::new(
stabilizer.net.stack,
"",
&net::get_device_prefix(
env!("CARGO_BIN_NAME"),
stabilizer.net.mac_address,
),
stabilizer.net.phy,
stabilizer.cycle_counter,
);
let network = {
let stack = stabilizer.net.stack;
let stack_manager = cortex_m::singleton!(: NetworkManager = NetworkManager::new(stack)).unwrap();
let processor = NetworkProcessor::new(
stack_manager.acquire_stack(),
stabilizer.net.phy,
stabilizer.cycle_counter,
);
let settings = MiniconfClient::new(
stack_manager.acquire_stack(),
"",
&net::get_device_prefix(
env!("CARGO_BIN_NAME"),
stabilizer.net.mac_address,
),
);
// TODO: Add telemetry client
NetworkUsers {
miniconf: settings,
processor,
}
};
let settings = Settings::default();
@ -120,7 +138,7 @@ const APP: () = {
afes: stabilizer.afes,
adcs: stabilizer.adcs,
dacs: stabilizer.dacs,
mqtt,
network,
digital_inputs: stabilizer.digital_inputs,
timestamper: stabilizer.timestamper,
telemetry: net::TelemetryBuffer::default(),
@ -211,22 +229,31 @@ const APP: () = {
[dac_samples[0][0], dac_samples[1][0]];
}
#[idle(resources=[mqtt], spawn=[settings_update])]
#[idle(resources=[network], spawn=[settings_update])]
fn idle(mut c: idle::Context) -> ! {
loop {
match c.resources.mqtt.lock(|mqtt| mqtt.update()) {
Some(Action::Sleep) => cortex_m::asm::wfi(),
Some(Action::UpdateSettings) => {
c.spawn.settings_update().unwrap()
}
_ => {}
// Update the smoltcp network stack.
let poll_result = c
.resources
.network
.lock(|network| network.processor.update());
// Service the MQTT configuration client.
if c.resources
.network
.lock(|network| network.miniconf.update())
== UpdateState::Updated
{
c.spawn.settings_update().unwrap()
} else if poll_result == UpdateState::NoChange {
cortex_m::asm::wfi();
}
}
}
#[task(priority = 1, resources=[mqtt, settings, afes])]
#[task(priority = 1, resources=[network, settings, afes])]
fn settings_update(mut c: settings_update::Context) {
let settings = c.resources.mqtt.settings();
let settings = c.resources.network.miniconf.settings();
c.resources.afes.0.set_gain(settings.afe[0]);
c.resources.afes.1.set_gain(settings.afe[1]);
@ -234,7 +261,7 @@ const APP: () = {
c.resources.settings.lock(|current| *current = *settings);
}
#[task(priority = 1, resources=[mqtt, digital_inputs, settings, telemetry], schedule=[telemetry])]
#[task(priority = 1, resources=[network, digital_inputs, settings, telemetry], schedule=[telemetry])]
fn telemetry(mut c: telemetry::Context) {
let mut telemetry =
c.resources.telemetry.lock(|telemetry| telemetry.clone());
@ -244,10 +271,12 @@ const APP: () = {
c.resources.digital_inputs.1.is_high().unwrap(),
];
let gains = c.resources.settings.lock(|settings| settings.afe.clone());
c.resources
.mqtt
.publish_telemetry(&telemetry.to_telemetry(gains[0], gains[1]));
let _gains = c.resources.settings.lock(|settings| settings.afe.clone());
// TODO: Publish telemetry.
//c.resources
// .mqtt
// .publish_telemetry(&telemetry.to_telemetry(gains[0], gains[1]));
let telemetry_period = c
.resources

View File

@ -13,23 +13,30 @@ mod messages;
mod mqtt_interface;
mod shared;
mod stack_manager;
use messages::{MqttMessage, SettingsResponse};
pub use mqtt_interface::MiniconfClient;
pub use stack_manager::NetworkProcessor;
pub use shared::NetworkManager;
mod telemetry;
use crate::hardware::NetworkStack;
pub type NetworkReference = shared::NetworkStackProxy<'static, NetworkStack>;
use messages::{MqttMessage, SettingsResponse};
use miniconf::Miniconf;
mod telemetry;
pub use mqtt_interface::MiniconfClient;
pub use shared::NetworkManager;
pub use stack_manager::NetworkProcessor;
pub use telemetry::{Telemetry, TelemetryBuffer};
pub type NetworkReference = shared::NetworkStackProxy<'static, NetworkStack>;
#[derive(Copy, Clone, PartialEq)]
pub enum UpdateState {
NoChange,
Updated,
}
pub struct NetworkUsers<S: Default + Clone + Miniconf> {
pub miniconf: MiniconfClient<S>,
pub processor: NetworkProcessor,
}
/// Get the MQTT prefix of a device.
///
/// # Args

View File

@ -2,7 +2,7 @@ use crate::hardware::design_parameters::MQTT_BROKER;
use heapless::{consts, String};
use super::{UpdateState, MqttMessage, SettingsResponse, NetworkReference};
use super::{MqttMessage, NetworkReference, SettingsResponse, UpdateState};
/// MQTT settings interface.
pub struct MiniconfClient<S>
@ -26,11 +26,7 @@ where
/// * `stack` - The network stack to use for communication.
/// * `client_id` - The ID of the MQTT client. May be an empty string for auto-assigning.
/// * `prefix` - The MQTT device prefix to use for this device.
pub fn new(
stack: NetworkReference,
client_id: &str,
prefix: &str,
) -> Self {
pub fn new(stack: NetworkReference, client_id: &str, prefix: &str) -> Self {
let mqtt =
minimq::MqttClient::new(MQTT_BROKER.into(), client_id, stack)
.unwrap();
@ -55,7 +51,6 @@ where
/// # Returns
/// An option containing an action that should be completed as a result of network servicing.
pub fn update(&mut self) -> UpdateState {
let mqtt_connected = match self.mqtt.is_connected() {
Ok(connected) => connected,
Err(minimq::Error::Network(

View File

@ -1,19 +1,15 @@
use shared_bus::{AtomicCheckMutex, BusMutex};
use minimq::embedded_nal;
use smoltcp_nal::smoltcp;
use shared_bus::{AtomicCheckMutex, BusMutex};
use crate::hardware::NetworkStack;
pub struct NetworkStackProxy<'a, S> {
mutex: &'a AtomicCheckMutex<S>
mutex: &'a AtomicCheckMutex<S>,
}
impl<'a> NetworkStackProxy<'a, NetworkStack> {
pub fn poll(&mut self, now: u32) -> Result<bool, smoltcp::Error> {
self.mutex.lock(|stack| stack.poll(now))
}
pub fn handle_link_reset(&mut self) {
self.mutex.lock(|stack| stack.handle_link_reset())
impl<'a, S> NetworkStackProxy<'a, S> {
pub fn lock<R, F: FnOnce(&mut S) -> R>(&mut self, f: F) -> R {
self.mutex.lock(|stack| f(stack))
}
}
@ -27,7 +23,7 @@ macro_rules! forward {
impl<'a, S> embedded_nal::TcpStack for NetworkStackProxy<'a, S>
where
S: embedded_nal::TcpStack
S: embedded_nal::TcpStack,
{
type TcpSocket = S::TcpSocket;
type Error = S::Error;
@ -41,17 +37,17 @@ where
}
pub struct NetworkManager {
mutex: AtomicCheckMutex<NetworkStack>
mutex: AtomicCheckMutex<NetworkStack>,
}
impl NetworkManager {
pub fn new(stack: NetworkStack) -> Self {
Self { mutex: AtomicCheckMutex::create(stack) }
Self {
mutex: AtomicCheckMutex::create(stack),
}
}
pub fn acquire_stack<'a>(&'a self) -> NetworkStackProxy<'a, NetworkStack> {
NetworkStackProxy {
mutex: &self.mutex
}
NetworkStackProxy { mutex: &self.mutex }
}
}

View File

@ -1,6 +1,6 @@
use super::{UpdateState, NetworkReference};
use super::{NetworkReference, UpdateState};
use crate::hardware::{EthernetPhy, CycleCounter};
use crate::hardware::{CycleCounter, EthernetPhy};
pub struct NetworkProcessor {
stack: NetworkReference,
@ -10,13 +10,24 @@ pub struct NetworkProcessor {
}
impl NetworkProcessor {
pub fn new(stack: NetworkReference, phy: EthernetPhy, clock: CycleCounter) -> Self {
Self { stack, phy, clock, network_was_reset: false }
pub fn new(
stack: NetworkReference,
phy: EthernetPhy,
clock: CycleCounter,
) -> Self {
Self {
stack,
phy,
clock,
network_was_reset: false,
}
}
pub fn update(&mut self) -> UpdateState {
// Service the network stack to process any inbound and outbound traffic.
let result = match self.stack.poll(self.clock.current_ms()) {
let now = self.clock.current_ms();
let result = match self.stack.lock(|stack| stack.poll(now)) {
Ok(true) => UpdateState::Updated,
Ok(false) => UpdateState::NoChange,
Err(err) => {
@ -34,9 +45,9 @@ impl NetworkProcessor {
// sending an excessive number of DHCP requests.
false if !self.network_was_reset => {
self.network_was_reset = true;
self.stack.handle_link_reset();
self.stack.lock(|stack| stack.handle_link_reset());
}
_ => {},
_ => {}
};
result