diff options
| -rw-r--r-- | embassy-net-nrf91/src/context.rs | 48 | ||||
| -rw-r--r-- | examples/nrf9160/src/bin/modem_tcp_client.rs | 6 |
2 files changed, 30 insertions, 24 deletions
diff --git a/embassy-net-nrf91/src/context.rs b/embassy-net-nrf91/src/context.rs index b532dca14..9c67cbc9f 100644 --- a/embassy-net-nrf91/src/context.rs +++ b/embassy-net-nrf91/src/context.rs | |||
| @@ -1,38 +1,46 @@ | |||
| 1 | //! Helper utility to configure a specific modem context. | ||
| 1 | use core::net::IpAddr; | 2 | use core::net::IpAddr; |
| 2 | use heapless::String; | ||
| 3 | use core::str::FromStr; | 3 | use core::str::FromStr; |
| 4 | use core::fmt::Write; | ||
| 5 | use heapless::Vec; | 4 | use heapless::Vec; |
| 6 | use at_commands::{builder::CommandBuilder, parser::CommandParser}; | 5 | use at_commands::{builder::CommandBuilder, parser::CommandParser}; |
| 7 | 6 | ||
| 8 | /// Provides a higher level API for configuring and reading information for a given | 7 | /// Provides a higher level API for controlling a given context. |
| 9 | /// context id. | ||
| 10 | pub struct Control<'a> { | 8 | pub struct Control<'a> { |
| 11 | control: crate::Control<'a>, | 9 | control: crate::Control<'a>, |
| 12 | cid: u8, | 10 | cid: u8, |
| 13 | } | 11 | } |
| 14 | 12 | ||
| 13 | /// Configuration for a given context | ||
| 15 | pub struct Config<'a> { | 14 | pub struct Config<'a> { |
| 16 | pub gateway: &'a str, | 15 | /// Desired APN address. |
| 16 | pub apn: &'a str, | ||
| 17 | /// Desired authentication protocol. | ||
| 17 | pub auth_prot: AuthProt, | 18 | pub auth_prot: AuthProt, |
| 19 | /// Credentials. | ||
| 18 | pub auth: Option<(&'a str, &'a str)>, | 20 | pub auth: Option<(&'a str, &'a str)>, |
| 19 | } | 21 | } |
| 20 | 22 | ||
| 23 | /// Authentication protocol. | ||
| 21 | #[repr(u8)] | 24 | #[repr(u8)] |
| 22 | pub enum AuthProt { | 25 | pub enum AuthProt { |
| 26 | /// No authentication. | ||
| 23 | None = 0, | 27 | None = 0, |
| 28 | /// PAP authentication. | ||
| 24 | Pap = 1, | 29 | Pap = 1, |
| 30 | /// CHAP authentication. | ||
| 25 | Chap = 2, | 31 | Chap = 2, |
| 26 | } | 32 | } |
| 27 | 33 | ||
| 34 | /// Error returned by control. | ||
| 28 | #[derive(Clone, Copy, PartialEq, Debug)] | 35 | #[derive(Clone, Copy, PartialEq, Debug)] |
| 29 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 36 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 30 | pub enum Error { | 37 | pub enum Error { |
| 38 | /// Not enough space for command. | ||
| 31 | BufferTooSmall, | 39 | BufferTooSmall, |
| 32 | AtCommand, | 40 | /// Error parsing response from modem. |
| 33 | AtParseError, | 41 | AtParseError, |
| 42 | /// Error parsing IP addresses. | ||
| 34 | AddrParseError, | 43 | AddrParseError, |
| 35 | Format, | ||
| 36 | } | 44 | } |
| 37 | 45 | ||
| 38 | impl From<at_commands::parser::ParseError> for Error { | 46 | impl From<at_commands::parser::ParseError> for Error { |
| @@ -41,17 +49,16 @@ impl From<at_commands::parser::ParseError> for Error { | |||
| 41 | } | 49 | } |
| 42 | } | 50 | } |
| 43 | 51 | ||
| 44 | impl From<core::fmt::Error> for Error { | 52 | /// Status of a given context. |
| 45 | fn from(_: core::fmt::Error) -> Self { | ||
| 46 | Self::Format | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | #[derive(PartialEq, Debug)] | 53 | #[derive(PartialEq, Debug)] |
| 51 | pub struct Status { | 54 | pub struct Status { |
| 55 | /// Attached to APN or not. | ||
| 52 | pub attached: bool, | 56 | pub attached: bool, |
| 57 | /// IP if assigned. | ||
| 53 | pub ip: Option<IpAddr>, | 58 | pub ip: Option<IpAddr>, |
| 59 | /// Gateway if assigned. | ||
| 54 | pub gateway: Option<IpAddr>, | 60 | pub gateway: Option<IpAddr>, |
| 61 | /// DNS servers if assigned. | ||
| 55 | pub dns: Vec<IpAddr, 2>, | 62 | pub dns: Vec<IpAddr, 2>, |
| 56 | } | 63 | } |
| 57 | 64 | ||
| @@ -66,16 +73,14 @@ impl defmt::Format for Status { | |||
| 66 | } | 73 | } |
| 67 | 74 | ||
| 68 | impl<'a> Control<'a> { | 75 | impl<'a> Control<'a> { |
| 76 | /// Create a new instance of a control handle for a given context. | ||
| 77 | /// | ||
| 78 | /// Will wait for the modem to be initialized if not. | ||
| 69 | pub async fn new(control: crate::Control<'a>, cid: u8) -> Self { | 79 | pub async fn new(control: crate::Control<'a>, cid: u8) -> Self { |
| 70 | control.wait_init().await; | 80 | control.wait_init().await; |
| 71 | Self { control, cid } | 81 | Self { control, cid } |
| 72 | } | 82 | } |
| 73 | 83 | ||
| 74 | /// Bypass modem configurator | ||
| 75 | pub async fn at_command(&self, req: &[u8], resp: &mut [u8]) -> usize { | ||
| 76 | self.control.at_command(req, resp).await | ||
| 77 | } | ||
| 78 | |||
| 79 | /// Configures the modem with the provided config. | 84 | /// Configures the modem with the provided config. |
| 80 | pub async fn configure(&self, config: Config<'_>) -> Result<(), Error> { | 85 | pub async fn configure(&self, config: Config<'_>) -> Result<(), Error> { |
| 81 | let mut cmd: [u8; 256] = [0; 256]; | 86 | let mut cmd: [u8; 256] = [0; 256]; |
| @@ -85,7 +90,7 @@ impl<'a> Control<'a> { | |||
| 85 | .named("+CGDCONT") | 90 | .named("+CGDCONT") |
| 86 | .with_int_parameter(self.cid) | 91 | .with_int_parameter(self.cid) |
| 87 | .with_string_parameter("IP") | 92 | .with_string_parameter("IP") |
| 88 | .with_string_parameter(config.gateway) | 93 | .with_string_parameter(config.apn) |
| 89 | .finish().map_err(|_| Error::BufferTooSmall)?; | 94 | .finish().map_err(|_| Error::BufferTooSmall)?; |
| 90 | let n = self.control.at_command(op, &mut buf).await; | 95 | let n = self.control.at_command(op, &mut buf).await; |
| 91 | CommandParser::parse(&buf[..n]).expect_identifier(b"OK").finish()?; | 96 | CommandParser::parse(&buf[..n]).expect_identifier(b"OK").finish()?; |
| @@ -112,6 +117,7 @@ impl<'a> Control<'a> { | |||
| 112 | Ok(()) | 117 | Ok(()) |
| 113 | } | 118 | } |
| 114 | 119 | ||
| 120 | /// Read current connectivity status for modem. | ||
| 115 | pub async fn status(&self) -> Result<Status, Error> { | 121 | pub async fn status(&self) -> Result<Status, Error> { |
| 116 | let mut cmd: [u8; 256] = [0; 256]; | 122 | let mut cmd: [u8; 256] = [0; 256]; |
| 117 | let mut buf: [u8; 256] = [0; 256]; | 123 | let mut buf: [u8; 256] = [0; 256]; |
| @@ -134,7 +140,7 @@ impl<'a> Control<'a> { | |||
| 134 | .with_int_parameter(self.cid) | 140 | .with_int_parameter(self.cid) |
| 135 | .finish().map_err(|_| Error::BufferTooSmall)?; | 141 | .finish().map_err(|_| Error::BufferTooSmall)?; |
| 136 | let n = self.control.at_command(op, &mut buf).await; | 142 | let n = self.control.at_command(op, &mut buf).await; |
| 137 | let (_, ip1, ip2, ) = CommandParser::parse(&buf[..n]) | 143 | let (_, ip1, _ip2, ) = CommandParser::parse(&buf[..n]) |
| 138 | .expect_identifier(b"+CGPADDR: ") | 144 | .expect_identifier(b"+CGPADDR: ") |
| 139 | .expect_int_parameter() | 145 | .expect_int_parameter() |
| 140 | .expect_optional_string_parameter() | 146 | .expect_optional_string_parameter() |
| @@ -154,7 +160,7 @@ impl<'a> Control<'a> { | |||
| 154 | .with_int_parameter(self.cid) | 160 | .with_int_parameter(self.cid) |
| 155 | .finish().map_err(|_| Error::BufferTooSmall)?; | 161 | .finish().map_err(|_| Error::BufferTooSmall)?; |
| 156 | let n = self.control.at_command(op, &mut buf).await; | 162 | let n = self.control.at_command(op, &mut buf).await; |
| 157 | let (_cid, _bid, _apn, _mask, gateway, dns1, dns2, _, _, _, _, mtu) = CommandParser::parse(&buf[..n]) | 163 | let (_cid, _bid, _apn, _mask, gateway, dns1, dns2, _, _, _, _, _mtu) = CommandParser::parse(&buf[..n]) |
| 158 | .expect_identifier(b"+CGCONTRDP: ") | 164 | .expect_identifier(b"+CGCONTRDP: ") |
| 159 | .expect_int_parameter() | 165 | .expect_int_parameter() |
| 160 | .expect_optional_int_parameter() | 166 | .expect_optional_int_parameter() |
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs index f80861693..55ab2a707 100644 --- a/examples/nrf9160/src/bin/modem_tcp_client.rs +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs | |||
| @@ -7,7 +7,7 @@ use core::ptr::addr_of_mut; | |||
| 7 | use core::str::FromStr; | 7 | use core::str::FromStr; |
| 8 | use core::slice; | 8 | use core::slice; |
| 9 | 9 | ||
| 10 | use defmt::{assert, info, warn, unwrap}; | 10 | use defmt::{info, warn, unwrap}; |
| 11 | use heapless::Vec; | 11 | use heapless::Vec; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 13 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; |
| @@ -93,7 +93,7 @@ async fn main(spawner: Spawner) { | |||
| 93 | 93 | ||
| 94 | static mut TRACE_BUF: [u8; 4096] = [0u8; 4096]; | 94 | static mut TRACE_BUF: [u8; 4096] = [0u8; 4096]; |
| 95 | let mut config = uarte::Config::default(); | 95 | let mut config = uarte::Config::default(); |
| 96 | config.baudrate = Baudrate::BAUD1M; | 96 | config.baudrate = Baudrate::BAUD115200; |
| 97 | let trace_writer = TraceWriter(BufferedUarteTx::new( | 97 | let trace_writer = TraceWriter(BufferedUarteTx::new( |
| 98 | //let trace_uart = BufferedUarteTx::new( | 98 | //let trace_uart = BufferedUarteTx::new( |
| 99 | unsafe { peripherals::SERIAL0::steal() }, | 99 | unsafe { peripherals::SERIAL0::steal() }, |
| @@ -128,7 +128,7 @@ async fn main(spawner: Spawner) { | |||
| 128 | let control = context::Control::new(control, 0).await; | 128 | let control = context::Control::new(control, 0).await; |
| 129 | 129 | ||
| 130 | unwrap!(control.configure(context::Config { | 130 | unwrap!(control.configure(context::Config { |
| 131 | gateway: "iot.nat.es", | 131 | apn: "iot.nat.es", |
| 132 | auth_prot: context::AuthProt::Pap, | 132 | auth_prot: context::AuthProt::Pap, |
| 133 | auth: Some(("orange", "orange")), | 133 | auth: Some(("orange", "orange")), |
| 134 | }).await); | 134 | }).await); |
