it-swarm.com.de

Wie wird die Bitrate der drahtlosen Schnittstelle im Unity-Bedienfeld angezeigt?

Ich habe 16.04 LTS auf einem alten Lenovo T410 ausgeführt. Ich stelle fest, dass mein Netzwerkverbindungsstatus sehr unterschiedlich ist. Ich hätte gerne einen einfacheren Weg, um zu sehen, mit welcher Geschwindigkeit mein WLAN von Moment zu Moment eine Verbindung herstellt (300Mb/s, 150Mb/s usw.), ohne jedes Mal nach Netzwerkanzeige> Verbindungsinformationen> "Geschwindigkeit" suchen zu müssen Zeit.

Hier ist die Ausgabe, die ich als Indikator verwenden möchte

connection info

Ich laufe schon indicator-multiload, also wäre es großartig, einen weiteren Abschnitt hinzuzufügen, aber ich suche eher eine digitale als eine grafische Ausgabe und benötige eher den Verbindungsstatus als die Bandbreitennutzung. Kann Indicator-Multiload dies tun?

3
SLT

Benutzerdefinierte Indikatoren zur Anzeige der Bitrate

Diese Antwort bietet zwei Lösungen zum Erstellen einer benutzerdefinierten Anzeige für die Anzeige der Bitrate der drahtlosen Schnittstelle im Unity-Bereich. Benutzer werden aufgefordert, die für sie am besten geeignete Auswahl zu treffen. Die Antwort ist so detailliert wie möglich, also entschuldigen Sie bitte die Textwand.

Begründung für zwei Lösungen

Es ist meine übliche Praxis, dem Benutzer Lösungen zur Verfügung zu stellen, die minimale Abhängigkeiten erfordern und so unabhängig wie möglich sind, während einfachste Lösungen gefunden werden. Lösung 1 basiert auf der Verwendung eines indicator-sysmonitor Von fossfreedom - einem unserer großartigen Community-Mitglieder und Moderatoren - und erfordert die Verwendung von zwei Elementen - benutzerdefiniertes Skript und der angegebene Indikator. Die Tatsache, dass ich irgendwo in den Dateisystemen /proc Oder /sys Keine Möglichkeit gefunden habe, die Bitrate einer Statistikdatei abzufragen, hat mich ebenfalls gestört. Daher habe ich einen zweiten Indikator erstellt, der sich jedoch auf Network Manager und dbus stützt. Die Vor- und Nachteile der einzelnen Methoden liegen auf der Hand: Eine Methode erfordert die Installation von indicator-sysmonitor Und eines benutzerdefinierten Skripts, funktioniert jedoch, wenn ein Benutzer Network Manager meidet, während die andere Methode besser für ein Ubuntu-Standardsystem geeignet ist, das Network Manager verwendet.

Im Idealfall ist die Lösung so unabhängig wie möglich und fragt bestimmte Bibliotheken und/oder Dateien in den Dateisystemen /proc Oder /sys Ab. Bei meinen bisherigen Recherchen habe ich jedoch keine solche Datei gefunden, und der Befehl iw, auf den sich eine der Lösungen stützt, tut dies intern. Erschwerend kommt hinzu, dass der 802.11-Funkstandard offenbar unterschiedliche Modulationsschemata zum Codieren des Signals aufweist und Bitratenberechnungen unter Berücksichtigung des Modulationsschemas und der Frequenz der verwendeten Schnittstelle durchgeführt werden. Es gibt zwar Möglichkeiten, TX und RX Bytes pro Sekunde abzurufen, die Daten unterscheiden sich jedoch von der Ausgabe von iw. Auf der anderen Seite scheint es für diese Aufgabe zu viel zu sein, bis auf C- und Systemebene vorzustoßen. Auch wenn ich mit beiden Lösungen nicht ganz zufrieden bin, liefern sie angemessene Ergebnisse für das, was diese Frage stellt.

