# WAP list with graph - help please

**URL:** <https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361>\
**Category:** General\
**Created:** [23 June 2023 07:06 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361 "2023-06-23T07:06:02Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 07:06 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/1 "2023-06-23T07:06:02Z")

</div>

I have some code that lists all the visible WAPs.  
(Though I don't think it is going to work for what I am wanting to do.) ☹

(python code)

```auto
#wifiscan.py
import subprocess
import json
import re
 
child = subprocess.Popen('sudo iwlist wlan0 scan | grep ESSID',shell=True,stdout=subprocess.PIPE)
output = child.communicate()[0]
output = output.decode("utf8")
output = output.replace(' ESSID:','')
output = output.replace(' "','')
output = output.replace('"','')
output = output.splitlines()
 
output = json.dumps(output)
 
print (output)

```

What I am wanting - now - is to also have the strength also included.

Then, run that code in the `python` node and get the output and show a graph with all the SSID names / strengths.

(Sorry folks. the _hamster_ is on holiday just now and I can't resolve how to parse the message and make a _graph_.)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 07:52 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/2 "2023-06-23T07:52:11Z")

</div>

Ok, so I change the line to:  
`grep -B2 ESSID` and I get the strength of the signal also.

Now I'm stuck on how to get ONLY the _FIRST_ and _LAST_ lines.  
I don't need the _middle_ one.

```auto
                    Quality=70/70 Signal level=-37 dBm  
                    Encryption key:on
                    ESSID:"Marys_Farm_2.4"

```

So all I need is the `Signal level` and `ESSID`.

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [23 June 2023 08:02 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/3 "2023-06-23T08:02:41Z")

</div>

This is what works for me - running on an ESP32-S2 Mini using MicroPython.

```auto
import network
import time
import ubinascii

# init wifi
wlan = network.WLAN(network.STA_IF) #initialize the wlan object
wlan.active(True) #activates the wlan interface
wlan.disconnect()

def scan():
    accessPoints = wlan.scan() #perform a WiFi Access Points scan

    num_rows = len(accessPoints)
    print("num wifi: ",num_rows)

    for ap in accessPoints: #this loop prints each AP found in a single row on shell
        ssid = ap[0].decode()
        if (ssid != ''):
            bssid = ubinascii.hexlify(ap[1],":").decode()
            ch = ap[2]
            rssi = ap[3]
            auth = hex(ap[4])
            vis = hex(ap[5])
            print("{:30s} | {:s} | {:2d} | {:3d} | {:s} | {:s}".format(ssid, bssid, ch, rssi, auth, vis))

# code starts here
start=time.time()
print("Start time: ",time.time(),"\n")

scan()
 
end=time.time()
print("\nEnd time: ",time.time())

print("\nrun time: ",end-start)

```

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 08:08 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/4 "2023-06-23T08:08:30Z")

</div>

My code is run on a RasPi.

The code you showed me errors:

```auto
Traceback (most recent call last):
  File "wifiscan2.py", line 1, in <module>
    import network
ModuleNotFoundError: No module named 'network'

```

I am very new to python. (3 - sorry)  
I understand the `network` _module_ is needed. But that may be because you are using the ESP32 and micropython.

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [23 June 2023 08:12 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/5 "2023-06-23T08:12:44Z")

</div>

I'll try it on a RPi when I get back home later today.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 08:13 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/6 "2023-06-23T08:13:13Z")

</div>

~~Sorry~~ Thanks (?) Dave.... I appreciate the help.

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [23 June 2023 08:21 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/7 "2023-06-23T08:21:34Z")

</div>

I'm not near a RPi (so can't try this) - this is what ChatGPT suggests for a RPi...  
Looks very similar to your listing.  
The function returns a 'tupple' so you can collect whatever parts you need.

```auto
import subprocess
import re

def scan_wifi():
    # Run the iwlist command to scan for wireless networks
    cmd = subprocess.Popen(['sudo', 'iwlist', 'wlan0', 'scan'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, _ = cmd.communicate()

    # Decode the output from bytes to string
    output = output.decode()

    # Extract the relevant information using regular expressions
    networks = re.findall(r'ESSID:"(.*?)".*?Frequency:(.*?)\s', output, re.DOTALL)

    # Return the list of networks
    return networks

wifi_networks = scan_wifi()

# Print the details of each network
for network in wifi_networks:
    ssid = network[0]
    frequency = network[1]
    print(f"Network: {ssid}, Frequency: {frequency}")

```

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 08:25 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/8 "2023-06-23T08:25:50Z")

</div>

(I can't get onto chatgpt.... But haven't tried that many times.)

That looks good.

Alas not quite. (Not your fault)

This is what I get:

