aeyah14
Posts: 19
Joined: Wed Jun 18, 2014 9:56 pm

Parsing iwlist scan

Thu Aug 28, 2014 8:23 am

Im a total beginner in python, and am currently making a project of some sort which involves me scanning for Access Points and retrieving signal strength. I saw this code which i can work with https://bbs.archlinux.org/viewtopic.php?id=88967

but lack understanding of it, i thought it was simple enough but i cant seem to get it to work, can someone help me with editing the code? i think i need to edit the function (cell) which i dont really get and i want to add the signal strength just like when i use
iwlist scan.
advance thank you for the senpais who will be willing to teach me

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: Parsing iwlist scan

Thu Aug 28, 2014 5:48 pm

Can you confirm what you'd like the output to be?

I've tweaked the script so it just runs directly in python (rather than having to pipe the iwlist output to the script) and get an output like this:

Code: Select all

Name        Address             Quality   Channel   Encryption  
MyHomeNet   00:11:22:33:44:55   100 %     6         WEP 
Last edited by elParaguayo on Thu Aug 28, 2014 10:14 pm, edited 1 time in total.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

aeyah14
Posts: 19
Joined: Wed Jun 18, 2014 9:56 pm

Re: Parsing iwlist scan

Thu Aug 28, 2014 7:08 pm

i would like to have another column for Signal Strength (dBm), as i understand the signal strength measurement was used in getting the Quality i would like to insert the signal strength next to it.

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: Parsing iwlist scan

Thu Aug 28, 2014 8:01 pm

Should be easy enough. I'll take a look later tonight.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: Parsing iwlist scan

Thu Aug 28, 2014 10:12 pm

Ok, this is tweaked to get the signal level data showing.

Code: Select all

#!/usr/bin/env python
#
# iwlistparse.py
# Hugo Chargois - 17 jan. 2010 - v.0.1
# Parses the output of iwlist scan into a table

import sys
import subprocess

interface = "wlan0"

# You can add or change the functions to parse the properties of each AP (cell)
# below. They take one argument, the bunch of text describing one cell in iwlist
# scan and return a property of that cell.

def get_name(cell):
    return matching_line(cell,"ESSID:")[1:-1]

def get_quality(cell):
    quality = matching_line(cell,"Quality=").split()[0].split('/')
    return str(int(round(float(quality[0]) / float(quality[1]) * 100))).rjust(3) + " %"

def get_channel(cell):
    return matching_line(cell,"Channel:")

def get_signal_level(cell):
    # Signal level is on same line as Quality data so a bit of ugly
    # hacking needed...
    return matching_line(cell,"Quality=").split("Signal level=")[1]


def get_encryption(cell):
    enc=""
    if matching_line(cell,"Encryption key:") == "off":
        enc="Open"
    else:
        for line in cell:
            matching = match(line,"IE:")
            if matching!=None:
                wpa=match(matching,"WPA Version ")
                if wpa!=None:
                    enc="WPA v."+wpa
        if enc=="":
            enc="WEP"
    return enc

def get_address(cell):
    return matching_line(cell,"Address: ")

# Here's a dictionary of rules that will be applied to the description of each
# cell. The key will be the name of the column in the table. The value is a
# function defined above.

rules={"Name":get_name,
       "Quality":get_quality,
       "Channel":get_channel,
       "Encryption":get_encryption,
       "Address":get_address,
       "Signal":get_signal_level
       }

# Here you can choose the way of sorting the table. sortby should be a key of
# the dictionary rules.

def sort_cells(cells):
    sortby = "Quality"
    reverse = True
    cells.sort(None, lambda el:el[sortby], reverse)

# You can choose which columns to display here, and most importantly in what order. Of
# course, they must exist as keys in the dict rules.

columns=["Name","Address","Quality","Signal", "Channel","Encryption"]




# Below here goes the boring stuff. You shouldn't have to edit anything below
# this point

def matching_line(lines, keyword):
    """Returns the first matching line in a list of lines. See match()"""
    for line in lines:
        matching=match(line,keyword)
        if matching!=None:
            return matching
    return None

def match(line,keyword):
    """If the first part of line (modulo blanks) matches keyword,
    returns the end of that line. Otherwise returns None"""
    line=line.lstrip()
    length=len(keyword)
    if line[:length] == keyword:
        return line[length:]
    else:
        return None

