Task 2 should be finished
This commit is contained in:
+146
@@ -0,0 +1,146 @@
|
|||||||
|
trace1 = load("traces/2412mhz.mat", "iq");
|
||||||
|
trace2 = load("traces/2432mhz.mat", "iq");
|
||||||
|
trace3 = load("traces/2452mhz.mat", "iq");
|
||||||
|
trace4 = load("traces/2472mhz.mat", "iq");
|
||||||
|
|
||||||
|
window = 512;
|
||||||
|
overlap = 64;
|
||||||
|
fft_precision = 2048;
|
||||||
|
|
||||||
|
sample_rate = 20e6; % 20 MS/s -> 20e6 S/s
|
||||||
|
|
||||||
|
% 1.
|
||||||
|
duration1 = length(trace1.iq) / sample_rate;
|
||||||
|
duration2 = length(trace2.iq) / sample_rate;
|
||||||
|
duration3 = length(trace3.iq) / sample_rate;
|
||||||
|
duration4 = length(trace4.iq) / sample_rate;
|
||||||
|
|
||||||
|
% 2.
|
||||||
|
% get all four plot values
|
||||||
|
[S1,F1,T1] = spectrogram(trace1.iq, window, overlap, fft_precision, sample_rate, "centered");
|
||||||
|
[S2,F2,T2] = spectrogram(trace2.iq, window, overlap, fft_precision, sample_rate, "centered");
|
||||||
|
[S3,F3,T3] = spectrogram(trace3.iq, window, overlap, fft_precision, sample_rate, "centered");
|
||||||
|
[S4,F4,T4] = spectrogram(trace4.iq, window, overlap, fft_precision, sample_rate, "centered");
|
||||||
|
|
||||||
|
mag1 = abs(S1).^2;
|
||||||
|
mag2 = abs(S2).^2;
|
||||||
|
mag3 = abs(S3).^2;
|
||||||
|
mag4 = abs(S4).^2;
|
||||||
|
|
||||||
|
% begin calibrated color scale
|
||||||
|
P1_dB = 10 * log10(mag1);
|
||||||
|
P2_dB = 10 * log10(mag2);
|
||||||
|
P3_dB = 10 * log10(mag3);
|
||||||
|
P4_dB = 10 * log10(mag4);
|
||||||
|
|
||||||
|
all_P_dB = [P1_dB(:); P2_dB(:); P3_dB(:); P4_dB(:)];
|
||||||
|
|
||||||
|
p_dB_min = min(all_P_dB);
|
||||||
|
p_dB_max = max(all_P_dB);
|
||||||
|
% end power calibrated color scale
|
||||||
|
|
||||||
|
if ~calculations_only
|
||||||
|
% plot all figures like example shows
|
||||||
|
figure(1);
|
||||||
|
imagesc(T1, F1, P1_dB);
|
||||||
|
axis ij;
|
||||||
|
xlabel("Time [s]");
|
||||||
|
ylabel("Freq. [Hz]");
|
||||||
|
title("Spectrogram Trace 1");
|
||||||
|
cb = colorbar;
|
||||||
|
ylabel(cb, "Power [dB]");
|
||||||
|
clim([p_dB_min p_dB_max]);
|
||||||
|
xlim([0 0.05]);
|
||||||
|
|
||||||
|
figure(2);
|
||||||
|
imagesc(T2, F2, P2_dB);
|
||||||
|
axis ij;
|
||||||
|
xlabel("Time [s]");
|
||||||
|
ylabel("Freq. [Hz]");
|
||||||
|
title("Spectrogram Trace 2");
|
||||||
|
cb = colorbar;
|
||||||
|
ylabel(cb, "Power [dB]");
|
||||||
|
clim([p_dB_min p_dB_max]);
|
||||||
|
xlim([0 0.05]);
|
||||||
|
|
||||||
|
figure(3);
|
||||||
|
imagesc(T3, F3, P3_dB);
|
||||||
|
axis ij;
|
||||||
|
xlabel("Time [s]");
|
||||||
|
ylabel("Freq. [Hz]");
|
||||||
|
title("Spectrogram Trace 3");
|
||||||
|
cb = colorbar;
|
||||||
|
ylabel(cb, "Power [dB]");
|
||||||
|
clim([p_dB_min p_dB_max]);
|
||||||
|
xlim([0 0.05]);
|
||||||
|
|
||||||
|
figure(4);
|
||||||
|
imagesc(T4, F4, P4_dB);
|
||||||
|
axis ij; % flip so its like the example fig
|
||||||
|
xlabel("Time [s]");
|
||||||
|
ylabel("Freq. [Hz]");
|
||||||
|
title("Spectrogram Trace 4");
|
||||||
|
cb = colorbar;
|
||||||
|
ylabel(cb, "Power [dB]");
|
||||||
|
clim([p_dB_min p_dB_max]);
|
||||||
|
xlim([0 0.05]); % reduce view so its like the example fig
|
||||||
|
end
|
||||||
|
|
||||||
|
% 3.
|
||||||
|
% taking the 10th percentile on the linear values or the logarithmic ones
|
||||||
|
% should not make any difference
|
||||||
|
|
||||||
|
noise_floor1_linear = prctile(mag1(:), 10);
|
||||||
|
noise_floor2_linear = prctile(mag2(:), 10);
|
||||||
|
noise_floor3_linear = prctile(mag3(:), 10);
|
||||||
|
noise_floor4_linear = prctile(mag4(:), 10);
|
||||||
|
|
||||||
|
noise_floor1 = 10 * log10(noise_floor1_linear);
|
||||||
|
noise_floor2 = prctile(P2_dB(:), 10);
|
||||||
|
noise_floor3 = prctile(P3_dB(:), 10);
|
||||||
|
noise_floor4 = prctile(P4_dB(:), 10);
|
||||||
|
|
||||||
|
% this is false -> linear avg on logarithmic values
|
||||||
|
% noise_floor_avg = sum([noise_floor1 noise_floor2, noise_floor3, noise_floor4]) / 4;
|
||||||
|
|
||||||
|
noise_floor_avg = 10 * log10(abs(sum([prctile(mag1(:), 10) prctile(mag2(:), 10) prctile(mag3(:), 10) prctile(mag4(:), 10)]) / 4));
|
||||||
|
|
||||||
|
% 4.
|
||||||
|
occupancy1 = sum(P1_dB(:) > noise_floor1 + 10) / numel(P1_dB) * 100;
|
||||||
|
occupancy2 = sum(P2_dB(:) > noise_floor2 + 10) / numel(P2_dB) * 100;
|
||||||
|
occupancy3 = sum(P3_dB(:) > noise_floor3 + 10) / numel(P3_dB) * 100;
|
||||||
|
occupancy4 = sum(P4_dB(:) > noise_floor4 + 10) / numel(P4_dB) * 100;
|
||||||
|
|
||||||
|
occupancies = [occupancy1 occupancy2 occupancy3 occupancy4];
|
||||||
|
channels = [1 5 9 13];
|
||||||
|
|
||||||
|
[occupancy_max, max_idx] = max(occupancies);
|
||||||
|
busiest_channel = channels(max_idx);
|
||||||
|
|
||||||
|
if ~calculations_only
|
||||||
|
disp("Results Task 1:" + newline)
|
||||||
|
|
||||||
|
disp("-- Trace duration ---")
|
||||||
|
disp("Channel 1 duration: " + duration1 + "s")
|
||||||
|
disp("Channel 5 duration: " + duration2 + "s")
|
||||||
|
disp("Channel 9 duration: " + duration3 + "s")
|
||||||
|
disp("Channel 13 duration: " + duration4 + "s" + newline)
|
||||||
|
|
||||||
|
disp("--- Noise floor ---")
|
||||||
|
disp("Distinct:")
|
||||||
|
disp("Channel 1 noise floor: " + noise_floor1 + "dB")
|
||||||
|
disp("Channel 5 noise floor: " + noise_floor2 + "dB")
|
||||||
|
disp("Channel 9 noise floor: " + noise_floor3 + "dB")
|
||||||
|
disp("Channel 13 noise floor: " + noise_floor4 + "dB" + newline)
|
||||||
|
|
||||||
|
disp("Combined:")
|
||||||
|
disp("Channel all noise floor: " + noise_floor_avg + "dB" + newline)
|
||||||
|
|
||||||
|
disp("-- Occupancy ---")
|
||||||
|
disp("Channel 1 occupancy: " + occupancy1 + "%")
|
||||||
|
disp("Channel 5 occupancy: " + occupancy2 + "%")
|
||||||
|
disp("Channel 9 occupancy: " + occupancy3 + "%")
|
||||||
|
disp("Channel 13 occupancy: " + occupancy4 + "%" + newline)
|
||||||
|
|
||||||
|
disp("Busiest channel: " + busiest_channel)
|
||||||
|
end
|
||||||
+70
-14
@@ -22,15 +22,19 @@ duration4 = length(trace4.iq) / sample_rate;
|
|||||||
[S3,F3,T3] = spectrogram(trace3.iq, window, overlap, fft_precision, sample_rate, "centered");
|
[S3,F3,T3] = spectrogram(trace3.iq, window, overlap, fft_precision, sample_rate, "centered");
|
||||||
[S4,F4,T4] = spectrogram(trace4.iq, window, overlap, fft_precision, sample_rate, "centered");
|
[S4,F4,T4] = spectrogram(trace4.iq, window, overlap, fft_precision, sample_rate, "centered");
|
||||||
|
|
||||||
|
mag1 = abs(S1).^2;
|
||||||
|
mag2 = abs(S2).^2;
|
||||||
|
mag3 = abs(S3).^2;
|
||||||
|
mag4 = abs(S4).^2;
|
||||||
|
|
||||||
% begin calibrated color scale
|
% begin calibrated color scale
|
||||||
P1_dB = 20 * log10(abs(S1).^2);
|
P1_dB = 10 * log10(mag1);
|
||||||
P2_dB = 20 * log10(abs(S2).^2);
|
P2_dB = 10 * log10(mag2);
|
||||||
P3_dB = 20 * log10(abs(S3).^2);
|
P3_dB = 10 * log10(mag3);
|
||||||
P4_dB = 20 * log10(abs(S4).^2);
|
P4_dB = 10 * log10(mag4);
|
||||||
|
|
||||||
all_P_dB = [P1_dB(:); P2_dB(:); P3_dB(:); P4_dB(:)];
|
all_P_dB = [P1_dB(:); P2_dB(:); P3_dB(:); P4_dB(:)];
|
||||||
|
|
||||||
% -50 to +50 so its like the example fig
|
|
||||||
p_dB_min = min(all_P_dB);
|
p_dB_min = min(all_P_dB);
|
||||||
p_dB_max = max(all_P_dB);
|
p_dB_max = max(all_P_dB);
|
||||||
% end power calibrated color scale
|
% end power calibrated color scale
|
||||||
@@ -46,7 +50,7 @@ if ~calculations_only
|
|||||||
cb = colorbar;
|
cb = colorbar;
|
||||||
ylabel(cb, "Power [dB]");
|
ylabel(cb, "Power [dB]");
|
||||||
clim([p_dB_min p_dB_max]);
|
clim([p_dB_min p_dB_max]);
|
||||||
xlim([0 0.05]);
|
% xlim([0 0.05]);
|
||||||
|
|
||||||
figure(2);
|
figure(2);
|
||||||
imagesc(T2, F2, P2_dB);
|
imagesc(T2, F2, P2_dB);
|
||||||
@@ -57,7 +61,7 @@ if ~calculations_only
|
|||||||
cb = colorbar;
|
cb = colorbar;
|
||||||
ylabel(cb, "Power [dB]");
|
ylabel(cb, "Power [dB]");
|
||||||
clim([p_dB_min p_dB_max]);
|
clim([p_dB_min p_dB_max]);
|
||||||
xlim([0 0.05]);
|
% xlim([0 0.05]);
|
||||||
|
|
||||||
figure(3);
|
figure(3);
|
||||||
imagesc(T3, F3, P3_dB);
|
imagesc(T3, F3, P3_dB);
|
||||||
@@ -68,7 +72,7 @@ if ~calculations_only
|
|||||||
cb = colorbar;
|
cb = colorbar;
|
||||||
ylabel(cb, "Power [dB]");
|
ylabel(cb, "Power [dB]");
|
||||||
clim([p_dB_min p_dB_max]);
|
clim([p_dB_min p_dB_max]);
|
||||||
xlim([0 0.05]);
|
% xlim([0 0.05]);
|
||||||
|
|
||||||
figure(4);
|
figure(4);
|
||||||
imagesc(T4, F4, P4_dB);
|
imagesc(T4, F4, P4_dB);
|
||||||
@@ -79,22 +83,70 @@ if ~calculations_only
|
|||||||
cb = colorbar;
|
cb = colorbar;
|
||||||
ylabel(cb, "Power [dB]");
|
ylabel(cb, "Power [dB]");
|
||||||
clim([p_dB_min p_dB_max]);
|
clim([p_dB_min p_dB_max]);
|
||||||
xlim([0 0.05]); % reduce view so its like the example fig
|
% xlim([0 0.05]); % reduce view so its like the example fig
|
||||||
end
|
end
|
||||||
|
|
||||||
|
%{
|
||||||
% 3.
|
% 3.
|
||||||
noise_floor1 = prctile(P1_dB(:), 10);
|
% taking the 10th percentile on the linear values or the logarithmic ones
|
||||||
noise_floor2 = prctile(P2_dB(:), 10);
|
% should not make any difference
|
||||||
noise_floor3 = prctile(P3_dB(:), 10);
|
|
||||||
noise_floor4 = prctile(P4_dB(:), 10);
|
|
||||||
|
|
||||||
noise_floor_avg = sum([noise_floor1 noise_floor2, noise_floor3, noise_floor4]) / 4;
|
noise_floor1_linear = prctile(mag1(:), 10);
|
||||||
|
noise_floor2_linear = prctile(mag2(:), 10);
|
||||||
|
noise_floor3_linear = prctile(mag3(:), 10);
|
||||||
|
noise_floor4_linear = prctile(mag4(:), 10);
|
||||||
|
|
||||||
|
noise_floor1 = linearTodB(noise_floor1_linear);
|
||||||
|
noise_floor2 = linearTodB(noise_floor2_linear);
|
||||||
|
noise_floor3 = linearTodB(noise_floor3_linear);
|
||||||
|
noise_floor4 = linearTodB(noise_floor4_linear);
|
||||||
|
|
||||||
|
% this is false -> linear avg on logarithmic values
|
||||||
|
% noise_floor_avg = sum([noise_floor1 noise_floor2, noise_floor3, noise_floor4]) / 4;
|
||||||
|
|
||||||
|
noise_floor_avg = linearTodB(mean([noise_floor1_linear noise_floor2_linear noise_floor3_linear noise_floor4_linear]));
|
||||||
|
|
||||||
% 4.
|
% 4.
|
||||||
occupancy1 = sum(P1_dB(:) > noise_floor1 + 10) / numel(P1_dB) * 100;
|
occupancy1 = sum(P1_dB(:) > noise_floor1 + 10) / numel(P1_dB) * 100;
|
||||||
occupancy2 = sum(P2_dB(:) > noise_floor2 + 10) / numel(P2_dB) * 100;
|
occupancy2 = sum(P2_dB(:) > noise_floor2 + 10) / numel(P2_dB) * 100;
|
||||||
occupancy3 = sum(P3_dB(:) > noise_floor3 + 10) / numel(P3_dB) * 100;
|
occupancy3 = sum(P3_dB(:) > noise_floor3 + 10) / numel(P3_dB) * 100;
|
||||||
occupancy4 = sum(P4_dB(:) > noise_floor4 + 10) / numel(P4_dB) * 100;
|
occupancy4 = sum(P4_dB(:) > noise_floor4 + 10) / numel(P4_dB) * 100;
|
||||||
|
%}
|
||||||
|
|
||||||
|
% 3.
|
||||||
|
% Sum all frequency bins per time slot to obtain total channel power.
|
||||||
|
channel_power1_linear = sum(mag1, 1);
|
||||||
|
channel_power2_linear = sum(mag2, 1);
|
||||||
|
channel_power3_linear = sum(mag3, 1);
|
||||||
|
channel_power4_linear = sum(mag4, 1);
|
||||||
|
|
||||||
|
channel_power1_dB = linearTodB(channel_power1_linear);
|
||||||
|
channel_power2_dB = linearTodB(channel_power2_linear);
|
||||||
|
channel_power3_dB = linearTodB(channel_power3_linear);
|
||||||
|
channel_power4_dB = linearTodB(channel_power4_linear);
|
||||||
|
|
||||||
|
noise_floor1_linear = prctile(channel_power1_linear, 10);
|
||||||
|
noise_floor2_linear = prctile(channel_power2_linear, 10);
|
||||||
|
noise_floor3_linear = prctile(channel_power3_linear, 10);
|
||||||
|
noise_floor4_linear = prctile(channel_power4_linear, 10);
|
||||||
|
|
||||||
|
noise_floor1 = linearTodB(noise_floor1_linear);
|
||||||
|
noise_floor2 = linearTodB(noise_floor2_linear);
|
||||||
|
noise_floor3 = linearTodB(noise_floor3_linear);
|
||||||
|
noise_floor4 = linearTodB(noise_floor4_linear);
|
||||||
|
|
||||||
|
noise_floor_avg = linearTodB(mean([
|
||||||
|
noise_floor1_linear
|
||||||
|
noise_floor2_linear
|
||||||
|
noise_floor3_linear
|
||||||
|
noise_floor4_linear
|
||||||
|
]));
|
||||||
|
|
||||||
|
% 4.
|
||||||
|
occupancy1 = sum(channel_power1_dB > noise_floor1 + 10) / numel(channel_power1_dB) * 100;
|
||||||
|
occupancy2 = sum(channel_power2_dB > noise_floor2 + 10) / numel(channel_power2_dB) * 100;
|
||||||
|
occupancy3 = sum(channel_power3_dB > noise_floor3 + 10) / numel(channel_power3_dB) * 100;
|
||||||
|
occupancy4 = sum(channel_power4_dB > noise_floor4 + 10) / numel(channel_power4_dB) * 100;
|
||||||
|
|
||||||
occupancies = [occupancy1 occupancy2 occupancy3 occupancy4];
|
occupancies = [occupancy1 occupancy2 occupancy3 occupancy4];
|
||||||
channels = [1 5 9 13];
|
channels = [1 5 9 13];
|
||||||
@@ -128,4 +180,8 @@ if ~calculations_only
|
|||||||
disp("Channel 13 occupancy: " + occupancy4 + "%" + newline)
|
disp("Channel 13 occupancy: " + occupancy4 + "%" + newline)
|
||||||
|
|
||||||
disp("Busiest channel: " + busiest_channel)
|
disp("Busiest channel: " + busiest_channel)
|
||||||
|
end
|
||||||
|
|
||||||
|
function val = linearTodB(toConvert)
|
||||||
|
val = 10 * log10(toConvert);
|
||||||
end
|
end
|
||||||
+219
-8
@@ -1,18 +1,81 @@
|
|||||||
channel_bandwidth = "CBW20"; % 20MHz
|
addpath("from_matlab_example");
|
||||||
|
|
||||||
rxFrame1 = trace1.iq(:);
|
rxFrame1 = trace1.iq(:);
|
||||||
rxFrame2 = trace2.iq(:);
|
rxFrame2 = trace2.iq(:);
|
||||||
rxFrame3 = trace3.iq(:);
|
rxFrame3 = trace3.iq(:);
|
||||||
rxFrame4 = trace4.iq(:);
|
rxFrame4 = trace4.iq(:);
|
||||||
|
|
||||||
function beaconFrames = extractBeaconFrames(rxFrame)
|
beaconFrames1 = extractBeaconFrames(rxFrame1);
|
||||||
beaconFrames = [];
|
beaconFrames2 = extractBeaconFrames(rxFrame2);
|
||||||
searchOffset = 0;
|
beaconFrames3 = extractBeaconFrames(rxFrame3);
|
||||||
|
beaconFrames4 = extractBeaconFrames(rxFrame4);
|
||||||
|
|
||||||
|
% 1.
|
||||||
|
disp("Beacon Frame 1")
|
||||||
|
printBeaconTable(beaconFrames1);
|
||||||
|
disp("Beacon Frame 2")
|
||||||
|
printBeaconTable(beaconFrames2);
|
||||||
|
disp("Beacon Frame 3")
|
||||||
|
printBeaconTable(beaconFrames3);
|
||||||
|
disp("Beacon Frame 4")
|
||||||
|
printBeaconTable(beaconFrames4);
|
||||||
|
|
||||||
|
% 2.
|
||||||
|
%{
|
||||||
|
Address 1: used to announce the destination station, in a beacon frame its
|
||||||
|
FF:FF:FF:FF:FF:FF (meaning broadcast to all stations)
|
||||||
|
Address 2: used to remark the source device address of the frame,
|
||||||
|
the ap mac who sent the beacon is inserted
|
||||||
|
Address 3: used for the bssid of the device sending the beacon, means
|
||||||
|
usually address 2 equals address 3, when no virtual ap is used
|
||||||
|
Address 4: this field does not exists, after the seq ctrl the frame body
|
||||||
|
follows containing beacon data instead of an address, like
|
||||||
|
timestamp, beacon interval, capability info, ssid, potentially
|
||||||
|
the channel number, see the extracts from 2.1
|
||||||
|
%}
|
||||||
|
|
||||||
|
% 3.
|
||||||
|
%{
|
||||||
|
Downlink:
|
||||||
|
Address 1: MAC of the destination station
|
||||||
|
Address 2: MAC of the AP which further routes the frame
|
||||||
|
Address 3: MAC of the initial sender which has started the process of
|
||||||
|
the frame to AP's
|
||||||
|
Address 4: not used
|
||||||
|
Uplink:
|
||||||
|
Address 1: MAC of the AP the WiFi frame should route through
|
||||||
|
(the connected AP)
|
||||||
|
Address 2: MAC of the sending station
|
||||||
|
Address 3: used to store the final destination MAC address
|
||||||
|
|
||||||
|
Address 4: not used
|
||||||
|
|
||||||
|
4 Address case:
|
||||||
|
Address 4: is only used in wireless bridge solutions, environments where
|
||||||
|
multiple AP's connect different LAN's to one big one
|
||||||
|
%}
|
||||||
|
|
||||||
|
function beaconFrames = extractBeaconFrames(rxFrame)
|
||||||
|
beaconFrames = struct( ...
|
||||||
|
"SSID", {}, ...
|
||||||
|
"BSSID", {}, ...
|
||||||
|
"Offset", {}, ...
|
||||||
|
"MAC_Config", {}, ...
|
||||||
|
"Bits", {}, ...
|
||||||
|
"SNR_dB", {} ...
|
||||||
|
);
|
||||||
|
|
||||||
|
searchOffset = 0;
|
||||||
|
index = 1;
|
||||||
|
|
||||||
while searchOffset < length(rxFrame)
|
while searchOffset < length(rxFrame)
|
||||||
|
oldOffset = searchOffset;
|
||||||
[bitsData, decParams, searchOffset, res] = recoverOFDMBits(rxFrame, searchOffset);
|
[bitsData, decParams, searchOffset, res] = recoverOFDMBits(rxFrame, searchOffset);
|
||||||
|
|
||||||
|
if searchOffset <= oldOffset
|
||||||
|
searchOffset = oldOffset + 1;
|
||||||
|
end
|
||||||
|
|
||||||
if isempty(bitsData)
|
if isempty(bitsData)
|
||||||
continue;
|
continue;
|
||||||
end
|
end
|
||||||
@@ -20,10 +83,158 @@ function beaconFrames = extractBeaconFrames(rxFrame)
|
|||||||
[cfgMAC, ~, decodeStatus] = wlanMPDUDecode(bitsData, SuppressWarnings=true);
|
[cfgMAC, ~, decodeStatus] = wlanMPDUDecode(bitsData, SuppressWarnings=true);
|
||||||
|
|
||||||
if ~decodeStatus && matches(cfgMAC.FrameType, "Beacon")
|
if ~decodeStatus && matches(cfgMAC.FrameType, "Beacon")
|
||||||
disp("Beacon at " + searchOffset);
|
if isempty(cfgMAC.ManagementConfig.SSID)
|
||||||
beaconFrames(end + 1) = cfgMAC;
|
ssid = "Hidden";
|
||||||
|
else
|
||||||
|
ssid = string(cfgMAC.ManagementConfig.SSID);
|
||||||
|
end
|
||||||
|
|
||||||
|
if isfield(res, "PacketOffset")
|
||||||
|
beaconFrames(index).Offset = res.PacketOffset;
|
||||||
|
else
|
||||||
|
beaconFrames(index).Offset = oldOffset;
|
||||||
|
end
|
||||||
|
|
||||||
|
if isfield(res, "LLTFSNR")
|
||||||
|
beaconFrames(index).SNR_dB = res.LLTFSNR;
|
||||||
|
else
|
||||||
|
beaconFrames(index).SNR_dB = NaN;
|
||||||
|
end
|
||||||
|
|
||||||
|
beaconFrames(index).SSID = ssid;
|
||||||
|
beaconFrames(index).BSSID = string(cfgMAC.Address3);
|
||||||
|
beaconFrames(index).MAC_Config = cfgMAC;
|
||||||
|
beaconFrames(index).Bits = bitsData;
|
||||||
|
|
||||||
|
index = index + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
beaconFrames1 = extractBeaconFrames(rxFrame1);
|
function printBeaconTable(beaconFrames)
|
||||||
|
beaconCount = numel(beaconFrames);
|
||||||
|
|
||||||
|
tableFormat = "%-20s %-18s %-10s %-8s %-8s %-8s %-12s %-8s %-80s\n";
|
||||||
|
|
||||||
|
if(beaconCount < 1)
|
||||||
|
disp("No valid beacons could be extracted")
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
fprintf("\n");
|
||||||
|
fprintf(tableFormat, ...
|
||||||
|
"SSID", "BSSID", "Interval", "B. ch.", "Op. ch.", "SNR", "Vendor", "Std.", "Rates");
|
||||||
|
|
||||||
|
for i = 1 : beaconCount
|
||||||
|
mgmt = beaconFrames(i).MAC_Config.ManagementConfig;
|
||||||
|
|
||||||
|
ssid = string(beaconFrames(i).SSID);
|
||||||
|
bssid = toMACAddress(beaconFrames(i).BSSID);
|
||||||
|
interval = string(mgmt.BeaconInterval);
|
||||||
|
snr = sprintf("%.1f", beaconFrames(i).SNR_dB);
|
||||||
|
|
||||||
|
[bch, opch] = extractChannels(mgmt);
|
||||||
|
vendor = lookupVendor(beaconFrames(i).BSSID);
|
||||||
|
rates = getRates(mgmt);
|
||||||
|
std = getWifiStandard(mgmt);
|
||||||
|
|
||||||
|
fprintf(tableFormat, ...
|
||||||
|
ssid, bssid, interval, bch, opch, snr, vendor, std, rates);
|
||||||
|
end
|
||||||
|
|
||||||
|
fprintf("\n");
|
||||||
|
end
|
||||||
|
|
||||||
|
function mac = toMACAddress(mac)
|
||||||
|
mac = upper(string(mac));
|
||||||
|
|
||||||
|
if strlength(mac) ~= 12
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
macChars = char(mac);
|
||||||
|
|
||||||
|
mac = string(sprintf("%s:%s:%s:%s:%s:%s", ...
|
||||||
|
macChars(1:2), ...
|
||||||
|
macChars(3:4), ...
|
||||||
|
macChars(5:6), ...
|
||||||
|
macChars(7:8), ...
|
||||||
|
macChars(9:10), ...
|
||||||
|
macChars(11:12)));
|
||||||
|
end
|
||||||
|
|
||||||
|
function rates = getRates(mgmt)
|
||||||
|
basicRates = string(mgmt.BasicRates);
|
||||||
|
additionalRates = string(mgmt.AdditionalRates);
|
||||||
|
|
||||||
|
if isempty(basicRates) && isempty(additionalRates)
|
||||||
|
rates = "-";
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
basicRates = "[" + strjoin(basicRates, ", ") + "]";
|
||||||
|
rates = strjoin([basicRates, additionalRates], ", ");
|
||||||
|
end
|
||||||
|
|
||||||
|
function vendor = lookupVendor(bssid)
|
||||||
|
bssid = upper(string(bssid));
|
||||||
|
|
||||||
|
if strlength(bssid) < 6
|
||||||
|
vendor = "-";
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
oui = extractBefore(bssid, 7);
|
||||||
|
|
||||||
|
switch oui
|
||||||
|
case { "C884A1", "5CE176" }
|
||||||
|
vendor = "Cisco";
|
||||||
|
case { "6466B3", "647002" }
|
||||||
|
vendor = "TP-Link";
|
||||||
|
otherwise
|
||||||
|
vendor = "Unknown";
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function std = getWifiStandard(mgmt)
|
||||||
|
rates = [string(mgmt.BasicRates), string(mgmt.AdditionalRates)];
|
||||||
|
|
||||||
|
if any(contains(rates, ["6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps", "24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"]))
|
||||||
|
std = "802.11g";
|
||||||
|
elseif any(contains(rates, ["1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps"]))
|
||||||
|
std = "802.11b";
|
||||||
|
else
|
||||||
|
std = "Unknown";
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [b_ch, op_ch] = extractChannels(mgmt)
|
||||||
|
b_ch = "-";
|
||||||
|
op_ch = "-";
|
||||||
|
|
||||||
|
ies = mgmt.InformationElements;
|
||||||
|
|
||||||
|
if(isempty(ies))
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1 : size(ies, 1)
|
||||||
|
id = ies{i, 1};
|
||||||
|
value = ies{i, 2};
|
||||||
|
|
||||||
|
if isempty(id) || isempty(value)
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
|
||||||
|
switch id(1)
|
||||||
|
case 3
|
||||||
|
b_ch = string(double(value(1)));
|
||||||
|
case 61
|
||||||
|
op_ch = string(double(value(1)));
|
||||||
|
end
|
||||||
|
|
||||||
|
if ~strcmp(b_ch, "-") && ~strcmp(op_ch, "-")
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+156
-19
@@ -10,17 +10,52 @@ beaconFrames2 = extractBeaconFrames(rxFrame2);
|
|||||||
beaconFrames3 = extractBeaconFrames(rxFrame3);
|
beaconFrames3 = extractBeaconFrames(rxFrame3);
|
||||||
beaconFrames4 = extractBeaconFrames(rxFrame4);
|
beaconFrames4 = extractBeaconFrames(rxFrame4);
|
||||||
|
|
||||||
cfgMAC = beaconFrames1(1).MAC_Config;
|
% 1.
|
||||||
mgmt = cfgMAC.ManagementConfig;
|
disp("Beacon Frame 1")
|
||||||
|
|
||||||
disp(mgmt)
|
|
||||||
properties(mgmt)
|
|
||||||
|
|
||||||
printBeaconTable(beaconFrames1);
|
printBeaconTable(beaconFrames1);
|
||||||
|
disp("Beacon Frame 2")
|
||||||
printBeaconTable(beaconFrames2);
|
printBeaconTable(beaconFrames2);
|
||||||
|
disp("Beacon Frame 3")
|
||||||
printBeaconTable(beaconFrames3);
|
printBeaconTable(beaconFrames3);
|
||||||
|
disp("Beacon Frame 4")
|
||||||
printBeaconTable(beaconFrames4);
|
printBeaconTable(beaconFrames4);
|
||||||
|
|
||||||
|
% 2.
|
||||||
|
%{
|
||||||
|
Address 1: used to announce the destination station, in a beacon frame its
|
||||||
|
FF:FF:FF:FF:FF:FF (meaning broadcast to all stations)
|
||||||
|
Address 2: used to remark the source device address of the frame,
|
||||||
|
the ap mac who sent the beacon is inserted
|
||||||
|
Address 3: used for the bssid of the device sending the beacon, means
|
||||||
|
usually address 2 equals address 3, when no virtual ap is used
|
||||||
|
Address 4: this field does not exists, after the seq ctrl the frame body
|
||||||
|
follows containing beacon data instead of an address, like
|
||||||
|
timestamp, beacon interval, capability info, ssid, potentially
|
||||||
|
the channel number, see the extracts from 2.1
|
||||||
|
%}
|
||||||
|
|
||||||
|
% 3.
|
||||||
|
%{
|
||||||
|
Downlink: AP -> Station
|
||||||
|
Address 1: MAC of the destination station
|
||||||
|
Address 2: MAC of the AP which transmits the frame
|
||||||
|
Address 3: MAC of the initial sender which has started the frame
|
||||||
|
Address 4: not used
|
||||||
|
|
||||||
|
Uplink: Station -> AP
|
||||||
|
Address 1: MAC of the AP that receives and potentially forwards the frame
|
||||||
|
Address 2: MAC of the sending station
|
||||||
|
Address 3: MAC of the final destination station
|
||||||
|
Address 4: not used
|
||||||
|
|
||||||
|
4 Address case: wireless bridge:
|
||||||
|
Address 1: MAC of the AP that should receive / transmit through the frame,
|
||||||
|
for example AP, bridge node, repeater or mesh node
|
||||||
|
Address 2: MAC of the transmitter (into the other network)
|
||||||
|
Address 3: MAC of the final destination
|
||||||
|
Address 4: MAC of the initial sender
|
||||||
|
%}
|
||||||
|
|
||||||
function beaconFrames = extractBeaconFrames(rxFrame)
|
function beaconFrames = extractBeaconFrames(rxFrame)
|
||||||
beaconFrames = struct( ...
|
beaconFrames = struct( ...
|
||||||
"SSID", {}, ...
|
"SSID", {}, ...
|
||||||
@@ -31,8 +66,6 @@ function beaconFrames = extractBeaconFrames(rxFrame)
|
|||||||
"SNR_dB", {} ...
|
"SNR_dB", {} ...
|
||||||
);
|
);
|
||||||
|
|
||||||
channel_bandwidth = "CBW20"; % 20MHz
|
|
||||||
|
|
||||||
searchOffset = 0;
|
searchOffset = 0;
|
||||||
index = 1;
|
index = 1;
|
||||||
|
|
||||||
@@ -80,25 +113,129 @@ function beaconFrames = extractBeaconFrames(rxFrame)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function printBeaconTable(beaconFrames)
|
function printBeaconTable(beaconFrames)
|
||||||
|
beaconCount = numel(beaconFrames);
|
||||||
|
|
||||||
|
tableFormat = "%-20s %-18s %-10s %-8s %-8s %-8s %-12s %-8s %-80s\n";
|
||||||
|
|
||||||
|
if(beaconCount < 1)
|
||||||
|
disp("No valid beacons could be extracted")
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
fprintf("\n");
|
fprintf("\n");
|
||||||
fprintf("%-20s %-18s %-10s %-8s %-8s %-8s %-12s %-8s %-20s\n", ...
|
fprintf(tableFormat, ...
|
||||||
"SSID", "BSSID", "Interval", "B. ch.", "Op. ch.", "SNR", "Vendor", "Std.", "Rates");
|
"SSID", "BSSID", "Interval", "B. ch.", "Op. ch.", "SNR", "Vendor", "Std.", "Rates");
|
||||||
|
|
||||||
for i = 1:numel(beaconFrames)
|
for i = 1 : beaconCount
|
||||||
|
mgmt = beaconFrames(i).MAC_Config.ManagementConfig;
|
||||||
|
|
||||||
ssid = string(beaconFrames(i).SSID);
|
ssid = string(beaconFrames(i).SSID);
|
||||||
bssid = string(beaconFrames(i).BSSID);
|
bssid = toMACAddress(beaconFrames(i).BSSID);
|
||||||
interval = string(beaconFrames(i).MAC_Config.ManagementConfig.BeaconInterval);
|
interval = string(mgmt.BeaconInterval);
|
||||||
snr = sprintf("%.1f", beaconFrames(i).SNR_dB);
|
snr = sprintf("%.1f", beaconFrames(i).SNR_dB);
|
||||||
|
|
||||||
bch = "-";
|
[bch, opch] = extractChannels(mgmt);
|
||||||
opch = "-";
|
vendor = lookupVendor(beaconFrames(i).BSSID);
|
||||||
vendor = "-";
|
rates = getRates(mgmt);
|
||||||
std = "-";
|
std = getWifiStandard(mgmt);
|
||||||
rates = "-";
|
|
||||||
|
|
||||||
fprintf("%-20s %-18s %-10s %-8s %-8s %-8s %-12s %-8s %-20s\n", ...
|
fprintf(tableFormat, ...
|
||||||
ssid, bssid, interval, bch, opch, snr, vendor, std, rates);
|
ssid, bssid, interval, bch, opch, snr, vendor, std, rates);
|
||||||
end
|
end
|
||||||
|
|
||||||
fprintf("\n");
|
fprintf("\n");
|
||||||
|
end
|
||||||
|
|
||||||
|
function mac = toMACAddress(mac)
|
||||||
|
mac = upper(string(mac));
|
||||||
|
|
||||||
|
if strlength(mac) ~= 12
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
macChars = char(mac);
|
||||||
|
|
||||||
|
mac = string(sprintf("%s:%s:%s:%s:%s:%s", ...
|
||||||
|
macChars(1:2), ...
|
||||||
|
macChars(3:4), ...
|
||||||
|
macChars(5:6), ...
|
||||||
|
macChars(7:8), ...
|
||||||
|
macChars(9:10), ...
|
||||||
|
macChars(11:12)));
|
||||||
|
end
|
||||||
|
|
||||||
|
function rates = getRates(mgmt)
|
||||||
|
basicRates = string(mgmt.BasicRates);
|
||||||
|
additionalRates = string(mgmt.AdditionalRates);
|
||||||
|
|
||||||
|
if isempty(basicRates) && isempty(additionalRates)
|
||||||
|
rates = "-";
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
basicRates = "[" + strjoin(basicRates, ", ") + "]";
|
||||||
|
rates = strjoin([basicRates, additionalRates], ", ");
|
||||||
|
end
|
||||||
|
|
||||||
|
function vendor = lookupVendor(bssid)
|
||||||
|
bssid = upper(string(bssid));
|
||||||
|
|
||||||
|
if strlength(bssid) < 6
|
||||||
|
vendor = "-";
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
oui = extractBefore(bssid, 7);
|
||||||
|
|
||||||
|
switch oui
|
||||||
|
case { "C884A1", "5CE176" }
|
||||||
|
vendor = "Cisco";
|
||||||
|
case { "6466B3", "647002" }
|
||||||
|
vendor = "TP-Link";
|
||||||
|
otherwise
|
||||||
|
vendor = "Unknown";
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function std = getWifiStandard(mgmt)
|
||||||
|
rates = [string(mgmt.BasicRates), string(mgmt.AdditionalRates)];
|
||||||
|
|
||||||
|
if any(contains(rates, ["6 Mbps", "9 Mbps", "12 Mbps", "18 Mbps", "24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"]))
|
||||||
|
std = "802.11g";
|
||||||
|
elseif any(contains(rates, ["1 Mbps", "2 Mbps", "5.5 Mbps", "11 Mbps"]))
|
||||||
|
std = "802.11b";
|
||||||
|
else
|
||||||
|
std = "Unknown";
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function [b_ch, op_ch] = extractChannels(mgmt)
|
||||||
|
b_ch = "-";
|
||||||
|
op_ch = "-";
|
||||||
|
|
||||||
|
ies = mgmt.InformationElements;
|
||||||
|
|
||||||
|
if(isempty(ies))
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1 : size(ies, 1)
|
||||||
|
id = ies{i, 1};
|
||||||
|
value = ies{i, 2};
|
||||||
|
|
||||||
|
if isempty(id) || isempty(value)
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
|
||||||
|
switch id(1)
|
||||||
|
case 3
|
||||||
|
b_ch = string(double(value(1)));
|
||||||
|
case 61
|
||||||
|
op_ch = string(double(value(1)));
|
||||||
|
end
|
||||||
|
|
||||||
|
if ~strcmp(b_ch, "-") && ~strcmp(op_ch, "-")
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user