Initial commit

This commit is contained in:
sqozz 2024-12-02 00:33:49 +01:00
commit 48f447bcbd
10 changed files with 237 additions and 0 deletions

23
config.example.yaml Normal file
View file

@ -0,0 +1,23 @@
vuserver:
api:
url: "http://localhost:5340"
password: "my_super_secret_password"
assets: "/home/user/Downloads/image_pack"
dials:
"0123456789ABCDEFGHIJKLMN":
aliases:
- "my_dial"
"RIBAILOFEE2CHOONGUVAHCAE":
aliases:
- "outside"
"ING6AHXOO3REI2WILAH8RAEW":
aliases:
- "inside"
config_sets:
"notebook":
"GPULoad": "my_dial"
"CPULoad": "inside"
"MEMUsage": "outside"

19
dial_configs/CPULoad.py Normal file
View file

@ -0,0 +1,19 @@
from dial_configs.dial_config import DialConfig
class CPULoad(DialConfig):
def __init__(self, target_dial, asset_path):
super().__init__(target_dial, asset_path, "cpu-load.png")
def transform_color(self, value):
return super().Colors.get_threshold_color(self, value)
def transform_value(self, json_data):
v = int(json_data.get("fields", {}).get("usage_idle", 0))
value = 100 - v
return value
def __eq__(self, other):
try:
return (other.get("name", "") == "cpu" and other.get("tages", {}).get("host", "") != "gameloader")
except Exception:
return False

14
dial_configs/GPULoad.py Normal file
View file

@ -0,0 +1,14 @@
from dial_configs.dial_config import DialConfig
class GPULoad(DialConfig):
def __init__(self, target_dial, asset_path):
super().__init__(target_dial, asset_path, "gpu-load.png")
def transform_color(self, value):
return super().Colors.get_threshold_color(self, value)
def __eq__(self, other):
try:
return (other.get("name", "") == "gpu_busy_percent")
except Exception:
return False

View file

@ -0,0 +1,25 @@
from dial_configs.dial_config import DialConfig
from vu1 import RGBColor
class GameloaderGamescopeFPS(DialConfig):
def __init__(self, target_dial, asset_path):
super().__init__(target_dial, asset_path, "fps.png")
def transform_color(self, value):
if fps < 60:
color = RGBColor(1.0, 0, 0)
else:
color = super().Colors.get_gradient_color(self, value, 30, 0)
return color
def transform_value(self, json_data):
FPS_MAX = 120
fps = float(json_data.get("fields", {}).get("fps", 0))
value = int((fps/FPS_MAX)*100)
return value
def __eq__(self, other):
try:
return (other.get("name", "") == "gamescope" and "fps" in other.get("fields", {}).keys() and other.get("tags", {}).get("host", "") == "gameloader")
except Exception:
return False

View file

@ -0,0 +1,14 @@
from dial_configs.dial_config import DialConfig
class LastKnownDiskUsedPercent(DialConfig):
def __init__(self, target_dial, asset_path):
super().__init__(target_dial, asset_path, "disk-usage.png")
def transform_color(self, value):
return super().Colors.get_threshold_color(self, value)
def __eq__(self, other):
try:
return (other.get("name", "") == "last_known_disk_used_percent" and other.get("fields", {}).get("path", "") == "/media") and other.get("fields", {}).get("from_host", "") == "companioncube"
except Exception:
return False

17
dial_configs/MEMUsage.py Normal file
View file

@ -0,0 +1,17 @@
from dial_configs.dial_config import DialConfig
class MEMUsage(DialConfig):
def __init__(self, target_dial, asset_path):
super().__init__(target_dial, asset_path, "mem.png")
def transform_color(self, value):
return super().Colors.get_gradient_color(self, value, 30, 0)
def transform_value(self, json_data):
return int(json_data.get("fields", {}).get("used_percent", 100))
def __eq__(self, other):
try:
return (other.get("name", "") == "mem")
except Exception:
return False

