Compare commits

..

5 Commits

5 changed files with 173 additions and 118 deletions

145
Cargo.lock generated
View File

@@ -265,6 +265,26 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" 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]] [[package]]
name = "cortex-m" name = "cortex-m"
version = "0.7.7" version = "0.7.7"
@@ -543,6 +563,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "ed25519"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
dependencies = [
"signature",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.9.0" version = "1.9.0"
@@ -579,6 +608,7 @@ dependencies = [
"embassy-sync", "embassy-sync",
"embedded-storage", "embedded-storage",
"embedded-storage-async", "embedded-storage-async",
"salty",
"signature", "signature",
] ]
@@ -764,21 +794,6 @@ dependencies = [
"heapless 0.7.16", "heapless 0.7.16",
] ]
[[package]]
name = "embassy-usb"
version = "0.1.0"
source = "git+https://github.com/embassy-rs/embassy#af7c93abba768057f1d3299c7b4f4aa4501b3e56"
dependencies = [
"defmt",
"embassy-futures",
"embassy-net-driver-channel",
"embassy-sync",
"embassy-usb-driver",
"heapless 0.7.16",
"ssmarshal",
"usbd-hid",
]
[[package]] [[package]]
name = "embassy-usb-driver" name = "embassy-usb-driver"
version = "0.1.0" version = "0.1.0"
@@ -911,12 +926,6 @@ dependencies = [
"log", "log",
] ]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@@ -1101,6 +1110,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"
@@ -1578,6 +1609,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"
@@ -1710,9 +1747,9 @@ name = "rp"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"const_format",
"cortex-m", "cortex-m",
"cortex-m-rt", "cortex-m-rt",
"crc16",
"cyw43", "cyw43",
"cyw43-pio", "cyw43-pio",
"defmt", "defmt",
@@ -1727,11 +1764,10 @@ dependencies = [
"embassy-rp", "embassy-rp",
"embassy-sync", "embassy-sync",
"embassy-time", "embassy-time",
"embassy-usb",
"embedded-io-async", "embedded-io-async",
"embedded-storage", "embedded-storage",
"git-version",
"heapless 0.7.16", "heapless 0.7.16",
"log",
"nourl", "nourl",
"panic-probe", "panic-probe",
"rand", "rand",
@@ -1816,6 +1852,16 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "salty"
version = "0.2.0"
source = "git+https://github.com/ycrypto/salty.git?rev=a9f17911a5024698406b75c0fac56ab5ccf6a8c7#a9f17911a5024698406b75c0fac56ab5ccf6a8c7"
dependencies = [
"ed25519",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@@ -1939,16 +1985,6 @@ dependencies = [
"lock_api", "lock_api",
] ]
[[package]]
name = "ssmarshal"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850"
dependencies = [
"encode_unicode",
"serde",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.0" version = "1.2.0"
@@ -2094,47 +2130,6 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "usb-device"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508"
[[package]]
name = "usbd-hid"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "975bd411f4a939986751ea09992a24fa47c4d25c6ed108d04b4c2999a4fd0132"
dependencies = [
"serde",
"ssmarshal",
"usb-device",
"usbd-hid-macros",
]
[[package]]
name = "usbd-hid-descriptors"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcbee8c6735e90894fba04770bc41e11fd3c5256018856e15dc4dd1e6c8a3dd1"
dependencies = [
"bitfield",
]
[[package]]
name = "usbd-hid-macros"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "261079a9ada015fa1acac7cc73c98559f3a92585e15f508034beccf6a2ab75a2"
dependencies = [
"byteorder",
"proc-macro2",
"quote",
"serde",
"syn 1.0.109",
"usbd-hid-descriptors",
]
[[package]] [[package]]
name = "vcell" name = "vcell"
version = "0.1.3" version = "0.1.3"

View File

@@ -28,14 +28,17 @@ embassy-rp = { version = "0.1", features = [
"critical-section-impl", "critical-section-impl",
] } ] }
embassy-boot-rp = { version = "0.1", features = ["nightly", "defmt"] } embassy-boot-rp = { version = "0.1", features = ["nightly", "defmt"] }
embassy-boot = { version = "0.1", features = ["nightly", "defmt"] } embassy-boot = { version = "0.1", features = [
"nightly",
"defmt",
"ed25519-salty",
] }
embassy-time = { version = "0.1", features = [ embassy-time = { version = "0.1", features = [
"defmt", "defmt",
"unstable-traits", "unstable-traits",
"defmt-timestamp-uptime", "defmt-timestamp-uptime",
"nightly", "nightly",
] } ] }
embassy-usb = { version = "0.1", features = ["defmt"] }
embassy-net = { version = "0.1", features = [ embassy-net = { version = "0.1", features = [
"tcp", "tcp",
"dhcpv4", "dhcpv4",
@@ -54,11 +57,9 @@ cyw43-pio = { git = "https://github.com/embassy-rs/embassy", features = [
"defmt", "defmt",
] } ] }
panic-probe = { version = "0.3", features = ["print-defmt"] } panic-probe = { version = "0.3", features = ["print-defmt"] }
log = "0.4"
static_cell = { version = "1.1", features = ["nightly"] } static_cell = { version = "1.1", features = ["nightly"] }
heapless = { version = "0.7.16", features = ["defmt", "serde"] } heapless = { version = "0.7.16", features = ["defmt", "serde"] }
embedded-io-async = { version = "0.5", features = ["defmt-03"] } embedded-io-async = { version = "0.5", features = ["defmt-03"] }
crc16 = "0.4"
dsmr5 = "0.3" dsmr5 = "0.3"
rust-mqtt = { version = "0.1.5", features = [ rust-mqtt = { version = "0.1.5", features = [
"defmt", "defmt",
@@ -82,21 +83,25 @@ smoltcp = { version = "0.10.0", default-features = false, features = [
nourl = { version = "0.1.1", features = ["defmt"] } 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"
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" }
embassy-rp = { 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-time = { git = "https://github.com/embassy-rs/embassy" }
embassy-usb = { git = "https://github.com/embassy-rs/embassy" }
embassy-net = { git = "https://github.com/embassy-rs/embassy" } embassy-net = { git = "https://github.com/embassy-rs/embassy" }
embassy-sync = { git = "https://github.com/embassy-rs/embassy" } embassy-sync = { git = "https://github.com/embassy-rs/embassy" }
embassy-futures = { git = "https://github.com/embassy-rs/embassy" } embassy-futures = { git = "https://github.com/embassy-rs/embassy" }
embassy-boot-rp = { git = "https://github.com/embassy-rs/embassy" } embassy-boot-rp = { git = "https://github.com/embassy-rs/embassy" }
embassy-boot = { git = "https://github.com/embassy-rs/embassy" } embassy-boot = { git = "https://github.com/embassy-rs/embassy" }
# Updated to embedded-io 0.5.0
rust-mqtt = { git = "https://git.huizinga.dev/Dreaded_X/rust-mqtt" } rust-mqtt = { git = "https://git.huizinga.dev/Dreaded_X/rust-mqtt" }
# Make mqtt:// and mqtts:// actually work
nourl = { git = "https://git.huizinga.dev/Dreaded_X/nourl" } nourl = { git = "https://git.huizinga.dev/Dreaded_X/nourl" }
# Waiting for this to get updated to embedded-io 0.5 properly
reqwless = { path = "../reqwless" } reqwless = { path = "../reqwless" }
[build-dependencies] [build-dependencies]

BIN
key.pub Normal file

Binary file not shown.

9
release.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
mkdir -p target/firmware
cargo objcopy --release --features=exclude_firmwares -- -O binary target/firmware/firmware
shasum -a 512 -b target/firmware/firmware | dd ibs=128 count=1 | xxd -p -r > target/firmware/checksum
signify -S -m target/firmware/checksum -s ~/Projects/crypt/R0/private/keys/firmware/pico_p1.sec -x target/firmware/checksum.sig
tail -n1 target/firmware/checksum.sig | base64 -d -i | dd ibs=10 skip=1 > target/firmware/signed
cat target/firmware/signed > target/firmware/firmware+signed
cat target/firmware/firmware >> target/firmware/firmware+signed

View File

@@ -25,12 +25,12 @@ use embassy_rp::{
clocks::RoscRng, clocks::RoscRng,
flash::{Flash, WRITE_SIZE}, flash::{Flash, WRITE_SIZE},
gpio::{Level, Output}, gpio::{Level, Output},
peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0, UART0}, peripherals::{DMA_CH1, PIN_23, PIN_25, PIO0, UART0},
pio::{self, Pio}, pio::{self, Pio},
uart::{self, BufferedUartRx, Parity}, uart::{self, Async, Parity, UartRx},
}; };
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,19 +49,27 @@ 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 defmt::{debug, error, info, warn, Debug2Format, Format}; use const_format::formatcp;
use defmt::{debug, error, info, trace, warn, Debug2Format};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs { bind_interrupts!(struct Irqs {
UART0_IRQ => uart::BufferedInterruptHandler<UART0>; UART0_IRQ => uart::InterruptHandler<UART0>;
PIO0_IRQ_0 => pio::InterruptHandler<PIO0>; 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!();
const PUBLIC_SIGNING_KEY: &[u8] = include_bytes!("../key.pub");
#[derive(Deserialize)]
struct UpdateMessage<'a> { struct UpdateMessage<'a> {
url: &'a str, url: &'a str,
} }
@@ -72,12 +80,30 @@ 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<
'static, 'static,
Output<'static, PIN_23>, Output<'static, PIN_23>,
PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH1>,
>, >,
) -> ! { ) -> ! {
runner.run().await runner.run().await
@@ -88,14 +114,14 @@ async fn net_task(stack: &'static Stack<cyw43::NetDriver<'static>>) -> ! {
stack.run().await stack.run().await
} }
async fn get_readout(rx: &mut BufferedUartRx<'static, UART0>) -> Readout { async fn get_readout(rx: &mut UartRx<'static, UART0, Async>) -> Readout {
let mut buffer: Vec<u8, 2048> = Vec::new(); let mut buffer: Vec<u8, 2048> = Vec::new();
buffer.push(b'/').unwrap(); buffer.push(b'/').unwrap();
let mut byte = [0; 1]; let mut byte = [0; 1];
debug!("Waiting for next telegram..."); debug!("Waiting for next telegram...");
loop { loop {
rx.read_exact(&mut byte).await.unwrap(); rx.read(&mut byte).await.unwrap();
if byte[0] == b'/' { if byte[0] == b'/' {
break; break;
@@ -112,7 +138,7 @@ async fn get_readout(rx: &mut BufferedUartRx<'static, UART0>) -> Readout {
debug!("Start of CRC detected"); debug!("Start of CRC detected");
let mut crc = [0; 4]; let mut crc = [0; 4];
rx.read_exact(&mut crc).await.unwrap(); rx.read(&mut crc).await.unwrap();
buffer.extend_from_slice(&crc).unwrap(); buffer.extend_from_slice(&crc).unwrap();
@@ -130,7 +156,7 @@ async fn get_readout(rx: &mut BufferedUartRx<'static, UART0>) -> Readout {
#[embassy_executor::task] #[embassy_executor::task]
async fn uart_rx_task( async fn uart_rx_task(
mut rx: BufferedUartRx<'static, UART0>, mut rx: UartRx<'static, UART0, Async>,
sender: Sender<'static, NoopRawMutex, dsmr5::state::State, 1>, sender: Sender<'static, NoopRawMutex, dsmr5::state::State, 1>,
) { ) {
info!("Wating for serial data"); info!("Wating for serial data");
@@ -188,8 +214,7 @@ async fn main(spawner: Spawner) {
config.parity = Parity::ParityNone; config.parity = Parity::ParityNone;
// config.invert_rx = true; // config.invert_rx = true;
let buf = make_static!([0u8; 2048]); let rx = UartRx::new(p.UART0, p.PIN_17, Irqs, p.DMA_CH0, config);
let rx = BufferedUartRx::new_with_rts(p.UART0, Irqs, p.PIN_1, p.PIN_3, buf, config);
spawner.spawn(uart_rx_task(rx, channel.sender())).unwrap(); spawner.spawn(uart_rx_task(rx, channel.sender())).unwrap();
@@ -204,7 +229,7 @@ async fn main(spawner: Spawner) {
cs, cs,
p.PIN_24, p.PIN_24,
p.PIN_29, p.PIN_29,
p.DMA_CH0, p.DMA_CH1,
); );
let (fw, clm) = unsafe { get_firmware() }; let (fw, clm) = unsafe { get_firmware() };
@@ -281,9 +306,10 @@ async fn main(spawner: Spawner) {
config.add_username(env!("MQTT_USERNAME")); config.add_username(env!("MQTT_USERNAME"));
config.add_password(env!("MQTT_PASSWORD")); config.add_password(env!("MQTT_PASSWORD"));
config.add_max_subscribe_qos(QualityOfService::QoS1); config.add_max_subscribe_qos(QualityOfService::QoS1);
config.add_client_id("pico"); config.add_client_id(ID);
// Leads to InsufficientBufferSize error // 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 recv_buffer = [0; 1024];
let mut write_buffer = [0; 4096]; 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 // 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("pico/test", b"connected", QualityOfService::QoS1, true) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, true)
.await .await
.unwrap(); .unwrap();
client.subscribe_to_topic("pico/test/update").await.unwrap(); client.subscribe_to_topic(TOPIC_UPDATE).await.unwrap();
// Turn LED off when connected // Turn LED off when connected
control.gpio_set(0, false).await; 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"); .expect("The buffer should be large enough to contain all the data");
client client
.send_message("pico/test", &msg, QualityOfService::QoS1, false) .send_message(TOPIC_BASE, &msg, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();
} }
@@ -386,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];
@@ -417,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("pico/test", b"preparing", QualityOfService::QoS1, false) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();
@@ -428,32 +461,45 @@ 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("pico/test", b"prepared", QualityOfService::QoS1, false) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();
// The first 64 bytes of the file contain the signature
let mut signature = [0; 64];
body.read_exact(&mut signature).await.unwrap();
trace!("Signature: {:?}", signature);
let mut buffer = AlignedBuffer([0; 4096]); let mut buffer = AlignedBuffer([0; 4096]);
let mut offset = 0; let mut size = 0;
while let Ok(read) = body.read(&mut buffer.0).await { while let Ok(read) = body.read(&mut buffer.0).await {
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(size, &buffer.0[..read]).unwrap();
offset += read as u32; size += read as u32;
}
let status = Status::Writing { progress: size }.vec();
client client
.send_message("pico/test", b"written", QualityOfService::QoS1, false) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();
debug!("Total size: {}", offset); }
debug!("Total size: {}", size);
updater.mark_updated().unwrap(); updater.verify_and_mark_updated(PUBLIC_SIGNING_KEY, &signature, size).unwrap();
// Update mqtt message should be send using retain
// TODO: Clear the message
let status = Status::UpdateComplete.vec();
client client
.send_message("pico/test", b"restarting", QualityOfService::QoS1, false) .send_message(TOPIC_STATUS, &status, QualityOfService::QoS1, false)
.await .await
.unwrap(); .unwrap();