Search code examples
delphiloggingwirelessrssi

Delphi routine to read RSSI of a wireless connection?


I want to write a simple utility to regularly log the RSSI of my WiFi router to a text file. Does anybody know of a Delphi library or API wrappers to read the RSSI value of a wireless router?


Solution

  • You can get the RSSI of your active network wifi connection using the Native Wifi API, after of call the WlanOpenHandle and WlanEnumInterfaces functions you must execute the WlanQueryInterface method passing the wlan_intf_opcode_current_connection enum value and a pointer to a WLAN_CONNECTION_ATTRIBUTES structure, from here you must access the wlanAssociationAttributes element and finally read the value of the wlanSignalQuality field.

    This is the description of this field.

    wlanSignalQuality

    A percentage value that represents the signal quality of the network. 
    

    WLAN_SIGNAL_QUALITY is of type ULONG. This member contains a value between 0 and 100. A value of 0 implies an actual RSSI signal strength of -100 dbm. A value of 100 implies an actual RSSI signal strength of -50 dbm. You can calculate the RSSI signal strength value for wlanSignalQuality values between 1 and 99 using linear interpolation.

    Try this sample code

    uses
      Windows,
      SysUtils,
      nduWlanAPI   in 'nduWlanAPI.pas',
      nduWlanTypes in 'nduWlanTypes.pas';
    
    procedure Scan();
    var
      hClient              : THandle;
      dwVersion            : DWORD;
      ResultInt            : DWORD;
      pInterface           : Pndu_WLAN_INTERFACE_INFO_LIST;
      i                    : Integer;
      pInterfaceGuid       : TGUID;
      pdwDataSize, RSSI    : DWORD;
      ppData               : pndu_WLAN_CONNECTION_ATTRIBUTES;
    begin
      ResultInt:=WlanOpenHandle(1, nil, @dwVersion, @hClient);
     try
      if  ResultInt<> ERROR_SUCCESS then
      begin
         WriteLn('Error Open CLient'+IntToStr(ResultInt));
         Exit;
      end;
    
      ResultInt:=WlanEnumInterfaces(hClient, nil, @pInterface);
      if  ResultInt<> ERROR_SUCCESS then
      begin
         WriteLn('Error Enum Interfaces '+IntToStr(ResultInt));
         exit;
      end;
    
      for i := 0 to pInterface^.dwNumberOfItems - 1 do
      begin
        Writeln('Interface  ' + pInterface^.InterfaceInfo[i].strInterfaceDescription);
        WriteLn('GUID       ' + GUIDToString(pInterface^.InterfaceInfo[i].InterfaceGuid));
        pInterfaceGuid:= pInterface^.InterfaceInfo[pInterface^.dwIndex].InterfaceGuid;
    
        ppData:=nil;
        pdwDataSize:=0;
        ResultInt:=WlanQueryInterface(hClient, @pInterfaceGuid, wlan_intf_opcode_current_connection, nil, @pdwDataSize, @ppData,nil);
        try
          if (ResultInt=ERROR_SUCCESS) and (pdwDataSize=SizeOf(Tndu_WLAN_CONNECTION_ATTRIBUTES)) then
          begin
            Writeln(Format('Profile %s',[ppData^.strProfileName]));
            Writeln(Format('Mac Address %.2x:%.2x:%.2x:%.2x:%.2x:%.2x',[
            ppData^.wlanAssociationAttributes.dot11Bssid[0],
            ppData^.wlanAssociationAttributes.dot11Bssid[1],
            ppData^.wlanAssociationAttributes.dot11Bssid[2],
            ppData^.wlanAssociationAttributes.dot11Bssid[3],
            ppData^.wlanAssociationAttributes.dot11Bssid[4],
            ppData^.wlanAssociationAttributes.dot11Bssid[5]]));
            RSSI := (ppData^.wlanAssociationAttributes.wlanSignalQuality div 2) - 100;
            Writeln(Format('RSSI %d dbm',[RSSI]));
          end;
        finally
          if ppData<>nil then
           WlanFreeMemory(ppData);
        end;
      end;
     finally
      WlanCloseHandle(hClient, nil);
     end;
    end;
    
    begin
      try
        Scan();
      except
        on E:Exception do
          Writeln(E.Classname, ': ', E.Message);
      end;
      Readln;
    end.
    

    Note : unfortunately AFAIK doesn't exist a official translation of the Native Wifi API headers to Delphi, so in the meantime you can use these.