Indicadores personalizados para exibir a taxa de bits
Esta resposta fornece duas soluções para criar um indicador personalizado para exibir a taxa de bits da interface sem fio no painel do Unity. Os usuários são encorajados a escolher qual deles atende melhor às suas necessidades. A resposta é feita o mais detalhada possível, então, por favor, desculpe a parede do texto.
Raciocínio para duas soluções
É minha prática frequente fornecer soluções ao usuário que exigem dependências mínimas e são tão autossuficientes quanto possível, ao mesmo tempo em que encontram a solução mais simples. A solução # 1 depende do uso de um indicator-sysmonitor
construído pela fossfreedom - um dos nossos grandes membros da comunidade e moderadores, e requer o uso de dois itens - script personalizado e o indicador mencionado. O fato de eu não conseguir encontrar uma maneira de consultar a taxa de bits a partir de um arquivo de estatísticas em algum lugar em /proc
ou /sys
filesystems também me incomodou. Daí eu criei um segundo indicador, que no entanto se baseia no Network Manager e no dbus. Assim, a vantagem e a desvantagem de cada método são aparentes: uma requer a instalação de indicator-sysmonitor
e script personalizado, mas funcionará se um usuário evitar o Network Manager, enquanto o outro é mais adequado para um sistema Ubuntu padrão que usa o Network Manager.
Idealmente, a solução seria tão autossuficiente quanto possível, consultando biblioteca e / ou arquivo específico em /proc
ou /sys
filesystems. Na minha pesquisa até agora, no entanto, não encontrei esse arquivo, e o comando iw
no qual uma das soluções se baseia faz isso internamente. O que também complica as coisas é que, aparentemente, o padrão sem fio 802.11 possui diferentes esquemas de modulação para codificar o sinal e os cálculos de taxa de bits são feitos considerando o esquema de modulação e a frequência da interface que está sendo usada. Embora haja maneiras de obter TX
e RX
bytes por segundo, os dados diferem do que iw
output exibe. Por outro lado, indo até o nível C e do sistema parece muito para essa tarefa. Assim, embora eu não esteja totalmente satisfeito com ambas as soluções, elas fornecem resultados apropriados para o que essa pergunta faz.
Solução 1: sysmonitor-indicador com script de shell personalizado
Indicador Sysmonitor é um indicador criado por fossfreedom , e normalmente é usado para exibir dados estatísticos comuns, como CPU e uso de memória , mas a melhor coisa é que permite o uso de scripts personalizados. Assim, a ideia é ter um script que possa consultar a taxa de bits de alguma forma e exibi-la via indicator-sysmonitor
. Por uma questão de TL; DR , veja a lista abreviada de etapas:
-
instale o indicador-sysmonitor rodando no terminal
sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor sudo apt-get update sudo apt-get install indicator-sysmonitor
-
Crie o script
~/bin/bitrate_script.sh
, torne-o executável comchmod +x ~/bin/bitrate_script.sh
com o seguinte conteúdo#!/bin/bash iw dev wlan7 link | awk -F '[ ]' '/tx bitrate:/{print ,}'
-
Configure o indicador-sysmonitor para exibir a saída do seu script como um sensor personalizado em Preferências- & gt; Avançado- & gt; Novo, usando
br
para o sensor e caminho completo para o script como comando.
Obtendo o indicador do sistema
Como explicado na página do GitHub do projeto, você pode instalá-lo a partir da fonte ou via PPA. O método PPA, na minha opinião, é o mais simples, portanto, dado aqui:
sudo add-apt-repository ppa:fossfreedom/indicator-sysmonitor
sudo apt-get update
sudo apt-get install indicator-sysmonitor
Uma vez instalado, ele pode ser chamado via linha de comando como indicator-sysmonitor
ou do traço Unity.
Configurando o script de shell da taxa de bits
Esse script de shell pode ser feito através da análise do comando iw dev <IFACE> link
. O comando usa a interface sem fio como argumento, por exemplo, wlan1
ou wlp6s5
(observe a diferença devido à nomenclatura da interface preditiva no systemd ) e exibe vários dados, entre os quais temos tx bitrate
. Por exemplo:
$ 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
Como você pode ver, a saída requer processamento de texto para gerar uma linha de texto (já que é o que o indicator-sysmonitor
requer), e isso pode ser feito através do comando awk
. Aqui está, por exemplo, a maneira como configurei meu script:
#!/bin/bash
iw dev wlan7 link | awk -F '[ ]' '/tx bitrate:/{print ,}'
Se você executar o script na linha de comando, a saída será simplesmente a taxa de bits e a string de unidades:
$ iw dev wlan7 link | awk -F '[ ]' '/tx bitrate:/{print ,}'
135.0 MBit/s
Lembre-se de tornar seu script executável com o comando chmod +x
, caso contrário, ele não será executado.
Exibindo a saída do script no indicador-sysmonitor
Para ser preciso, o indicador tem várias configurações nas preferências que ele chama de "sensores". Por exemplo, se você definir para exibir CPU: {cpu}
, exibirá CPU
como texto e substituirá a porcentagem real de uso da CPU, em vez da string de chaves. O melhor de tudo é que clicando no botão Novo , você pode adicionar um script personalizado para ser exibido como "sensor".
Na captura de tela, você pode ver que adicionei meu script personalizado como br
string de formatação do sensor e, em Comando, forneci o caminho completo para o script que está na minha pasta ~/WIP
. Não há nada de especial nessa pasta, apenas aconteceu de ser a localização das coisas em que eu trabalho atualmente (Work-In-Progress, basicamente). No entanto, os usuários geralmente são incentivados a colocar scripts na pasta ~/bin
, portanto, eu recomendo que você faça isso.
Se você seguiu as instruções corretamente até este ponto, você deve ter indicator-sysmonitor
mostrar a taxa de bits como na captura de tela.
Solução 2: indicador personalizado usando as propriedades do dbus do Python e do Network Manager
Eu não estava satisfeito com a solução acima, que conta com indicator-sysmonitor
e um script personalizado. Eu queria ter um indicador singular que faz o trabalho de dentro de si mesmo. Por isso, escrevi um indicador próprio em Python 3, que se baseia em informações que o Network Manager expõe via dbus
sistema de comunicação entre processos. Em suma, o grande trabalho é feito pelo Network Manager - apenas usamos as informações que ele fornece. A vantagem deste indicador é que o usuário não precisa definir a interface sem fio a ser usada - isso é feito automaticamente.
Teoria da operação
Indicador efetivamente repete a mesma ação - a função get_bitrates
a cada 1 segundo. Essa função consulta as propriedades do dbus em várias interfaces em sequência. Primeiro, ele obtém todos os dispositivos e filtra os dispositivos sem fio 802.11. Em seguida, iteramos sobre cada dispositivo wifi e consultamos seu nome e taxa de bits. Tudo é construído em uma seqüência de texto que é exibida na etiqueta do indicador.
Em teoria, o indicador deve ser capaz de determinar a taxa de bits para várias interfaces sem fio. Por exemplo, os usuários podem ter um chipset sem fio PCI-e interno e um chip USB. Infelizmente, não consegui testar isso devido a problemas com meu laptop, bem como devido a restrições de tempo. Posso testar isso em outro laptop assim que tiver a chance e editar a resposta de acordo.
Código-fonte
Também disponível em GitHub no meu repositório pessoal.
#!/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()
Configurando o indicador
Todas as regras padrão para tornar os arquivos executáveis também se aplicam aqui.
- Salve o código como
indicator-bitrate
file na pasta~/bin
- Torne o arquivo executável com
chmod +x ~/bin/indicator-bitrate
- Executar a partir da linha de comando via
~/bin/indicator-bitrate
. Se você deseja que isso seja iniciado automaticamente ao fazer login, abra Startup Applications do Unity Dash e adicione o caminho completo ao script como comando.
Conclusão
As duas soluções dadas nesta resposta devem satisfazer vários casos para fornecer os resultados desejados aos usuários. O primeiro indicador é um pouco mais flexível - ele permite exibir outras informações e estatísticas além da taxa de bits, enquanto a segunda solução faz o trabalho pela taxa de bits, mas apenas isso; no entanto, ele faz uso das informações de dbus do Network Manager, portanto, podemos ter certeza de que as informações são as mesmas que foram solicitadas na pergunta.
O indicador personalizado pode ser desenvolvido ou tornar-se a base para outros indicadores para exibir informações sem fio em mais detalhes. Relatórios de bugs e solicitações de recursos são bem-vindos na página do github.