Lösung 1: Indicator-Sysmonitor mit benutzerdefiniertem Shell-Skript

enter image description here

Indikator Sysmonitor ist ein Indikator, der von fossfreedom erstellt wurde und in der Regel zur Anzeige allgemeiner statistischer Daten wie CPU- und Speichernutzung verwendet wird. Das Beste daran ist jedoch, dass die Verwendung benutzerdefinierter Skripts möglich ist. Die Idee ist also, ein Skript zu haben, das die Bitrate irgendwie abfragen und über indicator-sysmonitor Anzeigen kann. Im Interesse von TL; DR ist hier eine verkürzte Liste von Schritten:

  1. installieren Sie Indicator-Sysmonitor, indem Sie im Terminal laufen

    Sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor
    Sudo apt-get update
    Sudo apt-get install indicator-sysmonitor
    
  2. Erstellen Sie das Skript ~/bin/bitrate_script.sh Und machen Sie es mit chmod +x ~/bin/bitrate_script.sh Mit folgendem Inhalt ausführbar

    #!/bin/bash
    iw dev wlan7 link | awk -F '[ ]' '/tx bitrate:/{print $3,$4}'
    
  3. Konfigurieren Sie indicator-sysmonitor so, dass die Ausgabe Ihres Skripts als benutzerdefinierter Sensor unter Einstellungen-> Erweitert-> Neu angezeigt wird. Verwenden Sie br für den Sensor und den vollständigen Pfad zum Skript als Befehl.

Indikator sysmonitor erhalten

Wie auf der GitHub-Seite des Projekts erklärt, können Sie es von der Quelle oder über PPA installieren. Die PPA-Methode ist meiner Meinung nach die einfachste, daher hier angegeben:

Sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor
Sudo apt-get update
Sudo apt-get install indicator-sysmonitor

Nach der Installation kann es über die Befehlszeile als indicator-sysmonitor Oder über Unity Dash aufgerufen werden.

Einrichten des Bitrate-Shell-Skripts

Ein solches Shell-Skript kann über den Parsing-Befehl iw dev <IFACE> link Ausgeführt werden. Der Befehl verwendet eine drahtlose Schnittstelle als Argument, zum Beispiel wlan1 Oder wlp6s5 (Beachten Sie den Unterschied aufgrund von prädiktive Schnittstellenbenennung in systemd ) und zeigt verschiedene Daten an, darunter wir habe tx bitrate. Zum Beispiel:

$ iw dev wlan7 link
Connected to XX:XX:XX:XX:XX:XX (on wlan7)
    SSID: my_wifi
    freq: 2447
    RX: 102456319 bytes (171120 packets)
    TX: 6992103 bytes (50371 packets)
    signal: -46 dBm
    tx bitrate: 150.0 MBit/s MCS 7 40MHz short GI

    bss flags:  short-preamble short-slot-time
    dtim period:    1
    beacon int: 100

Wie Sie sehen, erfordert die Ausgabe eine Textverarbeitung, um eine Textzeile auszugeben (da dies für indicator-sysmonitor Erforderlich ist), und dies kann über den Befehl awk erfolgen. Hier ist zum Beispiel die Art und Weise, wie ich mein Skript eingerichtet habe:

#!/bin/bash
iw dev wlan7 link | awk -F '[ ]' '/tx bitrate:/{print $3,$4}'

Wenn Sie das Skript in der Befehlszeile ausführen, werden einfach die Bitrate und die Einheitenzeichenfolge ausgegeben:

$ iw dev wlan7 link | awk -F '[ ]' '/tx bitrate:/{print $3,$4}'
135.0 MBit/s

Denken Sie daran, Ihr Skript mit dem Befehl chmod +x Ausführbar zu machen, da es sonst nicht ausgeführt werden kann.

Ausgabe des Skripts im indicator-sysmonitor anzeigen

