diff --git a/ChangeLog b/ChangeLog index 34252504..afbefce8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,7 @@ - Add support to be running behind the proxy * Hold the STOPPED and FINISHED state for at least 11s * Fix MK2(.5)S SN being broken on multi-instance images + * Implemented UPGRADE high lvl Connect command 0.7.0 (2023-05-19) * Fixed printer sends info about api key change to Connect after change diff --git a/prusa/link/printer_adapter/command_handlers.py b/prusa/link/printer_adapter/command_handlers.py index 77fb4a8c..697b5d29 100644 --- a/prusa/link/printer_adapter/command_handlers.py +++ b/prusa/link/printer_adapter/command_handlers.py @@ -8,6 +8,8 @@ import logging from pathlib import Path from re import Match +from subprocess import STDOUT, CalledProcessError, check_call, check_output +from sys import executable from threading import Event from time import time from typing import Dict, Optional, Set @@ -447,6 +449,32 @@ def waiter(sender, match): "or our serial reading component broke..") +class UpgradeLink(Command): + """Class for upgrading PrusaLink""" + command_name = "upgrade_link" + + def _run_command(self): + try: + output = \ + check_output( + [executable, '-m', 'pip', 'install', '-U', + '--upgrade-strategy', 'only-if-needed', 'prusalink'], + stderr=STDOUT).decode() + + # No update available + if "Installing collected packages" not in output: + raise CommandFailed("No update available") + + # New version was installed correctly - restart PrusaLink + check_call([executable, '-m', 'prusalink', 'restart']) + log.info("PrusaLink upgraded successfully") + + # There's a problem with package installation, or it does not exist + except CalledProcessError as exception: + raise CommandFailed("There's a problem with package installation, " + "or it does not exist") from exception + + class JobInfo(Command): """Class for sending/getting the job info""" command_name = "job_info" diff --git a/prusa/link/printer_adapter/prusa_link.py b/prusa/link/printer_adapter/prusa_link.py index 546fe549..1a35557b 100644 --- a/prusa/link/printer_adapter/prusa_link.py +++ b/prusa/link/printer_adapter/prusa_link.py @@ -59,6 +59,7 @@ StartPrint, StopPrint, UnloadFilament, + UpgradeLink, ) from .command_queue import CommandQueue, CommandResult from .file_printer import FilePrinter @@ -160,6 +161,7 @@ def __init__(self, cfg: Config, settings: Settings) -> None: self.printer.set_handler(CommandType.GCODE, self.execute_gcode) self.printer.set_handler(CommandType.PAUSE_PRINT, self.pause_print) self.printer.set_handler(CommandType.RESET_PRINTER, self.reset_printer) + self.printer.set_handler(CommandType.UPGRADE, self.upgrade_link) self.printer.set_handler(CommandType.RESUME_PRINT, self.resume_print) self.printer.set_handler(CommandType.START_PRINT, self.start_print) self.printer.set_handler(CommandType.STOP_PRINT, self.stop_print) @@ -504,6 +506,13 @@ def reset_printer(self, caller: SDKCommand) -> CommandResult: command = ResetPrinter(command_id=caller.command_id) return self.command_queue.force_command(command) + def upgrade_link(self, caller: SDKCommand) -> CommandResult: + """ + Connects the command to upgrade link from CONNECT with its handler + """ + command = UpgradeLink(command_id=caller.command_id) + return self.command_queue.do_command(command) + def job_info(self, caller: SDKCommand) -> CommandResult: """ Connects the command to send job info from CONNECT with its handler diff --git a/prusa/link/web/main.py b/prusa/link/web/main.py index 85800ef5..44f9f692 100644 --- a/prusa/link/web/main.py +++ b/prusa/link/web/main.py @@ -1,10 +1,9 @@ """Main pages and core API""" import logging -import subprocess from os import listdir from os.path import basename, getmtime, getsize, join from socket import gethostname -from subprocess import CalledProcessError, check_output +from subprocess import STDOUT, CalledProcessError, check_output from sys import executable, version from gcode_metadata import get_metadata @@ -635,7 +634,7 @@ def api_update(req, env): try: output = check_output( [executable, '-m', 'pip', 'install', '--no-deps', '--dry-run', - '-U', 'prusalink'], stderr=subprocess.STDOUT).decode() + '-U', 'prusalink'], stderr=STDOUT).decode() # There's a problem with package installation, or it does not exist except CalledProcessError as exception: raise conditions.UnavailableUpdate(exception.output.decode()) \ @@ -670,7 +669,7 @@ def api_update_post(req, env): check_output( [executable, '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'prusalink'], - stderr=subprocess.STDOUT).decode() + stderr=STDOUT).decode() # No update available if "Installing collected packages" not in output: