diff --git a/README.md b/README.md index 8b9d458..fd08435 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ # sys-oled -Script to display Helios4 system status for i2c OLED screen. +Script to display Helios4 system status for i2c OLED screen. + +* Based on [luma.oled](https://github.com/rm-hull/luma.oled) +* Script inspired from [sys_info.py](https://github.com/rm-hull/luma.examples/blob/master/examples/sys_info.py) example + +## TO DO +* How to install +* How to tweak/configure +* Add comment to code diff --git a/font/C&C Red Alert [INET].ttf b/font/C&C Red Alert [INET].ttf new file mode 100644 index 0000000..f07f953 Binary files /dev/null and b/font/C&C Red Alert [INET].ttf differ diff --git a/img/helios4_logo.png b/img/helios4_logo.png new file mode 100644 index 0000000..be45cf6 Binary files /dev/null and b/img/helios4_logo.png differ diff --git a/sys_oled.py b/sys_oled.py new file mode 100755 index 0000000..2746cd7 --- /dev/null +++ b/sys_oled.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +import signal +import os +import sys +import time +import psutil +from datetime import datetime +from luma.core import cmdline, error +from PIL import Image, ImageDraw, ImageFont + +# Define interval between image +interval = 4 + +font_path = os.path.abspath(os.path.join(os.path.dirname(__file__), + 'font', 'C&C Red Alert [INET].ttf')) +font = ImageFont.truetype(font_path, 12) + +def get_device(actual_args=None): + if actual_args is None: + actual_args = sys.argv[1:] + parser = cmdline.create_parser(description='luma.core arguments') + args = parser.parse_args(actual_args) + + if args.config: + config = cmdline.load_config(args.config) + args = parser.parse_args(config + actual_args) + + try: + device = cmdline.create_device(args) + except error.Error as e: + parser.error(e) + + return device + +def bytes2human(n): + 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) + return "%sB" % n + + +def cpu_usage(): + uptime = datetime.now().replace(microsecond=0) - datetime.fromtimestamp(psutil.boot_time()) + av1, av2, av3 = os.getloadavg() + return "ld: %.1f %.1f %.1f up: %s" \ + % (av1, av2, av3, str(uptime).split(',')[0]) + + +def mem_usage(): + usage = psutil.virtual_memory() + return "mem: %s / %s %.0f%%" \ + % (bytes2human(usage.used), bytes2human(usage.total), usage.percent) + + +def disk_usage(name, dir): + usage = psutil.disk_usage(dir) + return name + ": %s / %s - %.0f%%" \ + % (bytes2human(usage.used), bytes2human(usage.total), usage.percent) + + +def network(iface): + addr = psutil.net_if_addrs()[iface] + return "%s: %s" \ + % (iface, addr[0].address) + +def host_time(): + now = datetime.now() + hostname = os.uname()[1] + return hostname + " - " + now.strftime("%Y-%m-%d %H:%M") + +def status(device): + txt = Image.new('RGBA', device.size) + d = ImageDraw.Draw(txt) + d.text((0, 0), cpu_usage(), font=font, fill="white") + d.line([(0,13),(128,13)]) + d.text((0, 15), mem_usage(), font=font, fill="white") + d.text((0, 27), disk_usage('sd', '/'), font=font, fill="white") + d.text((0, 39), disk_usage('md0', '/'), font=font, fill="white") + d.text((0, 51), network('eth0'), font=font, fill="white") + + device.display(txt.convert(device.mode)) + + +def logo(device, msg): + img_path = os.path.abspath(os.path.join(os.path.dirname(__file__), + 'img', 'helios4_logo.png')) + logo = Image.open(img_path).convert("RGBA") + + background = Image.new("RGBA", device.size) + background.paste(logo, (0, 0)) + + txt = Image.new('RGBA', device.size) + d = ImageDraw.Draw(txt) + d.text((0,52), msg, font=font, fill="white") + + out = Image.alpha_composite(background, txt) + device.display(out.convert(device.mode)) + +def sigterm_handler(): + sys.exit(0) + +signal.signal(signal.SIGTERM, sigterm_handler) + + +def main(): + if 'HELIOS4_STARTING' in os.environ: + logo(device, "System Starting...") + device.persist = True + time.sleep(6) + else: + while True: + status(device) + time.sleep(interval) + logo(device, host_time()) + time.sleep(interval) + +if __name__ == "__main__": + try: + device = get_device() + main() + except KeyboardInterrupt: + pass diff --git a/systemd/sys_oled_start.service b/systemd/sys_oled_start.service new file mode 100644 index 0000000..36f4f60 --- /dev/null +++ b/systemd/sys_oled_start.service @@ -0,0 +1,9 @@ +[Unit] +Description=System Starting on OLED Display + +[Service] +Environment="SYSTEM_STARTING=1" +ExecStart=/usr/bin/python /usr/local/bin/sys_oled.py --display sh1106 + +[Install] +WantedBy=sysinit.target diff --git a/systemd/sys_oled_status.service b/systemd/sys_oled_status.service new file mode 100644 index 0000000..dcafe3c --- /dev/null +++ b/systemd/sys_oled_status.service @@ -0,0 +1,9 @@ +[Unit] +Description=System Status on OLED Display +After=sys_oled_start.service + +[Service] +ExecStart=/usr/bin/python /usr/local/bin/sys_oled.py --display sh1106 + +[Install] +WantedBy=multi-user.target