diff --git a/Cargo.lock b/Cargo.lock index 4beef55..2f9d971 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,21 +187,6 @@ dependencies = [ "generic-array 0.14.7", ] -[[package]] -name = "bootloader" -version = "0.1.0" -dependencies = [ - "cortex-m", - "cortex-m-rt", - "defmt", - "defmt-rtt", - "embassy-boot-rp", - "embassy-rp", - "embassy-sync", - "embassy-time", - "embedded-storage", -] - [[package]] name = "buffered-io" version = "0.2.1" @@ -293,7 +278,6 @@ checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" dependencies = [ "bare-metal", "bitfield", - "critical-section", "embedded-hal 0.2.7", "volatile-register", ] @@ -634,6 +618,7 @@ name = "embassy-embedded-hal" version = "0.1.0" source = "git+https://github.com/embassy-rs/embassy#af7c93abba768057f1d3299c7b4f4aa4501b3e56" dependencies = [ + "defmt", "embassy-futures", "embassy-sync", "embassy-time", @@ -1246,6 +1231,30 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "impl-tools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d82c305b1081f1a99fda262883c788e50ab57d36c00830bdd7e0a82894ad965c" +dependencies = [ + "autocfg", + "impl-tools-lib", + "proc-macro-error", + "syn 2.0.29", +] + +[[package]] +name = "impl-tools-lib" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85d3946d886eaab0702fa0c6585adcced581513223fa9df7ccfabbd9fa331a88" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.29", +] + [[package]] name = "indexmap" version = "2.0.0" @@ -1758,6 +1767,7 @@ dependencies = [ "dsmr5", "embassy-boot", "embassy-boot-rp", + "embassy-embedded-hal", "embassy-executor", "embassy-futures", "embassy-net", @@ -2141,12 +2151,14 @@ dependencies = [ "defmt", "defmt-rtt", "embassy-boot", + "embassy-futures", "embassy-net", "embassy-time", "embedded-io-async", "embedded-storage", "embedded-tls", "heapless 0.7.16", + "impl-tools", "nourl", "rand_core", "reqwless", diff --git a/Cargo.toml b/Cargo.toml index 86ddcdc..305d0ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ embassy-executor = { version = "0.3", features = [ "nightly", "integrated-timers", ] } +embassy-embedded-hal = { version = "0.1", features = ["defmt", "nightly"]} embassy-rp = { version = "0.1", features = [ "defmt", "unstable-traits", @@ -91,6 +92,7 @@ updater = { path = "../iot_tools/updater" } [patch.crates-io] embassy-executor = { git = "https://github.com/embassy-rs/embassy" } +embassy-embedded-hal = { git = "https://github.com/embassy-rs/embassy" } embassy-rp = { git = "https://github.com/embassy-rs/embassy" } embassy-time = { git = "https://github.com/embassy-rs/embassy" } embassy-net = { git = "https://github.com/embassy-rs/embassy" } diff --git a/src/main.rs b/src/main.rs index 1d164be..8471fae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,10 +2,10 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::cell::RefCell; +use core::{cell::RefCell, str::from_utf8}; use embassy_boot_rp::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; -use heapless::{String, Vec}; +use heapless::Vec; use rand::{ rngs::{SmallRng, StdRng}, RngCore, SeedableRng, @@ -43,7 +43,6 @@ use rust_mqtt::{ }, packet::v5::publish_packet::QualityOfService, }; -use serde::Deserialize; use static_cell::make_static; use const_format::formatcp; @@ -65,17 +64,6 @@ const PUBLIC_SIGNING_KEY: &[u8] = include_bytes!("../key.pub"); const FLASH_SIZE: usize = 2 * 1024 * 1024; -#[derive(Deserialize)] -struct UpdateMessage<'a> { - url: &'a str, -} - -impl UpdateMessage<'_> { - fn get_url(&self) -> String<1024> { - self.url.into() - } -} - #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner< @@ -187,6 +175,17 @@ async fn main(spawner: Spawner) { let channel = make_static!(Channel::::new()); + // TODO: Ideally we use async flash + // This has issues with alignment right now + let flash = Flash::<_, _, FLASH_SIZE>::new_blocking(p.FLASH); + let flash = Mutex::new(RefCell::new(flash)); + + let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); + let mut aligned = AlignedBuffer([0; WRITE_SIZE]); + let updater = BlockingFirmwareUpdater::new(config, &mut aligned.0); + + let mut updater = updater::Updater::new(updater, TOPIC_STATUS, VERSION, PUBLIC_SIGNING_KEY); + // === UART === let mut config = uart::Config::default(); config.parity = Parity::ParityNone; @@ -276,8 +275,6 @@ async fn main(spawner: Spawner) { } info!("TCP Connected!"); - let up = updater::Updater::new(TOPIC_STATUS, TOPIC_UPDATE, VERSION, PUBLIC_SIGNING_KEY); - let mut config = ClientConfig::new( MqttVersion::MQTTv5, // Use fast and simple PRNG to generate packet identifiers, there is no need for this to be @@ -289,7 +286,7 @@ async fn main(spawner: Spawner) { config.add_password(env!("MQTT_PASSWORD")); config.add_max_subscribe_qos(QualityOfService::QoS1); config.add_client_id(ID); - up.add_will(&mut config); + updater.add_will(&mut config); let mut recv_buffer = [0; 1024]; let mut write_buffer = [0; 1024]; @@ -301,19 +298,8 @@ async fn main(spawner: Spawner) { client.connect_to_broker().await.unwrap(); info!("MQTT Connected!"); - // TODO: Ideally we use async flash - // This has issues with alignment right now - let flash = Flash::<_, _, FLASH_SIZE>::new_blocking(p.FLASH); - let flash = Mutex::new(RefCell::new(flash)); - - let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); - let mut aligned = AlignedBuffer([0; WRITE_SIZE]); - let mut updater = BlockingFirmwareUpdater::new(config, &mut aligned.0); - - // We wait with marking as booted until everything is connected - updater.mark_booted().unwrap(); - - up.ready(&mut client).await; + client.subscribe_to_topic(TOPIC_UPDATE).await.unwrap(); + updater.ready(&mut client).await.unwrap(); // Turn LED off when connected control.gpio_set(0, false).await; @@ -342,26 +328,39 @@ async fn main(spawner: Spawner) { .await .unwrap(); } - Either3::Third(message) => { - let message = match message { - Ok(message) => message, - Err(err) => { - error!("Failed to receive MQTT message: {}", err); - continue; - } - }; - - let message = match serde_json_core::from_slice::(message.1) { - Ok((message, _)) => message, + Either3::Third(Ok((TOPIC_UPDATE, url))) => { + let url: Vec<_, 256> = match Vec::from_slice(url) { + Ok(url) => url, Err(_) => { - error!("Unable to parse update message"); + error!("URL is longer then buffer size"); + continue; + } + }; + let url = match from_utf8(&url) { + Ok(url) => url, + Err(err) => { + error!("Url is not valid utf-8 string: {}", Display2Format(&err)); + continue; + } + }; + let url = match Url::parse(url) { + Ok(url) => url, + Err(err) => { + error!("Failed to parse url: {}", err); continue; } }; - let url = message.get_url(); - let url = Url::parse(url.as_str()).unwrap(); - up.update(stack, &mut updater, &mut rng, &mut client, url).await; + if let Err(err) = updater.update(url, stack, &mut rng, &mut client).await { + error!("Update failed: {}", err) + } + } + Either3::Third(Ok(_)) => { + warn!("No handler for mqtt message"); + } + Either3::Third(Err(err)) => { + error!("Failed to receive MQTT message: {}", err); + continue; } } } @@ -379,4 +378,3 @@ async fn wait_for_config( yield_now().await; } } -