Compare commits
2 Commits
a7a052d4ce
...
3b6acbd65e
Author | SHA1 | Date | |
---|---|---|---|
3b6acbd65e | |||
0a7edc50e8 |
50
Cargo.lock
generated
50
Cargo.lock
generated
|
@ -265,6 +265,26 @@ version = "0.9.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
|
||||
|
||||
[[package]]
|
||||
name = "const_format"
|
||||
version = "0.2.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48"
|
||||
dependencies = [
|
||||
"const_format_proc_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_format_proc_macros"
|
||||
version = "0.2.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.7.7"
|
||||
|
@ -1101,6 +1121,28 @@ dependencies = [
|
|||
"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]]
|
||||
name = "group"
|
||||
version = "0.13.0"
|
||||
|
@ -1578,6 +1620,12 @@ dependencies = [
|
|||
"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]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
|
@ -1710,6 +1758,7 @@ name = "rp"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"const_format",
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"crc16",
|
||||
|
@ -1730,6 +1779,7 @@ dependencies = [
|
|||
"embassy-usb",
|
||||
"embedded-io-async",
|
||||
"embedded-storage",
|
||||
"git-version",
|
||||
"heapless 0.7.16",
|
||||
"log",
|
||||
"nourl",
|
||||
|
|
|
@ -82,6 +82,8 @@ smoltcp = { version = "0.10.0", default-features = false, features = [
|
|||
nourl = { version = "0.1.1", features = ["defmt"] }
|
||||
reqwless = { version = "0.5.0", features = ["defmt"] }
|
||||
embedded-storage = "0.3.0"
|
||||
const_format = "0.2.31"
|
||||
git-version = "0.3.5"
|
||||
|
||||
[patch.crates-io]
|
||||
embassy-executor = { git = "https://github.com/embassy-rs/embassy" }
|
||||
|
|
81
src/main.rs
81
src/main.rs
|
@ -30,7 +30,7 @@ use embassy_rp::{
|
|||
uart::{self, BufferedUartRx, Parity},
|
||||
};
|
||||
use embassy_sync::{
|
||||
blocking_mutex::{Mutex, raw::NoopRawMutex},
|
||||
blocking_mutex::{raw::NoopRawMutex, Mutex},
|
||||
channel::{Channel, Sender},
|
||||
};
|
||||
use embassy_time::{Duration, Ticker, Timer};
|
||||
|
@ -49,10 +49,11 @@ use rust_mqtt::{
|
|||
},
|
||||
packet::v5::publish_packet::QualityOfService,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use static_cell::make_static;
|
||||
|
||||
use defmt::{debug, error, info, warn, Debug2Format, Format};
|
||||
use const_format::formatcp;
|
||||
use defmt::{debug, error, info, warn, Debug2Format};
|
||||
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
|
@ -61,7 +62,13 @@ bind_interrupts!(struct Irqs {
|
|||
PIO0_IRQ_0 => pio::InterruptHandler<PIO0>;
|
||||
});
|
||||
|
||||
#[derive(Format, Deserialize)]
|
||||
const ID: &str = env!("ID");
|
||||
const TOPIC_BASE: &str = formatcp!("pico/{}", ID);
|
||||
const TOPIC_STATUS: &str = formatcp!("{}/status", TOPIC_BASE);
|
||||
const TOPIC_UPDATE: &str = formatcp!("{}/update", TOPIC_BASE);
|
||||
const VERSION: &str = git_version::git_version!();
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UpdateMessage<'a> {
|
||||
url: &'a str,
|
||||
}
|
||||
|
@ -72,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]
|
||||
async fn wifi_task(
|
||||
runner: cyw43::Runner<
|
||||
|
@ -281,9 +306,10 @@ async fn main(spawner: Spawner) {
|
|||
config.add_username(env!("MQTT_USERNAME"));
|
||||
config.add_password(env!("MQTT_PASSWORD"));
|
||||
config.add_max_subscribe_qos(QualityOfService::QoS1);
|
||||
config.add_client_id("pico");
|
||||
config.add_client_id(ID);
|
||||
// Leads to InsufficientBufferSize error
|
||||
config.add_will("pico/test", 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 write_buffer = [0; 4096];
|
||||
|
@ -307,12 +333,13 @@ async fn main(spawner: Spawner) {
|
|||
// We wait with marking as booted until everything is connected
|
||||
updater.mark_booted().unwrap();
|
||||
|
||||
let status = Status::Connected { version: VERSION }.vec();
|
||||
client
|
||||
.send_message("pico/test", b"connected", QualityOfService::QoS1, true)
|
||||
.send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, true)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
client.subscribe_to_topic("pico/test/update").await.unwrap();
|
||||
client.subscribe_to_topic(TOPIC_UPDATE).await.unwrap();
|
||||
|
||||
// Turn LED off when connected
|
||||
control.gpio_set(0, false).await;
|
||||
|
@ -337,7 +364,7 @@ async fn main(spawner: Spawner) {
|
|||
.expect("The buffer should be large enough to contain all the data");
|
||||
|
||||
client
|
||||
.send_message("pico/test", &msg, QualityOfService::QoS1, false)
|
||||
.send_message(TOPIC_BASE, &msg, QualityOfService::QoS1, false)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -386,13 +413,18 @@ async fn attempt_update<T, const MAX_PROPERTIES: usize, R, F>(
|
|||
updater: &mut BlockingFirmwareUpdater<'_, F, F>,
|
||||
client: &mut MqttClient<'_, T, MAX_PROPERTIES, R>,
|
||||
url: Url<'_>,
|
||||
)
|
||||
where
|
||||
) where
|
||||
T: embedded_io_async::Write + embedded_io_async::Read,
|
||||
R: rand::RngCore,
|
||||
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 mut rx_buffer = [0; 4096 * 2];
|
||||
|
@ -417,9 +449,10 @@ where
|
|||
|
||||
let mut body = resp.body().reader();
|
||||
|
||||
debug!("Preparing updater...");
|
||||
debug!("Erasing flash...");
|
||||
let status = Status::Erasing.vec();
|
||||
client
|
||||
.send_message("pico/test", b"preparing", QualityOfService::QoS1, false)
|
||||
.send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -428,9 +461,10 @@ where
|
|||
.map_err(|e| warn!("E: {:?}", Debug2Format(&e)))
|
||||
.unwrap();
|
||||
|
||||
debug!("Updater prepared!");
|
||||
debug!("Writing...");
|
||||
let status = Status::Writing { progress: 0 }.vec();
|
||||
client
|
||||
.send_message("pico/test", b"prepared", QualityOfService::QoS1, false)
|
||||
.send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -440,20 +474,23 @@ where
|
|||
if read == 0 {
|
||||
break;
|
||||
}
|
||||
debug!("Chunk size: {}", read);
|
||||
debug!("Writing chunk: {}", read);
|
||||
writer.write(offset, &buffer.0[..read]).unwrap();
|
||||
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("pico/test", b"written", QualityOfService::QoS1, false)
|
||||
.await
|
||||
.unwrap();
|
||||
debug!("Total size: {}", offset);
|
||||
|
||||
updater.mark_updated().unwrap();
|
||||
|
||||
let status = Status::UpdateComplete.vec();
|
||||
client
|
||||
.send_message("pico/test", b"restarting", QualityOfService::QoS1, false)
|
||||
.send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user