diff --git a/Mac.Tests/Mac.Tests.csproj b/Mac.Tests/Mac.Tests.csproj
index 96b25704..45c6605b 100644
--- a/Mac.Tests/Mac.Tests.csproj
+++ b/Mac.Tests/Mac.Tests.csproj
@@ -14,6 +14,6 @@
-
+
\ No newline at end of file
diff --git a/Mac.Tests/MacSignalParserTests.cs b/Mac.Tests/MacSignalParserTests.cs
index 5f08e7c4..a32ffd06 100644
--- a/Mac.Tests/MacSignalParserTests.cs
+++ b/Mac.Tests/MacSignalParserTests.cs
@@ -16,59 +16,34 @@ public async Task ResultsAreParsedIntoSignals()
//arrange
var logger = Substitute.For();
var signalParser = new MacSignalParser(logger);
- var contents = await File.ReadAllTextAsync("airport-output.txt");
+ var contents = await File.ReadAllTextAsync("system_profiler-output.txt");
//act
var signals = signalParser.Parse(contents).ToList();
//assert
Assert.Equal("net1", signals[0].SSID);
- Assert.Equal("xx:bf:xx:f7:13:xx", signals[0].MAC);
+ Assert.Empty(signals[0].MAC);
Assert.Equal(Frequency._2_4_GHz, signals[0].Frequency);
- Assert.Equal(11, signals[0].Channel);
- Assert.Equal(-83, signals[0].Strength);
+ Assert.Equal(9, signals[0].Channel);
+ Assert.Equal(-39, signals[0].Strength);
Assert.Equal("ssid🏎2", signals[1].SSID);
- Assert.Equal("xx:3d:xx:96:97:xx", signals[1].MAC);
+ Assert.Empty(signals[1].MAC);
Assert.Equal(Frequency._5_GHz, signals[1].Frequency);
- Assert.Equal(149, signals[1].Channel);
- Assert.Equal(-82, signals[1].Strength);
+ Assert.Equal(44, signals[1].Channel);
+ Assert.Equal(-50, signals[1].Strength);
Assert.Equal("access_point_3", signals[2].SSID);
- Assert.Equal("xx:3d:xx:96:98:xx", signals[2].MAC);
- Assert.Equal(Frequency._2_4_GHz, signals[2].Frequency);
- Assert.Equal(11, signals[2].Channel);
- Assert.Equal(-76, signals[2].Strength);
+ Assert.Empty(signals[2].MAC);
+ Assert.Equal(Frequency._5_GHz, signals[2].Frequency);
+ Assert.Equal(149, signals[2].Channel);
+ Assert.Equal(-42, signals[2].Strength);
Assert.Equal("wap-4", signals[3].SSID);
- Assert.Equal("xx:cb:xx:ad:a8:xx", signals[3].MAC);
+ Assert.Empty(signals[3].MAC);
Assert.Equal(Frequency._2_4_GHz, signals[3].Frequency);
- Assert.Equal(6, signals[3].Channel);
- Assert.Equal(-37, signals[3].Strength);
-
- Assert.Equal("router5", signals[4].SSID);
- Assert.Equal("xx:cb:xx:ad:a8:xx", signals[4].MAC);
- Assert.Equal(Frequency._5_GHz, signals[4].Frequency);
- Assert.Equal(149, signals[4].Channel);
- Assert.Equal(-42, signals[4].Strength);
- }
-
- [Fact]
- public async Task IgnoresInvalidResults()
- {
- //arrange
- var logger = Substitute.For();
- var signalParser = new MacSignalParser(logger);
- var contents = await File.ReadAllTextAsync("airport-output.txt");
- contents = contents
- .Replace("13:xx", "")
- .Replace("97:xx", "")
- .Replace("a8:xx", "");
-
- //act
- var signals = signalParser.Parse(contents);
-
- //assert
- Assert.Equal("access_point_3", signals.Single().SSID);
+ Assert.Equal(11, signals[3].Channel);
+ Assert.Equal(-90, signals[3].Strength);
}
}
\ No newline at end of file
diff --git a/Mac.Tests/airport-output.txt b/Mac.Tests/airport-output.txt
deleted file mode 100644
index e9abd230..00000000
--- a/Mac.Tests/airport-output.txt
+++ /dev/null
@@ -1,6 +0,0 @@
- SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group)
- net1 xx:bf:xx:f7:13:xx -83 11 Y -- WPA2(PSK/AES/AES)
- ssid🏎2 xx:3d:xx:96:97:xx -82 149 Y US WPA2(PSK/AES/AES)
- access_point_3 xx:3d:xx:96:98:xx -76 11 Y US WPA2(PSK/AES/AES)
- wap-4 xx:cb:xx:ad:a8:xx -37 6 Y US WPA2(PSK/AES/AES)
- router5 xx:cb:xx:ad:a8:xx -42 149 Y US WPA2(PSK/AES/AES)
diff --git a/Mac.Tests/system_profiler-output.txt b/Mac.Tests/system_profiler-output.txt
new file mode 100644
index 00000000..5cccb935
--- /dev/null
+++ b/Mac.Tests/system_profiler-output.txt
@@ -0,0 +1,162 @@
+{
+ "SPAirPortDataType" : [
+ {
+ "spairport_airport_interfaces" : [
+ {
+ "_name" : "en0",
+ "spairport_airport_other_local_wireless_networks" : [
+ {
+ "_name" : "net1",
+ "spairport_network_channel" : "9 (2GHz, 40MHz)",
+ "spairport_network_phymode" : "802.11",
+ "spairport_network_type" : "spairport_network_type_station",
+ "spairport_security_mode" : "pairport_security_mode_wpa3_transition",
+ "spairport_signal_noise" : "-39 dBm / -90 dBm"
+ },
+ {
+ "_name" : "ssid🏎2",
+ "spairport_network_channel" : "44 (5GHz, 80MHz)",
+ "spairport_network_phymode" : "802.11",
+ "spairport_network_type" : "spairport_network_type_station",
+ "spairport_security_mode" : "pairport_security_mode_wpa3_transition",
+ "spairport_signal_noise" : "-50 dBm / -90 dBm"
+ },
+ {
+ "_name" : "access_point_3",
+ "spairport_network_channel" : "149 (5GHz, 80MHz)",
+ "spairport_network_phymode" : "802.11",
+ "spairport_network_type" : "spairport_network_type_station",
+ "spairport_security_mode" : "pairport_security_mode_wpa3_transition",
+ "spairport_signal_noise" : "-42 dBm / -90 dBm"
+ },
+ {
+ "_name" : "wap-4",
+ "spairport_network_channel" : "11 (2GHz, 40MHz)",
+ "spairport_network_phymode" : "802.11",
+ "spairport_network_type" : "spairport_network_type_station",
+ "spairport_security_mode" : "spairport_security_mode_wpa2_personal",
+ "spairport_signal_noise" : "-90 dBm / -90 dBm"
+ }
+ ],
+ "spairport_caps_airdrop" : "spairport_caps_supported",
+ "spairport_caps_autounlock" : "spairport_caps_supported",
+ "spairport_caps_wow" : "spairport_caps_supported",
+ "spairport_current_network_information" : {
+ "_name" : "net1",
+ "spairport_network_channel" : "149 (5GHz, 80MHz)",
+ "spairport_network_country_code" : "US",
+ "spairport_network_mcs" : 7,
+ "spairport_network_phymode" : "802.11ac",
+ "spairport_network_rate" : 975,
+ "spairport_network_type" : "spairport_network_type_station",
+ "spairport_security_mode" : "pairport_security_mode_wpa3_transition",
+ "spairport_signal_noise" : "-48 dBm / -90 dBm"
+ },
+ "spairport_status_information" : "spairport_status_connected",
+ "spairport_supported_channels" : [
+ "1 (2GHz)",
+ "2 (2GHz)",
+ "3 (2GHz)",
+ "4 (2GHz)",
+ "5 (2GHz)",
+ "6 (2GHz)",
+ "7 (2GHz)",
+ "8 (2GHz)",
+ "9 (2GHz)",
+ "10 (2GHz)",
+ "11 (2GHz)",
+ "12 (2GHz)",
+ "13 (2GHz)",
+ "36 (5GHz)",
+ "40 (5GHz)",
+ "44 (5GHz)",
+ "48 (5GHz)",
+ "52 (5GHz)",
+ "56 (5GHz)",
+ "60 (5GHz)",
+ "64 (5GHz)",
+ "100 (5GHz)",
+ "104 (5GHz)",
+ "108 (5GHz)",
+ "112 (5GHz)",
+ "116 (5GHz)",
+ "120 (5GHz)",
+ "124 (5GHz)",
+ "128 (5GHz)",
+ "132 (5GHz)",
+ "136 (5GHz)",
+ "140 (5GHz)",
+ "144 (5GHz)",
+ "149 (5GHz)",
+ "153 (5GHz)",
+ "157 (5GHz)",
+ "161 (5GHz)",
+ "165 (5GHz)"
+ ],
+ "spairport_supported_phymodes" : "802.11 a/b/g/n/ac",
+ "spairport_wireless_card_type" : "spairport_wireless_card_type_wifi (0x14E4, 0x7BF)",
+ "spairport_wireless_country_code" : "US",
+ "spairport_wireless_firmware_version" : "wl0: Jul 10 2023 12:30:19 version 9.30.503.0.32.5.92 FWID 01-88a8883",
+ "spairport_wireless_locale" : "ETSI",
+ "spairport_wireless_mac_address" : "f0:18:98:2b:b7:78"
+ },
+ {
+ "_name" : "awdl0",
+ "spairport_current_network_information" : {
+ "spairport_network_type" : "spairport_network_type_station"
+ },
+ "spairport_supported_channels" : [
+ "1 (2GHz)",
+ "2 (2GHz)",
+ "3 (2GHz)",
+ "4 (2GHz)",
+ "5 (2GHz)",
+ "6 (2GHz)",
+ "7 (2GHz)",
+ "8 (2GHz)",
+ "9 (2GHz)",
+ "10 (2GHz)",
+ "11 (2GHz)",
+ "12 (2GHz)",
+ "13 (2GHz)",
+ "36 (5GHz)",
+ "40 (5GHz)",
+ "44 (5GHz)",
+ "48 (5GHz)",
+ "52 (5GHz)",
+ "56 (5GHz)",
+ "60 (5GHz)",
+ "64 (5GHz)",
+ "100 (5GHz)",
+ "104 (5GHz)",
+ "108 (5GHz)",
+ "112 (5GHz)",
+ "116 (5GHz)",
+ "120 (5GHz)",
+ "124 (5GHz)",
+ "128 (5GHz)",
+ "132 (5GHz)",
+ "136 (5GHz)",
+ "140 (5GHz)",
+ "144 (5GHz)",
+ "149 (5GHz)",
+ "153 (5GHz)",
+ "157 (5GHz)",
+ "161 (5GHz)",
+ "165 (5GHz)"
+ ],
+ "spairport_wireless_mac_address" : "5e:01:d5:ed:24:a0"
+ }
+ ],
+ "spairport_software_information" : {
+ "spairport_corewlan_version" : "16.0 (1657)",
+ "spairport_corewlankit_version" : "16.0 (1657)",
+ "spairport_diagnostics_version" : "11.0 (1163)",
+ "spairport_extra_version" : "17.0 (1728)",
+ "spairport_family_version" : "12.0 (1200.13.0)",
+ "spairport_profiler_version" : "15.0 (1502)",
+ "spairport_utility_version" : "6.3.9 (639.23)"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Mac/MacSignalParser.cs b/Mac/MacSignalParser.cs
index b5092823..c8e007ed 100644
--- a/Mac/MacSignalParser.cs
+++ b/Mac/MacSignalParser.cs
@@ -1,4 +1,5 @@
using System.Text;
+using System.Text.Json;
using WiFiSurveyor.Core;
namespace WiFiSurveyor.Mac;
@@ -11,39 +12,47 @@ public MacSignalParser(ILogger logger)
=> _logger = logger;
public IReadOnlyList Parse(string results)
- => results.Split("\n", StringSplitOptions.RemoveEmptyEntries)
- .Skip(1)
- .Select(line => GetSignal(Encoding.UTF8.GetBytes(line)))
+ => JsonSerializer.Deserialize(results)
+ .GetProperty("SPAirPortDataType").EnumerateArray().First()
+ .GetProperty("spairport_airport_interfaces").EnumerateArray().First()
+ .GetProperty("spairport_airport_other_local_wireless_networks").EnumerateArray()
+ .Select(j => GetSignal(j))
.Where(s => s is not null)
.Cast()
.ToArray();
- private Signal? GetSignal(ReadOnlySpan line)
+ private Signal? GetSignal(JsonElement json)
{
try
{
- return new()
+ return new Signal
{
- SSID = Encoding.UTF8.GetString(line[..32]).Trim(),
- MAC = Encoding.UTF8.GetString(line[32..50]).Trim(),
- Strength = short.Parse(Encoding.UTF8.GetString(line[50..55]).Trim()),
- Channel = GetChannel(Encoding.UTF8.GetString(line[55..64]).Trim()),
- Frequency = GetFrequency(Encoding.UTF8.GetString(line[55..64]).Trim())
+ SSID = GetString(json, "_name"),
+ MAC = string.Empty,
+ Strength = GetStrength(GetString(json, "spairport_signal_noise")),
+ Channel = GetChannel(GetString(json, "spairport_network_channel")),
+ Frequency = GetFrequency(GetString(json, "spairport_network_channel"))
};
}
catch (Exception e)
{
- _logger.LogIf(LogLevel.Warning, "{now}: Could not parse signal data -- {data}", DateTime.Now, Encoding.UTF8.GetString(line));
+ _logger.LogIf(LogLevel.Warning, "{now}: Could not parse signal data -- {data}", DateTime.Now, json.ToString());
_logger.LogIf(LogLevel.Debug, "{exception}", e.ToString());
return null;
}
}
- private static Frequency GetFrequency(string column)
- => GetChannel(column) < 32
+ private static string GetString(JsonElement json, string property)
+ => json.GetProperty(property).GetString() ?? string.Empty;
+
+ private static short GetStrength(string value)
+ => short.Parse(value.Split(' ')[0]);
+
+ private static Frequency GetFrequency(string value)
+ => GetChannel(value) < 32
? Frequency._2_4_GHz
: Frequency._5_GHz;
- private static byte GetChannel(string column)
- => byte.Parse(column.Split(',')[0]);
+ private static byte GetChannel(string value)
+ => byte.Parse(value.Split(' ')[0]);
}
\ No newline at end of file
diff --git a/Mac/MacSignalReader.cs b/Mac/MacSignalReader.cs
index 6d6f65d1..96e47957 100644
--- a/Mac/MacSignalReader.cs
+++ b/Mac/MacSignalReader.cs
@@ -9,5 +9,5 @@ public MacSignalReader(ICommandService commandService) : base(commandService)
{
}
- protected override ProcessStartInfo Info => new("/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport", " -s");
+ protected override ProcessStartInfo Info => new("system_profiler", "SPAirPortDataType -detailLevel full -json");
}
\ No newline at end of file