Skip to content

Commit 93ae975

Browse files
committed
feat: update wifiscanner for macOS v14.4>
1 parent dd700da commit 93ae975

File tree

3 files changed

+252
-4
lines changed

3 files changed

+252
-4
lines changed

libs/wifiscanner/Cargo.lock

Lines changed: 187 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/wifiscanner/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ path = "src/examples/main.rs"
1818
regex = "1"
1919
itertools = "0.10.0"
2020
tokio = { version = "1.40.0", features = ["process"] }
21+
os-version = "0.2.0"
22+
version-compare = "0.2.0"
2123

2224
[dev-dependencies]
2325
regex = "1"

libs/wifiscanner/src/sys/macos.rs

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,75 @@
11
use crate::{Error, Result, Wifi};
2+
use os_version::{self, MacOS};
3+
use regex::Regex;
4+
use tokio::process::Command;
5+
use version_compare::{compare_to, Cmp};
26

37
/// Returns a list of WiFi hotspots in your area - (OSX/MacOS) uses `airport`
48
pub(crate) async fn scan() -> Result<Vec<Wifi>> {
5-
use tokio::process::Command;
9+
let mac_version = match os_version::MacOS::detect() {
10+
Ok(version) => version,
11+
Err(_) => MacOS {
12+
version: "0.0.0".to_string(),
13+
},
14+
};
15+
16+
let r = match compare_to(mac_version.version, "14.4", Cmp::Ge) {
17+
Ok(cmp) => {
18+
if cmp {
19+
scan_system_profile().await
20+
} else {
21+
scan_airport().await
22+
}
23+
}
24+
Err(_) => scan_airport().await,
25+
};
26+
27+
return r;
28+
}
29+
30+
async fn scan_system_profile() -> Result<Vec<Wifi>> {
31+
let output = Command::new("system_profiler")
32+
.arg("SPAirPortDataType")
33+
.output()
34+
.await
35+
.map_err(|_| Error::CommandNotFound)?;
36+
let data = String::from_utf8_lossy(&output.stdout);
37+
parse_system_profile(&data)
38+
}
39+
40+
fn parse_system_profile(network_list: &str) -> Result<Vec<Wifi>> {
41+
let mut wifis: Vec<Wifi> = Vec::new();
42+
43+
let re = Regex::new(r"(?m)^\s+([^\n]+):\n\s+PHY Mode: [^\n]+\n\s+Channel: ([^\n]+)\n\s+.*?\n\s+Security: ([^\n]+)\n\s+Signal / Noise: ([^\n]+)")
44+
.unwrap();
45+
for w in re.captures_iter(network_list) {
46+
47+
let ssid = w[1].trim().to_string();
48+
let channel = w[2].split('(').next().unwrap().trim().to_string();
49+
let security = w[3].trim().to_string();
50+
let signal = w[4].split('/').next().unwrap().trim().to_string();
51+
52+
let wifi = Wifi{
53+
ssid,
54+
channel,
55+
signal_level: signal.split(' ').next().unwrap().trim().to_string(),
56+
security,
57+
mac: String::new(),
58+
};
59+
wifis.push(wifi);
60+
}
61+
62+
Ok(wifis)
63+
}
64+
65+
async fn scan_airport() -> Result<Vec<Wifi>> {
666
let output = Command::new(
767
"/System/Library/PrivateFrameworks/Apple80211.\
868
framework/Versions/Current/Resources/airport",
969
)
1070
.arg("-s")
11-
.output().await
71+
.output()
72+
.await
1273
.map_err(|_| Error::CommandNotFound)?;
1374

1475
let data = String::from_utf8_lossy(&output.stdout);

0 commit comments

Comments
 (0)