|
|
|
@ -14,6 +14,7 @@
|
|
|
|
|
//! access point credentials to `wpa_supplicant-<wlan_iface>.conf`.
|
|
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
|
collections::HashMap,
|
|
|
|
|
fs::OpenOptions,
|
|
|
|
|
io::prelude::*,
|
|
|
|
|
process::{Command, Stdio},
|
|
|
|
@ -106,8 +107,86 @@ pub struct Traffic {
|
|
|
|
|
pub transmitted: u64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Access point data including state and signal strength.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
#[cfg_attr(feature = "miniserde_support", derive(Serialize, Deserialize))]
|
|
|
|
|
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
|
|
|
|
|
pub struct AccessPoint {
|
|
|
|
|
/// Access point data retrieved via scan.
|
|
|
|
|
pub detail: Option<Scan>,
|
|
|
|
|
/// Current state of the access point (e.g. "Available" or "Out of range").
|
|
|
|
|
pub state: String,
|
|
|
|
|
/// Signal strength of the access point as a percentage.
|
|
|
|
|
pub signal: Option<i32>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl AccessPoint {
|
|
|
|
|
fn available(detail: Option<Scan>, signal: Option<i32>) -> AccessPoint {
|
|
|
|
|
AccessPoint {
|
|
|
|
|
detail,
|
|
|
|
|
state: String::from("Available"),
|
|
|
|
|
signal,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn saved() -> AccessPoint {
|
|
|
|
|
AccessPoint {
|
|
|
|
|
detail: None,
|
|
|
|
|
state: String::from("Out of range"),
|
|
|
|
|
signal: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* GET - Methods for retrieving data */
|
|
|
|
|
|
|
|
|
|
/// Retrieve combined list of available (in-range) and saved wireless access
|
|
|
|
|
/// points for a given network interface.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `iface` - A string slice holding the name of a wireless network interface
|
|
|
|
|
///
|
|
|
|
|
/// If the list results include one or more access points for the given network
|
|
|
|
|
/// interface, an `Ok` `Result` type is returned containing `HashMap<String,
|
|
|
|
|
/// AccessPoint>`.
|
|
|
|
|
///
|
|
|
|
|
/// Each entry in the returned `HashMap` contains an SSID (`String`) and
|
|
|
|
|
/// `AccessPoint` `struct`. If no access points are found, an empty `HashMap`
|
|
|
|
|
/// is returned in the `Result`. In the event of an error, a `NetworkError`
|
|
|
|
|
/// is returned in the `Result`.
|
|
|
|
|
pub fn all_networks(iface: &str) -> Result<HashMap<String, AccessPoint>, NetworkError> {
|
|
|
|
|
let mut wlan_networks = HashMap::new();
|
|
|
|
|
|
|
|
|
|
if let Ok(Some(networks)) = available_networks(iface) {
|
|
|
|
|
for ap in networks {
|
|
|
|
|
let ssid = ap.ssid.clone();
|
|
|
|
|
|
|
|
|
|
let rssi = ap.signal_level.clone();
|
|
|
|
|
// parse the string to a signed integer (for math)
|
|
|
|
|
let rssi_parsed = rssi.parse::<i32>().unwrap();
|
|
|
|
|
// perform rssi (dBm) to quality (%) conversion
|
|
|
|
|
let quality_percent = 2 * (rssi_parsed + 100);
|
|
|
|
|
|
|
|
|
|
let ap_detail = AccessPoint::available(Some(ap), Some(quality_percent));
|
|
|
|
|
wlan_networks.insert(ssid, ap_detail);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Ok(Some(networks)) = saved_networks() {
|
|
|
|
|
for saved_ssid in networks {
|
|
|
|
|
if !wlan_networks.contains_key(&saved_ssid) {
|
|
|
|
|
let ssid = saved_ssid.clone();
|
|
|
|
|
|
|
|
|
|
let ap_detail = AccessPoint::saved();
|
|
|
|
|
wlan_networks.insert(ssid, ap_detail);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(wlan_networks)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retrieve list of available wireless access points for a given network
|
|
|
|
|
/// interface.
|
|
|
|
|
///
|
|
|
|
|