def parse_cell(cell):
    """Applies the rules to the bunch of text describing a cell and returns the
    corresponding dictionary"""
    parsed_cell={}
    for key in rules:
        rule=rules[key]
        parsed_cell.update({key:rule(cell)})
    return parsed_cell

def print_table(table):
    widths=map(max,map(lambda l:map(len,l),zip(*table))) #functional magic

    justified_table = []
    for line in table:
        justified_line=[]
        for i,el in enumerate(line):
            justified_line.append(el.ljust(widths[i]+2))
        justified_table.append(justified_line)
    
    for line in justified_table:
        for el in line:
            print el,
        print

def print_cells(cells):
    table=[columns]
    for cell in cells:
        cell_properties=[]
        for column in columns:
            cell_properties.append(cell[column])
        table.append(cell_properties)
    print_table(table)

def main():
    """Pretty prints the output of iwlist scan into a table"""
    
    cells=[[]]
    parsed_cells=[]

    proc = subprocess.Popen(["iwlist", interface, "scan"],stdout=subprocess.PIPE, universal_newlines=True)
    out, err = proc.communicate()

    for line in out.split("\n"):
        cell_line = match(line,"Cell ")
        if cell_line != None:
            cells.append([])
            line = cell_line[-27:]
        cells[-1].append(line.rstrip())

    cells=cells[1:]

    for cell in cells:
        parsed_cells.append(parse_cell(cell))

    sort_cells(parsed_cells)

    print_cells(parsed_cells)

main()
Output is like this:

Code: Select all

Name        Address             Quality   Signal    Channel   Encryption  
MyHomeNet   00:11:22:33:44:55    84 %     -51 dBm   6         WEP  
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

aeyah14
Posts: 19
Joined: Wed Jun 18, 2014 9:56 pm

Re: Parsing iwlist scan

Fri Aug 29, 2014 8:13 am

thank you, code works perfectly.. :D

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: Parsing iwlist scan

Fri Aug 29, 2014 8:38 am

Great. Glad it works for you.

I'd suggest that you take a look at the changes to the code and see if you can understand why they work. This should then help if you want to make changes in the future.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

aeyah14
Posts: 19
Joined: Wed Jun 18, 2014 9:56 pm

Re: Parsing iwlist scan

Fri Aug 29, 2014 12:48 pm

i am, thank you :)

aeyah14
Posts: 19
Joined: Wed Jun 18, 2014 9:56 pm

Re: Parsing iwlist scan

Mon Sep 01, 2014 9:11 am

Sir ive studying about the project im making, its some sort of Rpi locator, do you think this will be possible in the code? like, it will continuously scan for Access points and when the specific access points i want is detected ill store the signal strength and scan again and store it again. similarly to this http://stackoverflow.com/questions/8881 ... -ssid-data
i guess it wont hurt to ask...
last question >.< i also found this, in your opinion will this be more suited in the project im making and can i implement this in raspberry pi? http://www.codeproject.com/Articles/637 ... or-Secrets

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: Parsing iwlist scan

Mon Sep 01, 2014 1:08 pm

You can easily record the data you want. In order to work out the best way of doing it for you, it would help if you can explain how you want to use the data.

As for the geolocation bit, I thought Google gears closed in 2012 so I don't think that last link helps.
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

aeyah14
Posts: 19
Joined: Wed Jun 18, 2014 9:56 pm

Re: Parsing iwlist scan

Mon Sep 01, 2014 1:47 pm

what i plan on doing is to turn the RPi into a simple navigational equipment, it continously scans for access points and when the raspberry pi met one of the conditions like where the Quality and Signal strength for the WiFiRouter 1 is like 90% and -50dBm i'd make a voice output. im concerned about is if i can somehow store the quality and signal strength of the specific AP i want in order to make the voice output conditions. thank you again for listening to my concerns :D

User avatar
elParaguayo
Posts: 1943
Joined: Wed May 16, 2012 12:46 pm
Location: London, UK

Re: Parsing iwlist scan

Mon Sep 01, 2014 1:51 pm

If you want to do some sort of navigation then, in my opinion, you'd be better off getting a GPS module for the pi rather than trying to use WiFi.