```auto
Network: Marys_Farm_2.4, Frequency: 2.462
Network: MyRepublic 49D9, Frequency: 5.745
Network: WiFi-AFB6-5G, Frequency: 5.765
Network: Marys_Farm_5, Frequency: 5.32
Network: TelstraCA5E31, Frequency: 5.32
Network: \x00\x00\x00\x00\x00\x00\x00\x00\x00, Frequency: 2.437
Network: WiFi-F852, Frequency: 5.18
Network: Optus_ABA172_5GHz, Frequency: 2.412
Network: PiNet, Frequency: 2.437
Network: Optus_ABA172, Frequency: 2.427
Network: WiFi-AFB6, Frequency: 2.412
Network: Aussie Broadband 4928, Frequency: 2.412
Network: LIFX Color 1000_142486_AJ, Frequency: 2.412
Network: OPTUS_69E639M, Frequency: 5.18
Network: WiFi-F852-5G, Frequency: 5.18

```

So that is the `frequency` not `signal strength`.  
I'll give it a go to see if I can work out what I need to get it showing me what I want.

Again: Thanks.

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [23 June 2023 08:29 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/9 "2023-06-23T08:29:36Z")

</div>

Try this...

```auto
import subprocess
import re

def scan_wifi():
    # Run the iwlist command to scan for wireless networks
    cmd = subprocess.Popen(['sudo', 'iwlist', 'wlan0', 'scan'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, _ = cmd.communicate()

    # Decode the output from bytes to string
    output = output.decode()

    # Extract the relevant information using regular expressions
    networks = re.findall(r'ESSID:"(.*?)".*?Frequency:(.*?)\s.*?Signal level=(.*?)\s', output, re.DOTALL)

    # Return the list of networks
    return networks

wifi_networks = scan_wifi()

for network in wifi_networks:
    ssid = network[0]
    frequency = network[1]
    signal_level = network[2]
    print(f"Network: {ssid}, Frequency: {frequency}, Signal Level: {signal_level}")

```

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 08:34 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/10 "2023-06-23T08:34:17Z")

</div>

Sorry, but two bits of code?  
(Train no longer on the tracks.)

If I run the top one - which looks like a starting point - I get nothing back.

I was about to ask how to get to see the entire `network[]` so I could change the fist one to give me what I want.

What is the second bit of code?

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [23 June 2023 08:38 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/11 "2023-06-23T08:38:44Z")

</div>

Sorry finger trouble at this end - try the listing above (again) as I've corrected it.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 08:42 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/12 "2023-06-23T08:42:39Z")

</div>

Love you Dave. 😉 (No, not in that way.)

I will delete the `frequency` part. Not needed.

I'll get it working I hope.  
Oh, ok, one quirk: I need to add a _separator_ between the names. (For the `split` node downstream).  
so to put a `,` between then I just put that at the end of the print line - yes?

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [23 June 2023 08:46 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/13 "2023-06-23T08:46:37Z")

</div>

Sounds as if you are now back on "track".  
As I said, I have no access to a RPi, so can't test anything until I get home later today.  
I'm sure another member of the Forum may well jump in and help with the Python syntax.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 08:48 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/14 "2023-06-23T08:48:18Z")

</div>

That's ok. And again: THANKS!

Yes, you were amazing helping me.

(I'd better mark the solution)

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 09:03 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/15 "2023-06-23T09:03:25Z")

</div>

(I'll have to do more digging and it isn't outputting what NR likes.)

This is what _works_

```auto
output = child.communicate()[0]
output = output.decode("utf8")
output = output.replace(' ESSID:','')
output = output.replace(' "','')
output = output.replace('"','')
output = output.splitlines()
 
output = json.dumps(output)
 
print (output)

```

So I will have to study the structure of that and apply it to the new code.

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [23 June 2023 10:24 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/16 "2023-06-23T10:24:12Z")

</div>

