summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-02-09 14:38:26 +0100
committerThomas Haller <thaller@redhat.com>2023-02-13 10:32:45 +0100
commit004ffb91cfaedfa2e2d7fdf38f65231f45e66845 (patch)
tree86a7ff8be5e639bd9d433d435ddc555d137b54e0
parenta798b4f3f6e0f77dd9019178fff48beefa5c7dc9 (diff)
downloadNetworkManager-004ffb91cfaedfa2e2d7fdf38f65231f45e66845.tar.gz
examples: rework "python/gi/show-wifi-networks.py" example
- only printing the scan list is not gonna cut it. It's usually stale, and we need to request a new scan. - don't hard-code the GEnum and GFlags values that we understand. We have libnm, which provides us some meta information about the data. Use it. - Some code cleanup. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1531
-rwxr-xr-xexamples/python/gi/show-wifi-networks.py249
1 files changed, 159 insertions, 90 deletions
diff --git a/examples/python/gi/show-wifi-networks.py b/examples/python/gi/show-wifi-networks.py
index eb71c4c441..edc712a041 100755
--- a/examples/python/gi/show-wifi-networks.py
+++ b/examples/python/gi/show-wifi-networks.py
@@ -5,10 +5,17 @@
#
import locale
+import math
+import os
+import re
+import time
+
import gi
gi.require_version("NM", "1.0")
-from gi.repository import NM
+from gi.repository import NM, GLib, Gio
+
+SCAN_THRESHOLD_MSEC = 10000
#
# This example lists Wi-Fi access points NetworkManager scanned on Wi-Fi devices.
@@ -19,116 +26,165 @@ from gi.repository import NM
# an error without it: http://www.python.org/dev/peps/pep-0263/
#
+NM80211Mode = getattr(NM, "80211Mode")
+NM80211ApFlags = getattr(NM, "80211ApFlags")
+NM80211ApSecurityFlags = getattr(NM, "80211ApSecurityFlags")
-def clamp(value, minvalue, maxvalue):
- return max(minvalue, min(value, maxvalue))
-
-
-def ssid_to_utf8(ap):
- ssid = ap.get_ssid()
- if not ssid:
- return ""
- return NM.utils_ssid_to_utf8(ap.get_ssid().get_data())
-
-
-def print_device_info(device):
- active_ap = dev.get_active_access_point()
- ssid = None
- if active_ap is not None:
- ssid = ssid_to_utf8(active_ap)
- info = "Device: %s | Driver: %s | Active AP: %s" % (
- dev.get_iface(),
- dev.get_driver(),
- ssid,
- )
- print(info)
- print("=" * len(info))
-
-
-def mode_to_string(mode):
- if mode == getattr(NM, "80211Mode").INFRA:
- return "INFRA"
- if mode == getattr(NM, "80211Mode").ADHOC:
- return "ADHOC"
- if mode == getattr(NM, "80211Mode").AP:
- return "AP"
- return "UNKNOWN"
+main_loop = GLib.MainLoop()
-def flags_to_string(flags):
- if flags & getattr(NM, "80211ApFlags").PRIVACY:
- return "PRIVACY"
- return "NONE"
+def gflags_to_str(flags_type, value):
+ if value == 0:
+ return "none"
+ str = ""
+ for n in sorted(dir(flags_type)):
+ if not re.search("^[A-Z0-9_]+$", n):
+ continue
+ flag_value = getattr(flags_type, n)
+ if value & flag_value:
+ value &= ~flag_value
+ str += " " + n
+ if value == 0:
+ break
+ if value:
+ str += " (0x%0x)" % (value,)
+ return str.lstrip()
-def security_flags_to_string(flags):
- NM_AP_FLAGS = getattr(NM, "80211ApSecurityFlags")
- str = ""
- if flags & NM_AP_FLAGS.PAIR_WEP40:
- str = str + " PAIR_WEP40"
- if flags & NM_AP_FLAGS.PAIR_WEP104:
- str = str + " PAIR_WEP104"
- if flags & NM_AP_FLAGS.PAIR_TKIP:
- str = str + " PAIR_TKIP"
- if flags & NM_AP_FLAGS.PAIR_CCMP:
- str = str + " PAIR_CCMP"
- if flags & NM_AP_FLAGS.GROUP_WEP40:
- str = str + " GROUP_WEP40"
- if flags & NM_AP_FLAGS.GROUP_WEP104:
- str = str + " GROUP_WEP104"
- if flags & NM_AP_FLAGS.GROUP_TKIP:
- str = str + " GROUP_TKIP"
- if flags & NM_AP_FLAGS.GROUP_CCMP:
- str = str + " GROUP_CCMP"
- if flags & NM_AP_FLAGS.KEY_MGMT_PSK:
- str = str + " KEY_MGMT_PSK"
- if flags & NM_AP_FLAGS.KEY_MGMT_802_1X:
- str = str + " KEY_MGMT_802_1X"
- if str:
- return str.lstrip()
- else:
- return "NONE"
+def genum_to_str(enum_type, value):
+ for n in sorted(dir(enum_type)):
+ if not re.search("^[A-Z0-9_]+$", n):
+ continue
+ enum_value = getattr(enum_type, n)
+ if value == enum_value:
+ return n
+ return "(%d" % (value,)
-def flags_to_security(flags, wpa_flags, rsn_flags):
+def ap_security_flags_to_security(flags, wpa_flags, rsn_flags):
str = ""
- if (
- (flags & getattr(NM, "80211ApFlags").PRIVACY)
- and (wpa_flags == 0)
- and (rsn_flags == 0)
- ):
+ if (flags & NM80211ApFlags.PRIVACY) and (wpa_flags == 0) and (rsn_flags == 0):
str = str + " WEP"
if wpa_flags != 0:
str = str + " WPA1"
if rsn_flags != 0:
str = str + " WPA2"
- if (wpa_flags & getattr(NM, "80211ApSecurityFlags").KEY_MGMT_802_1X) or (
- rsn_flags & getattr(NM, "80211ApSecurityFlags").KEY_MGMT_802_1X
+ if (wpa_flags & NM80211ApSecurityFlags.KEY_MGMT_802_1X) or (
+ rsn_flags & NM80211ApSecurityFlags.KEY_MGMT_802_1X
):
str = str + " 802.1X"
return str.lstrip()
+def ap_get_ssid(ap):
+ if ap is None:
+ return "not connected"
+ ssid = ap.get_ssid()
+ if ssid is None:
+ return "no ssid"
+ return '"%s"' % (NM.utils_ssid_to_utf8(ssid.get_data()),)
+
+
+def print_device_info(device):
+ if device.get_client() is None:
+ last_scan = "device disappeared"
+ else:
+ t = device.get_last_scan()
+ if t == 0:
+ last_scan = "no scan completed"
+ else:
+ t = (NM.utils_get_timestamp_msec() - t) / 1000.0
+ last_scan = "%0.2f sec ago" % (t,)
+ if device_needs_scan(device):
+ last_scan += " (stale)"
+
+ ap = device.get_active_access_point()
+ if ap is None:
+ active_ap = "none"
+ else:
+ active_ap = "%s (%s)" % (ap_get_ssid(ap), ap.get_path())
+
+ print("Device: %s" % (device.get_iface(),))
+ print("D-Bus path: %s" % (NM.Object.get_path(device),))
+ print("Driver: %s" % (device.get_driver(),))
+ print("Active AP: %s" % (active_ap,))
+ print("Last scan: %s" % (last_scan,))
+
+
def print_ap_info(ap):
strength = ap.get_strength()
frequency = ap.get_frequency()
flags = ap.get_flags()
wpa_flags = ap.get_wpa_flags()
rsn_flags = ap.get_rsn_flags()
- print("SSID: %s" % (ssid_to_utf8(ap)))
- print("BSSID: %s" % (ap.get_bssid()))
- print("Frequency: %s" % (frequency))
- print("Channel: %s" % (NM.utils_wifi_freq_to_channel(frequency)))
- print("Mode: %s" % (mode_to_string(ap.get_mode())))
- print("Flags: %s" % (flags_to_string(flags)))
- print("WPA flags: %s" % (security_flags_to_string(wpa_flags)))
- print("RSN flags: %s" % (security_flags_to_string(rsn_flags)))
- print("Security: %s" % (flags_to_security(flags, wpa_flags, rsn_flags)))
- print("Strength: %s %s%%" % (NM.utils_wifi_strength_bars(strength), strength))
- print
+
+ t = ap.get_last_seen()
+ if t < 0:
+ last_seen = "never"
+ else:
+ t = time.clock_gettime(time.CLOCK_BOOTTIME) - t
+ last_seen = "%s sec ago" % (math.ceil(t),)
+
+ print(" - D-Bus path: %s" % (ap.get_path(),))
+ print(" SSID: %s" % (ap_get_ssid(ap),))
+ print(" BSSID: %s" % (ap.get_bssid(),))
+ print(" Last seen: %s" % (last_seen,))
+ print(" Frequency: %s" % (frequency,))
+ print(" Channel: %s" % (NM.utils_wifi_freq_to_channel(frequency),))
+ print(" Mode: %s" % (genum_to_str(NM80211Mode, ap.get_mode()),))
+ print(" Flags: %s" % (gflags_to_str(NM80211ApFlags, flags),))
+ print(" WPA flags: %s" % (gflags_to_str(NM80211ApSecurityFlags, wpa_flags),))
+ print(" RSN flags: %s" % (gflags_to_str(NM80211ApSecurityFlags, rsn_flags),))
+ print(
+ " Security: %s"
+ % (ap_security_flags_to_security(flags, wpa_flags, rsn_flags),)
+ )
+ print(
+ " Strength: %s%% : %s"
+ % (
+ strength,
+ NM.utils_wifi_strength_bars(strength),
+ )
+ )
-if __name__ == "__main__":
+def device_needs_scan(device):
+ if device.get_client() is None:
+ # the device got deleted. We can forget about it.
+ return False
+ t = device.get_last_scan()
+ return t == 0 or t < NM.utils_get_timestamp_msec() - SCAN_THRESHOLD_MSEC
+
+
+def device_ensure_scanned(device):
+ if os.getenv("NO_SCAN") == "1":
+ return
+
+ if not device_needs_scan(device):
+ return
+
+ # kick off a new scan.
+ device.request_scan_async(None)
+
+ def cb():
+ main_loop.quit()
+
+ timeout_source = GLib.timeout_source_new(10 * 1000)
+ timeout_source.set_callback(cb)
+ timeout_source.attach(main_loop.get_context())
+
+ def cb(device, prop):
+ if not device_needs_scan(device):
+ main_loop.quit()
+
+ device.connect("notify", cb)
+
+ main_loop.run()
+
+ timeout_source.destroy()
+
+
+def main():
# Python apparently doesn't call setlocale() on its own? We have to call this or else
# NM.utils_wifi_strength_bars() will think the locale is ASCII-only, and return the
# fallback characters rather than the unicode bars
@@ -137,8 +193,21 @@ if __name__ == "__main__":
nmc = NM.Client.new(None)
devs = nmc.get_devices()
- for dev in devs:
- if dev.get_device_type() == NM.DeviceType.WIFI:
- print_device_info(dev)
- for ap in dev.get_access_points():
- print_ap_info(ap)
+ is_first = True
+ for device in devs:
+ if device.get_device_type() != NM.DeviceType.WIFI:
+ continue
+
+ if not is_first:
+ print("")
+ else:
+ is_first = False
+
+ device_ensure_scanned(device)
+ print_device_info(device)
+ for ap in device.get_access_points():
+ print_ap_info(ap)
+
+
+if __name__ == "__main__":
+ main()