From 6605d2837765ada764c5061122662148c5017471 Mon Sep 17 00:00:00 2001 From: Reid 'arrdem' McKenzie Date: Sun, 5 Dec 2021 11:35:09 -0700 Subject: [PATCH] A quick and dirty octoprint CURSES dashboard --- projects/octodash/BUILD | 9 +++ projects/octodash/__main__.py | 102 ++++++++++++++++++++++++++++++++++ tools/python/requirements.txt | 3 + 3 files changed, 114 insertions(+) create mode 100644 projects/octodash/BUILD create mode 100644 projects/octodash/__main__.py diff --git a/projects/octodash/BUILD b/projects/octodash/BUILD new file mode 100644 index 0000000..4e71cdb --- /dev/null +++ b/projects/octodash/BUILD @@ -0,0 +1,9 @@ +zapp_binary( + name = "octodash", + shebang = "/usr/bin/env /usr/bin/python3", + main = "__main__.py", + deps = [ + py_requirement("colored"), + py_requirement("octorest"), + ], +) diff --git a/projects/octodash/__main__.py b/projects/octodash/__main__.py new file mode 100644 index 0000000..0ba4694 --- /dev/null +++ b/projects/octodash/__main__.py @@ -0,0 +1,102 @@ +"""A quick and dirty octoprint status screen""" + +from configparser import ConfigParser +import curses +import os +from time import sleep +import signal + +from colored import fg, bg, attr +from octorest.client import OctoRest + + +def draw(screen, client): + """Poll the client for a status, draw it to the screen.""" + + # Screen details + rows, cols = screen.getmaxyx() + + # Poll the API + job = client.job_info() + # >>> client.job_info() + # {'job': {'averagePrintTime': 7965.021392323004, + # 'estimatedPrintTime': 6132.310772608108, + # 'filament': {'tool0': {'length': 8504.781600002587, + # 'volume': 20.456397036761484}}, + # 'file': {'date': 1638666604, + # 'display': 'v2-sides.gcode', + # 'name': 'v2-sides.gcode', + # 'origin': 'local', + # 'path': 'v2-sides.gcode', + # 'size': 1074906}, + # 'lastPrintTime': 7965.021392323004, + # 'user': '_api'}, + # 'progress': {'completion': 100.0, + # 'filepos': 1074906, + # 'printTime': 7965, + # 'printTimeLeft': 0, + # 'printTimeLeftOrigin': None}, + # 'state': 'Operational'} + printer = client.printer() + # >>> client.printer() + # {'sd': {'ready': False}, + # 'state': {'error': '', + # 'flags': {'cancelling': False, + # 'closedOrError': False, + # 'error': False, + # 'finishing': False, + # 'operational': True, + # 'paused': False, + # 'pausing': False, + # 'printing': False, + # 'ready': True, + # 'resuming': False, + # 'sdReady': False}, + # 'text': 'Operational'}, + # 'temperature': {'bed': {'actual': 23.05, 'offset': 0, 'target': 0.0}, + # 'tool0': {'actual': 23.71, 'offset': 0, 'target': 0.0}}} + + # Draw a screen + + flags = printer["state"]["flags"] + ready = not flags["error"] and flags["operational"] and flags["ready"] + printing = flags["printing"] + + file = job["job"]["file"] + progress = job["progress"] + completion = progress["completion"] / 100.0 + time_remaining = progress["printTimeLeft"] + + progress_cols = int(cols * completion) + progress_line = ("#" * progress_cols) + ("-" * (cols - progress_cols)) + + screen.addstr(0, 0, f"Ready: {ready}") + if printing: + screen.addstr(2, 0, f"Printing: {file['name']}") + screen.addstr(3, 0, f"Remaining print time: {time_remaining}") + + screen.addstr(5, 0, progress_line) + +if __name__ == "__main__": + config = ConfigParser() + config.read(os.path.expanduser("~/.config/octoprint-cli.ini")) + + client = OctoRest(url="http://" + config["server"]["ServerAddress"], + apikey=config["server"]["ApiKey"]) + + screen = curses.initscr() + + # Remap a SIGTERM to a kbd int so a clean shutdown is easy + def kbdint(*args): + raise KeyboardInterrupt() + + signal.signal(signal.SIGTERM, kbdint) + + while True: + try: + screen.clear() + draw(screen, client) + screen.refresh() + sleep(1) + except KeyboardInterrupt: + break diff --git a/tools/python/requirements.txt b/tools/python/requirements.txt index e34aa63..602f647 100644 --- a/tools/python/requirements.txt +++ b/tools/python/requirements.txt @@ -10,6 +10,7 @@ bleach==4.0.0 certifi==2020.12.5 chardet==4.0.0 click==8.0.3 +colored==1.4.3 commonmark==0.9.1 coverage==5.5 docutils==0.17 @@ -41,6 +42,7 @@ mirakuru==2.4.1 mistune==0.8.4 multidict==5.1.0 mypy-extensions==0.4.3 +octorest==0.4 openapi-schema-validator==0.1.5 openapi-spec-validator==0.3.0 packaging==20.9 @@ -103,6 +105,7 @@ urllib3==1.26.4 urwid==2.1.2 wcwidth==0.2.5 webencodings==0.5.1 +websocket-client==1.2.1 Werkzeug==2.0.1 wheel==0.36.2 yamllint==1.26.1