> [@Trying\_to\_learn](#):
>
> Ok, so I change the line to:  
> `sudo iwlist wlan0 scan | grep -B2 ESSID` and I get the strength of the signal also.
> 
> Now I'm stuck on how to get ONLY the _FIRST_ and _LAST_ lines.

If you use egrep instead of grep ("extended grep", I believe it is installed by default) you can search for lines containing either "ESSID" or "Signal", which might simplify further processing.

```auto
sudo iwlist wlan0 scan | egrep 'ESSID|Signal'
                    Quality=47/70 Signal level=-63 dBm
                    ESSID:"TALKTALK9B7661"
                    Quality=28/70 Signal level=-82 dBm
                    ESSID:"BT-JGAW38"
                    Quality=48/70 Signal level=-62 dBm
                    ESSID:"GreyWagtail561"
                    Quality=39/70 Signal level=-71 dBm
                    ESSID:"BT-S9A63M"
                    Quality=40/70 Signal level=-70 dBm
                    ESSID:"BTWi-fi"
                    Quality=45/70 Signal level=-65 dBm
                    ESSID:"BTWi-fi"
                    Quality=41/70 Signal level=-69 dBm
                    ESSID:"BTHub6-WX8H"
                    Quality=36/70 Signal level=-74 dBm
                    ESSID:"BT-75CPCX"
                    Quality=27/70 Signal level=-83 dBm

```

I usually use awk to further process multi-line shell output records, but you can use other Bash tools to reduce it to single lines. For example (sorry it's not obvious what it does)

```auto
 sudo iwlist wlan0 scan | egrep 'ESSID|Signal' |sed -z 's/\n//g; s/ *Q/\nQ/g; s/ */ /g; s/l l/l_l/g; s/:/=/g'

Quality=52/70 Signal_level=-58 dBm ESSID="TALKTALK9B7661"
Quality=28/70 Signal_level=-82 dBm ESSID="BT-JGAW38"
Quality=49/70 Signal_level=-61 dBm ESSID="GreyWagtail561"
Quality=42/70 Signal_level=-68 dBm ESSID="BTWi-fi"
Quality=43/70 Signal_level=-67 dBm ESSID="BTWi-fi"
Quality=45/70 Signal_level=-65 dBm ESSID="BTHub6-WX8H"
Quality=28/70 Signal_level=-82 dBm ESSID="BT-75CPCX"
Quality=31/70 Signal_level=-79 dBm ESSID="BTWi-fi"

```

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [23 June 2023 10:24 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/17 "2023-06-23T10:24:46Z")

</div>

How about creating a json object that you can (eventually) send to Node-RED via MQTT??  
Here's a snippet for you...

```auto
output = json.dumps({"ssid": network[0], "signal_level": network[2]})
print(output)

```

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 10:38 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/18 "2023-06-23T10:38:10Z")

</div>

Thanks.

I am still in the shallow part of the scheme for the O/S commands, so that is another problem for me.

I'll look at it but I will also look at Dave's reply too.

---

<div class="post-metadata">

**Author:** ![Trying\_to\_learn](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/trying_to_learn/32/28400_2.png) [@Trying\_to\_learn](https://discourse.nodered.org/u/Trying_to_learn)\
**Post date:** [23 June 2023 10:42 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/19 "2023-06-23T10:42:50Z")

</div>

> [@dynamicdave](#):
>
> ```auto
> output = json.dumps({"ssid": network[0], "signal_level": network[2]})
> print(output)
> 
> ```

Sorry Dave, something is being lost in translation for me.

(error)

```auto
exit code: 1, File "wifiscan5.py", line 25
    print(f"Network: {ssid}, Frequency: {frequency}, Signal Level: {signal_level}")
                                                                                 ^
SyntaxError: invalid syntax

```

Code:

```auto
import json
import subprocess
import re

def scan_wifi():
    # Run the iwlist command to scan for wireless networks
    cmd = subprocess.Popen(['sudo', 'iwlist', 'wlan0', 'scan'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, _ = cmd.communicate()

    # Decode the output from bytes to string
    output = output.decode()

    # Extract the relevant information using regular expressions
    networks = re.findall(r'ESSID:"(.*?)".*?Frequency:(.*?)\s.*?Signal level=(.*?)\s', output, re.DOTALL)

    # Return the list of networks
    return networks

wifi_networks = scan_wifi()

for network in wifi_networks:
    ssid = network[0]
    frequency = network[1]
    signal_level = network[2]
    print(f"Network: {ssid}, Frequency: {frequency}, Signal Level: {signal_level}")
# this = print(f,"Network: {ssid}, Level: {signal_level}")

    output = json.dumps({"ssid": network[0], "signal_level": network[2]})
    print(output)

```

I am bad with code at the start and leave a lot of old stuff in so I know what to NOT do in subsequent tries. When all working I take out all the comments that aren't needed/old lines.

For the sake of it this is how it is done in NR

```auto
[{"id":"057c784d0fb29dfc","type":"pythonshell in","z":"c56bddee.ca0a18","name":"wifiscan","pyfile":"/home/pi/python_stuff/wifiscan5.py","virtualenv":"","continuous":false,"stdInData":false,"x":145,"y":3490,"wires":[["b7ae270d16a37445","cab9900ce3a0acc3"]],"l":false},{"id":"cab9900ce3a0acc3","type":"debug","z":"c56bddee.ca0a18","name":"debug 10","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":450,"y":3330,"wires":[]}]

```

# OK, sorry, I goofed!

Line 25. I commented it out and it works.

Hang on.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [23 June 2023 10:49 UTC](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361/20 "2023-06-23T10:49:17Z")

</div>

I think you are nearly there now. ( so please don’t get diverted ) but this tool may help in future -[jc | CLI tool and python library that converts the output of popular command-line tools, file-types, and common strings to JSON, YAML, or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan.html)

[Next page](https://discourse.nodered.org/t/wap-list-with-graph-help-please/79361.md?page=2)
