frobarng: NetworkProvider done
This commit is contained in:
parent
36df032ecd
commit
1ae7d6b447
|
@ -3,9 +3,11 @@
|
|||
import asyncio
|
||||
import datetime
|
||||
import enum
|
||||
import ipaddress
|
||||
import logging
|
||||
import random
|
||||
import signal
|
||||
import socket
|
||||
import typing
|
||||
|
||||
import coloredlogs
|
||||
|
@ -22,6 +24,21 @@ C = typing.TypeVar("C", bound="ComposableText")
|
|||
Sortable = str | int
|
||||
|
||||
|
||||
def humanSize(numi: int) -> str:
|
||||
"""
|
||||
Returns a string of width 3+3
|
||||
"""
|
||||
num = float(numi)
|
||||
for unit in ("B ", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"):
|
||||
if abs(num) < 1000:
|
||||
if num >= 10:
|
||||
return "{:3d}{}".format(int(num), unit)
|
||||
else:
|
||||
return "{:.1f}{}".format(num, unit)
|
||||
num /= 1024
|
||||
return "{:d}YiB".format(numi)
|
||||
|
||||
|
||||
class ComposableText(typing.Generic[P, C]):
|
||||
|
||||
def __init__(
|
||||
|
@ -267,6 +284,7 @@ class Bar(ComposableText):
|
|||
super().__init__()
|
||||
self.parent: None
|
||||
self.children: typing.MutableSequence[Screen]
|
||||
self.longRunningTasks: list[asyncio.Task] = list()
|
||||
|
||||
self.refresh = asyncio.Event()
|
||||
self.taskGroup = asyncio.TaskGroup()
|
||||
|
@ -280,6 +298,10 @@ class Bar(ComposableText):
|
|||
continue
|
||||
Screen(parent=self, output=output.name)
|
||||
|
||||
def addLongRunningTask(self, coro: typing.Coroutine) -> None:
|
||||
task = self.taskGroup.create_task(coro)
|
||||
self.longRunningTasks.append(task)
|
||||
|
||||
async def run(self) -> None:
|
||||
cmd = [
|
||||
"lemonbar",
|
||||
|
@ -299,7 +321,6 @@ class Bar(ComposableText):
|
|||
await self.refresh.wait()
|
||||
self.refresh.clear()
|
||||
markup = self.getMarkup()
|
||||
# log.debug(markup)
|
||||
proc.stdin.write(markup.encode())
|
||||
|
||||
async def actionHandler() -> None:
|
||||
|
@ -310,21 +331,15 @@ class Bar(ComposableText):
|
|||
callback = self.actions[command]
|
||||
callback()
|
||||
|
||||
longRunningTasks = list()
|
||||
|
||||
def addLongRunningTask(coro: typing.Coroutine) -> None:
|
||||
task = self.taskGroup.create_task(coro)
|
||||
longRunningTasks.append(task)
|
||||
|
||||
async with self.taskGroup:
|
||||
addLongRunningTask(refresher())
|
||||
addLongRunningTask(actionHandler())
|
||||
self.addLongRunningTask(refresher())
|
||||
self.addLongRunningTask(actionHandler())
|
||||
for provider in self.providers:
|
||||
addLongRunningTask(provider.run())
|
||||
self.addLongRunningTask(provider.run())
|
||||
|
||||
def exit() -> None:
|
||||
log.info("Terminating")
|
||||
for task in longRunningTasks:
|
||||
for task in self.longRunningTasks:
|
||||
task.cancel()
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
@ -563,11 +578,50 @@ class NetworkProviderSection(StatefulSection):
|
|||
self.numberStates = 5 if self.wifi else 4
|
||||
self.state = 1 if self.wifi else 0
|
||||
|
||||
async def updateOnStateChange(self) -> None:
|
||||
while True:
|
||||
await self.stateChanged.wait()
|
||||
await self.provider.updateIface(self.iface)
|
||||
|
||||
async def getText(self) -> str | None:
|
||||
if self.ignore or not self.provider.if_stats[self.iface].isup:
|
||||
return None
|
||||
|
||||
text = self.icon
|
||||
|
||||
state = self.state + (0 if self.wifi else 1) # SSID
|
||||
if self.wifi and state >= 1:
|
||||
cmd = ["iwgetid", self.iface, "--raw"]
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
*cmd, stdout=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = await proc.communicate()
|
||||
text += f" {stdout.decode().strip()}"
|
||||
|
||||
if state >= 2: # Address
|
||||
for address in self.provider.if_addrs[self.iface]:
|
||||
if address.family == socket.AF_INET:
|
||||
net = ipaddress.IPv4Network(
|
||||
(address.address, address.netmask), strict=False
|
||||
)
|
||||
text += f" {net.with_prefixlen}"
|
||||
break
|
||||
|
||||
if state >= 3: # Speed
|
||||
prevRecv = self.provider.prev_io_counters[self.iface].bytes_recv
|
||||
recv = self.provider.io_counters[self.iface].bytes_recv
|
||||
prevSent = self.provider.prev_io_counters[self.iface].bytes_sent
|
||||
sent = self.provider.io_counters[self.iface].bytes_sent
|
||||
recvDiff = recv - prevRecv
|
||||
sentDiff = sent - prevSent
|
||||
dt = self.provider.time - self.provider.prev_time
|
||||
recvDiff /= dt
|
||||
sentDiff /= dt
|
||||
|
||||
text += f" ↓{humanSize(recvDiff)}↑{humanSize(sentDiff)}"
|
||||
|
||||
if state >= 4: # Counter
|
||||
text += f" ⇓{humanSize(recv)}⇑{humanSize(sent)}"
|
||||
|
||||
return text
|
||||
|
||||
|
||||
|
@ -582,12 +636,25 @@ class NetworkProvider(MirrorProvider):
|
|||
async def run(self) -> None:
|
||||
await super().run()
|
||||
|
||||
while True:
|
||||
# if_addrs: dict[str, list[psutil._common.snicaddr]] = psutil.net_if_addrs()
|
||||
# io_counters: dict[str, psutil._common.snetio] = psutil.net_io_counters(pernic=True)
|
||||
loop = asyncio.get_running_loop()
|
||||
self.time = loop.time()
|
||||
self.io_counters = psutil.net_io_counters(pernic=True)
|
||||
|
||||
while True:
|
||||
# Separate TaskGroup in case it takes longer than one second,
|
||||
# it doesn't fill the main TaskGroup
|
||||
async with asyncio.TaskGroup() as tg:
|
||||
self.prev_io_counters = self.io_counters
|
||||
self.prev_time = self.time
|
||||
# On-demand would only benefit if_addrs:
|
||||
# stats are used to determine display,
|
||||
# and we want to keep previous io_counters
|
||||
# so displaying stats is ~instant.
|
||||
self.time = loop.time()
|
||||
self.if_stats = psutil.net_if_stats()
|
||||
self.if_addrs = psutil.net_if_addrs()
|
||||
self.io_counters = psutil.net_io_counters(pernic=True)
|
||||
|
||||
for iface in self.if_stats:
|
||||
if iface not in self.sections:
|
||||
section = NetworkProviderSection(
|
||||
|
@ -595,6 +662,7 @@ class NetworkProvider(MirrorProvider):
|
|||
)
|
||||
self.sections[iface] = section
|
||||
|
||||
self.module.bar.addLongRunningTask(section.updateOnStateChange())
|
||||
tg.create_task(self.updateIface(iface))
|
||||
for iface, section in self.sections.items():
|
||||
if iface not in self.if_stats:
|
||||
|
|
Loading…
Reference in a new issue