-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MQTT settings/status/telemetry framework #149
Comments
Ryan and I discussed a few ideas yesterday, below are my notes: IntroductionWe are thinking about having a primary setting struct which would be a struct of structs of The Global Setting StructureThis structure would be user-defined. The settings framework would be given an Commit SettingsThe "commit settings" routine would be responsible for populating the resources MQTT UpdatesStill need to figure out the best way to process MQTT requests to update the
The advantage of proposal 1 is that settings updates will be very fast and Proposal 2 seeks to address the limitations of proposal 1, at the expense of Another design choice that needs to be evaluated is the granularity of the MQTT
Proposals 1/2 look like they would be simpler to implement, at the expense of Proposal 3 seeks to correct this issue, but may come at increased complexity, SummaryIdeally, the end result would allow us to do roughly something like below: Creating the settings struct: // Example Substructure
struct PidSettings {
p: u32,
i: u32,
d: u32,
};
// Primary Settings Structure
#[derive(MqttSettingTrait)]
struct MySettings {
color: Color,
pid1: PidSettings,
pid2: Pidsettings,
} The Idle task: // Create an instance of the settings manager
let settings = MqttSettings<MySettings>::new();
// Idle loop
loop {
// Get messages from MQTT
let message;
// Look at the topic prefix to see if we should hand to the settings manager.
if is_settings_message_topic(message) {
// Process the settings MQTT request, this will update an internal instance of the MySettings struct
settings.parse(message);
}
// If the message is a request to commit the settings
if is_commit_message(message) {
// Schedule the task to commit the settings, pass it a copy of the settings struct
cx.spawn.commit_settings(settings.get_settings()).unwrap();
}
} The commit task: #[task(resources = [led_driver, pid1_settings, pid2_settings])]
fn commit_settings(cx: commit_settings::Context, new_settings: MySettings) {
// Use the color setting to change the LED color
cx.resources.led_driver.lock(|led_driver| {
// Write to the LEDs
led_driver.write(new_settings.color);
});
// For the PID settings, just copy to the relevant resources
*cx.resources.pid1_settings = new_settings.pid1;
// If PID2 used a different structure for it's settings, just drive the From/Into trait
*cx.resources.pid2_settings = new_settings.pid2.into();
} External to the device, we publish an MQTT message to the |
261: MQTT settings and telemetry r=ryan-summers a=ryan-summers This PR replaces #242 This PR addresses #149 by exposing a simple MQTT-based settings interface **TODO**: - [x] Resolve mutable ownership issues in the `MqttInterface` - [x] Expand settings interface to `lockin.rs` - [x] Add all settings (not yet supported by `miniconf`) - [x] ~~Finalize and publish the `miniconf` package~~ Deferred to the future. - [x] Move `MqttInterface`-like behaviors over to `miniconf` - [x] Move smoltcp-nal to a separate crate - [x] Test on hardware - [x] ~~Implement stabilizer telemetry~~: Deferred to future Co-authored-by: Ryan Summers <[email protected]> Co-authored-by: Robert Jördens <[email protected]>
To make MQTT easy to deploy on Stabilizer (and Thermostat, Thermostat_EEM, Driver, Booster, Humpback etc.) we need to reduce it's footprint in the code by developing some kind of framework.
Status quo
For Stabilizer we have currently to route the json-over-TCP requests:
stabilizer/src/main.rs
Lines 109 to 158 in 66c917b
For Booster there is a sizeable amount of request routing, deserialization, serialization code. Adding a setting or telemetry quantity to the stack requires multiple adjustment in several different places.
Ideas
(ripped from #147): Stabilizer is somewhat similar to redpid (https://github.com/quartiq/redpid). Redpid has a pretty convenient solution to the settings/status problem. For migen/misoc we have a very generic way of configuration-status-registers. They are instantiated in code with a single line (e.g. https://github.com/quartiq/redpid/blob/master/gateware/limit.py#L55) and then end up on a bus with mapping generated automatically (https://github.com/quartiq/redpid/blob/master/test/csrmap.py#L109).
This is very different from Stabilizer in terms of code (HDL versus machine) and transport/protocol (HDL bus CSRs over other buses and serialization versus MQTT) but the user-facing concept is the same: lots of knobs and displays on a big switchboard. The knobs being connected to settings and the displays being connected to telemetry.
Maybe for Stabilizer we want something similar (a named map of settings and status values).
The settings aspect should be double-buffered/paged/ping-pong to allow atomic updates of multiple settings synchronously without having to transfer the entire settings space.
And we need to think a bit about the status telemetry: There might be a case for configurable rates and suppression of some telemetry updates.
Context
The text was updated successfully, but these errors were encountered: