From 8d14964b3e9490097303da6ca324a76637bc5505 Mon Sep 17 00:00:00 2001 From: Mathias Date: Fri, 29 Dec 2023 13:45:55 +0100 Subject: [PATCH] Update dependencies and fix tests --- Cargo.toml | 55 +++-- examples/rpi-pico/Cargo.toml | 17 +- examples/rpi-pico/src/bin/embassy-async.rs | 61 ++--- examples/rpi-pico/src/bin/embassy-perf.rs | 60 ++--- rust-toolchain.toml | 4 +- src/asynch/control.rs | 16 +- src/asynch/mod.rs | 14 +- src/asynch/runner.rs | 44 ++-- src/asynch/ublox_stack/dns.rs | 24 +- src/asynch/ublox_stack/mod.rs | 17 +- src/asynch/ublox_stack/tcp.rs | 9 +- src/blocking/client.rs | 20 +- src/blocking/dns.rs | 2 +- src/blocking/tcp_stack.rs | 12 +- src/blocking/udp_stack.rs | 31 ++- src/command/custom_digest.rs | 6 +- src/command/data_mode/urc.rs | 4 +- src/command/edm/mod.rs | 166 +++++-------- src/command/edm/urc.rs | 8 +- src/command/general/types.rs | 3 +- src/command/ping/types.rs | 3 +- src/command/ping/urc.rs | 3 +- src/connection.rs | 3 +- src/error.rs | 12 +- src/fmt.rs | 258 +++++++++++++++++++++ src/lib.rs | 2 + src/peer_builder.rs | 12 +- src/wifi/mod.rs | 8 +- src/wifi/options.rs | 3 +- src/wifi/supplicant.rs | 25 +- 30 files changed, 559 insertions(+), 343 deletions(-) create mode 100644 src/fmt.rs diff --git a/Cargo.toml b/Cargo.toml index 15ba63b..36bb672 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,34 +15,31 @@ name = "ublox_short_range" doctest = false [dependencies] -atat = { version = "0.19.0", features = ["derive", "defmt", "bytes"] } +atat = { version = "0.20.0", features = ["derive", "bytes"] } # atat = { git = "https://github.com/BlackbirdHQ/atat", rev = "70283be", features = ["derive", "defmt", "bytes"] } -heapless = { version = "^0.7", features = ["serde", "defmt-impl"] } +heapless = { version = "^0.8", features = ["serde"] } no-std-net = { version = "0.6", features = ["serde"] } serde = { version = "^1", default-features = false, features = ["derive"] } -ublox-sockets = { version = "0.5", features = [ - "defmt", - "edm", -], optional = true } +ublox-sockets = { version = "0.5", features = ["edm"], optional = true } postcard = "1.0.4" -smoltcp = { version = "0.9.1", default-features = false, optional = true } -atomic-polyfill = "1.0.2" - -defmt = { version = "0.3" } -embedded-hal = "=1.0.0-rc.1" -# embedded-nal = "0.6.0" -embassy-time = "0.1" -embassy-sync = "0.2" +portable-atomic = "1.5" + +defmt = { version = "0.3", optional = true } +log = { version = "0.4.14", optional = true } + +embedded-hal = "=1.0.0-rc.3" +embassy-time = "0.2" +embassy-sync = "0.5" embassy-futures = "0.1" -embassy-net-driver = "0.1" +embassy-net-driver = "0.2" -embedded-nal-async = { version = "0.5", optional = true } +embedded-nal-async = { version = "0.7", optional = true } futures = { version = "0.3.17", default-features = false, features = [ "async-await", ] } -embedded-io = "0.5" -embedded-io-async = "0.5" +embedded-io = "0.6" +embedded-io-async = "0.6" [features] default = ["async", "odin_w2xx", "ublox-sockets", "socket-tcp"] @@ -51,7 +48,13 @@ async = ["dep:embedded-nal-async", "atat/async", "ublox-sockets?/async"] std = [] -defmt = ["postcard/use-defmt"] +defmt = [ + "dep:defmt", + "postcard/use-defmt", + "heapless/defmt-03", + "atat/defmt", + "ublox-sockets/defmt", +] odin_w2xx = [] nina_w1xx = [] @@ -60,8 +63,14 @@ anna_b1xx = [] nina_b2xx = [] nina_b3xx = [] -socket-tcp = ["ublox-sockets?/socket-tcp", "smoltcp?/socket-tcp"] -socket-udp = ["ublox-sockets?/socket-udp", "smoltcp?/socket-udp"] +socket-tcp = [ + "ublox-sockets?/socket-tcp", + # "smoltcp?/socket-tcp" +] +socket-udp = [ + "ublox-sockets?/socket-udp", + # "smoltcp?/socket-udp" +] [workspace] members = [] @@ -73,4 +82,8 @@ exclude = ["examples"] atat = { path = "../atat/atat" } ublox-sockets = { path = "../ublox-sockets" } no-std-net = { path = "../no-std-net" } + +embassy-time = { path = "../embassy/embassy-time" } +embassy-sync = { path = "../embassy/embassy-sync" } +embassy-futures = { path = "../embassy/embassy-futures" } embassy-net-driver = { path = "../embassy/embassy-net-driver" } diff --git a/examples/rpi-pico/Cargo.toml b/examples/rpi-pico/Cargo.toml index e6c5c10..db9c02d 100644 --- a/examples/rpi-pico/Cargo.toml +++ b/examples/rpi-pico/Cargo.toml @@ -5,25 +5,24 @@ edition = "2021" [dependencies] -ublox-short-range-rs = { path = "../../", features = ["async", "defmt", "odin_w2xx", "ublox-sockets", "socket-tcp"] } -embassy-executor = { version = "0.1.0", features = ["defmt", "integrated-timers", "nightly"] } -embassy-time = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } +ublox-short-range-rs = { path = "../../", features = ["async", "odin_w2xx", "ublox-sockets", "socket-tcp"] } +embassy-executor = { version = "0.4", features = ["defmt", "integrated-timers", "nightly"] } +embassy-time = { version = "0.2", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-pac", "time-driver"] } embassy-futures = { version = "0.1.0" } -atomic-polyfill = "1.0.2" no-std-net = { version = "0.6", features = ["serde"] } -static_cell = { version = "1.1", features = ["nightly"] } +static_cell = { version = "2", features = ["nightly"] } defmt = "0.3.4" -defmt-rtt = "0.3" +defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] } -embedded-io-async = { version = "0.5.0" } -heapless = "0.7.15" +embedded-io-async = { version = "0.6" } +heapless = "0.8" [patch.crates-io] diff --git a/examples/rpi-pico/src/bin/embassy-async.rs b/examples/rpi-pico/src/bin/embassy-async.rs index 498292f..f1467cd 100644 --- a/examples/rpi-pico/src/bin/embassy-async.rs +++ b/examples/rpi-pico/src/bin/embassy-async.rs @@ -67,26 +67,22 @@ async fn echo_task( let ip_addr = match DnsSocket::new(stack).query(hostname, AddrType::IPv4).await { Ok(ip) => ip, Err(_) => { - defmt::error!("[{}] Failed to resolve IP addr", hostname); + error!("[{}] Failed to resolve IP addr", hostname); return; } }; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - defmt::info!( - "[{}] Connecting... {}", - hostname, - defmt::Debug2Format(&ip_addr) - ); + info!("[{}] Connecting... {}", hostname, debug2Format(&ip_addr)); if let Err(e) = socket.connect((ip_addr, port)).await { - defmt::warn!("[{}] connect error: {:?}", hostname, e); + warn!("[{}] connect error: {:?}", hostname, e); return; } - defmt::info!( + info!( "[{}] Connected to {:?}", hostname, - defmt::Debug2Format(&socket.remote_endpoint()) + debug2Format(&socket.remote_endpoint()) ); loop { @@ -96,25 +92,25 @@ async fn echo_task( write!(msg, "Hello {}! {}\n", ip_addr, cnt).unwrap(); cnt = cnt.wrapping_add(1); if let Err(e) = socket.write_all(msg.as_bytes()).await { - defmt::warn!("[{}] write error: {:?}", hostname, e); + warn!("[{}] write error: {:?}", hostname, e); break; } - defmt::info!("[{}] txd: {}", hostname, msg); + info!("[{}] txd: {}", hostname, msg); Timer::after(Duration::from_millis(400)).await; } Either::Second(res) => { let n = match res { Ok(0) => { - defmt::warn!("[{}] read EOF", hostname); + warn!("[{}] read EOF", hostname); break; } Ok(n) => n, Err(e) => { - defmt::warn!("[{}] {:?}", hostname, e); + warn!("[{}] {:?}", hostname, e); break; } }; - defmt::info!( + info!( "[{}] rxd {}", hostname, core::str::from_utf8(&buf[..n]).unwrap() @@ -138,7 +134,7 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(spawner: Spawner) { - defmt::info!("Hello World!"); + info!("Hello World!"); let p = embassy_rp::init(Default::default()); @@ -164,11 +160,7 @@ async fn main(spawner: Spawner) { let (rx, tx) = uart.split(); let buffers = &*make_static!(atat::Buffers::new()); - let (ingress, client) = buffers.split( - tx, - EdmDigester::default(), - atat::Config::new(), - ); + let (ingress, client) = buffers.split(tx, EdmDigester::default(), atat::Config::new()); defmt::unwrap!(spawner.spawn(ingress_task(ingress, rx))); let state = make_static!(State::new(client)); @@ -190,7 +182,7 @@ async fn main(spawner: Spawner) { defmt::unwrap!(spawner.spawn(net_task(stack))); // And now we can use it! - defmt::info!("Device initialized!"); + info!("Device initialized!"); let mut rx_buffer = [0; 256]; let mut tx_buffer = [0; 256]; @@ -202,7 +194,7 @@ async fn main(spawner: Spawner) { loop { match control.join_wpa2("test", "1234abcd").await { Ok(_) => { - defmt::info!("Network connected!"); + info!("Network connected!"); spawner .spawn(echo_task( &stack, @@ -225,7 +217,7 @@ async fn main(spawner: Spawner) { break; } Err(err) => { - defmt::info!("join failed with error={:?}. Retrying in 1 second", err); + info!("join failed with error={:?}. Retrying in 1 second", err); Timer::after(Duration::from_secs(1)).await; } } @@ -237,15 +229,12 @@ async fn main(spawner: Spawner) { // // socket.set_timeout(Some(Duration::from_secs(10))); let remote: SocketAddr = (Ipv4Addr::new(192, 168, 1, 183), 4444).into(); - defmt::info!("Connecting... {}", defmt::Debug2Format(&remote)); + info!("Connecting... {}", debug2Format(&remote)); if let Err(e) = socket.connect(remote).await { - defmt::warn!("connect error: {:?}", e); + warn!("connect error: {:?}", e); continue; } - defmt::info!( - "Connected to {:?}", - defmt::Debug2Format(&socket.remote_endpoint()) - ); + info!("Connected to {:?}", debug2Format(&socket.remote_endpoint())); 'inner: loop { match select(Timer::after(Duration::from_secs(3)), socket.read(&mut buf)).await { @@ -254,25 +243,25 @@ async fn main(spawner: Spawner) { write!(msg, "Hello world! {}\n", cnt).unwrap(); cnt = cnt.wrapping_add(1); if let Err(e) = socket.write_all(msg.as_bytes()).await { - defmt::warn!("write error: {:?}", e); + warn!("write error: {:?}", e); break; } - defmt::info!("txd: {}", msg); + info!("txd: {}", msg); Timer::after(Duration::from_millis(400)).await; } Either::Second(res) => { let n = match res { Ok(0) => { - defmt::warn!("read EOF"); + warn!("read EOF"); break; } Ok(n) => n, Err(e) => { - defmt::warn!("{:?}", e); + warn!("{:?}", e); break; } }; - defmt::info!("rxd [{}] {}", n, core::str::from_utf8(&buf[..n]).unwrap()); + info!("rxd [{}] {}", n, core::str::from_utf8(&buf[..n]).unwrap()); match &buf[..n] { b"c\n" => { @@ -296,11 +285,11 @@ async fn main(spawner: Spawner) { } } } - defmt::info!("Press USER button to reconnect socket!"); + info!("Press USER button to reconnect socket!"); btn.wait_for_any_edge().await; continue; } - defmt::info!("Press USER button to reconnect to WiFi!"); + info!("Press USER button to reconnect to WiFi!"); btn.wait_for_any_edge().await; } } diff --git a/examples/rpi-pico/src/bin/embassy-perf.rs b/examples/rpi-pico/src/bin/embassy-perf.rs index 2ba83d4..796fd84 100644 --- a/examples/rpi-pico/src/bin/embassy-perf.rs +++ b/examples/rpi-pico/src/bin/embassy-perf.rs @@ -60,7 +60,7 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(spawner: Spawner) { - defmt::info!("Hello World!"); + info!("Hello World!"); let p = embassy_rp::init(Default::default()); @@ -109,7 +109,7 @@ async fn main(spawner: Spawner) { } // And now we can use it! - defmt::info!("Device initialized!"); + info!("Device initialized!"); let down = test_download(stack).await; Timer::after(Duration::from_secs(SETTLE_TIME as _)).await; @@ -122,7 +122,7 @@ async fn main(spawner: Spawner) { // assert!(up > TEST_EXPECTED_UPLOAD_KBPS); // assert!(updown > TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS); - defmt::info!("Test OK"); + info!("Test OK"); cortex_m::asm::bkpt(); } @@ -143,23 +143,23 @@ const UPLOAD_PORT: u16 = 4322; const UPLOAD_DOWNLOAD_PORT: u16 = 4323; async fn test_download(stack: &'static UbloxStack) -> usize { - defmt::info!("Testing download..."); + info!("Testing download..."); let mut rx_buffer = [0; RX_BUFFER_SIZE]; let mut tx_buffer = [0; TX_BUFFER_SIZE]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); // socket.set_timeout(Some(Duration::from_secs(10))); - defmt::info!( + info!( "connecting to {:?}:{}...", - defmt::Debug2Format(&SERVER_ADDRESS), + debug2Format(&SERVER_ADDRESS), DOWNLOAD_PORT ); if let Err(e) = socket.connect((SERVER_ADDRESS, DOWNLOAD_PORT)).await { - defmt::error!("connect error: {:?}", e); + error!("connect error: {:?}", e); return 0; } - defmt::info!("connected, testing..."); + info!("connected, testing..."); let mut rx_buf = [0; 4096]; let mut total: usize = 0; @@ -167,12 +167,12 @@ async fn test_download(stack: &'static UbloxStack) -> us loop { match socket.read(&mut rx_buf).await { Ok(0) => { - defmt::error!("read EOF"); + error!("read EOF"); return 0; } Ok(n) => total += n, Err(e) => { - defmt::error!("read error: {:?}", e); + error!("read error: {:?}", e); return 0; } } @@ -182,28 +182,28 @@ async fn test_download(stack: &'static UbloxStack) -> us .ok(); let kbps = (total + 512) / 1024 / TEST_DURATION; - defmt::info!("download: {} kB/s", kbps); + info!("download: {} kB/s", kbps); kbps } async fn test_upload(stack: &'static UbloxStack) -> usize { - defmt::info!("Testing upload..."); + info!("Testing upload..."); let mut rx_buffer = [0; RX_BUFFER_SIZE]; let mut tx_buffer = [0; TX_BUFFER_SIZE]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); // socket.set_timeout(Some(Duration::from_secs(10))); - defmt::info!( + info!( "connecting to {:?}:{}...", - defmt::Debug2Format(&SERVER_ADDRESS), + debug2Format(&SERVER_ADDRESS), UPLOAD_PORT ); if let Err(e) = socket.connect((SERVER_ADDRESS, UPLOAD_PORT)).await { - defmt::error!("connect error: {:?}", e); + error!("connect error: {:?}", e); return 0; } - defmt::info!("connected, testing..."); + info!("connected, testing..."); let buf = [0; 4096]; let mut total: usize = 0; @@ -211,12 +211,12 @@ async fn test_upload(stack: &'static UbloxStack) -> usiz loop { match socket.write(&buf).await { Ok(0) => { - defmt::error!("write zero?!??!?!"); + error!("write zero?!??!?!"); return 0; } Ok(n) => total += n, Err(e) => { - defmt::error!("write error: {:?}", e); + error!("write error: {:?}", e); return 0; } } @@ -226,28 +226,28 @@ async fn test_upload(stack: &'static UbloxStack) -> usiz .ok(); let kbps = (total + 512) / 1024 / TEST_DURATION; - defmt::info!("upload: {} kB/s", kbps); + info!("upload: {} kB/s", kbps); kbps } async fn test_upload_download(stack: &'static UbloxStack) -> usize { - defmt::info!("Testing upload+download..."); + info!("Testing upload+download..."); let mut rx_buffer = [0; RX_BUFFER_SIZE]; let mut tx_buffer = [0; TX_BUFFER_SIZE]; let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); // socket.set_timeout(Some(Duration::from_secs(10))); - defmt::info!( + info!( "connecting to {:?}:{}...", - defmt::Debug2Format(&SERVER_ADDRESS), + debug2Format(&SERVER_ADDRESS), UPLOAD_DOWNLOAD_PORT ); if let Err(e) = socket.connect((SERVER_ADDRESS, UPLOAD_DOWNLOAD_PORT)).await { - defmt::error!("connect error: {:?}", e); + error!("connect error: {:?}", e); return 0; } - defmt::info!("connected, testing..."); + info!("connected, testing..."); let (mut reader, mut writer) = socket.split(); @@ -258,12 +258,12 @@ async fn test_upload_download(stack: &'static UbloxStack loop { match writer.write(&tx_buf).await { Ok(0) => { - defmt::error!("write zero?!??!?!"); + error!("write zero?!??!?!"); return 0; } Ok(_) => {} Err(e) => { - defmt::error!("write error: {:?}", e); + error!("write error: {:?}", e); return 0; } } @@ -274,12 +274,12 @@ async fn test_upload_download(stack: &'static UbloxStack loop { match reader.read(&mut rx_buf).await { Ok(0) => { - defmt::error!("read EOF"); + error!("read EOF"); return 0; } Ok(n) => total += n, Err(e) => { - defmt::error!("read error: {:?}", e); + error!("read error: {:?}", e); return 0; } } @@ -293,10 +293,10 @@ async fn test_upload_download(stack: &'static UbloxStack .await .is_err() { - defmt::error!("Test timed out"); + error!("Test timed out"); } let kbps = (total + 512) / 1024 / TEST_DURATION; - defmt::info!("upload+download: {} kB/s", kbps); + info!("upload+download: {} kB/s", kbps); kbps } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4bf55ae..41845fc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] -channel = "nightly-2023-02-07" -components = [ "rust-src", "rustfmt", "llvm-tools-preview", "clippy" ] +channel = "nightly-2023-12-24" +components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv6m-none-eabi", "thumbv7em-none-eabihf" diff --git a/src/asynch/control.rs b/src/asynch/control.rs index 96dc9d5..be438d9 100644 --- a/src/asynch/control.rs +++ b/src/asynch/control.rs @@ -32,7 +32,7 @@ impl<'a, AT: AtatClient> Control<'a, AT> { } pub(crate) async fn init(&mut self) -> Result<(), Error> { - defmt::debug!("Initalizing ublox control"); + debug!("Initalizing ublox control"); // read MAC addr. // let mut resp = self.at.send_edm(GetWifiMac).await?; // self.state_ch.set_ethernet_address( @@ -139,7 +139,9 @@ impl<'a, AT: AtatClient> Control<'a, AT> { self.at .send_edm(SetWifiStationConfig { config_id: CONFIG_ID, - config_param: WifiStationConfig::SSID(heapless::String::from(ssid)), + config_param: WifiStationConfig::SSID( + heapless::String::try_from(ssid).map_err(|_| Error::Overflow)?, + ), }) .await?; @@ -192,7 +194,9 @@ impl<'a, AT: AtatClient> Control<'a, AT> { self.at .send_edm(SetWifiStationConfig { config_id: CONFIG_ID, - config_param: WifiStationConfig::SSID(heapless::String::from(ssid)), + config_param: WifiStationConfig::SSID( + heapless::String::try_from(ssid).map_err(|_| Error::Overflow)?, + ), }) .await?; @@ -206,9 +210,9 @@ impl<'a, AT: AtatClient> Control<'a, AT> { self.at .send_edm(SetWifiStationConfig { config_id: CONFIG_ID, - config_param: WifiStationConfig::WpaPskOrPassphrase(heapless::String::from( - passphrase, - )), + config_param: WifiStationConfig::WpaPskOrPassphrase( + heapless::String::try_from(passphrase).map_err(|_| Error::Overflow)?, + ), }) .await?; diff --git a/src/asynch/mod.rs b/src/asynch/mod.rs index 19c918e..12a16f8 100644 --- a/src/asynch/mod.rs +++ b/src/asynch/mod.rs @@ -6,7 +6,7 @@ pub mod ublox_stack; pub(crate) mod state; use crate::command::edm::{urc::EdmEvent, EdmAtCmdWrapper}; -use atat::{asynch::AtatClient, AtatUrcChannel}; +use atat::asynch::AtatClient; use embassy_sync::{blocking_mutex::raw::NoopRawMutex, mutex::Mutex}; use embedded_hal::digital::OutputPin; use runner::Runner; @@ -20,18 +20,15 @@ const MAX_CONNS: usize = 8; pub struct AtHandle<'d, AT: AtatClient>(&'d Mutex); impl<'d, AT: AtatClient> AtHandle<'d, AT> { - async fn send_edm, const LEN: usize>( + async fn send_edm( &mut self, cmd: Cmd, ) -> Result { self.send(EdmAtCmdWrapper(cmd)).await } - async fn send, const LEN: usize>( - &mut self, - cmd: Cmd, - ) -> Result { - self.0.lock().await.send_retry::(&cmd).await + async fn send(&mut self, cmd: Cmd) -> Result { + self.0.lock().await.send_retry::(&cmd).await } } @@ -53,12 +50,11 @@ pub async fn new< 'a, AT: AtatClient, // AT: AtatClient + atat::UartExt, - SUB: AtatUrcChannel, RST: OutputPin, const URC_CAPACITY: usize, >( state: &'a mut State, - subscriber: &'a SUB, + subscriber: &'a atat::UrcChannel, reset: RST, ) -> ( Device<'a, AT, URC_CAPACITY>, diff --git a/src/asynch/runner.rs b/src/asynch/runner.rs index 83cecb8..2ef6ed2 100644 --- a/src/asynch/runner.rs +++ b/src/asynch/runner.rs @@ -76,7 +76,7 @@ impl< pub(crate) async fn init(&mut self) -> Result<(), Error> { // Initilize a new ublox device to a known state (set RS232 settings) - defmt::debug!("Initializing module"); + debug!("Initializing module"); // Hard reset module self.reset().await?; @@ -143,7 +143,7 @@ impl< } pub async fn reset(&mut self) -> Result<(), Error> { - defmt::warn!("Hard resetting Ublox Short Range"); + warn!("Hard resetting Ublox Short Range"); self.reset.set_low().ok(); Timer::after(Duration::from_millis(100)).await; self.reset.set_high().ok(); @@ -156,7 +156,7 @@ impl< } pub async fn restart(&mut self, store: bool) -> Result<(), Error> { - defmt::warn!("Soft resetting Ublox Short Range"); + warn!("Soft resetting Ublox Short Range"); if store { self.at.send_edm(StoreCurrentConfig).await?; } @@ -218,7 +218,7 @@ impl< let event = self.urc_subscription.next_message_pure().await; match event { EdmEvent::ATEvent(Urc::StartUp) => { - defmt::error!("AT startup event?! Device restarted unintentionally!"); + error!("AT startup event?! Device restarted unintentionally!"); } EdmEvent::ATEvent(Urc::WifiLinkConnected(WifiLinkConnected { connection_id: _, @@ -230,7 +230,7 @@ impl< con.network.bssid = bssid; con.network.channel = channel; } else { - defmt::debug!("[URC] Active network config discovered"); + debug!("[URC] Active network config discovered"); self.wifi_connection.replace( WifiConnection::new( WifiNetwork::new_station(bssid, channel), @@ -252,7 +252,7 @@ impl< con.wifi_state = WiFiState::Inactive; } DisconnectReason::SecurityProblems => { - defmt::error!("Wifi Security Problems"); + error!("Wifi Security Problems"); } _ => { con.wifi_state = WiFiState::NotConnected; @@ -276,7 +276,7 @@ impl< } EdmEvent::ATEvent(Urc::NetworkError(_)) => todo!(), EdmEvent::StartUp => { - defmt::error!("EDM startup event?! Device restarted unintentionally!"); + error!("EDM startup event?! Device restarted unintentionally!"); } _ => {} }; @@ -288,25 +288,29 @@ impl< status: NetworkStatus::InterfaceType(InterfaceType::WifiStation), .. } = self - .at.send_edm(GetNetworkStatus { + .at + .send_edm(GetNetworkStatus { interface_id, status: NetworkStatusParameter::InterfaceType, }) - .await? else { - return Err(Error::Network); - }; + .await? + else { + return Err(Error::Network); + }; let NetworkStatusResponse { status: NetworkStatus::Gateway(ipv4), .. } = self - .at.send_edm(GetNetworkStatus { + .at + .send_edm(GetNetworkStatus { interface_id, status: NetworkStatusParameter::Gateway, }) - .await? else { - return Err(Error::Network); - }; + .await? + else { + return Err(Error::Network); + }; let ipv4_up = core::str::from_utf8(ipv4.as_slice()) .ok() @@ -318,13 +322,15 @@ impl< status: NetworkStatus::IPv6LinkLocalAddress(ipv6), .. } = self - .at.send_edm(GetNetworkStatus { + .at + .send_edm(GetNetworkStatus { interface_id, status: NetworkStatusParameter::IPv6LinkLocalAddress, }) - .await? else { - return Err(Error::Network); - }; + .await? + else { + return Err(Error::Network); + }; let ipv6_up = core::str::from_utf8(ipv6.as_slice()) .ok() diff --git a/src/asynch/ublox_stack/dns.rs b/src/asynch/ublox_stack/dns.rs index fc9175b..734e740 100644 --- a/src/asynch/ublox_stack/dns.rs +++ b/src/asynch/ublox_stack/dns.rs @@ -55,15 +55,15 @@ impl<'a> DnsSocket<'a> { _ => {} } + let name_string = heapless::String::try_from(name).map_err(|_| Error::NameTooLong)?; + { let mut s = self.stack.borrow_mut(); if s.dns_queries - .insert(heapless::String::from(name), DnsQuery::new()) + .insert(name_string.clone(), DnsQuery::new()) .is_err() { - defmt::error!( - "Attempted to start more simultaneous DNS requests than the (4) supported" - ); + error!("Attempted to start more simultaneous DNS requests than the (4) supported"); } s.waker.wake(); } @@ -93,22 +93,19 @@ impl<'a> DnsSocket<'a> { let drop = OnDrop::new(|| { let mut s = self.stack.borrow_mut(); - s.dns_queries.remove(&heapless::String::from(name)); + s.dns_queries.remove(&name_string); }); let res = poll_fn(|cx| { let mut s = self.stack.borrow_mut(); - let query = s - .dns_queries - .get_mut(&heapless::String::from(name)) - .unwrap(); + let query = s.dns_queries.get_mut(&name_string).unwrap(); match query.state { DnsState::Ok(ip) => { - s.dns_queries.remove(&heapless::String::from(name)); + s.dns_queries.remove(&name_string); return Poll::Ready(Ok(ip)); } DnsState::Err => { - s.dns_queries.remove(&heapless::String::from(name)); + s.dns_queries.remove(&name_string); return Poll::Ready(Err(Error::Failed)); } _ => { @@ -138,8 +135,9 @@ impl<'a> embedded_nal_async::Dns for DnsSocket<'a> { async fn get_host_by_address( &self, - _addr: embedded_nal_async::IpAddr, - ) -> Result, Self::Error> { + addr: IpAddr, + result: &mut [u8], + ) -> Result { unimplemented!() } } diff --git a/src/asynch/ublox_stack/mod.rs b/src/asynch/ublox_stack/mod.rs index 4e4f595..ad32373 100644 --- a/src/asynch/ublox_stack/mod.rs +++ b/src/asynch/ublox_stack/mod.rs @@ -28,13 +28,13 @@ use super::state::{self, LinkState}; use super::AtHandle; use atat::asynch::AtatClient; -use atomic_polyfill::{AtomicBool, AtomicU8, Ordering}; use embassy_futures::select::{select4, Either4}; use embassy_sync::waitqueue::WakerRegistration; use embassy_time::{Duration, Ticker}; use embedded_nal_async::SocketAddr; use futures::pin_mut; use no_std_net::IpAddr; +use portable_atomic::{AtomicBool, AtomicU8, Ordering}; use ublox_sockets::{ AnySocket, ChannelId, PeerHandle, Socket, SocketHandle, SocketSet, SocketStorage, }; @@ -170,7 +170,7 @@ impl UbloxStack UbloxStack UbloxStack UbloxStack UbloxStack { if let Some(edm_channel) = tcp.edm_channel { - defmt::warn!("{}", tcp); + warn!("{}", tcp); return tcp.tx_dequeue(|payload| { let len = core::cmp::min(payload.len(), DATA_PACKAGE_SIZE); let res = if len != 0 { @@ -407,12 +407,12 @@ impl UbloxStack { - defmt::error!("Failed to connect?! {}", e) + error!("Failed to connect?! {}", e) } } } TxEvent::Send { edm_channel, data } => { - defmt::warn!("Sending {} bytes on {}", data.len(), edm_channel); + warn!("Sending {} bytes on {}", data.len(), edm_channel); at.send(EdmDataCommand { channel: edm_channel, data: &data, @@ -501,6 +501,7 @@ enum TxEvent { }, } +#[cfg(feature = "defmt")] impl defmt::Format for TxEvent { fn format(&self, fmt: defmt::Formatter) { match self { diff --git a/src/asynch/ublox_stack/tcp.rs b/src/asynch/ublox_stack/tcp.rs index 58d7586..d76013c 100644 --- a/src/asynch/ublox_stack/tcp.rs +++ b/src/asynch/ublox_stack/tcp.rs @@ -357,7 +357,7 @@ pub mod client { use core::mem::MaybeUninit; use core::ptr::NonNull; - use atomic_polyfill::{AtomicBool, Ordering}; + use portable_atomic::{AtomicBool, Ordering}; use super::*; @@ -406,11 +406,8 @@ pub mod client { async fn connect<'a>( &'a self, - remote: embedded_nal_async::SocketAddr, - ) -> Result, Self::Error> - where - Self: 'a, - { + remote: SocketAddr, + ) -> Result, Self::Error> { let remote_endpoint = (remote.ip(), remote.port()); let mut socket = TcpConnection::new(&self.stack, self.state)?; socket diff --git a/src/blocking/client.rs b/src/blocking/client.rs index f80d704..762d279 100644 --- a/src/blocking/client.rs +++ b/src/blocking/client.rs @@ -222,13 +222,9 @@ where Ok(response.version) } - pub fn retry_send( - &mut self, - cmd: &A, - attempts: usize, - ) -> Result + pub fn retry_send(&mut self, cmd: &A, attempts: usize) -> Result where - A: atat::AtatCmd, + A: atat::AtatCmd, { for _ in 0..attempts { match self.send_internal(cmd, true) { @@ -256,7 +252,7 @@ where self.clear_buffers()?; if let Some(ref mut pin) = self.config.rst_pin { - defmt::warn!("Hard resetting Ublox Short Range"); + warn!("Hard resetting Ublox Short Range"); pin.set_low().ok(); Timer::after(Duration::from_millis(50)).wait(); pin.set_high().ok(); @@ -286,7 +282,7 @@ where self.socket_map = SocketMap::default(); self.udp_listener = UdpListener::new(); - defmt::warn!("Soft resetting Ublox Short Range"); + warn!("Soft resetting Ublox Short Range"); self.send_internal(&EdmAtCmdWrapper(RebootDCE), false)?; self.clear_buffers()?; @@ -333,13 +329,13 @@ where Ok(()) } - pub(crate) fn send_internal( + pub(crate) fn send_internal( &mut self, req: &A, check_urc: bool, ) -> Result where - A: atat::AtatCmd, + A: atat::AtatCmd, { if check_urc { if let Err(e) = self.handle_urc() { @@ -795,9 +791,9 @@ where /// Send AT command /// Automaticaly waraps commands in EDM context - pub fn send_at(&mut self, cmd: A) -> Result + pub fn send_at(&mut self, cmd: A) -> Result where - A: atat::AtatCmd, + A: atat::AtatCmd, { if !self.initialized { self.init()?; diff --git a/src/blocking/dns.rs b/src/blocking/dns.rs index 2ee95d8..48b9904 100644 --- a/src/blocking/dns.rs +++ b/src/blocking/dns.rs @@ -24,7 +24,7 @@ where hostname: &str, _addr_type: AddrType, ) -> nb::Result { - defmt::debug!("Lookup hostname: {}", hostname); + debug!("Lookup hostname: {}", hostname); self.send_at(Ping { hostname, retry_num: 1, diff --git a/src/blocking/tcp_stack.rs b/src/blocking/tcp_stack.rs index 6de3f59..fb72ce3 100644 --- a/src/blocking/tcp_stack.rs +++ b/src/blocking/tcp_stack.rs @@ -37,11 +37,11 @@ where } } - defmt::debug!("[TCP] Opening socket"); + debug!("[TCP] Opening socket"); let socket_id = new_socket_num(sockets).unwrap(); sockets.add(TcpSocket::new(socket_id)).map_err(|e| { - defmt::error!("[TCP] Opening socket Error: {:?}", e); + error!("[TCP] Opening socket Error: {:?}", e); e }) } else { @@ -59,7 +59,7 @@ where return Err(Error::Illegal.into()); } - defmt::debug!("[TCP] Connect socket"); + debug!("[TCP] Connect socket"); self.connected_to_network().map_err(|_| Error::Illegal)?; let url = PeerUrlBuilder::new() @@ -98,7 +98,7 @@ where } } - defmt::trace!("[TCP] Connecting socket: {:?} to url: {=str}", socket, url); + trace!("[TCP] Connecting socket: {:?} to url: {=str}", socket, url); // TODO: Timeout? // TODO: Fix the fact that it doesen't wait for both connect messages @@ -191,7 +191,7 @@ where /// Close an existing TCP socket. fn close(&mut self, socket: Self::TcpSocket) -> Result<(), Self::Error> { if let Some(ref mut sockets) = self.sockets { - defmt::debug!("[TCP] Closing socket: {:?}", socket); + debug!("[TCP] Closing socket: {:?}", socket); // If the socket is not found it is already removed if let Ok(ref tcp) = sockets.get::>(socket) { // If socket is not closed that means a connection excists which has to be closed @@ -208,7 +208,7 @@ where Err(_) => return Err(Error::Unaddressable), } } else { - defmt::error!( + error!( "Illigal state! Socket connected but not in socket map: {:?}", tcp.handle() ); diff --git a/src/blocking/udp_stack.rs b/src/blocking/udp_stack.rs index 203bada..795bc93 100644 --- a/src/blocking/udp_stack.rs +++ b/src/blocking/udp_stack.rs @@ -40,13 +40,13 @@ where } let socket_id = new_socket_num(sockets).unwrap(); - defmt::debug!("[UDP] Opening socket"); + debug!("[UDP] Opening socket"); sockets.add(UdpSocket::new(socket_id)).map_err(|_| { - defmt::error!("[UDP] Opening socket Error: Socket set full"); + error!("[UDP] Opening socket Error: Socket set full"); Error::SocketSetFull }) } else { - defmt::error!("[UDP] Opening socket Error: Missing socket set"); + error!("[UDP] Opening socket Error: Missing socket set"); Err(Error::Illegal) } } @@ -59,14 +59,14 @@ where remote: SocketAddr, ) -> Result<(), Self::Error> { if self.sockets.is_none() { - defmt::error!("[UDP] Connecting socket Error: Missing socket set"); + error!("[UDP] Connecting socket Error: Missing socket set"); return Err(Error::Illegal); } let url = PeerUrlBuilder::new() .address(&remote) .udp() .map_err(|_| Error::Unaddressable)?; - defmt::debug!("[UDP] Connecting Socket: {:?} to URL: {=str}", socket, url); + debug!("[UDP] Connecting Socket: {:?} to URL: {=str}", socket, url); self.connected_to_network().map_err(|_| Error::Illegal)?; @@ -202,7 +202,7 @@ where self.spin().ok(); // Close server socket if self.udp_listener.is_bound(socket) { - defmt::debug!("[UDP] Closing Server socket: {:?}", socket); + debug!("[UDP] Closing Server socket: {:?}", socket); // ID 2 used by UDP server self.send_internal( @@ -218,7 +218,7 @@ where if let Some(ref mut sockets) = self.sockets { // If socket in socket set close if sockets.remove(socket).is_err() { - defmt::error!( + error!( "[UDP] Closing server socket error: No socket matching: {:?}", socket ); @@ -231,19 +231,19 @@ where // Close incomming connections while self.udp_listener.available(socket).unwrap_or(false) { if let Ok((connection_handle, _)) = self.udp_listener.get_remote(socket) { - defmt::debug!( + debug!( "[UDP] Closing incomming socket for Server: {:?}", connection_handle ); self.close(connection_handle)?; } else { - defmt::error!("[UDP] Incomming socket for server error - Listener says available, while nothing present"); + error!("[UDP] Incomming socket for server error - Listener says available, while nothing present"); } } // Unbind server socket in listener self.udp_listener.unbind(socket).map_err(|_| { - defmt::error!( + error!( "[UDP] Closing socket error: No server socket matching: {:?}", socket ); @@ -251,10 +251,10 @@ where }) // Handle normal sockets } else if let Some(ref mut sockets) = self.sockets { - defmt::debug!("[UDP] Closing socket: {:?}", socket); + debug!("[UDP] Closing socket: {:?}", socket); // If no sockets exists, nothing to close. if let Ok(ref mut udp) = sockets.get::>(socket) { - defmt::trace!("[UDP] Closing socket state: {:?}", udp.state()); + trace!("[UDP] Closing socket state: {:?}", udp.state()); match udp.state() { UdpState::Closed => { sockets.remove(socket).ok(); @@ -269,7 +269,7 @@ where } } } else { - defmt::error!( + error!( "[UDP] Closing socket error: No socket matching: {:?}", socket ); @@ -301,10 +301,9 @@ where return Err(Error::Illegal); } - defmt::debug!( + debug!( "[UDP] binding socket: {:?} to port: {:?}", - socket, - local_port + socket, local_port ); // ID 2 used by UDP server diff --git a/src/command/custom_digest.rs b/src/command/custom_digest.rs index cf6a4c4..a7b8dd5 100644 --- a/src/command/custom_digest.rs +++ b/src/command/custom_digest.rs @@ -18,12 +18,12 @@ impl Digester for EdmDigester { return (DigestResult::None, 0); } - defmt::trace!("Digest {:?}", LossyStr(&buf)); + trace!("Digest {:?}", LossyStr(&buf)); if buf.len() >= STARTUPMESSAGE.len() && buf[..2] == *b"\r\n" { if let Some(i) = buf[2..].windows(2).position(|x| x == *b"\r\n") { // Two for starting position, one for index -> len and one for the window size. let len = i + 4; - defmt::trace!("Digest common at {:?}; i: {:?}", LossyStr(&buf[..len]), i); + trace!("Digest common at {:?}; i: {:?}", LossyStr(&buf[..len]), i); if buf[..len] == *STARTUPMESSAGE { return ( DigestResult::Urc(&buf[..STARTUPMESSAGE.len()]), @@ -67,7 +67,7 @@ impl Digester for EdmDigester { // Debug statement for trace properly if !buf.is_empty() { - defmt::trace!("Digest {:?}", LossyStr(&buf)); + trace!("Digest {:?}", LossyStr(&buf)); } // Filter message by payload diff --git a/src/command/data_mode/urc.rs b/src/command/data_mode/urc.rs index 35eb098..8eb2441 100644 --- a/src/command/data_mode/urc.rs +++ b/src/command/data_mode/urc.rs @@ -17,14 +17,14 @@ pub struct PeerConnected { // #[at_arg(position = 3)] // pub local_address: IpAddr, #[at_arg(position = 3)] - #[defmt(Debug2Format)] + #[cfg_attr(feature = "defmt", defmt(Debug2Format))] pub local_address: Bytes<40>, #[at_arg(position = 4)] pub local_port: u16, // #[at_arg(position = 5)] // pub remote_address: IpAddr, #[at_arg(position = 5)] - #[defmt(Debug2Format)] + #[cfg_attr(feature = "defmt", defmt(Debug2Format))] pub remote_address: Bytes<40>, #[at_arg(position = 6)] pub remote_port: u16, diff --git a/src/command/edm/mod.rs b/src/command/edm/mod.rs index 64021f1..ae46aea 100644 --- a/src/command/edm/mod.rs +++ b/src/command/edm/mod.rs @@ -23,97 +23,30 @@ pub(crate) fn calc_payload_len(resp: &[u8]) -> usize { // using the parameter. Instead the parameter must // be set to 0 and the serial settings will take effect when the module is reset. #[derive(Debug, Clone)] -pub(crate) struct EdmAtCmdWrapper, const LEN: usize>(pub T); +pub(crate) struct EdmAtCmdWrapper(pub T); -impl atat::AtatCmd<1024> for EdmAtCmdWrapper -where - T: AtatCmd, -{ +impl atat::AtatCmd for EdmAtCmdWrapper { type Response = T::Response; + const MAX_LEN: usize = T::MAX_LEN + 6; + const MAX_TIMEOUT_MS: u32 = T::MAX_TIMEOUT_MS; - fn as_bytes(&self) -> Vec { - let at_vec = self.0.as_bytes(); - let payload_len = (at_vec.len() + 2) as u16; - [ + fn write(&self, buf: &mut [u8]) -> usize { + let at_len = self.0.write(&mut buf[5..]); + let payload_len = (at_len + 2) as u16; + + buf[0..5].copy_from_slice(&[ STARTBYTE, (payload_len >> 8) as u8 & EDM_SIZE_FILTER, (payload_len & 0xffu16) as u8, 0x00, PayloadType::ATRequest as u8, - ] - .iter() - .cloned() - .chain(at_vec) - .chain(core::iter::once(ENDBYTE)) - .collect() - } + ]); - fn parse( - &self, - resp: Result<&[u8], atat::InternalError>, - ) -> core::result::Result { - let resp = resp.and_then(|resp| { - if resp.len() < PAYLOAD_OVERHEAD - || !resp.starts_with(&[STARTBYTE]) - || !resp.ends_with(&[ENDBYTE]) - { - return Err(atat::InternalError::InvalidResponse); - }; + buf[5 + at_len] = ENDBYTE; - let payload_len = calc_payload_len(resp); - - if resp.len() != payload_len + EDM_OVERHEAD - || resp[4] != PayloadType::ATConfirmation as u8 - { - return Err(atat::InternalError::InvalidResponse); - } - - // Recieved OK response code in EDM response? - match resp - .windows(b"\r\nOK".len()) - .position(|window| window == b"\r\nOK") - { - // Cutting OK out leaves an empth string for NoResponse, for - // other responses just removes "\r\nOK\r\n" - Some(pos) => Ok(&resp[AT_COMMAND_POSITION..pos]), - // Isolate the AT_response - None => Ok(&resp[AT_COMMAND_POSITION..PAYLOAD_POSITION + payload_len]), - } - }); - - self.0.parse(resp) - } -} - -/////////////////////// Temp Solution for fixed size /////////////////////// -#[derive(Debug, Clone)] -pub(crate) struct BigEdmAtCmdWrapper, const LEN: usize>(pub T); - -impl atat::AtatCmd<2054> for BigEdmAtCmdWrapper -where - T: AtatCmd, -{ - type Response = T::Response; - - const MAX_TIMEOUT_MS: u32 = T::MAX_TIMEOUT_MS; - - fn as_bytes(&self) -> Vec { - let at_vec = self.0.as_bytes(); - let payload_len = (at_vec.len() + 2) as u16; - [ - STARTBYTE, - (payload_len >> 8) as u8 & EDM_SIZE_FILTER, - (payload_len & 0xffu16) as u8, - 0x00, - PayloadType::ATRequest as u8, - ] - .iter() - .cloned() - .chain(at_vec) - .chain(core::iter::once(ENDBYTE)) - .collect() + 5 + at_len + 1 } fn parse( @@ -152,7 +85,6 @@ where self.0.parse(resp) } } -////////////////////////////////////////////////////////////////////////////////////////////// #[derive(Debug, Clone)] pub struct EdmDataCommand<'a> { @@ -160,54 +92,57 @@ pub struct EdmDataCommand<'a> { pub data: &'a [u8], } // wifi::socket::EGRESS_CHUNK_SIZE + PAYLOAD_OVERHEAD = 512 + 6 + 1 = 519 -impl<'a> atat::AtatCmd<{ DATA_PACKAGE_SIZE + 7 }> for EdmDataCommand<'a> { +impl<'a> atat::AtatCmd for EdmDataCommand<'a> { type Response = NoResponse; + const MAX_LEN: usize = DATA_PACKAGE_SIZE + 7; + const EXPECTS_RESPONSE_CODE: bool = false; - fn as_bytes(&self) -> Vec { + fn parse( + &self, + _resp: Result<&[u8], atat::InternalError>, + ) -> core::result::Result { + Ok(NoResponse) + } + + fn write(&self, buf: &mut [u8]) -> usize { let payload_len = (self.data.len() + 3) as u16; - [ + buf[0..6].copy_from_slice(&[ STARTBYTE, (payload_len >> 8) as u8 & EDM_SIZE_FILTER, (payload_len & 0xffu16) as u8, 0x00, PayloadType::DataCommand as u8, self.channel.0, - ] - .iter() - .cloned() - .chain(self.data.iter().cloned()) - .chain(core::iter::once(ENDBYTE)) - .collect() - } + ]); - fn parse( - &self, - _resp: Result<&[u8], atat::InternalError>, - ) -> core::result::Result { - Ok(NoResponse) + buf[6..6 + self.data.len()].copy_from_slice(self.data); + buf[6 + self.data.len()] = ENDBYTE; + + 6 + self.data.len() + 1 } } #[derive(Debug, Clone)] pub struct EdmResendConnectEventsCommand; -impl atat::AtatCmd<6> for EdmResendConnectEventsCommand { +impl atat::AtatCmd for EdmResendConnectEventsCommand { type Response = NoResponse; - fn as_bytes(&self) -> Vec { - [ + const MAX_LEN: usize = 6; + + fn write(&self, buf: &mut [u8]) -> usize { + buf[0..6].copy_from_slice(&[ STARTBYTE, 0x00, 0x02, 0x00, PayloadType::ResendConnectEventsCommand as u8, ENDBYTE, - ] - .iter() - .cloned() - .collect() + ]); + + 6 } fn parse( @@ -221,18 +156,18 @@ impl atat::AtatCmd<6> for EdmResendConnectEventsCommand { #[derive(Debug, Clone)] pub struct SwitchToEdmCommand; -impl atat::AtatCmd<6> for SwitchToEdmCommand { +impl atat::AtatCmd for SwitchToEdmCommand { type Response = NoResponse; + const MAX_LEN: usize = 6; + const MAX_TIMEOUT_MS: u32 = 2000; - fn as_bytes(&self) -> Vec { + fn write(&self, buf: &mut [u8]) -> usize { ChangeMode { mode: data_mode::types::Mode::ExtendedDataMode, } - .as_bytes() - .into_iter() - .collect() + .write(buf) } fn parse( @@ -279,7 +214,11 @@ mod test { PayloadType::ATConfirmation as u8, 0x55, ]; - assert_eq!(parse.as_bytes(), correct_cmd); + + let mut buf = [0u8; as AtatCmd>::MAX_LEN]; + let len = parse.write(&mut buf); + + assert_eq!(buf[..len], correct_cmd); assert_eq!(parse.parse(Ok(response)), Ok(correct_response)); let parse = EdmAtCmdWrapper(SystemStatus { @@ -319,7 +258,10 @@ mod test { 0x0A, 0x55, ]; - assert_eq!(parse.as_bytes(), correct); + let mut buf = [0u8; as AtatCmd>::MAX_LEN]; + let len = parse.write(&mut buf); + + assert_eq!(buf[..len], correct); assert_eq!(parse.parse(Ok(response)), Ok(correct_response)); } @@ -451,7 +393,11 @@ mod test { fn change_to_edm_cmd() { let resp = &[0xAA, 0x00, 0x02, 0x00, 0x71, 0x55]; let correct = Vec::<_, 6>::from_slice(b"ATO2\r\n").unwrap(); - assert_eq!(SwitchToEdmCommand.as_bytes(), correct); + + let mut buf = [0u8; SwitchToEdmCommand::MAX_LEN]; + let len = SwitchToEdmCommand.write(&mut buf); + + assert_eq!(buf[..len], correct); assert_eq!(SwitchToEdmCommand.parse(Ok(resp)).unwrap(), NoResponse); } } diff --git a/src/command/edm/urc.rs b/src/command/edm/urc.rs index bc011a3..dbe3c5a 100644 --- a/src/command/edm/urc.rs +++ b/src/command/edm/urc.rs @@ -26,7 +26,7 @@ impl AtatUrc for EdmEvent { /// Parse the response into a `Self::Response` instance. fn parse(resp: &[u8]) -> Option { - defmt::trace!("[Parse URC] {:?}", LossyStr(resp)); + trace!("[Parse URC] {:?}", LossyStr(resp)); // Startup message? // TODO: simplify mayby no packet check. if resp.len() >= STARTUPMESSAGE.len() @@ -59,12 +59,12 @@ impl AtatUrc for EdmEvent { || !resp.starts_with(&[STARTBYTE]) || !resp.ends_with(&[ENDBYTE]) { - defmt::error!("[Parse URC Start/End byte Error] {:?}", LossyStr(&resp)); + error!("[Parse URC Start/End byte Error] {:?}", LossyStr(&resp)); return None; }; let payload_len = calc_payload_len(resp); if resp.len() != payload_len + EDM_OVERHEAD { - defmt::error!("[Parse URC lenght Error] {:?}", LossyStr(resp)); + error!("[Parse URC lenght Error] {:?}", LossyStr(resp)); return None; } @@ -157,7 +157,7 @@ impl AtatUrc for EdmEvent { PayloadType::StartEvent => EdmEvent::StartUp.into(), _ => { - defmt::error!("[Parse URC Error] {:?}", LossyStr(resp)); + error!("[Parse URC Error] {:?}", LossyStr(resp)); None } } diff --git a/src/command/general/types.rs b/src/command/general/types.rs index 80dfb95..ac24d4d 100644 --- a/src/command/general/types.rs +++ b/src/command/general/types.rs @@ -89,7 +89,7 @@ impl core::str::FromStr for FirmwareVersion { let (patch, meta) = match patch_meta.split_once('-') { Some((patch_str, meta)) => ( patch_str.parse().map_err(|_| DeserializeError)?, - Some(heapless::String::from(meta)), + heapless::String::try_from(meta).ok(), ), None => (patch_meta.parse().map_err(|_| DeserializeError)?, None), }; @@ -103,6 +103,7 @@ impl core::str::FromStr for FirmwareVersion { } } +#[cfg(feature = "defmt")] impl defmt::Format for FirmwareVersion { fn format(&self, fmt: defmt::Formatter) { if let Some(meta) = &self.meta { diff --git a/src/command/ping/types.rs b/src/command/ping/types.rs index cfe102c..16fdaa8 100644 --- a/src/command/ping/types.rs +++ b/src/command/ping/types.rs @@ -25,7 +25,8 @@ use atat::atat_derive::AtatEnum; /// - Default value: 1000 // pub type Inteval = u16; -#[derive(Debug, PartialEq, Clone, Copy, AtatEnum, defmt::Format)] +#[derive(Debug, PartialEq, Clone, Copy, AtatEnum)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] pub enum PingError { /// 1 - 6: Internal error (ping level) diff --git a/src/command/ping/urc.rs b/src/command/ping/urc.rs index 856d63c..0abc5c7 100644 --- a/src/command/ping/urc.rs +++ b/src/command/ping/urc.rs @@ -38,7 +38,8 @@ pub struct PingResponse { pub rtt: i32, } -#[derive(Debug, PartialEq, Clone, AtatResp, defmt::Format)] +#[derive(Debug, PartialEq, Clone, AtatResp)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PingErrorResponse { #[at_arg(position = 0)] pub error: PingError, diff --git a/src/connection.rs b/src/connection.rs index e657393..c270887 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,6 +1,7 @@ use crate::network::{WifiMode, WifiNetwork}; -#[derive(Debug, Clone, Copy, PartialEq, defmt::Format)] +#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WiFiState { Inactive, /// Searching for Wifi diff --git a/src/error.rs b/src/error.rs index 8fe05fb..5c4d426 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,7 @@ pub use ublox_sockets::Error as SocketError; -#[derive(Debug, defmt::Format)] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { Overflow, SetState, @@ -46,7 +47,8 @@ impl From for Error { } /// Error that occurs when attempting to connect to a wireless network. -#[derive(Debug, defmt::Format)] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WifiConnectionError { /// Failed to connect to wireless network. FailedToConnect, @@ -72,7 +74,8 @@ impl From for WifiConnectionError { } } -#[derive(Debug, defmt::Format)] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WifiError { // The specified wifi is currently disabled. Try switching it on. WifiDisabled, @@ -88,7 +91,8 @@ pub enum WifiError { // Other, } -#[derive(Debug, defmt::Format)] +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum WifiHotspotError { /// Failed to ceate wireless hotspot. CreationFailed, diff --git a/src/fmt.rs b/src/fmt.rs new file mode 100644 index 0000000..3476f4c --- /dev/null +++ b/src/fmt.rs @@ -0,0 +1,258 @@ +#![macro_use] +#![allow(unused_macros)] + +use core::fmt::{Debug, Display, LowerHex}; + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::debug_assert!($($x)*); + } + }; +} + +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::debug_assert_eq!($($x)*); + } + }; +} + +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::debug_assert_ne!($($x)*); + } + }; +} + +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unreachable { + ($($x:tt)*) => { + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) + }; +} + +macro_rules! panic { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::panic!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::panic!($($x)*); + } + }; +} + +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} + +#[allow(unused)] +pub(crate) struct Bytes<'a>(pub &'a [u8]); + +impl<'a> Debug for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> Display for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +impl<'a> LowerHex for Bytes<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#02x?}", self.0) + } +} + +#[cfg(feature = "defmt")] +impl<'a> defmt::Format for Bytes<'a> { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, "{:02x}", self.0) + } +} diff --git a/src/lib.rs b/src/lib.rs index 867ba7d..9f5cb6a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,8 @@ #![cfg_attr(feature = "async", feature(impl_trait_projections))] #![cfg_attr(feature = "async", feature(type_alias_impl_trait))] +mod fmt; + #[cfg(feature = "async")] pub mod asynch; diff --git a/src/peer_builder.rs b/src/peer_builder.rs index 8334b53..02f18bf 100644 --- a/src/peer_builder.rs +++ b/src/peer_builder.rs @@ -133,7 +133,10 @@ mod test { #[test] fn udp_ipv4_url() { let address = "192.168.0.1:8080".parse().unwrap(); - let url = PeerUrlBuilder::new().address(&address).udp().unwrap(); + let url = PeerUrlBuilder::new() + .address(&address) + .udp::<128>() + .unwrap(); assert_eq!(url, "udp://192.168.0.1:8080/"); } @@ -142,7 +145,10 @@ mod test { let address = "[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]:8080" .parse() .unwrap(); - let url = PeerUrlBuilder::new().address(&address).udp().unwrap(); + let url = PeerUrlBuilder::new() + .address(&address) + .udp::<128>() + .unwrap(); assert_eq!(url, "udp://[fe80::202:b3ff:fe1e:8329]:8080/"); } @@ -152,7 +158,7 @@ mod test { .hostname("example.org") .port(2000) .local_port(2001) - .udp() + .udp::<128>() .unwrap(); assert_eq!(url, "udp://example.org:2000/?local_port=2001"); } diff --git a/src/wifi/mod.rs b/src/wifi/mod.rs index 623f2ca..15f6b48 100644 --- a/src/wifi/mod.rs +++ b/src/wifi/mod.rs @@ -39,7 +39,7 @@ impl SocketMap { channel_id: ChannelId, socket_handle: SocketHandle, ) -> Result<(), ()> { - defmt::trace!("[SOCK_MAP] {:?} tied to {:?}", socket_handle, channel_id); + trace!("[SOCK_MAP] {:?} tied to {:?}", socket_handle, channel_id); self.channel_map .insert(channel_id, socket_handle) .map_err(drop)?; @@ -47,7 +47,7 @@ impl SocketMap { } pub fn remove_channel(&mut self, channel_id: &ChannelId) -> Result<(), ()> { - defmt::trace!("[SOCK_MAP] {:?} removed", channel_id); + trace!("[SOCK_MAP] {:?} removed", channel_id); self.channel_map.remove(channel_id).ok_or(())?; Ok(()) } @@ -63,13 +63,13 @@ impl SocketMap { } pub fn insert_peer(&mut self, peer: PeerHandle, socket_handle: SocketHandle) -> Result<(), ()> { - defmt::trace!("[SOCK_MAP] {:?} tied to {:?}", socket_handle, peer); + trace!("[SOCK_MAP] {:?} tied to {:?}", socket_handle, peer); self.peer_map.insert(peer, socket_handle).map_err(drop)?; Ok(()) } pub fn remove_peer(&mut self, peer: &PeerHandle) -> Result<(), ()> { - defmt::trace!("[SOCK_MAP] {:?} removed", peer); + trace!("[SOCK_MAP] {:?} removed", peer); self.peer_map.remove(peer).ok_or(())?; Ok(()) } diff --git a/src/wifi/options.rs b/src/wifi/options.rs index f76b581..aac9dd3 100644 --- a/src/wifi/options.rs +++ b/src/wifi/options.rs @@ -55,7 +55,8 @@ impl HotspotOptions { } } -#[derive(Debug, Clone, Default, Serialize, Deserialize, defmt::Format)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ConnectionOptions { pub ssid: String<64>, pub password: Option>, diff --git a/src/wifi/supplicant.rs b/src/wifi/supplicant.rs index b11e40f..dabd5bf 100644 --- a/src/wifi/supplicant.rs +++ b/src/wifi/supplicant.rs @@ -22,7 +22,7 @@ use super::{ options::ConnectionOptions, }; -use defmt::debug; +use debug; /// Supplicant is used to /// @@ -60,12 +60,9 @@ impl<'a, C, const N: usize> Supplicant<'a, C, N> where C: atat::blocking::AtatClient, { - fn send_at, const LEN: usize>( - &mut self, - req: &A, - ) -> Result { + fn send_at(&mut self, req: &A) -> Result { self.client.send(req).map_err(|e| { - defmt::error!("{:?}: {=[u8]:a}", e, req.as_bytes()); + error!("{:?}: {=[u8]:a}", e, req.as_bytes()); e.into() }) } @@ -130,7 +127,7 @@ where // but should this be the case, the module is already having unexpected behaviour } else { // This causes unexpected behaviour - defmt::error!("Two configs are active on startup!"); + error!("Two configs are active on startup!"); return Err(Error::Supplicant); } } else if load.is_err() { @@ -145,7 +142,7 @@ where if let WifiStationConfigR::SSID(ssid) = parameter { if !ssid.is_empty() { - defmt::error!("Shadow store bug!"); + error!("Shadow store bug!"); // This should fix the issue self.remove_connection(config_id) .map_err(|_| Error::Supplicant)?; @@ -279,7 +276,7 @@ where debug!("[SUP] Remove connection: {:?}", config_id); // check for active if self.is_config_in_use(config_id) { - defmt::error!("Config id is active!"); + error!("Config id is active!"); return Err(WifiConnectionError::Illegal); } @@ -315,7 +312,7 @@ where // check for active if self.is_config_in_use(config_id) { - defmt::error!("Config id is active!"); + error!("Config id is active!"); return Err(WifiConnectionError::Illegal); } @@ -522,12 +519,12 @@ where } // check for active connection if self.is_config_in_use(active_on_startup) { - defmt::error!("Active on startup is active!"); + error!("Active on startup is active!"); return Err(WifiConnectionError::Illegal); } } if self.is_config_in_use(config_id) { - defmt::error!("Config id is active!"); + error!("Config id is active!"); return Err(WifiConnectionError::Illegal); } @@ -570,7 +567,7 @@ where if let Some(active_on_startup) = self.active_on_startup.clone() { // check for active connection if self.is_config_in_use(active_on_startup) { - defmt::error!("Active on startup is active!"); + error!("Active on startup is active!"); return Err(WifiConnectionError::Illegal); } // if any active remove this asset. @@ -597,7 +594,7 @@ where } } else if let Some(ref con) = self.wifi_connection { if con.activated && con.config_id == config_id { - defmt::error!("One of the IDs being changed is activated!"); + error!("One of the IDs being changed is activated!"); return true; } }