Um genau zu sein, hat der Indikator verschiedene Einstellungen in den Einstellungen, die er "Sensoren" nennt. Wenn Sie beispielsweise festlegen, dass CPU: {cpu} Angezeigt wird, wird CPU als Text angezeigt und anstelle der geschweiften Klammern der tatsächliche Prozentsatz der CPU-Auslastung angegeben. Das Tolle daran ist, dass durch Klicken New können Sie ein benutzerdefiniertes Skript hinzufügen, das als "Sensor" angezeigt wird.

Auf dem Screenshot sehen Sie, dass ich mein benutzerdefiniertes Skript als br Sensorformatierungszeichenfolge hinzugefügt habe und für Command den vollständigen Pfad zu dem Skript angegeben habe, das sich in meinem Ordner ~/WIP Befindet. Dieser Ordner hat nichts Besonderes, er ist zufällig der Speicherort für das Material, an dem ich gerade arbeite (im Grunde genommen Work-In-Progress). Benutzer werden jedoch normalerweise aufgefordert, Skripte im Ordner ~/bin Abzulegen. Daher würde ich Ihnen empfehlen, dies zu tun.

Wenn Sie die Anweisungen bis zu diesem Punkt ordnungsgemäß befolgt haben, sollte indicator-sysmonitor Die Bitrate genau wie im Screenshot anzeigen.


Lösung 2: Benutzerdefinierte Anzeige mit Python und den dbus-Eigenschaften von Network Manager

indicator-bitrate in action

Ich war mit der obigen Lösung, die auf indicator-sysmonitor Und einem benutzerdefinierten Skript basiert, nicht ganz zufrieden. Ich wollte einen singulären Indikator haben, der die Arbeit von alleine erledigt. Daher habe ich in Python 3) einen eigenen Indikator geschrieben, der sich auf Informationen stützt, die Network Manager über das Interprozess-Kommunikationssystem dbus preisgibt. Kurz gesagt, die große Arbeit ist erledigt Der Vorteil dieses Indikators ist, dass der Benutzer die zu verwendende drahtlose Schnittstelle nicht definieren muss - dies geschieht automatisch.

Betriebstheorie

Die Anzeige wiederholt effektiv die gleiche Aktion - die Funktion get_bitrates Alle 1 Sekunde. Diese Funktion fragt die dbus-Eigenschaften nacheinander an mehreren Schnittstellen ab. Zunächst werden alle Geräte abgerufen und 802.11-Funkgeräte herausgefiltert. Als Nächstes iterieren wir über jedes WLAN-Gerät und fragen dessen Namen und Bitrate ab. Alles ist in einer Textfolge aufgebaut, die dann auf dem Indikatoretikett angezeigt wird.

Theoretisch sollte der Indikator die Bitrate für mehrere drahtlose Schnittstellen bestimmen können. Beispielsweise können Benutzer über einen internen PCI-e-Funkchipsatz und einen USB-Chip verfügen. Leider konnte ich dies aufgrund von Problemen mit meinem Laptop sowie aus Zeitgründen nicht testen. Ich kann dies auf einem anderen Laptop testen, sobald ich die Möglichkeit dazu habe, und die Antwort entsprechend bearbeiten.

Quellcode

Auch verfügbar auf GitHub in meinem persönlichen Repository.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import dbus
import gi
gi.require_version('AppIndicator3', '0.1')
import signal
from gi.repository import AppIndicator3,Gtk,GLib

