Earlier this year I used the excellent "WiFi Radar" program to determine the channels used by other near-by access points, and found they were mostly clustered near the top end of the band. I then selected a low channel for my router to minimise the chances of interference.
However, I recently checked once again and found other APs on the channel I was using!
With an ever increasing number of WiFi APs, what I needed was an indication of both channel AND signal level to determine the safest channel to use, hence this mini project.
I'm using 2 Linux commands and I pipe the output for use by my app:-
- iwconfig is required to find the local Wifi interface (i.e. on the pc you are using).
- iwlist is used to scan for any Wifi Access Points within range.
The iwlist command requires root privileges. One solution is to modify your sudoers file by adding the following line at the end of the file;
%admin ALL = NOPASSWD: /sbin/iwlist
This will allow any user with admin rights to run this WiFiScanner.
ToDo list; I've kept the program listed below fairly minimal, so it does not include any error handling. There are other parameters that may be of interest (such as MAC address) that can easily be extracted from the iwlist output (in a terminal run "sudo iwlist" to see what is available).
Other possible enhancements include:-
- listing APs in order of signal (i.e. highest to lowest Link Quality)
- keeping a list of all APs detected in the last (say) month
- adding a simple graph for each AP (see my Simple Chart Class from an earlier post)
- creating a graph where the x-axis is channels 1 to 13 and y-axis is largest signal for each channel
Maybe if you have an idea you can also post it here.
The basic WifiScanner code;
' Gambas class file
'**************************************************************************
'WifiScanner
'Like the excellent app "Wifi Radar", this app lists Wifi Access Points
'but also shows Link Quality in addition to Channel number.
'This should help to select a Wifi Channel that is less prone to
'interference from strong neighbouring signals.
'As iwlist requires root Privileges to run, you may need to mod sudoers.
'Steve Davis
'Dec 2009
'***************************************************************************
PUBLIC strAccPoints AS String[10] 'to hold Access Point + Channel + Quality
PUBLIC SUB Form_Open()
lblWifiInterface.Text = GetWifiInterface()
tmrScanner.Start()
END
'---------------------------------------------------
PUBLIC FUNCTION GetWifiInterface() AS String
DIM hFile AS File
DIM strLine AS String
DIM strWifi AS String
SHELL "iwconfig > /tmp/Pipe_iwconfig" WAIT
hFile = PIPE "/tmp/Pipe_iwconfig" FOR INPUT
DO UNTIL Eof(hFile)
LINE INPUT #hFile, strLine
IF InStr(strLine, "ESSID") > 0 THEN 'found a Wifi interface
strWifi = Trim(Mid(strLine, 1, InStr(strLine, " ")))
ENDIF
LOOP
RETURN strWifi
END
'---------------------------------------------------
PUBLIC FUNCTION GetESSIDs(strInterface AS String) AS Boolean
DIM hFile AS File
DIM strLine AS String
DIM strAccessPoint AS String
DIM strChannel AS String
DIM strQuality AS String
DIM index AS Integer
SHELL "sudo iwlist " & strInterface & " scan > /tmp/Pipe_iwlist" WAIT
hFile = PIPE "/tmp/Pipe_iwlist" FOR INPUT
DO UNTIL Eof(hFile)
LINE INPUT #hFile, strLine
'find access point...
IF InStr(strLine, "ESSID") > 0 THEN 'found a Wifi access point
strAccessPoint = Mid(strLine, InStr(strLine, ":") + 1)
strAccPoints[index] = Mid(strAccessPoint, 2, Len(strAccessPoint) - 2)
ENDIF
'...get channel number...
IF InStr(strLine, "Channel") > 0 THEN 'found access point Channel
strChannel = Mid(strLine, InStr(strLine, "Channel"))
strChannel = Mid(strChannel, 1, InStr(strChannel, ")") - 1)
strAccPoints[index] = strAccPoints[index] & " : " & strChannel
ENDIF
'...get Link Quality
IF InStr(strLine, "Quality") > 0 THEN 'found access point Link Quality
strQuality = Mid(strLine, InStr(strLine, ":") + 1)
strQuality = Mid(strQuality, 1, InStr(strQuality, " ") - 1)
strAccPoints[index] = strAccPoints[index] & " : " & strQuality & "%"
INC index
ENDIF
LOOP
END
'---------------------------------------------------
PUBLIC SUB tmrScanner_Timer()
DIM index AS Integer
GetESSIDs(lblWifiInterface.Text)
lstAccessPoints.Clear()
FOR index = 0 TO 9
lstAccessPoints.Add(strAccPoints[index], index)
NEXT
END