Compare commits
6 Commits
bdd3b7ab9b
...
0814eedf13
Author | SHA1 | Date |
---|---|---|
glyph | 0814eedf13 | |
glyph | 4fb4ea2f9c | |
glyph | 8e283fbc6e | |
glyph | 67f33385e5 | |
glyph | a9bcc267a2 | |
glyph | a513b7aa5b |
|
@ -2293,7 +2293,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peach-network"
|
name = "peach-network"
|
||||||
version = "0.4.2"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"get_if_addrs",
|
"get_if_addrs",
|
||||||
"miniserde",
|
"miniserde",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "peach-network"
|
name = "peach-network"
|
||||||
version = "0.4.2"
|
version = "0.5.0"
|
||||||
authors = ["Andrew Reid <glyph@mycelial.technology>"]
|
authors = ["Andrew Reid <glyph@mycelial.technology>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Query and configure network interfaces."
|
description = "Query and configure network interfaces."
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
//! access point credentials to `wpa_supplicant-<wlan_iface>.conf`.
|
//! access point credentials to `wpa_supplicant-<wlan_iface>.conf`.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
fs::OpenOptions,
|
fs::OpenOptions,
|
||||||
io::prelude::*,
|
io::prelude::*,
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
|
@ -106,8 +107,86 @@ pub struct Traffic {
|
||||||
pub transmitted: u64,
|
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 */
|
/* 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
|
/// Retrieve list of available wireless access points for a given network
|
||||||
/// interface.
|
/// interface.
|
||||||
///
|
///
|
||||||
|
|
|
@ -212,6 +212,10 @@ pub fn mount_peachpub_routes(
|
||||||
routes::settings::network::configure_dns::handle_form(request)
|
routes::settings::network::configure_dns::handle_form(request)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
(GET) (/settings/network/wifi) => {
|
||||||
|
Response::html(routes::settings::network::list_aps::build_template())
|
||||||
|
},
|
||||||
|
|
||||||
(GET) (/settings/network/wifi/modify) => {
|
(GET) (/settings/network/wifi/modify) => {
|
||||||
Response::html(routes::settings::network::modify_ap::build_template(request, None)).reset_flash()
|
Response::html(routes::settings::network::modify_ap::build_template(request, None)).reset_flash()
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,34 +1,30 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use maud::{html, Markup, PreEscaped};
|
use maud::{html, Markup, PreEscaped};
|
||||||
use peach_network::{network, AccessPoint};
|
use peach_network::{network, network::AccessPoint};
|
||||||
use rouille::Request;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{templates, utils::theme};
|
||||||
templates,
|
|
||||||
utils::{flash::FlashRequest, theme},
|
|
||||||
};
|
|
||||||
|
|
||||||
// ROUTE: /settings/network/wifi
|
// ROUTE: /settings/network/wifi
|
||||||
|
|
||||||
/// Retrieve network state data required by the WiFi network list template.
|
/// Retrieve network state data required by the WiFi network list template.
|
||||||
fn get_network_state_data(ap: &str, wlan: &str) -> (String, String, HashMap<String, AccessPoint>) {
|
fn get_network_state_data(ap: &str, wlan: &str) -> (String, String, HashMap<String, AccessPoint>) {
|
||||||
let ap_state = match network::state("ap0") {
|
let ap_state = match network::state(ap) {
|
||||||
Ok(Some(state)) => state,
|
Ok(Some(state)) => state,
|
||||||
Err(_) => "Interface unavailable".to_string(),
|
_ => "Interface unavailable".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let wlan_ssid = match network::ssid("wlan0") {
|
let wlan_ssid = match network::ssid(wlan) {
|
||||||
Ok(Some(ssid)) => ssid,
|
Ok(Some(ssid)) => ssid,
|
||||||
Err(_) => "Not connected".to_string(),
|
_ => "Not connected".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let wlan_networks = match network::all_networks("wlan0") {
|
let network_list = match network::all_networks(wlan) {
|
||||||
Ok(networks) => networks,
|
Ok(networks) => networks,
|
||||||
Err(_) => HashMap::new(),
|
Err(_) => HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
(ap_state, wlan_ssid, wlan_networks)
|
(ap_state, wlan_ssid, network_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_network_connected_elements(ssid: String) -> Markup {
|
fn render_network_connected_elements(ssid: String) -> Markup {
|
||||||
|
@ -68,10 +64,10 @@ fn render_network_unavailable_elements(ssid: String, ap_state: String) -> Markup
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WiFi network list template builder.
|
/// WiFi network list template builder.
|
||||||
pub fn build_template(request: &Request) -> PreEscaped<String> {
|
pub fn build_template() -> PreEscaped<String> {
|
||||||
let (ap_state, wlan_ssid, wlan_networks) = get_network_state_data("ap0", "wlan0");
|
let (ap_state, wlan_ssid, network_list) = get_network_state_data("ap0", "wlan0");
|
||||||
|
|
||||||
html! {
|
let list_template = html! {
|
||||||
div class="card center" {
|
div class="card center" {
|
||||||
div class="center list-container" {
|
div class="center list-container" {
|
||||||
ul class="list" {
|
ul class="list" {
|
||||||
|
@ -79,8 +75,12 @@ pub fn build_template(request: &Request) -> PreEscaped<String> {
|
||||||
li class="list-item light-bg warning-border" {
|
li class="list-item light-bg warning-border" {
|
||||||
"Enable WiFi client mode to view saved and available networks."
|
"Enable WiFi client mode to view saved and available networks."
|
||||||
}
|
}
|
||||||
} @else if wlan_networks {
|
} @else if network_list.is_empty() {
|
||||||
@for (ssid, ap) in wlan_networks {
|
li class="list-item light-bg" {
|
||||||
|
"No saved or available networks found."
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
@for (ssid, ap) in network_list {
|
||||||
li {
|
li {
|
||||||
@if ssid == wlan_ssid {
|
@if ssid == wlan_ssid {
|
||||||
(render_network_connected_elements(ssid))
|
(render_network_connected_elements(ssid))
|
||||||
|
@ -91,13 +91,17 @@ pub fn build_template(request: &Request) -> PreEscaped<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} @else {
|
|
||||||
li class="list-item light-bg" {
|
|
||||||
"No saved or available networks found."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let body =
|
||||||
|
templates::nav::build_template(list_template, "WiFi Networks", Some("/settings/network"));
|
||||||
|
|
||||||
|
let theme = theme::get_theme();
|
||||||
|
|
||||||
|
templates::base::build_template(body, theme)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue