feat: implement firmware build
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
169
kiauh/components/klipper_firmware/firmware_utils.py
Normal file
169
kiauh/components/klipper_firmware/firmware_utils.py
Normal file
@@ -0,0 +1,169 @@
|
||||
# ======================================================================= #
|
||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||
# #
|
||||
# This file is part of KIAUH - Klipper Installation And Update Helper #
|
||||
# https://github.com/dw-0/kiauh #
|
||||
# #
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||
# ======================================================================= #
|
||||
|
||||
from subprocess import CalledProcessError, check_output, Popen, PIPE, STDOUT, run
|
||||
from typing import List
|
||||
|
||||
from components.klipper import KLIPPER_DIR
|
||||
from components.klipper_firmware import SD_FLASH_SCRIPT
|
||||
from components.klipper_firmware.flash_options import (
|
||||
FlashOptions,
|
||||
FlashMethod,
|
||||
)
|
||||
from utils.logger import Logger
|
||||
from utils.system_utils import log_process
|
||||
|
||||
|
||||
def find_firmware_file(method: FlashMethod) -> bool:
|
||||
target = KLIPPER_DIR.joinpath("out")
|
||||
target_exists = target.exists()
|
||||
if method is FlashMethod.REGULAR:
|
||||
f1 = "klipper.elf.hex"
|
||||
f2 = "klipper.elf"
|
||||
fw_file_exists = target.joinpath(f1).exists() and target.joinpath(f2).exists()
|
||||
elif method is FlashMethod.SD_CARD:
|
||||
fw_file_exists = target.joinpath("klipper.bin").exists()
|
||||
else:
|
||||
raise Exception("Unknown flash method")
|
||||
|
||||
return target_exists and fw_file_exists
|
||||
|
||||
|
||||
def find_usb_device_by_id() -> List[str]:
|
||||
try:
|
||||
command = "find /dev/serial/by-id/* 2>/dev/null"
|
||||
output = check_output(command, shell=True, text=True)
|
||||
return output.splitlines()
|
||||
except CalledProcessError as e:
|
||||
Logger.print_error("Unable to find a USB device!")
|
||||
Logger.print_error(e, prefix=False)
|
||||
return []
|
||||
|
||||
|
||||
def find_uart_device() -> List[str]:
|
||||
try:
|
||||
command = '"find /dev -maxdepth 1 -regextype posix-extended -regex "^\/dev\/tty(AMA0|S0)$" 2>/dev/null"'
|
||||
output = check_output(command, shell=True, text=True)
|
||||
return output.splitlines()
|
||||
except CalledProcessError as e:
|
||||
Logger.print_error("Unable to find a UART device!")
|
||||
Logger.print_error(e, prefix=False)
|
||||
return []
|
||||
|
||||
|
||||
def find_usb_dfu_device() -> List[str]:
|
||||
try:
|
||||
command = '"lsusb | grep "DFU" | cut -d " " -f 6 2>/dev/null"'
|
||||
output = check_output(command, shell=True, text=True)
|
||||
return output.splitlines()
|
||||
except CalledProcessError as e:
|
||||
Logger.print_error("Unable to find a USB DFU device!")
|
||||
Logger.print_error(e, prefix=False)
|
||||
return []
|
||||
|
||||
|
||||
def get_sd_flash_board_list() -> List[str]:
|
||||
if not KLIPPER_DIR.exists() or not SD_FLASH_SCRIPT.exists():
|
||||
return []
|
||||
|
||||
try:
|
||||
cmd = f"{SD_FLASH_SCRIPT} -l"
|
||||
blist = check_output(cmd, shell=True, text=True)
|
||||
return blist.splitlines()[1:]
|
||||
except CalledProcessError as e:
|
||||
Logger.print_error(f"An unexpected error occured:\n{e}")
|
||||
|
||||
|
||||
def start_flash_process(flash_options: FlashOptions) -> None:
|
||||
Logger.print_status(f"Flashing '{flash_options.selected_mcu}' ...")
|
||||
try:
|
||||
if not flash_options.flash_method:
|
||||
raise Exception("Missing value for flash_method!")
|
||||
if not flash_options.flash_command:
|
||||
raise Exception("Missing value for flash_command!")
|
||||
if not flash_options.selected_mcu:
|
||||
raise Exception("Missing value for selected_mcu!")
|
||||
if not flash_options.connection_type:
|
||||
raise Exception("Missing value for connection_type!")
|
||||
if (
|
||||
flash_options.flash_method == FlashMethod.SD_CARD
|
||||
and not flash_options.selected_board
|
||||
):
|
||||
raise Exception("Missing value for selected_board!")
|
||||
|
||||
if flash_options.flash_method is FlashMethod.REGULAR:
|
||||
cmd = [
|
||||
"make",
|
||||
flash_options.flash_command.value,
|
||||
f"FLASH_DEVICE={flash_options.selected_mcu}",
|
||||
]
|
||||
elif flash_options.flash_method is FlashMethod.SD_CARD:
|
||||
if not SD_FLASH_SCRIPT.exists():
|
||||
raise Exception("Unable to find Klippers sdcard flash script!")
|
||||
cmd = [
|
||||
SD_FLASH_SCRIPT,
|
||||
"-b",
|
||||
flash_options.selected_baudrate,
|
||||
flash_options.selected_mcu,
|
||||
flash_options.selected_board,
|
||||
]
|
||||
else:
|
||||
raise Exception("Invalid value for flash_method!")
|
||||
|
||||
process = Popen(cmd, cwd=KLIPPER_DIR, stdout=PIPE, stderr=STDOUT, text=True)
|
||||
log_process(process)
|
||||
|
||||
rc = process.returncode
|
||||
if rc != 0:
|
||||
raise Exception(f"Flashing failed with returncode: {rc}")
|
||||
else:
|
||||
Logger.print_ok("Flashing successfull!", start="\n", end="\n\n")
|
||||
|
||||
except (Exception, CalledProcessError):
|
||||
Logger.print_error("Flashing failed!", start="\n")
|
||||
Logger.print_error("See the console output above!", end="\n\n")
|
||||
|
||||
|
||||
def run_make_clean() -> None:
|
||||
try:
|
||||
run(
|
||||
"make clean",
|
||||
cwd=KLIPPER_DIR,
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
except CalledProcessError as e:
|
||||
Logger.print_error(f"Unexpected error:\n{e}")
|
||||
raise
|
||||
|
||||
|
||||
def run_make_menuconfig() -> None:
|
||||
try:
|
||||
run(
|
||||
"make PYTHON=python3 menuconfig",
|
||||
cwd=KLIPPER_DIR,
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
except CalledProcessError as e:
|
||||
Logger.print_error(f"Unexpected error:\n{e}")
|
||||
raise
|
||||
|
||||
|
||||
def run_make() -> None:
|
||||
try:
|
||||
run(
|
||||
"make PYTHON=python3",
|
||||
cwd=KLIPPER_DIR,
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
except CalledProcessError as e:
|
||||
Logger.print_error(f"Unexpected error:\n{e}")
|
||||
raise
|
||||
111
kiauh/components/klipper_firmware/menus/klipper_build_menu.py
Normal file
111
kiauh/components/klipper_firmware/menus/klipper_build_menu.py
Normal file
@@ -0,0 +1,111 @@
|
||||
# ======================================================================= #
|
||||
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
|
||||
# #
|
||||
# This file is part of KIAUH - Klipper Installation And Update Helper #
|
||||
# https://github.com/dw-0/kiauh #
|
||||
# #
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||
# ======================================================================= #
|
||||
|
||||
import textwrap
|
||||
from typing import Type, Optional
|
||||
|
||||
from components.klipper import KLIPPER_DIR
|
||||
from components.klipper_firmware.firmware_utils import (
|
||||
run_make_clean,
|
||||
run_make_menuconfig,
|
||||
run_make,
|
||||
)
|
||||
from core.menus import Option
|
||||
from core.menus.base_menu import BaseMenu
|
||||
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_GREEN, COLOR_RED
|
||||
from utils.logger import Logger
|
||||
from utils.system_utils import (
|
||||
check_package_install,
|
||||
update_system_package_lists,
|
||||
install_system_packages,
|
||||
)
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class KlipperBuildFirmwareMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
self.deps = ["build-essential", "dpkg-dev", "make"]
|
||||
self.missing_deps = check_package_install(self.deps)
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
from core.menus.advanced_menu import AdvancedMenu
|
||||
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu if previous_menu is not None else AdvancedMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
if len(self.missing_deps) == 0:
|
||||
self.input_label_txt = "Press ENTER to continue"
|
||||
self.default_option = Option(method=self.start_build_process, menu=False)
|
||||
else:
|
||||
self.input_label_txt = "Press ENTER to install dependencies"
|
||||
self.default_option = Option(method=self.install_missing_deps, menu=False)
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = " [ Build Firmware Menu ] "
|
||||
color = COLOR_CYAN
|
||||
count = 62 - len(color) - len(RESET_FORMAT)
|
||||
menu = textwrap.dedent(
|
||||
f"""
|
||||
/=======================================================\\
|
||||
| {color}{header:~^{count}}{RESET_FORMAT} |
|
||||
|-------------------------------------------------------|
|
||||
| The following dependencies are required: |
|
||||
| |
|
||||
"""
|
||||
)[1:]
|
||||
|
||||
for d in self.deps:
|
||||
status_ok = f"{COLOR_GREEN}*INSTALLED*{RESET_FORMAT}"
|
||||
status_missing = f"{COLOR_RED}*MISSING*{RESET_FORMAT}"
|
||||
status = status_missing if d in self.missing_deps else status_ok
|
||||
padding = 39 - len(d) + len(status) + (len(status_ok) - len(status))
|
||||
d = f" {COLOR_CYAN}● {d}{RESET_FORMAT}"
|
||||
menu += f"| {d}{status:>{padding}} |\n"
|
||||
|
||||
menu += "| |\n"
|
||||
if len(self.missing_deps) == 0:
|
||||
line = f"{COLOR_GREEN}All dependencies are met!{RESET_FORMAT}"
|
||||
else:
|
||||
line = f"{COLOR_RED}Dependencies are missing!{RESET_FORMAT}"
|
||||
|
||||
menu += f"| {line:<62} |\n"
|
||||
|
||||
print(menu, end="")
|
||||
|
||||
def install_missing_deps(self, **kwargs) -> None:
|
||||
try:
|
||||
update_system_package_lists(silent=False)
|
||||
Logger.print_status("Installing system packages...")
|
||||
install_system_packages(self.missing_deps)
|
||||
except Exception as e:
|
||||
Logger.print_error(e)
|
||||
Logger.print_error("Installding dependencies failed!")
|
||||
finally:
|
||||
# restart this menu
|
||||
KlipperBuildFirmwareMenu().run()
|
||||
|
||||
def start_build_process(self, **kwargs) -> None:
|
||||
try:
|
||||
run_make_clean()
|
||||
run_make_menuconfig()
|
||||
run_make()
|
||||
|
||||
Logger.print_ok("Firmware successfully built!")
|
||||
Logger.print_ok(f"Firmware file located in '{KLIPPER_DIR}/out'!")
|
||||
|
||||
except Exception as e:
|
||||
Logger.print_error(e)
|
||||
Logger.print_error("Building Klipper Firmware failed!")
|
||||
|
||||
finally:
|
||||
self.previous_menu().run()
|
||||
@@ -7,9 +7,10 @@
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||
# ======================================================================= #
|
||||
import textwrap
|
||||
from typing import Optional, Type
|
||||
|
||||
from components.klipper_firmware.flash_options import FlashOptions, FlashMethod
|
||||
from core.menus import FooterType
|
||||
from core.menus import FooterType, Option
|
||||
from core.menus.base_menu import BaseMenu
|
||||
from utils.constants import COLOR_RED, RESET_FORMAT
|
||||
|
||||
@@ -20,11 +21,19 @@ class KlipperNoFirmwareErrorMenu(BaseMenu):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.set_previous_menu(None)
|
||||
self.set_options()
|
||||
|
||||
self.flash_options = FlashOptions()
|
||||
self.default_option = self.go_back
|
||||
self.footer_type = FooterType.BLANK
|
||||
self.input_label_txt = "Press ENTER to go back to [Advanced Menu]"
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
pass
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.default_option = Option(self.go_back, False)
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = "!!! NO FIRMWARE FILE FOUND !!!"
|
||||
color = COLOR_RED
|
||||
@@ -62,11 +71,15 @@ class KlipperNoFirmwareErrorMenu(BaseMenu):
|
||||
class KlipperNoBoardTypesErrorMenu(BaseMenu):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.default_option = self.go_back
|
||||
self.footer_type = FooterType.BLANK
|
||||
self.input_label_txt = "Press ENTER to go back to [Main Menu]"
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
pass
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.default_option = Option(self.go_back, False)
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = "!!! ERROR GETTING BOARD LIST !!!"
|
||||
color = COLOR_RED
|
||||
|
||||
@@ -7,16 +7,28 @@
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||
# ======================================================================= #
|
||||
import textwrap
|
||||
from typing import Type, Optional
|
||||
|
||||
from core.menus.base_menu import BaseMenu
|
||||
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW
|
||||
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
class KlipperFlashMethodHelpMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
from components.klipper_firmware.menus.klipper_flash_menu import (
|
||||
KlipperFlashMethodMenu,
|
||||
)
|
||||
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu if previous_menu is not None else KlipperFlashMethodMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
pass
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = " < ? > Help: Flash MCU < ? > "
|
||||
@@ -57,11 +69,22 @@ class KlipperFlashMethodHelpMenu(BaseMenu):
|
||||
print(menu, end="")
|
||||
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
class KlipperFlashCommandHelpMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
from components.klipper_firmware.menus.klipper_flash_menu import (
|
||||
KlipperFlashCommandMenu,
|
||||
)
|
||||
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu if previous_menu is not None else KlipperFlashCommandMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
pass
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = " < ? > Help: Flash MCU < ? > "
|
||||
@@ -89,11 +112,24 @@ class KlipperFlashCommandHelpMenu(BaseMenu):
|
||||
print(menu, end="")
|
||||
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
class KlipperMcuConnectionHelpMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
from components.klipper_firmware.menus.klipper_flash_menu import (
|
||||
KlipperSelectMcuConnectionMenu,
|
||||
)
|
||||
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu
|
||||
if previous_menu is not None
|
||||
else KlipperSelectMcuConnectionMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
pass
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = " < ? > Help: Flash MCU < ? > "
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
import textwrap
|
||||
import time
|
||||
from typing import Type, Optional
|
||||
|
||||
from components.klipper_firmware.flash_options import (
|
||||
FlashOptions,
|
||||
@@ -16,7 +17,7 @@ from components.klipper_firmware.flash_options import (
|
||||
FlashCommand,
|
||||
ConnectionType,
|
||||
)
|
||||
from components.klipper_firmware.flash_utils import (
|
||||
from components.klipper_firmware.firmware_utils import (
|
||||
find_usb_device_by_id,
|
||||
find_uart_device,
|
||||
find_usb_dfu_device,
|
||||
@@ -33,7 +34,7 @@ from components.klipper_firmware.menus.klipper_flash_help_menu import (
|
||||
KlipperFlashCommandHelpMenu,
|
||||
KlipperFlashMethodHelpMenu,
|
||||
)
|
||||
from core.menus import FooterType
|
||||
from core.menus import FooterType, Option
|
||||
|
||||
from core.menus.base_menu import BaseMenu
|
||||
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW, COLOR_RED
|
||||
@@ -44,20 +45,22 @@ from utils.logger import Logger
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class KlipperFlashMethodMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
self.help_menu = KlipperFlashMethodHelpMenu
|
||||
self.options = {
|
||||
"1": self.select_regular,
|
||||
"2": self.select_sdcard,
|
||||
}
|
||||
self.input_label_txt = "Select flash method"
|
||||
self.footer_type = FooterType.BACK_HELP
|
||||
|
||||
self.flash_options = FlashOptions()
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
self.previous_menu: Type[BaseMenu] = previous_menu
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.options = {
|
||||
"1": Option(self.select_regular, menu=False),
|
||||
"2": Option(self.select_sdcard, menu=False),
|
||||
}
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = " [ MCU Flash Menu ] "
|
||||
subheader = f"{COLOR_YELLOW}ATTENTION:{RESET_FORMAT}"
|
||||
@@ -95,7 +98,7 @@ class KlipperFlashMethodMenu(BaseMenu):
|
||||
|
||||
def goto_next_menu(self, **kwargs):
|
||||
if find_firmware_file(self.flash_options.flash_method):
|
||||
KlipperFlashCommandMenu(previous_menu=self).run()
|
||||
KlipperFlashCommandMenu(previous_menu=self.__class__).run()
|
||||
else:
|
||||
KlipperNoFirmwareErrorMenu().run()
|
||||
|
||||
@@ -103,21 +106,25 @@ class KlipperFlashMethodMenu(BaseMenu):
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class KlipperFlashCommandMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
self.help_menu = KlipperFlashCommandHelpMenu
|
||||
self.options = {
|
||||
"1": self.select_flash,
|
||||
"2": self.select_serialflash,
|
||||
}
|
||||
self.default_option = self.select_flash
|
||||
self.input_label_txt = "Select flash command"
|
||||
self.footer_type = FooterType.BACK_HELP
|
||||
|
||||
self.flash_options = FlashOptions()
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu if previous_menu is not None else KlipperFlashMethodMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.options = {
|
||||
"1": Option(self.select_flash, menu=False),
|
||||
"2": Option(self.select_serialflash, menu=False),
|
||||
}
|
||||
self.default_option = Option(self.select_flash, menu=False)
|
||||
|
||||
def print_menu(self) -> None:
|
||||
menu = textwrap.dedent(
|
||||
"""
|
||||
@@ -140,28 +147,34 @@ class KlipperFlashCommandMenu(BaseMenu):
|
||||
self.goto_next_menu()
|
||||
|
||||
def goto_next_menu(self, **kwargs):
|
||||
KlipperSelectMcuConnectionMenu(previous_menu=self).run()
|
||||
KlipperSelectMcuConnectionMenu(previous_menu=self.__class__).run()
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class KlipperSelectMcuConnectionMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu, standalone: bool = False):
|
||||
def __init__(
|
||||
self, previous_menu: Optional[Type[BaseMenu]] = None, standalone: bool = False
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
self.__standalone = standalone
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
self.help_menu = KlipperMcuConnectionHelpMenu
|
||||
self.options = {
|
||||
"1": self.select_usb,
|
||||
"2": self.select_dfu,
|
||||
"3": self.select_usb_dfu,
|
||||
}
|
||||
self.input_label_txt = "Select connection type"
|
||||
self.footer_type = FooterType.BACK_HELP
|
||||
|
||||
self.flash_options = FlashOptions()
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu if previous_menu is not None else KlipperFlashCommandMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.options = {
|
||||
"1": Option(method=self.select_usb, menu=False),
|
||||
"2": Option(method=self.select_dfu, menu=False),
|
||||
"3": Option(method=self.select_usb_dfu, menu=False),
|
||||
}
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = "Make sure that the controller board is connected now!"
|
||||
color = COLOR_YELLOW
|
||||
@@ -221,23 +234,32 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
|
||||
self.goto_next_menu()
|
||||
|
||||
def goto_next_menu(self, **kwargs):
|
||||
KlipperSelectMcuIdMenu(previous_menu=self).run()
|
||||
KlipperSelectMcuIdMenu(previous_menu=self.__class__).run()
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class KlipperSelectMcuIdMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
self.flash_options = FlashOptions()
|
||||
self.mcu_list = self.flash_options.mcu_list
|
||||
options = {f"{index}": self.flash_mcu for index in range(len(self.mcu_list))}
|
||||
self.options = options
|
||||
self.input_label_txt = "Select MCU to flash"
|
||||
self.footer_type = FooterType.BACK_HELP
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu
|
||||
if previous_menu is not None
|
||||
else KlipperSelectMcuConnectionMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.options = {
|
||||
f"{i}": Option(self.flash_mcu, False, f"{i}")
|
||||
for i in range(len(self.mcu_list))
|
||||
}
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = "!!! ATTENTION !!!"
|
||||
header2 = f"[{COLOR_CYAN}List of available MCUs{RESET_FORMAT}]"
|
||||
@@ -268,24 +290,30 @@ class KlipperSelectMcuIdMenu(BaseMenu):
|
||||
self.flash_options.selected_mcu = selected_mcu
|
||||
|
||||
if self.flash_options.flash_method == FlashMethod.SD_CARD:
|
||||
KlipperSelectSDFlashBoardMenu(previous_menu=self).run()
|
||||
KlipperSelectSDFlashBoardMenu(previous_menu=self.__class__).run()
|
||||
elif self.flash_options.flash_method == FlashMethod.REGULAR:
|
||||
KlipperFlashOverviewMenu(previous_menu=self).run()
|
||||
KlipperFlashOverviewMenu(previous_menu=self.__class__).run()
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class KlipperSelectSDFlashBoardMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
self.flash_options = FlashOptions()
|
||||
self.available_boards = get_sd_flash_board_list()
|
||||
self.input_label_txt = "Select board type"
|
||||
|
||||
options = {f"{i}": self.board_select for i in range(len(self.available_boards))}
|
||||
self.options = options
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu if previous_menu is not None else KlipperSelectMcuIdMenu
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.options = {
|
||||
f"{i}": Option(self.board_select, False, f"{i}")
|
||||
for i in range(len(self.available_boards))
|
||||
}
|
||||
|
||||
def print_menu(self) -> None:
|
||||
if len(self.available_boards) < 1:
|
||||
@@ -331,20 +359,27 @@ class KlipperSelectSDFlashBoardMenu(BaseMenu):
|
||||
min_count=0,
|
||||
allow_go_back=True,
|
||||
)
|
||||
KlipperFlashOverviewMenu(previous_menu=self).run()
|
||||
KlipperFlashOverviewMenu(previous_menu=self.__class__).run()
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class KlipperFlashOverviewMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: BaseMenu):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
|
||||
self.previous_menu: BaseMenu = previous_menu
|
||||
self.flash_options = FlashOptions()
|
||||
self.options = {"Y": self.execute_flash, "N": self.abort_process}
|
||||
self.input_label_txt = "Perform action (default=Y)"
|
||||
self.default_option = self.execute_flash
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
self.previous_menu: Type[BaseMenu] = previous_menu
|
||||
|
||||
def set_options(self) -> None:
|
||||
self.options = {
|
||||
"Y": Option(self.execute_flash, menu=False),
|
||||
"N": Option(self.abort_process, menu=False),
|
||||
}
|
||||
|
||||
self.default_option = Option(self.execute_flash, menu=False)
|
||||
|
||||
def print_menu(self) -> None:
|
||||
header = "!!! ATTENTION !!!"
|
||||
@@ -397,7 +432,7 @@ class KlipperFlashOverviewMenu(BaseMenu):
|
||||
start_flash_process(self.flash_options)
|
||||
Logger.print_info("Returning to MCU Flash Menu in 5 seconds ...")
|
||||
time.sleep(5)
|
||||
KlipperFlashMethodMenu(previous_menu=AdvancedMenu()).run()
|
||||
KlipperFlashMethodMenu(previous_menu=AdvancedMenu).run()
|
||||
|
||||
def abort_process(self, **kwargs):
|
||||
from core.menus.advanced_menu import AdvancedMenu
|
||||
|
||||
@@ -8,30 +8,37 @@
|
||||
# ======================================================================= #
|
||||
|
||||
import textwrap
|
||||
from typing import Type, Optional
|
||||
|
||||
from components.klipper_firmware.menus.klipper_build_menu import (
|
||||
KlipperBuildFirmwareMenu,
|
||||
)
|
||||
from components.klipper_firmware.menus.klipper_flash_menu import (
|
||||
KlipperFlashMethodMenu,
|
||||
KlipperSelectMcuConnectionMenu,
|
||||
)
|
||||
from core.menus import Option
|
||||
from core.menus.base_menu import BaseMenu
|
||||
from utils.constants import COLOR_YELLOW, RESET_FORMAT
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
class AdvancedMenu(BaseMenu):
|
||||
def __init__(self):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
from core.menus.main_menu import MainMenu
|
||||
|
||||
self.previous_menu: BaseMenu = MainMenu()
|
||||
self.previous_menu: Type[BaseMenu] = (
|
||||
previous_menu if previous_menu is not None else MainMenu
|
||||
)
|
||||
|
||||
def set_options(self):
|
||||
self.options = {
|
||||
"1": None,
|
||||
"2": None,
|
||||
"3": None,
|
||||
"4": self.flash,
|
||||
"5": None,
|
||||
"6": self.get_id,
|
||||
"3": Option(method=self.build, menu=True),
|
||||
"4": Option(method=self.flash, menu=False),
|
||||
"6": Option(method=self.get_id, menu=False),
|
||||
}
|
||||
|
||||
def print_menu(self):
|
||||
@@ -56,8 +63,14 @@ class AdvancedMenu(BaseMenu):
|
||||
)[1:]
|
||||
print(menu, end="")
|
||||
|
||||
def build(self, **kwargs):
|
||||
KlipperBuildFirmwareMenu(previous_menu=self.__class__).run()
|
||||
|
||||
def flash(self, **kwargs):
|
||||
KlipperFlashMethodMenu(previous_menu=self).run()
|
||||
KlipperFlashMethodMenu(previous_menu=self.__class__).run()
|
||||
|
||||
def get_id(self, **kwargs):
|
||||
KlipperSelectMcuConnectionMenu(previous_menu=self, standalone=True).run()
|
||||
KlipperSelectMcuConnectionMenu(
|
||||
previous_menu=self.__class__,
|
||||
standalone=True,
|
||||
).run()
|
||||
|
||||
@@ -190,7 +190,8 @@ def update_system_package_lists(silent: bool, rls_info_change=False) -> None:
|
||||
|
||||
Logger.print_ok("System package list update successful!")
|
||||
except CalledProcessError as e:
|
||||
kill(f"Error updating system package list:\n{e.stderr.decode()}")
|
||||
Logger.print_error(f"Error updating system package list:\n{e.stderr.decode()}")
|
||||
raise
|
||||
|
||||
|
||||
def check_package_install(packages: List[str]) -> List[str]:
|
||||
@@ -210,8 +211,6 @@ def check_package_install(packages: List[str]) -> List[str]:
|
||||
)
|
||||
if "installed" not in result.stdout.strip("'").split():
|
||||
not_installed.append(package)
|
||||
else:
|
||||
Logger.print_ok(f"{package} already installed.")
|
||||
|
||||
return not_installed
|
||||
|
||||
@@ -230,7 +229,8 @@ def install_system_packages(packages: List[str]) -> None:
|
||||
|
||||
Logger.print_ok("Packages installed successfully.")
|
||||
except CalledProcessError as e:
|
||||
kill(f"Error installing packages:\n{e.stderr.decode()}")
|
||||
Logger.print_error(f"Error installing packages:\n{e.stderr.decode()}")
|
||||
raise
|
||||
|
||||
|
||||
def mask_system_service(service_name: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user