In terms of storing data, it doesn't really sound like you need to store the scanned data. It sounds like you've got a preset list of wifi id's and when one of these is found and the signal strength is above a certain threshold then you want to trigger an audio alert. Is that correct?
RPi Information Screen: plugin based system for displaying weather, travel information, football scores etc.

aeyah14
Posts: 19
Joined: Wed Jun 18, 2014 9:56 pm

Re: Parsing iwlist scan

Mon Sep 01, 2014 2:43 pm

in regards to gps, i considered it but i read in localization articles that gps is not that specific in approximating distance and is bad at indoor localization.

Yes that is it, scans for APs and audio output on the certain signal strengths.

paulv
Posts: 558
Joined: Tue Jan 15, 2013 12:10 pm
Location: Netherlands

Re: Parsing iwlist scan

Tue Nov 04, 2014 4:05 am

Really nifty and clever bit of coding.

Something must have changed over time in the code for iwlist, because the program did not work when I tried it.

I got the following error message:

Code: Select all

Traceback (most recent call last):
  File "/home/pi/iwlistparse.py", line 153, in <module>
    main()
  File "/home/pi/iwlistparse.py", line 148, in main
    print_cells(parsed_cells)
  File "/home/pi/iwlistparse.py", line 124, in print_cells
    print_table(table)
  File "/home/pi/iwlistparse.py", line 103, in print_table
    widths=map(max,map(lambda l:map(len,l),zip(*table))) #functional magic
  File "/home/pi/iwlistparse.py", line 103, in <lambda>
    widths=map(max,map(lambda l:map(len,l),zip(*table))) #functional magic
TypeError: object of type 'NoneType' has no len()
There are actually three areas in the code that need an update. One you can find via the link to your web site, and that deals with the recognition of the WPA2 encryption protocol.
The function that needs to change according to your fix would now be:

Code: Select all

def get_encryption(cell):
    enc=""
    if matching_line(cell,"Encryption key:") == "off":
        enc="Open"
    else:
        for line in cell:
            matching = match(line,"IE:")
            if matching!=None:
                wpa2=match(matching,"IEEE 802.11i/WPA2 Version ")
                if wpa2!=None:
                    #enc="WPA2 v."+wpa2
                    enc="WPA2"
                wpa=match(matching,"WPA Version ")
                if wpa!=None:
                    enc="WPA v."+wpa
        if enc=="":
            enc="WEP"
    return enc
The other bit of code that needs to be updated has to do with the Channel. In the probably changed reporting of the iwlist command, your software no longer finds "Channel". The result is the same runtime error.
The code has to be modified to look for "Frequency".
The following function works:

Code: Select all

def get_channel(cell):
    frequency = matching_line(cell,"Frequency:")
    channel = frequency[frequency.index("(")+9:frequency.index(")")]
    return channel
In the "new" iwlist command, Signal is no longer represented by dBm, but as a factor. This could be further processed to show a percentage, as with the Quality by changing the function as follows:

Code: Select all

def get_signal_level(cell):
    # Signal level is on same line as Quality data so a bit of ugly
    # hacking needed...
    level = matching_line(cell,"Quality=").split("Signal level=")[1]
    level = level.split()[0].split('/')
    return str(int(round(float(level[0]) / float(level[1]) * 100))).rjust(3) + " %"
The result now looks as follows again:

Code: Select all

Name          Address             Quality   Signal   Channel   Encryption
Summer 110    20:AA:4B:C8:E2:60   100 %      89 %    6         WPA2
linksys 108   00:21:29:B1:53:3B   100 %     100 %    1         WPA2
Summer 110    00:23:69:CA:5A:D4    97 %      46 %    6         WPA2
RSS-351540    0C:47:3D:BD:AB:D9    63 %      43 %    7         WPA2
I hope this helps.
paulv

jiminycricket
Posts: 2
Joined: Sun Feb 08, 2015 6:24 pm

Re: Parsing iwlist scan

Sun Feb 08, 2015 6:38 pm

I forked and updated that code to include Signal Strength and Bit Rates. I've also made it more accessible from within Python code. See https://github.com/jsh2134/iw_parse/

Code: Select all