class IndicatorBitrate(object):

    def __init__(self):
        self.app = AppIndicator3.Indicator.new(
            'indicator-bitrate', "gtk-network",
            AppIndicator3.IndicatorCategory.HARDWARE
        )
        self.app_menu = Gtk.Menu()
        self.quit_button = Gtk.MenuItem('quit')
        self.quit_button.connect('activate', lambda *args: Gtk.main_quit())
        self.app_menu.append(self.quit_button)
        self.app.set_menu(self.app_menu)
        self.app_menu.show_all()
        self.app.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
        self.update_label()

    def call_dbus_method(self, bus_type, obj, path, interface, method, arg):
        """ utility: executes dbus method on specific interface"""
        if bus_type == "session":
            bus = dbus.SessionBus()
        if bus_type == "system":
            bus = dbus.SystemBus()
        proxy = bus.get_object(obj, path)
        method = proxy.get_dbus_method(method, interface)
        if arg:
            return method(arg)
        else:
            return method()

    def get_dbus_property(self, bus_type, obj, path, iface, prop):
        """ utility:reads properties defined on specific dbus interface"""
        if bus_type == "session":
            bus = dbus.SessionBus()
        if bus_type == "system":
            bus = dbus.SystemBus()
        proxy = bus.get_object(obj, path)
        aux = 'org.freedesktop.DBus.Properties'
        props_iface = dbus.Interface(proxy, aux)
        try:
            props = props_iface.Get(iface, prop)
            return props
        except:
            return None

    def update_label(self):
        self.app.set_label(self.get_bitrates(), '')
        GLib.timeout_add_seconds(1, self.set_app_label)

    def set_app_label(self):
        self.update_label()

    def get_bitrates(self):
        # https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NMDeviceType
        base = ['system', 'org.freedesktop.NetworkManager']
        call = base + [ '/org/freedesktop/NetworkManager', 'org.freedesktop.NetworkManager',
                        'GetAllDevices',None]
        devs = list(self.call_dbus_method(*call))

        wifi_devs = []
        for dev in devs:
            call = base + [dev,'org.freedesktop.NetworkManager.Device',
                           'DeviceType']

            if int(self.get_dbus_property(*call)) == 2:
                wifi_devs.append(dev)

        stats = []
        for dev in wifi_devs:
            # org.freedesktop.NetworkManager.Device.ActiveConnection
            call = base + [dev, 'org.freedesktop.NetworkManager.Device', 'IpInterface']
            iface = self.get_dbus_property(*call)
            call = base + [dev, 'org.freedesktop.NetworkManager.Device.Wireless',
                           'Bitrate']
            bitrate = int(self.get_dbus_property(*call))/1000
            # bitrate given by this property is in kilobits/second (Kb/s)
            # according to documentation 
            stats.append((iface,bitrate))
        return " ".join([str(i[0])+": "+str(i[1])+'Mb/s' for i in stats]) if stats else "None"

ind = IndicatorBitrate()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

Einstellen des Indikators

Auch hier gelten alle Standardregeln, um Dateien ausführbar zu machen.

  1. Speichern Sie den Code als indicator-bitrate - Datei im Ordner ~/bin
  2. Mache die Datei ausführbar mit chmod +x ~/bin/indicator-bitrate
  3. Führen Sie von der Kommandozeile aus über ~/bin/indicator-bitrate. Wenn dies beim Anmelden automatisch gestartet werden soll, öffnen Sie Startanwendungen in Unity Dash und fügen Sie dem Skript den vollständigen Pfad als Befehl hinzu.

Fazit

Die beiden in dieser Antwort angegebenen Lösungen sollten mehrere Fälle erfüllen, um den Benutzern die gewünschten Ergebnisse zu liefern. Der erste Indikator ist etwas flexibler - er ermöglicht die Anzeige anderer Informationen und Statistiken zusätzlich zur Bitrate, während die zweite Lösung die Bitrate übernimmt. Es werden jedoch die dbus-Informationen von Network Manager verwendet. Daher können wir sicher sein, dass die Informationen mit denen übereinstimmen, die in der Frage angefordert wurden.

Der benutzerdefinierte Indikator kann weiterentwickelt werden oder zur Grundlage für andere Indikatoren werden, um drahtlose Informationen detaillierter anzuzeigen. Fehlerberichte und Feature-Anfragen sind auf der verlinkten Github-Seite willkommen.

4