View file

@ -0,0 +1,23 @@
from dial_configs.dial_config import DialConfig
import functools
class ThinkPadFan(DialConfig):
def __init__(self, target_dial, asset_path):
super().__init__(target_dial, asset_path, "fan-speed.png")
self.other_fans = {}
def transform_color(self, value):
return super().Colors.get_threshold_color(self, value)
def transform_value(self, json_data):
FAN_MAX = 3500
self.other_fans[json_data["tags"]["feature"]] = json_data.get("fields", {}).get("input", FAN_MAX)
avg_rpm = functools.reduce(lambda x,y: x+y, self.other_fans.values()) / len(self.other_fans.values())
value = int((avg_rpm/FAN_MAX)*100)
return value
def __eq__(self, other):
try:
return (other.get("name", "") == "sensors" and "fan" in other.get("tags", {}).get("feature", []))
except Exception:
return False

4
dial_configs/__init__.py Normal file
View file

@ -0,0 +1,4 @@
from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py') and not f.endswith('dial_config.py')]

View file

@ -0,0 +1,37 @@
from vu1 import RGBColor,HSVColor
from os.path import join as pathjoin
class DialConfig(object):
def __init__(self, target_dial, asset_path, bg_filename):
self.dial = target_dial
self.asset_path = asset_path
self.bg_filename = bg_filename
def __eq__(self, other):
pass
@property
def background_image(self):
return pathjoin(self.asset_path, self.bg_filename)
def transform_value(self, json_data):
return json_data.get("fields", {}).get("value", 0)
def transform_color(self, value):
return self.Colors.get_gradient_color(self, value)
class Colors(object):
def get_threshold_color(self, value):
if value >= 0 and value <= 50:
return RGBColor(1.0, 1.0, 1.0)
if value > 50 and value < 75:
return RGBColor(0, 1.0, 0)
elif value > 75 and value < 90:
return RGBColor(1.0, 1.0, 0)
elif value >= 90:
return RGBColor(1.0, 0, 0)
def get_gradient_color(self, value, min_hue=0, max_hue=132):
hue = min_hue + (((max_hue-min_hue)/100)*value)
hue_float = (1/360)*hue
return HSVColor(hue=hue_float, saturation=1, value=1)

61
main.py Executable file
View file

@ -0,0 +1,61 @@
#!/usr/bin/env python3
import vu1
import sys
import pdb
import json
import yaml
import requests
import argparse
from dial_configs import *
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--config')
args = parser.parse_args()
def get_config(config_file_path="config.yaml"):
config = {}
with open(config_file_path, "r") as fd:
config = yaml.safe_load(fd.read())
return config
def find_dial(config, id_or_alias):
dials = config.get("dials", {})
if id_or_alias in dials:
return id_or_alias
else:
for k, dial in dials.items():
if id_or_alias in dial.get("aliases", []):
return k
return None
config = get_config(args.config)
print(config, flush=True)
api_config = config.get("vuserver", {}).get("api", {})
API = vu1.DialServer(api_config.get("url", "http://localhost:5340"), api_config.get("password", ""))
# generate objects with according dial objects based on user config
config_set = []
for metric, dial in config.get("config_sets", {}).get("notebook", []).items():
d = API.dials[API.dials.index(find_dial(config, dial))]
m = getattr(eval(metric), metric)(d, config.get("assets", "./assets")) # build instance of a matching dial_config class
config_set.append(m)
for line in sys.stdin:
metric = json.loads(line)
fields = metric.get("fields", {})
if metric in config_set:
dial_config = config_set[config_set.index(metric)]
#print("config for {metric_name} matched {conf}".format(metric_name=metric.get("name", "<noname>"), conf=type(dial_config)), flush=True)
value = dial_config.transform_value(metric)
image = dial_config.background_image
color = dial_config.transform_color(value)
dial = dial_config.dial
try:
dial.image = image
dial.value = value
dial.color = color
except Exception:
pass
continue