97 lines
2.6 KiB
Python
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()
|