Main Content

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.

WLAN activity scanner example 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 function. The function returns all available radio setup configurations that you saved using the Radio Setup 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 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 function provides. For more information on tuning these values, see Triggered WLAN Waveform Capture Using Preamble Detection.

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 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 (WLAN Toolbox) 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

See Also

Functions

Objects

Related Topics