diff options
| author | Ulf Lilleengen <[email protected]> | 2024-09-04 12:58:33 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2024-09-04 12:58:33 +0200 |
| commit | b76b7ca9f5d64e83f7f69a6f7d97ba605ab2af7f (patch) | |
| tree | 9577beb7c10d467a92d06ac7e96c662c84f74e39 /examples/nrf9160/src/bin | |
| parent | aabdd45424ae71550be542a3a62872b33a4e0717 (diff) | |
Use at-commands crate and support DNS
* Use at-commands for building and parsing AT commands which has better
error handling.
* Retrieve DNS servers
* Retrieve gateway
* Update example to configure embassy-net with retrieved parameters.
Diffstat (limited to 'examples/nrf9160/src/bin')
| -rw-r--r-- | examples/nrf9160/src/bin/modem_tcp_client.rs | 78 |
1 files changed, 21 insertions, 57 deletions
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs index 817ad17c7..f80861693 100644 --- a/examples/nrf9160/src/bin/modem_tcp_client.rs +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs | |||
| @@ -5,9 +5,10 @@ use core::mem::MaybeUninit; | |||
| 5 | use core::net::IpAddr; | 5 | use core::net::IpAddr; |
| 6 | use core::ptr::addr_of_mut; | 6 | use core::ptr::addr_of_mut; |
| 7 | use core::str::FromStr; | 7 | use core::str::FromStr; |
| 8 | use core::{slice, str}; | 8 | use core::slice; |
| 9 | 9 | ||
| 10 | use defmt::{assert, info, warn, unwrap}; | 10 | use defmt::{assert, info, warn, unwrap}; |
| 11 | use heapless::Vec; | ||
| 11 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 12 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 13 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; |
| 13 | use embassy_net_nrf91::{Runner, State, context}; | 14 | use embassy_net_nrf91::{Runner, State, context}; |
| @@ -146,10 +147,23 @@ async fn main(spawner: Spawner) { | |||
| 146 | }; | 147 | }; |
| 147 | let addr = Ipv4Address(addr.octets()); | 148 | let addr = Ipv4Address(addr.octets()); |
| 148 | 149 | ||
| 150 | let gateway = if let Some(IpAddr::V4(addr)) = status.gateway { | ||
| 151 | Some(Ipv4Address(addr.octets())) | ||
| 152 | } else { | ||
| 153 | None | ||
| 154 | }; | ||
| 155 | |||
| 156 | let mut dns_servers = Vec::new(); | ||
| 157 | for dns in status.dns { | ||
| 158 | if let IpAddr::V4(ip) = dns { | ||
| 159 | unwrap!(dns_servers.push(Ipv4Address(ip.octets()))); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 149 | stack.set_config_v4(embassy_net::ConfigV4::Static(embassy_net::StaticConfigV4 { | 163 | stack.set_config_v4(embassy_net::ConfigV4::Static(embassy_net::StaticConfigV4 { |
| 150 | address: Ipv4Cidr::new(addr, 32), | 164 | address: Ipv4Cidr::new(addr, 32), |
| 151 | gateway: None, | 165 | gateway, |
| 152 | dns_servers: Default::default(), | 166 | dns_servers, |
| 153 | })); | 167 | })); |
| 154 | 168 | ||
| 155 | let mut rx_buffer = [0; 4096]; | 169 | let mut rx_buffer = [0; 4096]; |
| @@ -159,15 +173,16 @@ async fn main(spawner: Spawner) { | |||
| 159 | socket.set_timeout(Some(Duration::from_secs(10))); | 173 | socket.set_timeout(Some(Duration::from_secs(10))); |
| 160 | 174 | ||
| 161 | info!("Connecting..."); | 175 | info!("Connecting..."); |
| 162 | let host_addr = embassy_net::Ipv4Address::from_str("83.51.182.206").unwrap(); | 176 | let host_addr = embassy_net::Ipv4Address::from_str("45.79.112.203").unwrap(); |
| 163 | if let Err(e) = socket.connect((host_addr, 8000)).await { | 177 | if let Err(e) = socket.connect((host_addr, 4242)).await { |
| 164 | warn!("connect error: {:?}", e); | 178 | warn!("connect error: {:?}", e); |
| 179 | Timer::after_secs(1).await; | ||
| 165 | continue; | 180 | continue; |
| 166 | } | 181 | } |
| 167 | info!("Connected to {:?}", socket.remote_endpoint()); | 182 | info!("Connected to {:?}", socket.remote_endpoint()); |
| 168 | 183 | ||
| 169 | let msg = b"Hello world!\n"; | 184 | let msg = b"Hello world!\n"; |
| 170 | loop { | 185 | for _ in 0..10 { |
| 171 | if let Err(e) = socket.write_all(msg).await { | 186 | if let Err(e) = socket.write_all(msg).await { |
| 172 | warn!("write error: {:?}", e); | 187 | warn!("write error: {:?}", e); |
| 173 | break; | 188 | break; |
| @@ -177,54 +192,3 @@ async fn main(spawner: Spawner) { | |||
| 177 | } | 192 | } |
| 178 | } | 193 | } |
| 179 | } | 194 | } |
| 180 | |||
| 181 | fn is_whitespace(char: u8) -> bool { | ||
| 182 | match char { | ||
| 183 | b'\r' | b'\n' | b' ' => true, | ||
| 184 | _ => false, | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | fn is_separator(char: u8) -> bool { | ||
| 189 | match char { | ||
| 190 | b',' | b'\r' | b'\n' | b' ' => true, | ||
| 191 | _ => false, | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | fn split_field<'a>(data: &mut &'a [u8]) -> &'a [u8] { | ||
| 196 | while !data.is_empty() && is_whitespace(data[0]) { | ||
| 197 | *data = &data[1..]; | ||
| 198 | } | ||
| 199 | |||
| 200 | if data.is_empty() { | ||
| 201 | return &[]; | ||
| 202 | } | ||
| 203 | |||
| 204 | if data[0] == b'"' { | ||
| 205 | let data2 = &data[1..]; | ||
| 206 | let end = data2.iter().position(|&x| x == b'"').unwrap_or(data2.len()); | ||
| 207 | let field = &data2[..end]; | ||
| 208 | let mut rest = &data2[data2.len().min(end + 1)..]; | ||
| 209 | if rest.first() == Some(&b'\"') { | ||
| 210 | rest = &rest[1..]; | ||
| 211 | } | ||
| 212 | while !rest.is_empty() && is_separator(rest[0]) { | ||
| 213 | rest = &rest[1..]; | ||
| 214 | } | ||
| 215 | *data = rest; | ||
| 216 | field | ||
| 217 | } else { | ||
| 218 | let end = data.iter().position(|&x| is_separator(x)).unwrap_or(data.len()); | ||
| 219 | let field = &data[0..end]; | ||
| 220 | let rest = &data[data.len().min(end + 1)..]; | ||
| 221 | *data = rest; | ||
| 222 | field | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | fn pop_prefix(data: &mut &[u8], prefix: &[u8]) { | ||
| 227 | assert!(data.len() >= prefix.len()); | ||
| 228 | assert!(&data[..prefix.len()] == prefix); | ||
| 229 | *data = &data[prefix.len()..]; | ||
| 230 | } | ||
