Controller/tsgrain_controller/io/console.py

97 lines
2.6 KiB
Python

# coding=utf-8
import curses
import logging
import math
from typing import Dict, Optional
from tsgrain_controller import io, util, models
class CursesHandler(logging.Handler):
def __init__(self, screen):
logging.Handler.__init__(self)
self.screen = screen
self.screen.scrollok(True)
self.screen.idlok(True)
self.screen.leaveok(True)
self.screen.refresh()
def emit(self, record):
try:
msg = self.format(record)
screen = self.screen
fs = "\n%s"
screen.addstr(fs % msg)
screen.refresh()
except (KeyboardInterrupt, SystemExit):
raise
except: # pylint: disable=bare-except
self.handleError(record)
class Io(util.StoppableThread, io.Io):
def __init__(self, app: models.AppInterface):
super().__init__(0.01)
self.app = app
self._screen: Optional = None
self._outputs: Dict[str, bool] = {}
def setup(self):
screen = curses.initscr()
curses.noecho()
curses.curs_set(0)
screen.nodelay(True)
max_y, max_x = screen.getmaxyx()
width_half = math.floor(max_x / 2)
self._screen = curses.newwin(max_y, width_half, 0, 0)
win_log = curses.newwin(max_y, width_half, 0, width_half)
formatter_display = logging.Formatter(
'%(asctime)-8s|%(levelname)-5s| %(message)-s', '%H:%M:%S')
mh = CursesHandler(win_log)
mh.setFormatter(formatter_display)
self.app.get_logger().handlers = []
self.app.get_logger().addHandler(mh)
self._screen.nodelay(True)
logging.debug('Window size: max_x=%d, max_y=%d, width_half=%d', max_x,
max_y, width_half)
def write_output(self, key: str, val: bool):
self._outputs[key] = val
def run_cycle(self):
c = self._screen.getch()
def state_str(state: bool) -> str:
if state:
return ''
return ''
# Mode key (0)
if c == 48:
self._trigger_cb('BT_MODE')
# Zone keys (1-7)
elif 49 <= c <= 55:
self._trigger_cb(f'BT_Z_{c - 48}')
self._screen.erase()
self._screen.addstr(0, 0,
'Buttons: 1-7: Manual control, 0: Auto on/off')
i = 1
for key, output in self._outputs.items():
self._screen.addstr(i, 0, f'{key}: {state_str(output)}')
i += 1
def cleanup(self):
curses.echo()
curses.curs_set(1)
curses.endwin()