Improved status reporting

This commit is contained in:
Dreaded_X 2023-09-07 01:45:41 +02:00
parent 0a7edc50e8
commit 3b6acbd65e
Signed by: Dreaded_X
GPG Key ID: FA5F485356B0D2D4
3 changed files with 80 additions and 19 deletions

29
Cargo.lock generated
View File

@ -1121,6 +1121,28 @@ dependencies = [
"polyval", "polyval",
] ]
[[package]]
name = "git-version"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899"
dependencies = [
"git-version-macro",
"proc-macro-hack",
]
[[package]]
name = "git-version-macro"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "group" name = "group"
version = "0.13.0" version = "0.13.0"
@ -1598,6 +1620,12 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "proc-macro-hack"
version = "0.5.20+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.66" version = "1.0.66"
@ -1751,6 +1779,7 @@ dependencies = [
"embassy-usb", "embassy-usb",
"embedded-io-async", "embedded-io-async",
"embedded-storage", "embedded-storage",
"git-version",
"heapless 0.7.16", "heapless 0.7.16",
"log", "log",
"nourl", "nourl",

View File

@ -83,6 +83,7 @@ nourl = { version = "0.1.1", features = ["defmt"] }
reqwless = { version = "0.5.0", features = ["defmt"] } reqwless = { version = "0.5.0", features = ["defmt"] }
embedded-storage = "0.3.0" embedded-storage = "0.3.0"
const_format = "0.2.31" const_format = "0.2.31"
git-version = "0.3.5"
[patch.crates-io] [patch.crates-io]
embassy-executor = { git = "https://github.com/embassy-rs/embassy" } embassy-executor = { git = "https://github.com/embassy-rs/embassy" }

View File

@ -30,7 +30,7 @@ use embassy_rp::{
uart::{self, BufferedUartRx, Parity}, uart::{self, BufferedUartRx, Parity},
}; };
use embassy_sync::{ use embassy_sync::{
blocking_mutex::{Mutex, raw::NoopRawMutex}, blocking_mutex::{raw::NoopRawMutex, Mutex},
channel::{Channel, Sender}, channel::{Channel, Sender},
}; };
use embassy_time::{Duration, Ticker, Timer}; use embassy_time::{Duration, Ticker, Timer};
@ -49,11 +49,11 @@ use rust_mqtt::{
}, },
packet::v5::publish_packet::QualityOfService, packet::v5::publish_packet::QualityOfService,
}; };
use serde::Deserialize; use serde::{Deserialize, Serialize};
use static_cell::make_static; use static_cell::make_static;
use const_format::formatcp; use const_format::formatcp;
use defmt::{debug, error, info, warn, Debug2Format, Format}; use defmt::{debug, error, info, warn, Debug2Format};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -66,8 +66,9 @@ const ID: &str = env!("ID");
const TOPIC_BASE: &str = formatcp!("pico/{}", ID); const TOPIC_BASE: &str = formatcp!("pico/{}", ID);
const TOPIC_STATUS: &str = formatcp!("{}/status", TOPIC_BASE); const TOPIC_STATUS: &str = formatcp!("{}/status", TOPIC_BASE);
const TOPIC_UPDATE: &str = formatcp!("{}/update", TOPIC_BASE); const TOPIC_UPDATE: &str = formatcp!("{}/update", TOPIC_BASE);
const VERSION: &str = git_version::git_version!();
#[derive(Format, Deserialize)] #[derive(Deserialize)]
struct UpdateMessage<'a> { struct UpdateMessage<'a> {
url: &'a str, url: &'a str,
} }
@ -78,6 +79,24 @@ impl UpdateMessage<'_> {
} }
} }
#[derive(Serialize)]
#[serde(rename_all = "snake_case", tag = "status")]
enum Status<'a> {
Connected { version: &'a str },
Disconnected,
PreparingUpdate,
Erasing,
Writing { progress: u32 },
UpdateComplete,
}
impl Status<'_> {
fn vec(&self) -> Vec<u8, 1024> {
serde_json_core::to_vec(self)
.expect("The buffer should be large enough to contain all the data")
}
}
#[embassy_executor::task] #[embassy_executor::task]
async fn wifi_task( async fn wifi_task(
runner: cyw43::Runner< runner: cyw43::Runner<
@ -289,7 +308,8 @@ async fn main(spawner: Spawner) {
config.add_max_subscribe_qos(QualityOfService::QoS1); config.add_max_subscribe_qos(QualityOfService::QoS1);
config.add_client_id(ID); config.add_client_id(ID);
// Leads to InsufficientBufferSize error // Leads to InsufficientBufferSize error
config.add_will(TOPIC_STATUS, b"disconnected", true); let msg: &Vec<_, 1024> = make_static!(Status::Disconnected.vec());
config.add_will(TOPIC_STATUS, &msg, true);
let mut recv_buffer = [0; 1024]; let mut recv_buffer = [0; 1024];
let mut write_buffer = [0; 4096]; let mut write_buffer = [0; 4096];
@ -313,8 +333,9 @@ async fn main(spawner: Spawner) {
// We wait with marking as booted until everything is connected // We wait with marking as booted until everything is connected
updater.mark_booted().unwrap(); updater.mark_booted().unwrap();
let status = Status::Connected { version: VERSION }.vec();
client client
.send_message(TOPIC_STATUS, b"connected", QualityOfService::QoS1, true) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, true)
.await .await
.unwrap(); .unwrap();
@ -392,13 +413,18 @@ async fn attempt_update<T, const MAX_PROPERTIES: usize, R, F>(
updater: &mut BlockingFirmwareUpdater<'_, F, F>, updater: &mut BlockingFirmwareUpdater<'_, F, F>,
client: &mut MqttClient<'_, T, MAX_PROPERTIES, R>, client: &mut MqttClient<'_, T, MAX_PROPERTIES, R>,
url: Url<'_>, url: Url<'_>,
) ) where
where
T: embedded_io_async::Write + embedded_io_async::Read, T: embedded_io_async::Write + embedded_io_async::Read,
R: rand::RngCore, R: rand::RngCore,
F: NorFlash, F: NorFlash,
{ {
info!("Installing OTA..."); info!("Preparing for OTA...");
let status = Status::PreparingUpdate.vec();
client
.send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await
.unwrap();
let ip = stack.dns_query(url.host(), DnsQueryType::A).await.unwrap()[0]; let ip = stack.dns_query(url.host(), DnsQueryType::A).await.unwrap()[0];
let mut rx_buffer = [0; 4096 * 2]; let mut rx_buffer = [0; 4096 * 2];
@ -423,9 +449,10 @@ where
let mut body = resp.body().reader(); let mut body = resp.body().reader();
debug!("Preparing updater..."); debug!("Erasing flash...");
let status = Status::Erasing.vec();
client client
.send_message(TOPIC_STATUS, b"preparing", QualityOfService::QoS1, false) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();
@ -434,9 +461,10 @@ where
.map_err(|e| warn!("E: {:?}", Debug2Format(&e))) .map_err(|e| warn!("E: {:?}", Debug2Format(&e)))
.unwrap(); .unwrap();
debug!("Updater prepared!"); debug!("Writing...");
let status = Status::Writing { progress: 0 }.vec();
client client
.send_message(TOPIC_STATUS, b"prepared", QualityOfService::QoS1, false) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();
@ -446,20 +474,23 @@ where
if read == 0 { if read == 0 {
break; break;
} }
debug!("Chunk size: {}", read); debug!("Writing chunk: {}", read);
writer.write(offset, &buffer.0[..read]).unwrap(); writer.write(offset, &buffer.0[..read]).unwrap();
offset += read as u32; offset += read as u32;
let status = Status::Writing { progress: offset }.vec();
client
.send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await
.unwrap();
} }
client
.send_message(TOPIC_STATUS, b"written", QualityOfService::QoS1, false)
.await
.unwrap();
debug!("Total size: {}", offset); debug!("Total size: {}", offset);
updater.mark_updated().unwrap(); updater.mark_updated().unwrap();
let status = Status::UpdateComplete.vec();
client client
.send_message(TOPIC_STATUS, b"restarting", QualityOfService::QoS1, false) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();