aboutsummaryrefslogtreecommitdiff
path: root/embassy-net-nrf91/src/context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-net-nrf91/src/context.rs')
-rw-r--r--embassy-net-nrf91/src/context.rs86
1 files changed, 84 insertions, 2 deletions
diff --git a/embassy-net-nrf91/src/context.rs b/embassy-net-nrf91/src/context.rs
index 954830417..f73719224 100644
--- a/embassy-net-nrf91/src/context.rs
+++ b/embassy-net-nrf91/src/context.rs
@@ -5,6 +5,7 @@ use core::str::FromStr;
5use at_commands::builder::CommandBuilder; 5use at_commands::builder::CommandBuilder;
6use at_commands::parser::CommandParser; 6use at_commands::parser::CommandParser;
7use heapless::Vec; 7use heapless::Vec;
8use embassy_time::{Timer, Duration};
8 9
9/// Provides a higher level API for controlling a given context. 10/// Provides a higher level API for controlling a given context.
10pub struct Control<'a> { 11pub struct Control<'a> {
@@ -23,6 +24,8 @@ pub struct Config<'a> {
23} 24}
24 25
25/// Authentication protocol. 26/// Authentication protocol.
27#[derive(Clone, Copy, PartialEq, Debug)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26#[repr(u8)] 29#[repr(u8)]
27pub enum AuthProt { 30pub enum AuthProt {
28 /// No authentication. 31 /// No authentication.
@@ -84,7 +87,7 @@ impl<'a> Control<'a> {
84 } 87 }
85 88
86 /// Configures the modem with the provided config. 89 /// Configures the modem with the provided config.
87 pub async fn configure(&self, config: Config<'_>) -> Result<(), Error> { 90 pub async fn configure(&self, config: &Config<'_>) -> Result<(), Error> {
88 let mut cmd: [u8; 256] = [0; 256]; 91 let mut cmd: [u8; 256] = [0; 256];
89 let mut buf: [u8; 256] = [0; 256]; 92 let mut buf: [u8; 256] = [0; 256];
90 93
@@ -118,9 +121,64 @@ impl<'a> Control<'a> {
118 let n = self.control.at_command(op, &mut buf).await; 121 let n = self.control.at_command(op, &mut buf).await;
119 CommandParser::parse(&buf[..n]).expect_identifier(b"OK").finish()?; 122 CommandParser::parse(&buf[..n]).expect_identifier(b"OK").finish()?;
120 123
124 let op = CommandBuilder::create_set(&mut cmd, true)
125 .named("%XPDNCFG")
126 .with_int_parameter(1)
127 .finish()
128 .map_err(|_| Error::BufferTooSmall)?;
129 let n = self.control.at_command(op, &mut buf).await;
130 CommandParser::parse(&buf[..n]).expect_identifier(b"OK").finish()?;
131
132
133
134 Ok(())
135 }
136
137 /// Attach to the PDN
138 pub async fn attach(&self) -> Result<(), Error> {
139 let mut cmd: [u8; 256] = [0; 256];
140 let mut buf: [u8; 256] = [0; 256];
141 let op = CommandBuilder::create_set(&mut cmd, true)
142 .named("+CGATT")
143 .with_int_parameter(1)
144 .finish()
145 .map_err(|_| Error::BufferTooSmall)?;
146 let n = self.control.at_command(op, &mut buf).await;
147 CommandParser::parse(&buf[..n]).expect_identifier(b"OK").finish()?;
148 Ok(())
149 }
150
151 /// Read current connectivity status for modem.
152 pub async fn detach(&self) -> Result<(), Error> {
153 let mut cmd: [u8; 256] = [0; 256];
154 let mut buf: [u8; 256] = [0; 256];
155 let op = CommandBuilder::create_set(&mut cmd, true)
156 .named("+CGATT")
157 .with_int_parameter(0)
158 .finish()
159 .map_err(|_| Error::BufferTooSmall)?;
160 let n = self.control.at_command(op, &mut buf).await;
161 CommandParser::parse(&buf[..n]).expect_identifier(b"OK").finish()?;
121 Ok(()) 162 Ok(())
122 } 163 }
123 164
165 async fn attached(&self) -> Result<bool, Error> {
166 let mut cmd: [u8; 256] = [0; 256];
167 let mut buf: [u8; 256] = [0; 256];
168
169 let op = CommandBuilder::create_query(&mut cmd, true)
170 .named("+CGATT")
171 .finish()
172 .map_err(|_| Error::BufferTooSmall)?;
173 let n = self.control.at_command(op, &mut buf).await;
174 let (res,) = CommandParser::parse(&buf[..n])
175 .expect_identifier(b"+CGATT: ")
176 .expect_int_parameter()
177 .expect_identifier(b"\r\nOK")
178 .finish()?;
179 Ok(res == 1)
180 }
181
124 /// Read current connectivity status for modem. 182 /// Read current connectivity status for modem.
125 pub async fn status(&self) -> Result<Status, Error> { 183 pub async fn status(&self) -> Result<Status, Error> {
126 let mut cmd: [u8; 256] = [0; 256]; 184 let mut cmd: [u8; 256] = [0; 256];
@@ -162,7 +220,6 @@ impl<'a> Control<'a> {
162 220
163 let ip = if let Some(ip) = ip1 { 221 let ip = if let Some(ip) = ip1 {
164 let ip = IpAddr::from_str(ip).map_err(|_| Error::AddrParseError)?; 222 let ip = IpAddr::from_str(ip).map_err(|_| Error::AddrParseError)?;
165 self.control.open_raw_socket().await;
166 Some(ip) 223 Some(ip)
167 } else { 224 } else {
168 None 225 None
@@ -219,4 +276,29 @@ impl<'a> Control<'a> {
219 dns, 276 dns,
220 }) 277 })
221 } 278 }
279
280 /// Run a control loop for this context, ensuring that reaattach is handled.
281 pub async fn run<F: Fn(&Status)>(&self, config: &Config<'_>, reattach: F) -> Result<(), Error> {
282 self.configure(config).await?;
283 while !self.attached().await? {
284 Timer::after(Duration::from_secs(1)).await;
285 }
286 let status = self.status().await?;
287 let mut fd = self.control.open_raw_socket().await;
288 reattach(&status);
289
290 loop {
291 if !self.attached().await? {
292 // TODO: self.control.close_raw_socket(fd).await;
293 self.attach().await?;
294 while !self.attached().await? {
295 Timer::after(Duration::from_secs(1)).await;
296 }
297 let status = self.status().await?;
298 // TODO: let mut fd = self.control.open_raw_socket().await;
299 reattach(&status);
300 }
301 Timer::after(Duration::from_secs(10)).await;
302 }
303 }
222} 304}