Last active
July 5, 2020 17:59
-
-
Save asquelt/0ea1c64436f24cbdb70e57516d0bc4df to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# Copyright (c) 2014-18 Richard Hull and contributors | |
# See LICENSE.rst for details. | |
# PYTHON_ARGCOMPLETE_OK | |
""" | |
Display basic system information. | |
Needs psutil (+ dependencies) installed:: | |
$ sudo apt-get install python-dev | |
$ sudo -H pip install psutil | |
""" | |
import os | |
import sys | |
import time | |
import socket | |
from datetime import datetime | |
if os.name != 'posix': | |
sys.exit('{} platform not supported'.format(os.name)) | |
from demo_opts import get_device | |
from luma.core.render import canvas | |
from PIL import ImageFont, Image, ImageSequence | |
from luma.core.sprite_system import framerate_regulator | |
try: | |
import psutil | |
except ImportError: | |
print("The psutil library was not found. Run 'sudo -H pip install psutil' to install it.") | |
sys.exit() | |
import threading | |
from collections import deque | |
def calc_ul_dl(rate, dt=3, interface='lo'): | |
t0 = time.time() | |
counter = psutil.net_io_counters(pernic=True)[interface] | |
tot = (counter.bytes_sent, counter.bytes_recv) | |
while True: | |
last_tot = tot | |
time.sleep(dt) | |
counter = psutil.net_io_counters(pernic=True)[interface] | |
t1 = time.time() | |
tot = (counter.bytes_sent, counter.bytes_recv) | |
ul, dl = [(now - last) / (t1 - t0) * 10.0 | |
for now, last in zip(tot, last_tot)] | |
rate.append((ul, dl)) | |
t0 = time.time() | |
# Create the ul/dl thread and a deque of length 1 to hold the ul/dl- values | |
transfer_rate_br_lan = deque(maxlen=1) | |
transfer_rate_eth0 = deque(maxlen=1) | |
transfer_rate_wwan0 = deque(maxlen=1) | |
t0 = threading.Thread(target=calc_ul_dl, args=(transfer_rate_br_lan,1,'br-lan')) | |
t1 = threading.Thread(target=calc_ul_dl, args=(transfer_rate_eth0,1,'eth0')) | |
t2 = threading.Thread(target=calc_ul_dl, args=(transfer_rate_wwan0,1,'wwan0')) | |
# The program will exit if there are only daemonic threads left. | |
t0.daemon = True | |
t1.daemon = True | |
t2.daemon = True | |
t0.start() | |
t1.start() | |
t2.start() | |
# TODO: custom font bitmaps for up/down arrows | |
# TODO: Load histogram | |
def bytes2human(n): | |
""" | |
>>> bytes2human(10000) | |
'9K' | |
>>> bytes2human(100001221) | |
'95M' | |
""" | |
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') | |
prefix = {} | |
for i, s in enumerate(symbols): | |
prefix[s] = 1 << (i + 1) * 10 | |
for s in reversed(symbols): | |
if n >= prefix[s]: | |
value = int(float(n) / prefix[s]) | |
return '%s%s' % (value, s) | |
if n == 0: | |
return '--' | |
return "%sB" % n | |
def sys_uptime(): | |
uptime = datetime.now() - datetime.fromtimestamp(psutil.boot_time()) | |
return "%s Up: %s" \ | |
% (socket.gethostname(), str(uptime).split('.')[0].replace(' days,','d').replace(' day,','d')) | |
def cpu_usage(): | |
# load average, uptime | |
#uptime = datetime.now() - datetime.fromtimestamp(psutil.boot_time()) | |
av1, av2, av3 = os.getloadavg() | |
#return "Ld:%.1f %.1f %.1f Up: %s" \ | |
# % (av1, av2, av3, str(uptime).split('.')[0]) | |
return "%s Ld: %.1f %.1f %.1f" \ | |
% (socket.gethostname(), av1, av2, av3) | |
def mem_usage(): | |
usage = psutil.virtual_memory() | |
return "Mem: %s %.0f%%" \ | |
% (bytes2human(usage.used), 100 - usage.percent) | |
#return "Mem: %.0f%%" \ | |
# % (100 - usage.percent) | |
def temperature(): | |
temp = psutil.sensors_temperatures()['soc-thermal'][0] | |
return "Th: %.0f'C" \ | |
% temp.current | |
def disk_usage(dir): | |
usage = psutil.disk_usage(dir) | |
return "SD: %s %.0f%%" \ | |
% (bytes2human(usage.used), usage.percent) | |
def network(iface,rate,ip=False): | |
if ip: | |
if psutil.net_if_stats()[iface].isup: | |
return "%s" % \ | |
(psutil.net_if_addrs()[iface][0].address) | |
else: | |
return "*** %s is DOWN ***" % iface | |
try: | |
stat = "UL %5s DL %5s" % \ | |
(bytes2human(int(rate[-1][0])), bytes2human(int(rate[-1][1]))) | |
return stat | |
except: | |
stat = psutil.net_io_counters(pernic=True)[iface] | |
return "Tx %5s Rx %5s" % \ | |
(bytes2human(stat.bytes_sent), bytes2human(stat.bytes_recv)) | |
def stats(device,Flag): | |
regulator = framerate_regulator(fps=15) | |
img_path = os.path.abspath(os.path.join(os.path.dirname(__file__), | |
'images', 'banana.gif')) | |
banana = Image.open(img_path) | |
size = [min(*device.size)] * 2 | |
posn = ((device.width - size[0]) // 2, device.height - size[1]) | |
# use custom font | |
font_path = os.path.abspath(os.path.join(os.path.dirname(__file__), | |
'fonts', 'C&C Red Alert [INET].ttf')) | |
font2 = ImageFont.truetype(font_path, 12) | |
if not Flag: | |
for loop in range(1,5): | |
for frame in ImageSequence.Iterator(banana): | |
with regulator: | |
background = Image.new("RGB", device.size, "white") | |
background.paste(frame.resize(size, resample=Image.LANCZOS), posn) | |
device.display(background.convert(device.mode)) | |
for iter in range(1,8): | |
with canvas(device) as draw: | |
draw.rectangle((0, 0, device.width, 12), outline="white", fill="white") | |
draw.rectangle((0, 0, 1, 1), outline="black", fill="black") | |
draw.rectangle((0, 11, 1, 12), outline="black", fill="black") | |
draw.rectangle((device.width-2, 0, device.width, 1), outline="black", fill="black") | |
draw.rectangle((device.width-2, 11, device.width, 12), outline="black", fill="black") | |
if Flag: | |
draw.text((1, 0), cpu_usage(), font=font2, fill="black") | |
else: | |
draw.text((1, 0), sys_uptime(), font=font2, fill="black") | |
if device.height >= 32: | |
if Flag: | |
draw.text((0, 14), mem_usage() + ' ' + temperature(), font=font2, fill="white") | |
else: | |
draw.text((0, 14), disk_usage('/') + ' ' + temperature(), font=font2, fill="white") | |
if device.height >= 64: | |
try: | |
draw.text((0, 26), 'LAN:', font=font2, fill="white") | |
draw.text((26, 26), network('br-lan',transfer_rate_br_lan,Flag), font=font2, fill="white") | |
except KeyError: | |
# no network enabled/available | |
draw.text((26, 26), '*** br-lan is UNKNOWN ***', font=font2, fill="white") | |
try: | |
draw.text((0, 38), 'WAN:', font=font2, fill="white") | |
draw.text((26, 38), network('eth0',transfer_rate_eth0,Flag), font=font2, fill="white") | |
except KeyError: | |
# no network enabled/available | |
draw.text((26, 38), '*** eth0 is UNKNOWN ***', font=font2, fill="white") | |
try: | |
draw.text((0, 50), 'LTE:', font=font2, fill="white") | |
draw.text((26, 50), network('wwan0',transfer_rate_wwan0,Flag), font=font2, fill="white") | |
except KeyError: | |
# no network enabled/available | |
draw.text((26, 50), '*** wwan0 is UNKNOWN ***', font=font2, fill="white") | |
time.sleep(1) | |
def main(): | |
Flag = False | |
while True: | |
stats(device,Flag) | |
#time.sleep(8) | |
if Flag: | |
Flag = False | |
else: | |
Flag = True | |
if __name__ == "__main__": | |
try: | |
device = get_device() | |
main() | |
except KeyboardInterrupt: | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment