diff --git a/Cargo.toml b/Cargo.toml index 1d2c818..b20382b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,32 +14,26 @@ features = [ "std", "nonblocking", "mock", "helpers" ] std = [ ] nonblocking = [ ] mock = [ "embedded-hal-mock" ] -helpers = [ "structopt", "humantime", "std", "pcap-file", "libc", "byteorder", "rolling-stats" ] +helpers = [ "clap", "humantime", "std", "pcap-file", "libc", "byteorder", "rolling-stats" ] default = [ ] [dependencies] -embedded-hal = "1.0.0-alpha.7" +embedded-hal = "1.0.0" +embedded-hal-mock = { version = "0.10.0", optional = true } nb = "1.0.0" log = { version = "0.4.14", default_features = false } defmt = { version = "0.3.0", optional = true } +chrono = { version = "0.4.19", default_features = false } humantime = { version = "2.0.1", optional = true } pcap-file = { version = "1.1.1", optional = true } -structopt = { version = "0.3.14", optional = true } async-std = { version = "1.4.0", optional = true } libc = { version = "0.2.71", optional = true } byteorder = { version = "1.3.4", optional = true } -rolling-stats = { version = "0.5.0", optional = true } +rolling-stats = { version = "0.7.0", optional = true } thiserror = { version = "1.0.30", optional = true } - -[dependencies.chrono] -version = "0.4.19" -default_features = false - -[dependencies.embedded-hal-mock] -version = "0.8.0" -optional = true +clap = { version = "4.4.7", optional = true, features = [ "derive" ] } [dev-dependencies] anyhow = "1.0.44" diff --git a/src/blocking.rs b/src/blocking.rs index 1f04472..5ff4959 100644 --- a/src/blocking.rs +++ b/src/blocking.rs @@ -1,6 +1,6 @@ //! Blocking APIs on top of the base radio traits //! -//! These implementations use the radio's DelayUs implementation to +//! These implementations use the radio's DelayNs implementation to //! poll on completion of operations. //! //! ## @@ -9,16 +9,13 @@ use core::fmt::Debug; use core::time::Duration; -use embedded_hal::delay::blocking::DelayUs; - -#[cfg(not(feature = "defmt"))] -use log::debug; +use embedded_hal::delay::DelayNs; #[cfg(feature = "defmt")] use defmt::debug; -#[cfg(feature = "structopt")] -use structopt::StructOpt; +#[cfg(feature = "clap")] +use clap::Parser; #[cfg(feature = "std")] use std::string::ToString; @@ -27,15 +24,15 @@ use crate::{Receive, State, Transmit}; /// BlockingOptions for blocking radio functions #[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "structopt", derive(StructOpt))] +#[cfg_attr(feature = "clap", derive(Parser))] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct BlockingOptions { /// Interval for polling for device state - #[cfg_attr(feature="structopt", structopt(long, default_value="100us", parse(try_from_str=crate::duration_from_str)))] + #[cfg_attr(feature="clap", clap(long, default_value="100us", value_parser=crate::duration_from_str))] pub poll_interval: Duration, /// Timeout for blocking operation - #[cfg_attr(feature="structopt", structopt(long, default_value="100ms", parse(try_from_str=crate::duration_from_str)))] + #[cfg_attr(feature="clap", clap(long, default_value="100ms", value_parser=crate::duration_from_str))] pub timeout: Duration, } @@ -66,19 +63,19 @@ impl From for BlockingError { } /// Blocking transmit function implemented over `radio::Transmit` and `radio::Power` using the provided -/// `BlockingOptions` and radio-internal `DelayUs` impl to poll for completion +/// `BlockingOptions` and radio-internal `DelayNs` impl to poll for completion #[cfg_attr( feature = "mock", doc = r##" ``` # use radio::*; # use radio::mock::*; -use radio::blocking::{BlockingTransmit, BlockingOptions}; +use radio::{BlockingTransmit, BlockingOptions}; # let mut radio = MockRadio::new(&[ # Transaction::start_transmit(vec![0xaa, 0xbb], None), # Transaction::check_transmit(Ok(false)), -# Transaction::delay_us(100), +# Transaction::delay_ns(100000), # Transaction::check_transmit(Ok(true)), # ]); # @@ -102,7 +99,7 @@ pub trait BlockingTransmit { impl BlockingTransmit for T where - T: Transmit + DelayUs, + T: Transmit + DelayNs, E: Debug, { fn do_transmit( @@ -132,7 +129,7 @@ where } // Wait for next poll - let _ = self.delay_us(tx_options.poll_interval.as_micros() as u32); + self.delay_us(tx_options.poll_interval.as_micros() as u32); } Ok(()) @@ -140,14 +137,14 @@ where } /// Blocking receive function implemented over `radio::Receive` using the provided `BlockingOptions` -/// and radio-internal `DelayUs` impl to poll for completion +/// and radio-internal `DelayNs` impl to poll for completion #[cfg_attr( feature = "mock", doc = r##" ``` # use radio::*; # use radio::mock::*; -use radio::blocking::{BlockingReceive, BlockingOptions}; +use radio::{BlockingReceive, BlockingOptions}; let data = [0xaa, 0xbb]; let info = BasicInfo::new(-81, 0); @@ -155,7 +152,7 @@ let info = BasicInfo::new(-81, 0); # let mut radio = MockRadio::new(&[ # Transaction::start_receive(None), # Transaction::check_receive(true, Ok(false)), -# Transaction::delay_us(100), +# Transaction::delay_ns(100000), # Transaction::check_receive(true, Ok(true)), # Transaction::get_received(Ok((data.to_vec(), info.clone()))), # ]); @@ -187,7 +184,7 @@ pub trait BlockingReceive { impl BlockingReceive for T where - T: Receive + DelayUs, + T: Receive + DelayNs, ::Info: Debug, I: Debug, E: Debug, @@ -215,7 +212,7 @@ where return Err(BlockingError::Timeout); } - let _ = self.delay_us(rx_options.poll_interval.as_micros() as u32); + self.delay_us(rx_options.poll_interval.as_micros() as u32); } } } @@ -231,7 +228,7 @@ pub trait BlockingSetState { impl BlockingSetState for T where - T: State + DelayUs, + T: State + DelayNs, S: Debug + core::cmp::PartialEq + Copy, E: Debug, { @@ -264,7 +261,7 @@ where } // Delay before next loop - let _ = self.delay_us(options.poll_interval.as_micros() as u32); + self.delay_us(options.poll_interval.as_micros() as u32); } } } diff --git a/src/helpers.rs b/src/helpers.rs index 0ae014a..1f61d9e 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -17,38 +17,40 @@ use log::{debug, info}; #[cfg(feature = "defmt")] use defmt::{debug, info}; - -use embedded_hal::delay::blocking::DelayUs; +use clap::Parser; +use embedded_hal::delay::DelayNs; use humantime::Duration as HumanDuration; -use structopt::StructOpt; use byteorder::{ByteOrder, NetworkEndian}; use pcap_file::{pcap::PcapHeader, DataLink, PcapWriter}; use rolling_stats::Stats; -use crate::blocking::*; -use crate::{Power, Receive, ReceiveInfo, Rssi, Transmit}; +use crate::*; +use crate::{ + blocking::{BlockingError, BlockingOptions, BlockingReceive, BlockingTransmit}, + Power, Receive, ReceiveInfo, Rssi, Transmit, +}; /// Basic operations supported by the helpers package -#[derive(Clone, StructOpt, PartialEq, Debug)] +#[derive(Clone, Parser, PartialEq, Debug)] pub enum Operation { - #[structopt(name = "tx")] + #[clap(name = "tx")] /// Transmit a packet Transmit(TransmitOptions), - #[structopt(name = "rx")] + #[clap(name = "rx")] /// Receive a packet Receive(ReceiveOptions), - #[structopt(name = "rssi")] + #[clap(name = "rssi")] /// Poll RSSI on the configured channel Rssi(RssiOptions), - #[structopt(name = "echo")] + #[clap(name = "echo")] /// Echo back received messages (useful with Link Test mode) Echo(EchoOptions), - #[structopt(name = "ping-pong")] + #[clap(name = "ping-pong")] /// Link test (ping-pong) mode LinkTest(PingPongOptions), } @@ -60,7 +62,7 @@ where + Receive + Rssi + Power - + DelayUs, + + DelayNs, I: ReceiveInfo + Default + std::fmt::Debug, E: std::fmt::Debug, { @@ -80,27 +82,27 @@ where } /// Configuration for Transmit operation -#[derive(Clone, StructOpt, PartialEq, Debug)] +#[derive(Clone, Parser, PartialEq, Debug)] pub struct TransmitOptions { /// Data to be transmitted - #[structopt(long)] + #[clap(long)] pub data: Vec, /// Power in dBm (range -18dBm to 13dBm) - #[structopt(long)] + #[clap(long)] pub power: Option, /// Specify period for repeated transmission - #[structopt(long)] + #[clap(long)] pub period: Option, - #[structopt(flatten)] + #[clap(flatten)] pub blocking_options: BlockingOptions, } pub fn do_transmit(radio: &mut T, options: TransmitOptions) -> Result<(), BlockingError> where - T: Transmit + Power + DelayUs, + T: Transmit + Power + DelayNs, E: core::fmt::Debug, { // Set output power if specified @@ -114,7 +116,7 @@ where // Delay for repeated transmission or exit match &options.period { - Some(p) => radio.delay_us(p.as_micros() as u32).unwrap(), + Some(p) => radio.delay_us(p.as_micros() as u32), None => break, } } @@ -123,28 +125,28 @@ where } /// Configuration for Receive operation -#[derive(Clone, StructOpt, PartialEq, Debug)] +#[derive(Clone, Parser, PartialEq, Debug)] pub struct ReceiveOptions { /// Run continuously - #[structopt(long = "continuous")] + #[clap(long = "continuous")] pub continuous: bool, - #[structopt(flatten)] + #[clap(flatten)] pub pcap_options: PcapOptions, - #[structopt(flatten)] + #[clap(flatten)] pub blocking_options: BlockingOptions, } -#[derive(Clone, StructOpt, PartialEq, Debug)] +#[derive(Clone, Parser, PartialEq, Debug)] pub struct PcapOptions { /// Create and write capture output to a PCAP file - #[structopt(long, group = "1")] + #[clap(long, group = "1")] pub pcap_file: Option, /// Create and write to a unix pipe for connection to wireshark - #[structopt(long, group = "1")] + #[clap(long, group = "1")] pub pcap_pipe: Option, } @@ -216,7 +218,7 @@ pub fn do_receive( options: ReceiveOptions, ) -> Result where - T: Receive + DelayUs, + T: Receive + DelayNs, I: std::fmt::Debug, E: std::fmt::Debug, { @@ -262,27 +264,25 @@ where radio.start_receive()?; } - radio - .delay_us(options.blocking_options.poll_interval.as_micros() as u32) - .unwrap(); + radio.delay_us(options.blocking_options.poll_interval.as_micros() as u32); } } /// Configuration for RSSI operation -#[derive(Clone, StructOpt, PartialEq, Debug)] +#[derive(Clone, Parser, PartialEq, Debug)] pub struct RssiOptions { /// Specify period for RSSI polling - #[structopt(long = "period", default_value = "1s")] + #[clap(long = "period", default_value = "1s")] pub period: HumanDuration, /// Run continuously - #[structopt(long = "continuous")] + #[clap(long = "continuous")] pub continuous: bool, } pub fn do_rssi(radio: &mut T, options: RssiOptions) -> Result<(), E> where - T: Receive + Rssi + DelayUs, + T: Receive + Rssi + DelayNs, I: std::fmt::Debug, E: std::fmt::Debug, { @@ -297,7 +297,7 @@ where radio.check_receive(true)?; - radio.delay_us(options.period.as_micros() as u32).unwrap(); + radio.delay_us(options.period.as_micros() as u32); if !options.continuous { break; @@ -308,25 +308,25 @@ where } /// Configuration for Echo operation -#[derive(Clone, StructOpt, PartialEq, Debug)] +#[derive(Clone, Parser, PartialEq, Debug)] pub struct EchoOptions { /// Run continuously - #[structopt(long = "continuous")] + #[clap(long = "continuous")] pub continuous: bool, /// Power in dBm (range -18dBm to 13dBm) - #[structopt(long = "power")] + #[clap(long = "power")] pub power: Option, /// Specify delay for response message - #[structopt(long = "delay", default_value = "100ms")] + #[clap(long = "delay", default_value = "100ms")] pub delay: HumanDuration, /// Append RSSI and LQI to repeated message - #[structopt(long = "append-info")] + #[clap(long = "append-info")] pub append_info: bool, - #[structopt(flatten)] + #[clap(flatten)] pub blocking_options: BlockingOptions, } @@ -336,10 +336,7 @@ pub fn do_echo( options: EchoOptions, ) -> Result> where - T: Receive - + Transmit - + Power - + DelayUs, + T: Receive + Transmit + Power + DelayNs, I: ReceiveInfo + std::fmt::Debug, E: std::fmt::Debug, { @@ -372,7 +369,7 @@ where } // Wait for turnaround delay - radio.delay_us(options.delay.as_micros() as u32).unwrap(); + radio.delay_us(options.delay.as_micros() as u32); // Transmit respobnse radio.do_transmit(&buff[..n], options.blocking_options.clone())?; @@ -384,33 +381,31 @@ where } // Wait for poll delay - radio - .delay_us(options.blocking_options.poll_interval.as_micros() as u32) - .unwrap(); + radio.delay_us(options.blocking_options.poll_interval.as_micros() as u32); } } /// Configuration for Echo operation -#[derive(Clone, StructOpt, PartialEq, Debug)] +#[derive(Clone, Parser, PartialEq, Debug)] pub struct PingPongOptions { /// Specify the number of rounds to tx/rx - #[structopt(long, default_value = "100")] + #[clap(long, default_value = "100")] pub rounds: u32, /// Power in dBm (range -18dBm to 13dBm) - #[structopt(long)] + #[clap(long)] pub power: Option, /// Specify delay for response message - #[structopt(long, default_value = "100ms")] + #[clap(long, default_value = "100ms")] pub delay: HumanDuration, /// Parse RSSI and other info from response messages /// (echo server must have --append-info set) - #[structopt(long)] + #[clap(long)] pub parse_info: bool, - #[structopt(flatten)] + #[clap(flatten)] pub blocking_options: BlockingOptions, } @@ -426,7 +421,7 @@ pub fn do_ping_pong( options: PingPongOptions, ) -> Result> where - T: Receive + Transmit + Power + DelayUs, + T: Receive + Transmit + Power + DelayNs, I: ReceiveInfo, E: std::fmt::Debug, { @@ -490,7 +485,7 @@ where } // Wait for send delay - radio.delay_us(options.delay.as_micros() as u32).unwrap(); + radio.delay_us(options.delay.as_micros() as u32); } Ok(link_info) diff --git a/src/lib.rs b/src/lib.rs index 5fe69ad..1b8fe41 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,9 +125,9 @@ impl From for BasicChannel { } } -impl Into for BasicChannel { - fn into(self) -> u16 { - self.0 +impl From for u16 { + fn from(val: BasicChannel) -> Self { + val.0 } } @@ -272,7 +272,7 @@ mod tests { impl From for TestRegister1 { fn from(value: u8) -> Self { - Self { value: value } + Self { value } } } diff --git a/src/mock.rs b/src/mock.rs index 1cc7657..96fde02 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -11,9 +11,9 @@ use std::convert::Infallible; use std::fmt::Debug; use std::vec::Vec; -use log::{debug}; +use log::debug; -use embedded_hal::delay::blocking::DelayUs; +use embedded_hal::delay::DelayNs; use embedded_hal_mock::common::Generic; @@ -217,9 +217,9 @@ impl Transaction { } /// Delay for a certain time - pub fn delay_us(ms: u32) -> Self { + pub fn delay_ns(ns: u32) -> Self { Self { - request: Request::DelayUs(ms), + request: Request::DelayNs(ns), response: Response::Ok, } } @@ -247,7 +247,7 @@ enum Request { CheckReceive(bool), GetReceived, - DelayUs(u32), + DelayNs(u32), } #[derive(Debug, Clone, PartialEq)] @@ -271,7 +271,7 @@ impl From> for Response { } } -impl DelayUs for Radio +impl DelayNs for Radio where St: PartialEq + Debug + Clone, Reg: PartialEq + Debug + Clone, @@ -280,14 +280,10 @@ where Irq: PartialEq + Debug + Clone, E: PartialEq + Debug + Clone, { - type Error = Infallible; + fn delay_ns(&mut self, ns: u32) { + let n = self.next().expect("no expectation for delay_ns call"); - fn delay_us(&mut self, ms: u32) -> Result<(), Self::Error> { - let n = self.next().expect("no expectation for delay_us call"); - - assert_eq!(&n.request, &Request::DelayUs(ms)); - - Ok(()) + assert_eq!(&n.request, &Request::DelayNs(ns)); } }