From d8fb197876f30f8f539a9d8f0b7f0c0a77ec2752 Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Mon, 19 Feb 2024 23:34:51 -0800 Subject: add network interface, cpu and memory modules These are all refreshed from a shared thread. When the next update time for multiple such modules overlaps, repainting the panel is triggered only once. --- panel.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/panel.py b/panel.py index aad51eb..b67d2f2 100755 --- a/panel.py +++ b/panel.py @@ -3,9 +3,11 @@ # Copyright 2024 David Vazgenovich Shakaryan import os +import psutil import queue import subprocess import threading +import time from datetime import datetime from zoneinfo import ZoneInfo @@ -31,6 +33,10 @@ class Fmt: def label(cls, s): return cls.fg('#7b51ca', s) + @classmethod + def labelled(cls, label, s): + return cls.label(label) + cls.spacer() + s + @classmethod def spacer(cls, n=1): return f'%{{O{n * 7}}}' @@ -298,6 +304,63 @@ class ModInputAvail(Mod): self.out = None self.repaint() +class IntervalTimer(): + def __init__(self): + self.t = None + self.lock = threading.Lock() + self.func_intervals = {} + self.func_next_time = {} + self.e_repaint = None + + def run(self): + with self.lock: + if self.t is None: + self.t = threading.Thread(target=self.work, daemon=True) + self.t.start() + + def work(self): + while True: + now = time.time() + for func, ival in self.func_intervals.items(): + if now > self.func_next_time.get(func, 0): + func() + self.func_next_time[func] = now - (now % ival) + ival + self.e_repaint.set() + time.sleep(min(self.func_next_time.values()) - time.time()) + +class ModInterval(Mod): + timer = IntervalTimer() + + def __init__(self, interval=1, **kwargs): + super().__init__(**kwargs) + self.timer.func_intervals[self.refresh] = interval + + def run(self): + if not self.timer.e_repaint: + self.timer.e_repaint = self.e_repaint + self.timer.run() + +class ModNetIf(ModInterval): + def __init__(self, ifname, label=None, **kwargs): + super().__init__(**kwargs) + self.ifname = ifname + self.label = label or ifname + + def refresh(self): + stats = psutil.net_if_stats().get(self.ifname) + state = 'up' if stats and stats.isup else 'down' + self.out = Fmt.labelled(self.label, state) + +class ModCPU(ModInterval): + def refresh(self): + percent = psutil.cpu_percent() + self.out = Fmt.labelled('CPU', f'{percent:.0f}%%') + +class ModMem(ModInterval): + def refresh(self): + percent = psutil.virtual_memory().percent + self.out = Fmt.labelled('MEM', f'{percent:.0f}%%') + class Panel: def __init__(self, *mods): self.e_repaint = threading.Event() @@ -347,6 +410,9 @@ Panel( ModInputAvail( '/dev/input/by-id/usb-HID_Keyboard_HID_Keyboard-event-kbd', unavail_text='NO KEYBOARD'), + ModNetIf('wg0', interval=1), + ModCPU(interval=0.5), + ModMem(interval=0.5), ModDate( fmts=('%Y-%m-%d %H:%M:%S', '%H:%M'), tzs=({'id': None}, {'id': 'UTC'}, -- cgit v1.2.3-70-g09d2