Created
October 1, 2022 07:04
-
-
Save knockshore/a1e41bf5539666020303f7d49cf77cbc to your computer and use it in GitHub Desktop.
pikvm
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 python3 | |
# ========================================================================== # | |
# # | |
# KVMD-OLED - Small OLED daemon for Pi-KVM. # | |
# # | |
# Copyright (C) 2018 Maxim Devaev <[email protected]> # | |
# # | |
# This program is free software: you can redistribute it and/or modify # | |
# it under the terms of the GNU General Public License as published by # | |
# the Free Software Foundation, either version 3 of the License, or # | |
# (at your option) any later version. # | |
# # | |
# This program is distributed in the hope that it will be useful, # | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
# GNU General Public License for more details. # | |
# # | |
# You should have received a copy of the GNU General Public License # | |
# along with this program. If not, see <https://www.gnu.org/licenses/>. # | |
# # | |
# ========================================================================== # | |
# Replaces /usr/bin/kvmd-oled | |
# Place 'i2c-dev' at the end of /etc/modules-load.d/kvmd.conf | |
# Place 'dtparam=i2c_arm=on' at the end of /boot/config.txt | |
# Run 'systemctl enable --now kvmd-oled' | |
# Reboot | |
import sys | |
import socket | |
import logging | |
import datetime | |
import time | |
import os | |
from typing import Tuple | |
import netifaces | |
import psutil | |
from luma.core import cmdline | |
from luma.core.render import canvas | |
from PIL import ImageFont | |
# ===== | |
_logger = logging.getLogger("oled") | |
# ===== | |
def _get_ip() -> Tuple[str, str]: | |
try: | |
gws = netifaces.gateways() | |
if "default" not in gws: | |
raise RuntimeError(f"No default gateway: {gws}") | |
iface = "" | |
for proto in [socket.AF_INET, socket.AF_INET6]: | |
if proto in gws["default"]: | |
iface = gws["default"][proto][1] | |
break | |
else: | |
raise RuntimeError(f"No iface for the gateway {gws['default']}") | |
for addr in netifaces.ifaddresses(iface).get(proto, []): | |
return (iface, addr["addr"]) | |
except Exception: | |
# _logger.exception("Can't get iface/IP") | |
return ("<no-iface>", "<no-ip>") | |
def _get_uptime() -> str: | |
uptime = datetime.timedelta(seconds=int(time.time() - psutil.boot_time())) | |
pl = {"days": uptime.days} | |
(pl["hours"], rem) = divmod(uptime.seconds, 3600) | |
(pl["mins"], pl["secs"]) = divmod(rem, 60) | |
return "{days}d {hours}h {mins}m".format(**pl) | |
# ===== | |
def main() -> None: | |
logging.basicConfig(level=logging.INFO, format="%(message)s") | |
logging.getLogger("PIL").setLevel(logging.ERROR) | |
parser = cmdline.create_parser(description="Display FQDN and IP on the OLED") | |
parser.add_argument("--font", default="/usr/share/fonts/TTF/ProggyTiny.ttf", help="Font path") | |
parser.add_argument("--font-size", default=16, type=int, help="Font size") | |
parser.add_argument("--interval", default=5, type=int, help="Screens interval") | |
options = parser.parse_args(sys.argv[1:]) | |
if options.config: | |
config = cmdline.load_config(options.config) | |
options = parser.parse_args(config + sys.argv[1:]) | |
device = cmdline.create_device(options) | |
font = ImageFont.truetype(options.font, options.font_size) | |
display_types = cmdline.get_display_types() | |
if options.display not in cmdline.get_display_types()["emulator"]: | |
_logger.info("Iface: %s", options.interface) | |
_logger.info("Display: %s", options.display) | |
_logger.info("Size: %dx%d", device.width, device.height) | |
try: | |
with canvas(device) as draw: | |
text = f"=====================\n Welcome to Pi-KVM \n=====================" | |
draw.multiline_text((0, 0), text, font=font, fill="white") | |
time.sleep(options.interval) | |
summary = 0 | |
while True: | |
with canvas(device) as draw: | |
summary = summary % 4 | |
if summary == 0: | |
var = os.popen(" pistat | grep 'CPU temp' | cut -d ' ' -f 3 | cut -d '.' -f 1 ") | |
ctemp = var.read().replace('\n', '') | |
var = os.popen(" pistat | grep 'GPU temp' | cut -d ' ' -f 3 | cut -d '.' -f 1 ") | |
gtemp = var.read().replace('\n', '') | |
text = f"Hostname: {socket.getfqdn()}\n Uptime: {_get_uptime().upper()}\nCPU: {ctemp}'C GPU: {gtemp}'C" | |
elif summary == 1: | |
var = os.popen(" v=$( ip -o a show | grep 'eth0' | grep 'inet ' | cut -d ' ' -f 7 | cut -d '/' -f 1 ); if [[ \"$v\" != \"\" ]]; then printf ' ETH: '$v; count+=1; else echo \'No Ethernet connected\'; fi ") | |
eth = var.read().replace('\n', '') | |
var = os.popen(" v=$( ip -o a show | grep 'wlan0' | grep 'inet ' | cut -d ' ' -f 7 | cut -d '/' -f 1 ); if [[ \"$v\" != \"\" ]]; then printf 'WLAN: '$v; count+=1; else echo \'No Wi-Fi connected\'; fi ") | |
wlan = var.read().replace('\n', '') | |
var = os.popen(" v=$( netctl-auto list | grep '*' | cut -d '-' -f 2 ); if [[ \"$v\" != \"\" ]]; then printf 'SSID: '$v; count+=1; else echo \''; fi ") | |
ssid = var.read().replace('\n', '') | |
text = f"{eth}\n{wlan}\n{ssid}" # Pi 4 | |
#text = f"{wlan}\n{ssid}" # Pi Zero | |
elif summary == 2: | |
time.sleep(options.interval) | |
var = os.popen(" pistat | grep Pi | cut -d ' ' -f 2,3,4,6 ") # Pi 4 | |
#var = os.popen(" pistat | grep Pi | cut -d ' ' -f 2,3,4,5 ") # Pi Zero | |
rpi = var.read().replace('\n', '') | |
var = os.popen(" pacman -Q | grep 'kvmd ' | cut -d '-' -f 1 ") | |
kvmd = var.read().replace('\n', '').upper() | |
var = os.popen(" pacman -Q | grep kvmd-platform | cut -d '-' -f 3 ") | |
plat = var.read().replace('\n', '').upper() | |
var = os.popen(" pacman -Q | grep kvmd-platform | cut -d '-' -f 4 ") | |
hdmi = var.read().replace('\n', '').upper() | |
var = os.popen(" pistat | grep 'Throttled past' | cut -d ' ' -f 3 ") | |
ovht = var.read().replace('\n', '').upper() | |
var = os.popen(" pistat | grep 'Undervoltage past' | cut -d ' ' -f 3 ") | |
undv = var.read().replace('\n', '').upper() | |
text = f"{rpi}\n{kvmd} {plat} {hdmi}\nOVHT: {ovht:<3} UNDV: {undv:<3}" | |
else: | |
var = os.popen(" free -h --si | grep 'Mem' | tr -s ' ' | cut -d ' ' -f 2 ") | |
ramtot = var.read().replace('\n', '') | |
var = os.popen(" free -h --si | grep 'Mem' | tr -s ' ' | cut -d ' ' -f 3 ") | |
ramuse = var.read().replace('\n', '') | |
var = os.popen(" free -h --si | grep 'Mem' | tr -s ' ' | cut -d ' ' -f 4 ") | |
ramfre = var.read().replace('\n', '') | |
var = os.popen(" df -h --total | grep 'total' | tr -s ' ' | cut -d ' ' -f 2 ") | |
hddtot = var.read().replace('\n', '') | |
var = os.popen(" df -h --total | grep 'total' | tr -s ' ' | cut -d ' ' -f 3 ") | |
hdduse = var.read().replace('\n', '') | |
var = os.popen(" df -h --total | grep 'total' | tr -s ' ' | cut -d ' ' -f 4 ") | |
hddfre = var.read().replace('\n', '') | |
text = f" Used Free \n RAM: {ramuse:>6} {ramfre:>6} \n HDD: {hdduse:>6} {hddfre:>6} \n" | |
draw.multiline_text((0, 0), text, font=font, fill="white") | |
summary += 1 | |
time.sleep(options.interval) | |
except (SystemExit, KeyboardInterrupt): | |
pass | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
source: https://pastebin.com/u/sekazi