>>> import iw_parse
>>> networks = iw_parse.get_interfaces(interface='wlan0')
>>> print networks
[{'Address': 'F8:1E:DF:F9:B0:0B',
  'Channel': '3',
  'Encryption': 'WEP',
  'Name': 'Francis',
  'Bit Rates': '144 Mb/s',
  'Signal Level': '42',
  'Name': 'Francis',
  'Quality': '100'},
 {'Address': '86:1B:5E:33:17:D4',
  'Channel': '6',
  'Encryption': 'Open',
  'Bit Rates': '54 Mb/s',
  'Signal Level': '72',
  'Name': 'optimumwifi',
  'Quality': '100'},
    ...

freshd
Posts: 11
Joined: Wed Jul 16, 2014 1:37 pm

Re: Parsing iwlist scan

Wed Feb 18, 2015 12:15 am

Is it possible to represent the value grabbed from the quality cell in iwlist as an integer?

Dahmke
Posts: 1
Joined: Sun Mar 01, 2015 12:14 pm

Re: Parsing iwlist scan

Sun Mar 01, 2015 12:17 pm

Hi Guys,

How can I modify the code, so I just can se the Network I am connected to?

fahad888
Posts: 21
Joined: Mon Jun 08, 2015 11:34 am

Re: Parsing iwlist scan

Mon Jun 08, 2015 1:24 pm

hi guys
i create that code for iwlist python

then i type "iwlist interface scan"
but i got message that interface doesnt support scanning???

any help with that

User avatar
rpdom
Posts: 15391
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Parsing iwlist scan

Mon Jun 08, 2015 3:23 pm

You need to put the name of the interface (wlan0 usually), not the word "interface".

iwlist wlan0 scan

chualh1
Posts: 1
Joined: Wed Sep 16, 2015 3:10 am

Re: Parsing iwlist scan

Wed Sep 16, 2015 3:38 am

Hi guys,
Im doing a project to measure the signal strength of a specific access point. Once it hits a certain threshold it will be program to do another task. Anyone knows how do I extract a specific data and compare it to a value? (Sorry im a total beginner in Python)

MattMcL
Posts: 1
Joined: Fri Feb 26, 2016 3:00 am

Re: Parsing iwlist scan

Fri Feb 26, 2016 3:01 am

Any way I can get it to find clients rather than access points?

stderr
Posts: 2178
Joined: Sat Dec 01, 2012 11:29 pm

Re: Parsing iwlist scan

Fri Feb 26, 2016 5:55 am

MattMcL wrote:Any way I can get it to find clients rather than access points?
Aircrack-ng is one way. Of course if you are trying to figure out who is interfering with you today, you'll find out and the next thing you know it'll be someone else. Wifi is a total mess unless you move to the badlands of South Dakota to hang out with Martin Sheen. Of course you'll find out he's always on his phone checking his Facebook, "Oh, I got another like!"

minerva_mcgonagall
Posts: 13
Joined: Mon Jun 20, 2016 8:53 am

Re: Parsing iwlist scan

Mon Jun 20, 2016 9:02 am

Hi,
I have a problem with iwlist... it takes too long and i'm looking for something that doesn't use system commands.
I want to find BSSID (mac address and RSSI actually) of around WIFIs using Python.
I found a little code with scapy but it doesn't work.
could anybody help me?
Thanks a lot
Last edited by minerva_mcgonagall on Tue Jun 21, 2016 10:32 am, edited 1 time in total.

User avatar
DougieLawson
Posts: 36312
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: Parsing iwlist scan

Mon Jun 20, 2016 11:49 am

You may be able to get the results quicker with aircrack-ng

https://www.aircrack-ng.org
Note: Having anything humorous in your signature is completely banned on this forum. Wear a tin-foil hat and you'll get a ban.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

minerva_mcgonagall
Posts: 13
Joined: Mon Jun 20, 2016 8:53 am

Re: Parsing iwlist scan

Tue Jun 21, 2016 10:20 am

DougieLawson wrote:You may be able to get the results quicker with aircrack-ng

https://www.aircrack-ng.org

Thanks
I installed aircrack-ng but it jumps to different channels while scanning WIFIs.
I need to get BSSID of all available WIFIs at the same time. like what iwlist does.

Return to “Python”