pythonwifidbus

dbus RequestScan Method in python


I'm trying to reverse engineer this sample code I found online which i don't understand. As I understand it, the code returns the SSID's that my wlan0 device finds.

What troubles me, is the list of AP's my wireless interface finds doesn't seem to update, i've read everything I can find on dbus, i think i need to use the RequestScan method, but i'm not really sure....

how to I refresh the list of access points? I think line of code (line 89) accesspoints_paths_list = device.GetAccessPoints() is where the RequestScan method should be? I thought the correct statement would be device.RequestScan() but that produces the following error:

ERROR:dbus.connection:Unable to set arguments () according to signature 'a{sv}': <class 'TypeError'>: More items found in D-Bus signature than in Python arguments
Traceback (most recent call last):
  File "/home/hms/iphone-7.py", line 89, in <module>
    device.RequestScan()
  File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 141, in __call__
    return self._connection.call_blocking(self._named_service,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/dbus/connection.py", line 625, in call_blocking
    message.append(signature=signature, *args)
TypeError: More items found in D-Bus signature than in Python arguments

This is my code:

#!/usr/bin/python
# -*- coding:UTF-8 -*-

import os, time
import shutil, glob, subprocess, re, sys
# from wireless import Wireless
import dbus


os.system('clear')
print (" iPhone test BB-78")

goal_ssid="tiphone"
goal_pw="password"


if __name__ == "__main__":
    bus = dbus.SystemBus()
    manager_bus_object = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")

    manager = dbus.Interface(manager_bus_object, "org.freedesktop.NetworkManager")
    
    manager_props = dbus.Interface(manager_bus_object,"org.freedesktop.DBus.Properties")

    was_wifi_enabled = manager_props.Get("org.freedesktop.NetworkManager","WirelessEnabled")

    device_path = manager.GetDeviceByIpIface("wlan0")
    print ("wlan0 path:    ", device_path, "\n")


    was_wifi_enabled = manager_props.Get("org.freedesktop.NetworkManager", "WirelessEnabled")
    if was_wifi_enabled:
        was_wifi_enabled="WiFi ON"
    else:
        was_wifi_enabled="WiFi OFF"    


    print ("the result of testing if WiFi is enabled is", was_wifi_enabled,"\n")


    # Connect to the device's Wireless interface and obtain list of access
    # points.
    device = dbus.Interface(bus.get_object("org.freedesktop.NetworkManager", device_path), "org.freedesktop.NetworkManager.Device.Wireless")
    accesspoints_paths_list = device.GetAccessPoints()


    # Identify our access point. We do this by comparing our desired SSID
    # to the SSID reported by the AP.
    our_ap_path = None
    y=1
    z=1

    while not our_ap_path:

        x=1
        print ("Scan numnber:", z,"the program has found", len(accesspoints_paths_list), "APs")
        for ap_path in accesspoints_paths_list:
            ap_props = dbus.Interface(bus.get_object("org.freedesktop.NetworkManager", ap_path), "org.freedesktop.DBus.Properties")
            ap_ssid = ap_props.Get("org.freedesktop.NetworkManager.AccessPoint", "Ssid")


            str_ap_ssid = "".join(chr(i) for i in ap_ssid)
            print (x, str_ap_ssid)
            x=x+1       
            if str_ap_ssid == goal_ssid:
                our_ap_path = ap_path

        for ap_path in accesspoints_paths_list:
            ap_props = dbus.Interface(bus.get_object("org.freedesktop.NetworkManager", ap_path), "org.freedesktop.DBus.Properties")
            ap_ssid = ap_props.Get("org.freedesktop.NetworkManager.AccessPoint", "Ssid")
            str_ap_ssid = "".join(chr(i) for i in ap_ssid)
            if str_ap_ssid == goal_ssid:
                our_ap_path = ap_path
                break

        if not our_ap_path:
            print ("AP not found :(")
            print("sleeping 10 seconds before refreshing \n")
            time.sleep(5)
            y=y+1
            if y==5:
                y=1
                os.system('clear')
        z=z+1



        
        accesspoints_paths_list = device.GetAccessPoints()





            
        


    print ("AP found")
    print ("Our AP: ", our_ap_path)
    print("will try to connect now")

Solution

  • To refresh the list of access points with dbus, you need to request a scan before fetching the results. here's a basic structure for an update

    import dbus
    import time
    
    def scan_access_points():
        bus = dbus.SystemBus()
        device = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager/Devices/0')
        device_interface = dbus.Interface(device, 'org.freedesktop.NetworkManager.Device.Wireless')
    
        device_interface.RequestScan({})
    
        time.sleep(2)
        
        accesspoints_paths_list = device_interface.GetAccessPoints()
        
        for ap_path in accesspoints_paths_list:
            ap = bus.get_object('org.freedesktop.NetworkManager', ap_path)
            ap_properties = dbus.Interface(ap, 'org.freedesktop.DBus.Properties')
            ssid = ap_properties.Get('org.freedesktop.NetworkManager.AccessPoint', 'SsId')
            print(f"SSID: {ssid}")
    
    scan_access_points()