WLAN Activity Scanner
This example shows how to scan for Wi-Fi® network activity using a software-defined radio (SDR) and preamble detection. The example scans over WLAN channels in the 2.4 GHz and 5 GHz bands and uses an SDR preamble detector to detect and capture orthogonal frequency-division multiplexing (OFDM) packets from the air. The example uses a WLAN OFDM signal descriptor helper object to configure the SDR preamble detector for each WLAN channel, and then plots the detected WLAN activity across the band.
Introduction
In this example, you use hWLANOFDMDescriptor
helper objects to describe WLAN OFDM signals that you want to detect and capture. Using the configureDetector
helper function, you configure an SDR preamble detector to scan for each signal by setting the following parameters:
Center frequency
Sample rate
Preamble
Trigger offset
After you detect the signals, you postprocess them for visualisation and analysis. This diagram shows the workflow.
Describe Wireless Signals
Describe the WLAN signals that you want to look for using the hWLANOFDMDescriptor
helper object. Use the checkboxes to select the bands and channel bandwidths to scan. The hWLANOFDMDescriptor
generates an object for each appropriate WLAN channel defined by the IEEE® 802.11 standard.
wsds = []; if false% Search for 5MHz Channel Bandwidth WLAN Signals wsds = [wsds,hWLANOFDMDescriptor(Band=2.4,ChannelBandwidth="CBW5")]; %#ok<*UNRCH> wsds = [wsds,hWLANOFDMDescriptor(Band=5,ChannelBandwidth="CBW5")]; end if false% Search for 10MHz Channel Bandwidth WLAN Signals wsds = [wsds,hWLANOFDMDescriptor(Band=2.4,ChannelBandwidth="CBW10")]; wsds = [wsds,hWLANOFDMDescriptor(Band=5,ChannelBandwidth="CBW10")]; end if true% Search for 20MHz Channel Bandwidth WLAN Signals wsds = [wsds,hWLANOFDMDescriptor(Band=2.4,ChannelBandwidth="CBW20")]; wsds = [wsds,hWLANOFDMDescriptor(Band=5,ChannelBandwidth="CBW20")]; end if true% Search for 40MHz Channel Bandwidth WLAN Signals wsds = [wsds,hWLANOFDMDescriptor(Band=2.4,ChannelBandwidth="CBW40")]; wsds = [wsds,hWLANOFDMDescriptor(Band=5,ChannelBandwidth="CBW40")]; end if true% Search for 80MHz Channel Bandwidth WLAN Signals wsds = [wsds,hWLANOFDMDescriptor(Band=5,ChannelBandwidth="CBW80")]; end if false% Search for 160MHz Channel Bandwidth WLAN Signals wsds = [wsds,hWLANOFDMDescriptor(Band=5,ChannelBandwidth="CBW160")]; end
Create and Configure Radio as Preamble Detector
Set Up Radio
Call the radioConfigurations
(Wireless Testbench) function. The function returns all available radio setup configurations that you saved using the Radio Setup (Wireless Testbench) wizard.
savedRadioConfigurations = radioConfigurations;
To update the dropdown menu with your saved radio setup configuration names, click Update. Then select the radio to use with this example.
savedRadioConfigurationNames = [string({savedRadioConfigurations.Name})]; radio = savedRadioConfigurationNames(1) ;
Configure Preamble Detector
Create a preambleDetector
(Wireless Testbench) object with the specified radio. Because the object requires exclusive access to radio hardware resources, before running this example for the first time, clear any other object associated with the specified radio. In subsequent runs, to speed up the execution of the example, reuse your new workspace object.
if ~exist("pd","var") pd = preambleDetector(radio); end
To update the dropdown menu with the antennas available for capture on your radio, call the hCaptureAntennas
helper function. Then select the antenna to use with this example.
captureAntennaSelection = hCaptureAntennas(radio);
pd.Antennas = captureAntennaSelection(1);
Tune Preamble Detector
Set the adaptive threshold gain, the adaptive threshold offset, and the radio gain values of the preamble detector for the local environment. You can calibrate these values by exploring the trigger points that the plotThreshold
(Wireless Testbench) function provides. For more information on tuning these values, see Triggered WLAN Waveform Capture Using Preamble Detection (Wireless Testbench).
pd.ThresholdMethod = "adaptive"; pd.AdaptiveThresholdGain = 0.3; pd.AdaptiveThresholdOffset = 0.001; pd.RadioGain = 30;
Scan for Wireless Signals
Use the configureDetector
helper function to configure the preamble detector with an appropriate preamble, trigger offset, sampling rate, and center frequency. Set the detection timeout to 100 milliseconds, which is the expected periodicity of a WLAN beacon packet. Alternatively, set a longer timeout to increase the probability of detection on non-beacon channels. Then use the capture
(Wireless Testbench) function to detect and capture the described WLAN signal. If the detection is successful, save the captured signal with metadata.
captures = []; wb = hCaptureWaitBar(length(wsds)); for wsd = wsds hUpdateCaptureWaitBar(wb,wsd) if strcmp(wsd.ChannelBandwidth,"CBW80") || strcmp(wsd.ChannelBandwidth,"CBW160") % High bandwidth limits sample rate options. May exceed maximum trigger offset. sampleRate=hNearestGreaterSampleRate(radio,str2double(extractAfter(wsd.ChannelBandwidth,"CBW"))*1e6); pd = configureDetector(wsd,pd,SampleRate=sampleRate); else pd = configureDetector(wsd,pd); end [data,timestamp,~,detectionSuccessful] = capture(pd,milliseconds(10), milliseconds(100)); if detectionSuccessful % Save to structure captures = [captures,struct(Data=data, Timestamp=timestamp, SampleRate=pd.SampleRate, Descriptor=wsd)]; %#ok<AGROW> end end close(wb) if isempty(captures) disp("No signals detected") return end
Tabulate and Plot Detections
Calculate Power
Calculate the power of the captured legacy preamble sequences.
fullscale = single(intmax('int16')); for ii = 1:length(captures) switch captures(ii).Descriptor.ChannelBandwidth case "CBW5" pTime = 80e-6; case "CBW10" pTime = 40e-6; otherwise pTime = 20e-6; end % Calculate preamble length in Samples pLen = 1:ceil(pTime*captures(ii).SampleRate); % Calculate the power of the IQ samples in the detected PSS power = mean(abs(single(captures(ii).Data)).^2); % Calculate the dBFS value for the power powerDBFS = 10*log10(power/fullscale^2); captures(ii).Power = powerDBFS; %#ok<SAGROW> end
Tabulate Detected Signals
Display the detections in a table.
if isempty(captures) disp("No wireless signals were detected.") return end detectedWirelessSignals = [captures.Descriptor]'; wlanDetectionTable = table; for ii = 1:length(captures) wlanDetectionTable(ii,:) = table(... string(class(detectedWirelessSignals(ii))),... detectedWirelessSignals(ii).CenterFrequency/1e6,... detectedWirelessSignals(ii).Band,... detectedWirelessSignals(ii).Channel,... double(extractAfter(detectedWirelessSignals(ii).ChannelBandwidth,"CBW")),... captures(ii).Power,... VariableNames=["Detected Wireless Signal","Center Frequency (MHz)","Band","Channel", "CBW","Signal Power Estimate (dBFS)"]); end disp(wlanDetectionTable)
Detected Wireless Signal Center Frequency (MHz) Band Channel CBW Signal Power Estimate (dBFS) ________________________ ______________________ ____ _______ ___ ____________________________ "hWLANOFDMDescriptor" 2412 2.4 1 20 -26.417 "hWLANOFDMDescriptor" 2437 2.4 6 20 -33.22 "hWLANOFDMDescriptor" 2462 2.4 11 20 -34.477 "hWLANOFDMDescriptor" 2472 2.4 13 20 -17.338 "hWLANOFDMDescriptor" 5180 5 36 20 -30.054 "hWLANOFDMDescriptor" 5200 5 40 20 -31.316 "hWLANOFDMDescriptor" 5220 5 44 20 -31.6 "hWLANOFDMDescriptor" 5240 5 48 20 -34.363 "hWLANOFDMDescriptor" 5260 5 52 20 -48.501 "hWLANOFDMDescriptor" 5280 5 56 20 -51.677 "hWLANOFDMDescriptor" 5300 5 60 20 -48.551 "hWLANOFDMDescriptor" 5320 5 64 20 -50.265 "hWLANOFDMDescriptor" 5500 5 100 20 -36.456 "hWLANOFDMDescriptor" 5540 5 108 20 -39.064 "hWLANOFDMDescriptor" 5765 5 153 20 -22.932 "hWLANOFDMDescriptor" 2452 2.4 9 40 -26.806 "hWLANOFDMDescriptor" 5755 5 151 40 -23.793 "hWLANOFDMDescriptor" 5210 5 42 80 -28.112
Plot Detected Signals
For each band, plot the power of the detected signals by using the hPlotWLANDetections
helper function.
hPlotWLANDetections(wlanDetectionTable);
Further Exploration
Consider using the Recover and Analyze Packets in 802.11 Waveform example to analyze the contents and formats of the WLAN packets you captured. You can save the captured data to baseband files, which are compatible with this example.
if false% Save captures to baseband files for capture = captures wsd = capture.Descriptor; bbw = comm.BasebandFileWriter("WLAN_"+... strrep(string(wsd.Band),".",",")+"GHz_Channel"+string(wsd.Channel)+... "_"+string(datetime(capture.Timestamp,"Format","yyyyMMddHHmmssSSS"))+".bb",... capture.SampleRate,wsd.CenterFrequency,... struct(WirelessSignalDescriptor=class(wsd),Band=wsd.Band,... ChannelBandwidth=char(wsd.ChannelBandwidth),Channel=wsd.Channel,... PreamblePowerDBFS=capture.Power)); bbw(capture.Data); release(bbw); end end