Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNS server configuration + AP #87

Merged
merged 3 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions src/asynch/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
.wait_response(Duration::from_millis(Cmd::MAX_TIMEOUT_MS.into()))
.await?;
let response: &atat::Response<INGRESS_BUF_SIZE> = &response.borrow();
info!("response: {:?}", defmt::Debug2Format(&response));

Check failure on line 124 in src/asynch/control.rs

View workflow job for this annotation

GitHub Actions / Test

failed to resolve: use of undeclared crate or module `defmt`

Check failure on line 124 in src/asynch/control.rs

View workflow job for this annotation

GitHub Actions / clippy

failed to resolve: use of undeclared crate or module `defmt`

error[E0433]: failed to resolve: use of undeclared crate or module `defmt` --> src/asynch/control.rs:124:37 | 124 | info!("response: {:?}", defmt::Debug2Format(&response)); | ^^^^^ use of undeclared crate or module `defmt`
GustavToft marked this conversation as resolved.
Show resolved Hide resolved
cmd.parse(response.into())
}
}
Expand Down Expand Up @@ -182,7 +183,7 @@
Ok(mac.to_be_bytes()[2..].try_into().unwrap())
}

async fn get_wifi_status(&self) -> Result<WifiStatusVal, Error> {
GustavToft marked this conversation as resolved.
Show resolved Hide resolved
pub async fn get_wifi_status(&self) -> Result<WifiStatusVal, Error> {
match (&self.at_client)
.send_retry(&GetWifiStatus {
status_id: StatusId::Status,
Expand Down Expand Up @@ -333,41 +334,56 @@
ap_config_param: AccessPointConfig::IPv4Mode(IPv4Mode::Static),
})
.await?;
}

// Network IP address
if let Some(ip) = options.ip {
(&self.at_client)
.send_retry(&SetWifiAPConfig {
ap_config_id: AccessPointId::Id0,
ap_config_param: AccessPointConfig::IPv4Address(ip),
ap_config_param: AccessPointConfig::IPv4Address(
options.ip.unwrap_or(Ipv4Addr::new(192, 168, 2, 1)),
),
})
.await?;
}
// Network Subnet mask
if let Some(subnet) = options.subnet {

(&self.at_client)
.send_retry(&SetWifiAPConfig {
ap_config_id: AccessPointId::Id0,
ap_config_param: AccessPointConfig::SubnetMask(subnet),
ap_config_param: AccessPointConfig::SubnetMask(
options.subnet.unwrap_or(Ipv4Addr::new(255, 255, 255, 0)),
),
})
.await?;
}
// Network Default gateway
if let Some(gateway) = options.gateway {

(&self.at_client)
.send_retry(&SetWifiAPConfig {
ap_config_id: AccessPointId::Id0,
ap_config_param: AccessPointConfig::DefaultGateway(gateway),
ap_config_param: AccessPointConfig::DefaultGateway(
options.gateway.unwrap_or(Ipv4Addr::new(192, 168, 2, 1)),
),
})
.await?;
}
// Network Primary DNS
if let Some(dns) = options.dns {

// Network Primary + Secondary DNS
let primary = match options.dns.as_slice() {
&[primary] => Some(primary),
&[primary, secondary] => {
(&self.at_client)
.send_retry(&SetWifiAPConfig {
ap_config_id: AccessPointId::Id0,
ap_config_param: AccessPointConfig::SecondaryDNS(secondary),
})
.await?;

Some(primary)
}
_ => None,
};

if let Some(primary) = primary {
(&self.at_client)
.send_retry(&SetWifiAPConfig {
ap_config_id: AccessPointId::Id0,
ap_config_param: AccessPointConfig::PrimaryDNS(dns),
ap_config_param: AccessPointConfig::PrimaryDNS(primary),
})
.await?;
}
Expand Down
95 changes: 68 additions & 27 deletions src/asynch/network.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
use core::str::FromStr as _;

use atat::{asynch::AtatClient, UrcChannel, UrcSubscription};
use core::str::FromStr as _;
use embassy_time::{with_timeout, Duration, Timer};
use embedded_hal::digital::OutputPin as _;
use no_std_net::{Ipv4Addr, Ipv6Addr};

use crate::{
command::{
network::{
responses::NetworkStatusResponse,
types::{InterfaceType, NetworkStatus, NetworkStatusParameter},
responses::{APStatusResponse, NetworkStatusResponse},
types::{APStatusParameter, InterfaceType, NetworkStatus, NetworkStatusParameter},
urc::{NetworkDown, NetworkUp},
GetNetworkStatus,
GetAPStatus, GetNetworkStatus,
},
system::{RebootDCE, StoreCurrentConfig},
wifi::{
types::DisconnectReason,
types::{AccessPointStatus, DisconnectReason},
urc::{WifiLinkConnected, WifiLinkDisconnected},
},
Urc,
Expand Down Expand Up @@ -88,12 +87,16 @@ where
connection_id: _,
bssid,
channel,
}) => self.ch.update_connection_with(|con| {
con.wifi_state = WiFiState::Connected;
con.network
.replace(WifiNetwork::new_station(bssid, channel));
}),
}) => {
info!("wifi link connected");
self.ch.update_connection_with(|con| {
con.wifi_state = WiFiState::Connected;
con.network
.replace(WifiNetwork::new_station(bssid, channel));
})
}
Urc::WifiLinkDisconnected(WifiLinkDisconnected { reason, .. }) => {
info!("Wifi link disconnected");
self.ch.update_connection_with(|con| {
con.wifi_state = match reason {
DisconnectReason::NetworkDisabled => {
Expand Down Expand Up @@ -124,19 +127,18 @@ where
Urc::EthernetLinkUp(_) => warn!("Not yet implemented [EthernetLinkUp]"),
Urc::EthernetLinkDown(_) => warn!("Not yet implemented [EthernetLinkDown]"),
Urc::NetworkUp(NetworkUp { interface_id }) => {
//self.network_status_callback(interface_id).await?;
self.ch.update_connection_with(|con| {
con.ipv6_link_local_up = true;
con.ipv4_up = true;

#[cfg(feature = "ipv6")]
{
con.ipv6_up = ipv6_up
}
});
if interface_id > 10 {
self.ap_status_callback().await?;
} else {
self.network_status_callback(interface_id).await?;
}
}
Urc::NetworkDown(NetworkDown { interface_id }) => {
self.network_status_callback(interface_id).await?;
if interface_id > 10 {
self.ap_status_callback().await?;
} else {
self.network_status_callback(interface_id).await?;
}
}
Urc::NetworkError(_) => warn!("Not yet implemented [NetworkError]"),
_ => {}
Expand All @@ -152,13 +154,10 @@ where
// credentials have been restored from persistent memory. This although
// the wifi station has been started. So we assume that this type is
// also ok.
info!("Entered network_status_callback");
let NetworkStatusResponse {
status:
NetworkStatus::InterfaceType(
InterfaceType::WifiStation
| InterfaceType::Unknown
| InterfaceType::WifiAccessPoint,
),
NetworkStatus::InterfaceType(InterfaceType::WifiStation | InterfaceType::Unknown),
..
} = self
.at_client
Expand All @@ -170,6 +169,7 @@ where
else {
return Err(Error::Network);
};
info!("Network status changed");

GustavToft marked this conversation as resolved.
Show resolved Hide resolved
let NetworkStatusResponse {
status: NetworkStatus::IPv4Address(ipv4),
Expand All @@ -184,12 +184,17 @@ where
else {
return Err(Error::Network);
};
info!(
"Network status callback ipv4: {:?}",
core::str::from_utf8(&ipv4).ok()
);

let ipv4_up = core::str::from_utf8(ipv4.as_slice())
.ok()
.and_then(|s| Ipv4Addr::from_str(s).ok())
.map(|ip| !ip.is_unspecified())
.unwrap_or_default();
info!("Network status callback ipv4: {:?}", ipv4_up);

#[cfg(feature = "ipv6")]
let ipv6_up = {
Expand Down Expand Up @@ -227,13 +232,19 @@ where
else {
return Err(Error::Network);
};
info!(
"Network status callback ipv6: {:?}",
core::str::from_utf8(&ipv6_link_local).ok()
);

let ipv6_link_local_up = core::str::from_utf8(ipv6_link_local.as_slice())
.ok()
.and_then(|s| Ipv6Addr::from_str(s).ok())
.map(|ip| !ip.is_unspecified())
.unwrap_or_default();

info!("Network status callback ipv6: {:?}", ipv6_link_local_up);

// Use `ipv4_addr` & `ipv6_addr` to determine link state
self.ch.update_connection_with(|con| {
con.ipv6_link_local_up = ipv6_link_local_up;
Expand All @@ -248,6 +259,36 @@ where
Ok(())
}

async fn ap_status_callback(&mut self) -> Result<(), Error> {
let APStatusResponse {
status_val: AccessPointStatus::Status(ap_status),
..
} = self
.at_client
.send_retry(&GetAPStatus {
status_id: APStatusParameter::Status,
})
.await?
else {
return Err(Error::Network);
};
info!("AP status callback Status: {:?}", ap_status);

let ap_status = ap_status.into();

self.ch.update_connection_with(|con| {
con.ipv6_link_local_up = ap_status;
con.ipv4_up = ap_status;

#[cfg(feature = "ipv6")]
{
con.ipv6_up = ap_status;
}
});

Ok(())
}

async fn wait_startup(&mut self, timeout: Duration) -> Result<(), Error> {
let fut = async {
loop {
Expand Down
10 changes: 10 additions & 0 deletions src/command/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ use types::*;

use super::NoResponse;

/// 7.10 Wi-Fi Acess point status +UWAPSTAT
///
/// Read status of Wi-Fi interface id.
#[derive(Clone, AtatCmd)]
#[at_cmd("+UWAPSTAT", APStatusResponse, attempts = 3, timeout_ms = 1000)]
pub struct GetAPStatus {
#[at_arg(position = 0)]
pub status_id: APStatusParameter,
}

/// 10.1 Network host name +UNHN
///
/// Sets a new host name.
Expand Down
8 changes: 8 additions & 0 deletions src/command/network/responses.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
//! Responses for Network Commands
use crate::command::wifi::types::AccessPointStatus;

use super::types::*;
use atat::atat_derive::AtatResp;

/// 7.10 WiFi AP status +UWAPSTAT
#[derive(Clone, AtatResp)]
pub struct APStatusResponse {
pub status_val: AccessPointStatus,
}

/// 10.2 Network status +UNSTAT
#[derive(Clone, AtatResp)]
pub struct NetworkStatusResponse {
Expand Down
33 changes: 33 additions & 0 deletions src/command/network/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@ use heapless::String;

use crate::command::OnOff;

#[derive(Clone, PartialEq, AtatEnum)]
pub enum APStatus {
// 0: The <status_val> is the currently used SSID.
#[at_arg(value = 0)]
SSID(String<64>),
// 1: The <status_val> is the currently used BSSID.
#[at_arg(value = 1)]
BSSID(#[at_arg(len = 20)] Bytes<20>),
// 2: The <status_val> is the currently used channel.
#[at_arg(value = 2)]
Channel(u8),
// 3: The <status_val> is the current status of the access point.
// - 0: disabled
// - 1: enabled
#[at_arg(value = 3)]
Status(OnOff),
}

#[derive(Clone, PartialEq, AtatEnum)]
#[repr(u8)]
pub enum APStatusParameter {
// 0: The <status_val> is the currently used SSID.
SSID = 0,
// 1: The <status_val> is the currently used BSSID.
BSSID = 1,
// 2: The <status_val> is the currently used channel.
Channel = 2,
// 3: The <status_val> is the current status of the access point.
// • 0: disabled
// • 1: enabled
Status = 3,
}

#[derive(Clone, PartialEq, AtatEnum)]
pub enum NetworkStatus {
/// 0: The <status_val> is the interface hardware address (displayed only if applicable).
Expand Down
2 changes: 1 addition & 1 deletion src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@ impl WifiConnection {
}

pub fn is_connected(&self) -> bool {
(self.is_config_up() || self.is_access_point()) && self.wifi_state == WiFiState::Connected
self.is_config_up() && self.wifi_state == WiFiState::Connected
}
}
Loading
Loading