From 63faeb37349a8fb48c1e0108dd5bfacbdc591018 Mon Sep 17 00:00:00 2001 From: gryf Date: Sun, 1 May 2022 15:11:02 +0200 Subject: [PATCH] Add almost working dockapp. --- pywmtemp.py | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100755 pywmtemp.py diff --git a/pywmtemp.py b/pywmtemp.py new file mode 100755 index 0000000..e465b99 --- /dev/null +++ b/pywmtemp.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python +""" +Simple dockapp +""" +import argparse +import os +import re +import sys +import time + +import wmdocklib +from wmdocklib import helpers +from wmdocklib import pywmgeneral +import yaml + + +XDG_CONF_DIR = os.getenv('XDG_CONFIG_HOME', os.path.expanduser('~/.config')) +# expected bitmap contained font should be found in the same location as main +# program +FONT = '''\ +/* XPM */ +static char *_x8_lcd[] = { +/* columns rows colors chars-per-pixel */ +"192 48 10 1 ", +" c #202020", +". c #440000", +"X c #542A00", +"o c #004941", +"O c #007D71", +"+ c #920000", +"@ c #E00000", +"# c #A85500", +"$ c #FF8200", +"% c #20B6AE", +/* pixels */ +" ooo oOo %o% %o% o%o OoooO %%o oo% oo% %oo ooo ooo ooo ooo ooo oooO %%% oooO O%%%O O%%%O %ooo% O%%%O O%%%O O%%%O O%%%O O%%%O ooo ooo oo%O ooo O%oo O%%%O ", +"o o o % o o% %o oO Oo oOOO% % % % Oo o Oo o O o o O o % % o O o o o o o o o o % % % o % o % o % % % % o % o o % % % % % o o o o o O o o o o O o % % ", +"o o o % o oO Oo %OOO% % o o Oo oOO o o O o oO o o Oo oO Oo o O o o o o o o o o Oo % % o % o % o % % % % o % o o % % % % % o O o o O o oO o %OOO% o Oo o % ", +" ooo oOo ooo %o% %%% o%o %oo ooo %oo oo% O%%%O O%%%O ooo O%%%O ooo o%o OoooO oooO O%%%O %%%O O%%%O %%%%O O%%%O oooO O%%%O O%%%O ooo ooo Oooo ooo oooO oo%O ", +"o o o % o o o %OOO% o % oO o % O % o o oO o o Oo oO Oo o O o o o o o o o oO o % % o % % o o % o % o % % % o % % % o % o o o o oO o %OOO% o Oo o O o ", +"o o o o o o oO Oo %OOOo % % % Oo o o o O o o O o % % o O o o O o o o o OOo % o % % o % % o o % o % o % % % o % % % o % o O o o O o o O o o o o O o o o ", +" ooo o%o ooo %o% o%o OoooO %%oO ooo oo% %oo ooo ooo o%o ooo o%% Oooo %%% oooO O%%%O O%%%O oooO O%%%O O%%%O ooo% O%%%O O%%%O ooo o%o oo%O ooo O%oo o%o ", +" O O ", +" %%% %%% O%%% %%% O%%% O%%%O O%%%O %%%O OoooO oOo O%%%O OoooO Oooo %O% O%%% %%% O%%% %%% O%%% %%% O%O%O OoooO OoooO OoooO OoooO OoooO O%%%O O%%o o%o o%%O o%o ooo ", +"% % % % % % % o % % % o % o % o % % o % o o % % % % o % % % % % % % % % % % % % % O o % o % % % % % % % % % % o % % o o% %o o % oO Oo o o ", +"% OO% % % % % % o % % % o % o % o % % o % o o % % % % o % % % % % % % % % % % % % % o o % o % % % % % % O% %O %O O% o %O % o o % o o % % % o o ", +"Oo%oO O%%%O O%%% Oooo OoooO O%%%O O%%% Ooo%% O%%%O oOo oooO O%%% Oooo OoOoO OoooO OoooO O%%% OoooO O%%% %%% oOo OoooO OoooO OoOoO o%%%o o%o%o o%o Oooo ooo oooO ooo ooo ", +"% OO% % % % % % o % % % o % o % % % % o % o o % % % % o % % % % % % % % o % % % % % o % o % o % % % % % % % O% %O o % o O% o % o o o o % o o o o ", +"% % % % % % o % % % o % o % % % % o % o % % % % % o % % % % % % % % o % %% % % O % o % o % % O% %O % % % % % o % o % o % o o o o % o o o o ", +" %%% OoooO O%%% %%% O%%% O%%%O Oooo %%% OoooO oOo %%% OoooO O%%%O Oo oO OoooO %%% Oooo %%%O OoooO %%% o%o %%% O%O O%O%O OoooO oOo O%%%O O%%o ooo o%%O ooo ooo ", +" ", +" XXX X#X $X$ $X$ X$X #XXX# $$X XX$ XX$ $XX XXX XXX XXX XXX XXX XXX# $$$ XXX# #$$$# #$$$# $XXX$ #$$$# #$$$# #$$$# #$$$# #$$$# XXX XXX XX$# XXX #$XX #$$$# ", +"X X X $ X X$ $X X# #X X###$ $ $ $ #X X #X X # X X # X $ $ X # X X X X X X X X $ $ $ X $ X $ X $ $ $ $ X $ X X $ $ $ $ $ X X X X X # X X X X # X $ $ ", +"X X X $ X X# #X $###$ $ X X #X X## X X # X X# X X #X X# #X X # X X X X X X X X #X $ $ X $ X $ X $ $ $ $ X $ X X $ $ $ $ $ X # X X # X X# X $###$ X #X X $ ", +" XXX X#X XXX $X$ $$$ X$X $XX XXX $XX XX$ #$$$# #$$$# XXX #$$$# XXX X$X #XXX# XXX# #$$$# $$$# #$$$# $$$$# #$$$# XXX# #$$$# #$$$# XXX XXX #XXX XXX XXX# XX$# ", +"X X X $ X X X $###$ X $ X# X $ # $ X X X# X X #X X# #X X # X X X X X X X X# X $ $ X $ $ X X $ X $ X $ $ $ X $ $ $ X $ X X X X X# X $###$ X #X X # X ", +"X X X X X X X# #X $###X $ $ $ #X X X X # X X # X $ $ X # X X # X X X X ##X $ X $ $ X $ $ X X $ X $ X $ $ $ X $ $ $ X $ X # X X # X X # X X X X # X X X ", +" XXX X$X XXX $X$ X$X #XXX# $$X# XXX XX$ $XX XXX XXX X$X XXX X$$ #XXX $$$ XXX# #$$$# #$$$# XXX# #$$$# #$$$# XXX$ #$$$# #$$$# XXX X$X XX$# XXX #$XX X$X ", +" # # ", +" $$$ $$$ #$$$ $$$ #$$$ #$$$# #$$$# $$$# #XXX# X#X #$$$# #XXX# #XXX $#$ #$$$ $$$ #$$$ $$$ #$$$ $$$ #$#$# #XXX# #XXX# #XXX# #XXX# #XXX# #$$$# #$$X X$X X$$# X$X XXX ", +"$ $ $ $ $ $ $ X $ $ $ X $ X $ X $ $ X $ X X $ $ $ $ X $ $ $ $ $ $ $ $ $ $ $ $ $ $ # X $ X $ $ $ $ $ $ $ $ $ $ X $ $ X X$ $X X $ X# #X X X ", +"$ ##$ $ $ $ $ $ X $ $ $ X $ X $ X $ $ X $ X X $ $ $ $ X $ $ $ $ $ $ $ $ $ $ $ $ $ $ X X $ X $ $ $ $ $ $ #$ $# $# #$ X $# $ X X $ X X $ $ $ X X ", +"#X$X# #$$$# #$$$ #XXX #XXX# #$$$# #$$$ #XX$$ #$$$# X#X XXX# #$$$ #XXX #X#X# #XXX# #XXX# #$$$ #XXX# #$$$ $$$ X#X #XXX# #XXX# #X#X# X$$$X X$X$X X$X #XXX XXX XXX# XXX XXX ", +"$ ##$ $ $ $ $ $ X $ $ $ X $ X $ $ $ $ X $ X X $ $ $ $ X $ $ $ $ $ $ $ $ X $ $ $ $ $ X $ X $ X $ $ $ $ $ $ $ #$ $# X $ X #$ X $ X X X X $ X X X X ", +"$ $ $ $ $ $ X $ $ $ X $ X $ $ $ $ X $ X $ $ $ $ $ X $ $ $ $ $ $ $ $ X $ $$ $ $ # $ X $ X $ $ #$ $# $ $ $ $ $ X $ X $ X $ X X X X $ X X X X ", +" $$$ #XXX# #$$$ $$$ #$$$ #$$$# #XXX $$$ #XXX# X#X $$$ #XXX# #$$$# #X X# #XXX# $$$ #XXX $$$# #XXX# $$$ X$X $$$ #$# #$#$# #XXX# X#X #$$$# #$$X XXX X$$# XXX XXX ", +" ", +" ... .+. @.@ @.@ .@. +...+ @@. ..@ ..@ @.. ... ... ... ... ... ...+ @@@ ...+ +@@@+ +@@@+ @...@ +@@@+ +@@@+ +@@@+ +@@@+ +@@@+ ... ... ..@+ ... +@.. +@@@+ ", +". . . @ . .@ @. .+ +. .+++@ @ @ @ +. . +. . + . . + . @ @ . + . . . . . . . . @ @ @ . @ . @ . @ @ @ @ . @ . . @ @ @ @ @ . . . . . + . . . . + . @ @ ", +". . . @ . .+ +. @+++@ @ . . +. .++ . . + . .+ . . +. .+ +. . + . . . . . . . . +. @ @ . @ . @ . @ @ @ @ . @ . . @ @ @ @ @ . + . . + . .+ . @+++@ . +. . @ ", +" ... .+. ... @.@ @@@ .@. @.. ... @.. ..@ +@@@+ +@@@+ ... +@@@+ ... .@. +...+ ...+ +@@@+ @@@+ +@@@+ @@@@+ +@@@+ ...+ +@@@+ +@@@+ ... ... +... ... ...+ ..@+ ", +". . . @ . . . @+++@ . @ .+ . @ + @ . . .+ . . +. .+ +. . + . . . . . . . .+ . @ @ . @ @ . . @ . @ . @ @ @ . @ @ @ . @ . . . . .+ . @+++@ . +. . + . ", +". . . . . . .+ +. @+++. @ @ @ +. . . . + . . + . @ @ . + . . + . . . . ++. @ . @ @ . @ @ . . @ . @ . @ @ @ . @ @ @ . @ . + . . + . . + . . . . + . . . ", +" ... .@. ... @.@ .@. +...+ @@.+ ... ..@ @.. ... ... .@. ... .@@ +... @@@ ...+ +@@@+ +@@@+ ...+ +@@@+ +@@@+ ...@ +@@@+ +@@@+ ... .@. ..@+ ... +@.. .@. ", +" + + ", +" @@@ @@@ +@@@ @@@ +@@@ +@@@+ +@@@+ @@@+ +...+ .+. +@@@+ +...+ +... @+@ +@@@ @@@ +@@@ @@@ +@@@ @@@ +@+@+ +...+ +...+ +...+ +...+ +...+ +@@@+ +@@. .@. .@@+ .@. ... ", +"@ @ @ @ @ @ @ . @ @ @ . @ . @ . @ @ . @ . . @ @ @ @ . @ @ @ @ @ @ @ @ @ @ @ @ @ @ + . @ . @ @ @ @ @ @ @ @ @ @ . @ @ . .@ @. . @ .+ +. . . ", +"@ ++@ @ @ @ @ @ . @ @ @ . @ . @ . @ @ . @ . . @ @ @ @ . @ @ @ @ @ @ @ @ @ @ @ @ @ @ . . @ . @ @ @ @ @ @ +@ @+ @+ +@ . @+ @ . . @ . . @ @ @ . . ", +"+.@.+ +@@@+ +@@@ +... +...+ +@@@+ +@@@ +..@@ +@@@+ .+. ...+ +@@@ +... +.+.+ +...+ +...+ +@@@ +...+ +@@@ @@@ .+. +...+ +...+ +.+.+ .@@@. .@.@. .@. +... ... ...+ ... ... ", +"@ ++@ @ @ @ @ @ . @ @ @ . @ . @ @ @ @ . @ . . @ @ @ @ . @ @ @ @ @ @ @ @ . @ @ @ @ @ . @ . @ . @ @ @ @ @ @ @ +@ @+ . @ . +@ . @ . . . . @ . . . . ", +"@ @ @ @ @ @ . @ @ @ . @ . @ @ @ @ . @ . @ @ @ @ @ . @ @ @ @ @ @ @ @ . @ @@ @ @ + @ . @ . @ @ +@ @+ @ @ @ @ @ . @ . @ . @ . . . . @ . . . . ", +" @@@ +...+ +@@@ @@@ +@@@ +@@@+ +... @@@ +...+ .+. @@@ +...+ +@@@+ +. .+ +...+ @@@ +... @@@+ +...+ @@@ .@. @@@ +@+ +@+@+ +...+ .+. +@@@+ +@@. ... .@@+ ... ... ", +" +++++ " +}; +''' + + +class SensorDockApp(wmdocklib.DockApp): + """ + Discover and display values for defined in config temperatures or other + readings using information found on /sys file system. + """ + background_color = '#202020' + x_offset = 4 + y_offset = 3 + font_dimentions = (6, 8) + + def __init__(self, args=None): + super().__init__(args) + self.font = FONT + self.max_chars_in_line = None + self.conf = {} + self.critical = 0 + self.warning = 0 + + self._read_config() + self._find_sys_files() + + def _read_config(self): + conf = os.path.join(XDG_CONF_DIR, 'pywmtemp.yaml') + if self.args.config: + conf = self.args.config + + with open(conf) as fobj: + self.conf = yaml.safe_load(fobj) + + def _find_sys_files(self): + for root, dirs, files in os.walk('/sys/devices'): + for fname in files: + match = re.match(r'^temp(?P\d)_label', fname) + if not match: + continue + with open(os.path.join(root, fname)) as fobj: + sys_label = fobj.read().strip() + for item in self.conf['readings']: + if item.get('find_sys_label') == sys_label: + item['fname'] = os.path.join(root, + f'temp{match["n"]}_' + f'input') + + def run(self): + self.prepare_pixmaps() + self.max_chars_in_line = int((self.width - 2 * self.x_offset) / + self.char_width) + self.max_rows = int((self.height - 2 * self.x_offset) / + self.char_height) + self.open_xwindow() + + if len(self.conf['readings']) > self.max_rows: + print("Too many lines to fit into dockapp.") + return + + append = True + while self.max_rows - len(self.conf['readings']) > 0: + if append: + self.conf['readings'].append({'empty': 'empty'}) + else: + self.conf['readings'].insert(0, {'empty': 'empty'}) + append = not append + + try: + self.main_loop() + except KeyboardInterrupt: + pass + + def main_loop(self): + + while True: + self.check_for_events() + position = 1 + for item in self.conf['readings']: + self.add_string(self.get_reading(item), 1, position) + position += self.char_height + while position < self.max_rows * self.char_height: + self.add_string(' ' * self.max_chars_in_line, 1, position) + position += self.char_height + pywmgeneral.put_pixel(32, 32, int('ffff88', 16)) + pywmgeneral.put_pixel(33, 33, int('ffff88', 16)) + pywmgeneral.put_pixel(32, 33, int('ffff88', 16)) + pywmgeneral.put_pixel(33, 32, int('ffff88', 16)) + self.redraw() + time.sleep(0.5) + + def get_reading(self, item): + if 'fname' not in item: + return ' ' * self.max_chars_in_line + + with open(item['fname']) as fobj: + value = fobj.read().strip() + + if item.get('divide'): + value = int(int(value)/int(item['divide'])) + label = item['label'] + if len(f"{label}{value}{item['unit']}") > self.max_chars_in_line: + return 'ERRTOOLNG' + + while len(f"{label}{value}{item['unit']}") != self.max_chars_in_line: + label += ' ' + + # shift charset depending on the threshold defined in config, assuming + # charset is the same row(s) copied with different color for warning + # and critival. + # FIXME: remove hardcoded multiplies in favor of automatically + # computed factors. + displacement = 0 + if item.get('override_warning'): + if value >= item['override_warning']: + displacement = int(self.charset_width / self.char_width) * 2 + if item.get('override_critical'): + if value >= item['override_critical']: + displacement = int(self.charset_width / self.char_width) * 4 + + string = f"{label}{value}{item['unit']}".replace('°', '\\').upper() + if displacement: + string = ''.join([chr(ord(i) + displacement) for i in string]) + + return string + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-c', '--config', help='Alternate config file') + args = parser.parse_args() + + dockapp = SensorDockApp(args) + dockapp.run() + + +if __name__ == '__main__': + main()