From 406b64d1e5ce4bead3d150826ba2ef71daa523e5 Mon Sep 17 00:00:00 2001 From: Pedro Lamas Date: Mon, 14 Oct 2024 16:18:10 +0100 Subject: [PATCH 1/4] refactor: add client name to Moonraker not found dialog (#574) Signed-off-by: Pedro Lamas Co-authored-by: dw-0 --- kiauh/components/webui_client/client_dialogs.py | 6 +++--- kiauh/components/webui_client/client_setup.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kiauh/components/webui_client/client_dialogs.py b/kiauh/components/webui_client/client_dialogs.py index a615fb4..95bd693 100644 --- a/kiauh/components/webui_client/client_dialogs.py +++ b/kiauh/components/webui_client/client_dialogs.py @@ -13,15 +13,15 @@ from components.webui_client.base_data import BaseWebClient from core.logger import DialogType, Logger -def print_moonraker_not_found_dialog() -> None: +def print_moonraker_not_found_dialog(name: str) -> None: Logger.print_dialog( DialogType.WARNING, [ "No local Moonraker installation was found!", "\n\n", - "It is possible to install Mainsail without a local Moonraker installation. " + f"It is possible to install {name} without a local Moonraker installation. " "If you continue, you need to make sure, that Moonraker is installed on " - "another machine in your network. Otherwise Mainsail will NOT work " + f"another machine in your network. Otherwise {name} will NOT work " "correctly.", ], ) diff --git a/kiauh/components/webui_client/client_setup.py b/kiauh/components/webui_client/client_setup.py index 5827c4f..1db9d13 100644 --- a/kiauh/components/webui_client/client_setup.py +++ b/kiauh/components/webui_client/client_setup.py @@ -67,7 +67,7 @@ def install_client(client: BaseWebClient) -> None: enable_remotemode = False if not mr_instances: - print_moonraker_not_found_dialog() + print_moonraker_not_found_dialog(client.display_name) if not get_confirm(f"Continue {client.display_name} installation?"): return From a368331693e3ecc90d0291f82206b7bf42808a90 Mon Sep 17 00:00:00 2001 From: CODeRUS Date: Fri, 18 Oct 2024 18:56:21 +0200 Subject: [PATCH 2/4] feat(flashing): Flash RP2040 in Boot Mode (#580) * feat(flashing): Flash RP2040 in Boot Mode * docs: add info about STM32 DFU and RP2040 boot modes --- .../components/klipper_firmware/firmware_utils.py | 15 +++++++++++++++ .../components/klipper_firmware/flash_options.py | 1 + .../menus/klipper_flash_help_menu.py | 15 +++++++++++++++ .../klipper_firmware/menus/klipper_flash_menu.py | 10 ++++++++++ 4 files changed, 41 insertions(+) diff --git a/kiauh/components/klipper_firmware/firmware_utils.py b/kiauh/components/klipper_firmware/firmware_utils.py index a4fee31..435a96d 100644 --- a/kiauh/components/klipper_firmware/firmware_utils.py +++ b/kiauh/components/klipper_firmware/firmware_utils.py @@ -90,6 +90,21 @@ def find_usb_dfu_device() -> List[str]: return [] +def find_usb_rp2_boot_device() -> List[str]: + try: + output = check_output("lsusb", shell=True, text=True, stderr=DEVNULL) + device_list = [] + if output: + devices = output.splitlines() + device_list = [d.split(" ")[5] for d in devices if "RP2 Boot" in d] + return device_list + + except CalledProcessError as e: + Logger.print_error("Unable to find a USB RP2 Boot 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 [] diff --git a/kiauh/components/klipper_firmware/flash_options.py b/kiauh/components/klipper_firmware/flash_options.py index da12d1a..023df67 100644 --- a/kiauh/components/klipper_firmware/flash_options.py +++ b/kiauh/components/klipper_firmware/flash_options.py @@ -26,6 +26,7 @@ class FlashCommand(Enum): class ConnectionType(Enum): USB = "USB" USB_DFU = "USB (DFU)" + USB_RP2040 = "USB (RP2040)" UART = "UART" diff --git a/kiauh/components/klipper_firmware/menus/klipper_flash_help_menu.py b/kiauh/components/klipper_firmware/menus/klipper_flash_help_menu.py index 831375e..f69ea21 100644 --- a/kiauh/components/klipper_firmware/menus/klipper_flash_help_menu.py +++ b/kiauh/components/klipper_firmware/menus/klipper_flash_help_menu.py @@ -143,6 +143,8 @@ class KlipperMcuConnectionHelpMenu(BaseMenu): count = 62 - len(color) - len(RESET_FORMAT) subheader1 = f"{COLOR_CYAN}USB:{RESET_FORMAT}" subheader2 = f"{COLOR_CYAN}UART:{RESET_FORMAT}" + subheader3 = f"{COLOR_CYAN}USB DFU:{RESET_FORMAT}" + subheader4 = f"{COLOR_CYAN}USB RP2040 Boot:{RESET_FORMAT}" menu = textwrap.dedent( f""" ╔═══════════════════════════════════════════════════════╗ @@ -164,6 +166,19 @@ class KlipperMcuConnectionHelpMenu(BaseMenu): ║ port your controller board is connected to when using ║ ║ this connection method. ║ ║ ║ + ║ {subheader3:<62} ║ + ║ Selecting USB DFU as the connection method will scan ║ + ║ the USB ports for connected controller boards in ║ + ║ STM32 DFU mode, which is usually done by holding down ║ + ║ the BOOT button or setting a special jumper on the ║ + ║ board before powering up. ║ + ║ ║ + ║ {subheader4:<62} ║ + ║ Selecting USB RP2 Boot as the connection method will ║ + ║ scan the USB ports for connected RP2040 controller ║ + ║ boards in Boot mode, which is usually done by holding ║ + ║ down the BOOT button before powering up. ║ + ║ ║ ╟───────────────────────────────────────────────────────╢ """ )[1:] diff --git a/kiauh/components/klipper_firmware/menus/klipper_flash_menu.py b/kiauh/components/klipper_firmware/menus/klipper_flash_menu.py index 9c0c8b1..b1373f0 100644 --- a/kiauh/components/klipper_firmware/menus/klipper_flash_menu.py +++ b/kiauh/components/klipper_firmware/menus/klipper_flash_menu.py @@ -17,6 +17,7 @@ from components.klipper_firmware.firmware_utils import ( find_uart_device, find_usb_device_by_id, find_usb_dfu_device, + find_usb_rp2_boot_device, get_sd_flash_board_list, start_flash_process, ) @@ -177,6 +178,7 @@ class KlipperSelectMcuConnectionMenu(BaseMenu): "1": Option(method=self.select_usb), "2": Option(method=self.select_dfu), "3": Option(method=self.select_usb_dfu), + "4": Option(method=self.select_usb_rp2040), } def print_menu(self) -> None: @@ -193,6 +195,7 @@ class KlipperSelectMcuConnectionMenu(BaseMenu): ║ 1) USB ║ ║ 2) UART ║ ║ 3) USB (DFU mode) ║ + ║ 4) USB (RP2040 mode) ║ ╟───────────────────────────┬───────────────────────────╢ """ )[1:] @@ -210,6 +213,10 @@ class KlipperSelectMcuConnectionMenu(BaseMenu): self.flash_options.connection_type = ConnectionType.USB_DFU self.get_mcu_list() + def select_usb_rp2040(self, **kwargs): + self.flash_options.connection_type = ConnectionType.USB_RP2040 + self.get_mcu_list() + def get_mcu_list(self, **kwargs): conn_type = self.flash_options.connection_type @@ -222,6 +229,9 @@ class KlipperSelectMcuConnectionMenu(BaseMenu): elif conn_type is ConnectionType.USB_DFU: Logger.print_status("Identifying MCU connected via USB in DFU mode ...") self.flash_options.mcu_list = find_usb_dfu_device() + elif conn_type is ConnectionType.USB_RP2040: + Logger.print_status("Identifying MCU connected via USB in RP2 Boot mode ...") + self.flash_options.mcu_list = find_usb_rp2_boot_device() if len(self.flash_options.mcu_list) < 1: Logger.print_warn("No MCUs found!") From 674c174224f7a7bf586f08c5f98301a023a88541 Mon Sep 17 00:00:00 2001 From: dw-0 Date: Sun, 20 Oct 2024 18:11:30 +0200 Subject: [PATCH 3/4] fix: correctly add Spoolman to moonraker.asvc (#581) Signed-off-by: Dominik Willner --- scripts/spoolman.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/spoolman.sh b/scripts/spoolman.sh index ba1f2bb..fd29edd 100644 --- a/scripts/spoolman.sh +++ b/scripts/spoolman.sh @@ -127,9 +127,9 @@ managed_services: Spoolman regex="${HOME//\//\\/}\/([A-Za-z0-9_]+)\/moonraker\.asvc" moonraker_asvc=$(find "${HOME}" -maxdepth 2 -type f -regextype posix-extended -regex "${regex}" | sort) - if [[ -n ${moonraker_asvc} ]]; then + if ! grep -q "^Spoolman$" "${moonraker_asvc}"; then status_msg "Adding Spoolman service to moonraker.asvc..." - /bin/sh -c "echo 'Spoolman' >> ${moonraker_asvc}" + sed -i '$a''Spoolman' "${moonraker_asvc}" fi } @@ -248,7 +248,7 @@ function get_spoolman_status() { function get_local_spoolman_version() { [[ ! -d "${SPOOLMAN_DIR}" ]] && return - + local version version=$(grep -o '"version":\s*"[^"]*' "${SPOOLMAN_DIR}"/release_info.json | cut -d'"' -f4) echo "${version}" From ff6162d7998b17cc2c2db237047685109444b9a1 Mon Sep 17 00:00:00 2001 From: dw-0 Date: Mon, 21 Oct 2024 19:30:03 +0200 Subject: [PATCH 4/4] refactor: do not silently configure Fluidd for port 81 (#582) * refactor: use port 80 as default for fluidd Signed-off-by: Dominik Willner * refactor: improve port selection logic, write last port selection for client to kiauh.cfg Signed-off-by: Dominik Willner --------- Signed-off-by: Dominik Willner --- default.kiauh.cfg | 2 +- .../components/webui_client/client_dialogs.py | 33 +++++++++++-------- kiauh/components/webui_client/client_setup.py | 24 ++------------ kiauh/components/webui_client/client_utils.py | 29 ++++++++++++++-- 4 files changed, 49 insertions(+), 39 deletions(-) diff --git a/default.kiauh.cfg b/default.kiauh.cfg index cd36055..9c73204 100644 --- a/default.kiauh.cfg +++ b/default.kiauh.cfg @@ -14,5 +14,5 @@ port: 80 unstable_releases: False [fluidd] -port: 81 +port: 80 unstable_releases: False diff --git a/kiauh/components/webui_client/client_dialogs.py b/kiauh/components/webui_client/client_dialogs.py index 95bd693..e6fd5ab 100644 --- a/kiauh/components/webui_client/client_dialogs.py +++ b/kiauh/components/webui_client/client_dialogs.py @@ -40,20 +40,25 @@ def print_client_already_installed_dialog(name: str) -> None: def print_client_port_select_dialog( name: str, port: int, ports_in_use: List[int] ) -> None: - Logger.print_dialog( - DialogType.CUSTOM, - [ - f"Please select the port, {name} should be served on. If your are unsure " - f"what to select, hit Enter to apply the suggested value of: {port}", - "\n\n", - f"In case you need {name} to be served on a specific port, you can set it " - f"now. Make sure that the port is not already used by another application " - f"on your system!", - "\n\n", - "The following ports were found to be in use already:", - *[f"● {port}" for port in ports_in_use], - ], - ) + dialog_content: List[str] = [ + f"Please select the port, {name} should be served on. If your are unsure " + f"what to select, hit Enter to apply the suggested value of: {port}", + "\n\n", + f"In case you need {name} to be served on a specific port, you can set it " + f"now. Make sure that the port is not already used by another application " + f"on your system!", + ] + + if ports_in_use: + dialog_content.extend( + [ + "\n\n", + "The following ports were found to be in use already:", + *[f"● {port}" for port in ports_in_use], + ] + ) + + Logger.print_dialog(DialogType.CUSTOM, dialog_content) def print_install_client_config_dialog(client: BaseWebClient) -> None: diff --git a/kiauh/components/webui_client/client_setup.py b/kiauh/components/webui_client/client_setup.py index 1db9d13..7db8218 100644 --- a/kiauh/components/webui_client/client_setup.py +++ b/kiauh/components/webui_client/client_setup.py @@ -23,7 +23,6 @@ from components.webui_client.client_config.client_config_setup import ( install_client_config, ) from components.webui_client.client_dialogs import ( - print_client_port_select_dialog, print_install_client_config_dialog, print_moonraker_not_found_dialog, ) @@ -33,18 +32,15 @@ from components.webui_client.client_utils import ( create_nginx_cfg, detect_client_cfg_conflict, enable_mainsail_remotemode, - get_next_free_port, - is_valid_port, - read_ports_from_nginx_configs, + get_client_port_selection, symlink_webui_nginx_log, ) from core.instance_manager.instance_manager import InstanceManager from core.logger import Logger -from core.settings.kiauh_settings import KiauhSettings from utils.common import check_install_dependencies from utils.config_utils import add_config_section from utils.fs_utils import unzip -from utils.input_utils import get_confirm, get_number_input +from utils.input_utils import get_confirm from utils.instance_utils import get_instances from utils.sys_utils import ( cmd_sysctl_service, @@ -92,21 +88,7 @@ def install_client(client: BaseWebClient) -> None: question = f"Download the recommended {client_config.display_name}?" install_client_cfg = get_confirm(question, allow_go_back=False) - settings = KiauhSettings() - port: int = settings.get(client.name, "port") - ports_in_use: List[int] = read_ports_from_nginx_configs() - - # check if configured port is a valid number and not in use already - valid_port = is_valid_port(port, ports_in_use) - while not valid_port: - next_port = get_next_free_port(ports_in_use) - print_client_port_select_dialog(client.display_name, next_port, ports_in_use) - port = get_number_input( - f"Configure {client.display_name} for port", - min_count=int(next_port), - default=next_port, - ) - valid_port = is_valid_port(port, ports_in_use) + port: int = get_client_port_selection(client) check_install_dependencies({"nginx"}) diff --git a/kiauh/components/webui_client/client_utils.py b/kiauh/components/webui_client/client_utils.py index 1c17aac..206f0b2 100644 --- a/kiauh/components/webui_client/client_utils.py +++ b/kiauh/components/webui_client/client_utils.py @@ -21,6 +21,7 @@ from components.webui_client.base_data import ( BaseWebClient, WebClientType, ) +from components.webui_client.client_dialogs import print_client_port_select_dialog from components.webui_client.fluidd_data import FluiddData from components.webui_client.mainsail_data import MainsailData from core.backup_manager.backup_manager import BackupManager @@ -33,7 +34,7 @@ from core.constants import ( RESET_FORMAT, ) from core.logger import Logger -from core.settings.kiauh_settings import KiauhSettings +from core.settings.kiauh_settings import KiauhSettings, WebUiSettings from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import ( SimpleConfigParser, ) @@ -44,6 +45,7 @@ from utils.git_utils import ( get_latest_remote_tag, get_latest_unstable_tag, ) +from utils.input_utils import get_number_input from utils.instance_utils import get_instances @@ -368,8 +370,29 @@ def read_ports_from_nginx_configs() -> List[int]: return sorted(ports_to_ints_list, key=lambda x: int(x)) -def is_valid_port(port: int, ports_in_use: List[int]) -> bool: - return port not in ports_in_use +def get_client_port_selection(client: BaseWebClient) -> int: + settings = KiauhSettings() + default_port: int = int(settings.get(client.name, "port")) + + ports_in_use: List[int] = read_ports_from_nginx_configs() + next_free_port: int = get_next_free_port(ports_in_use) + + port: int = next_free_port if default_port in ports_in_use else default_port + + print_client_port_select_dialog(client.display_name, port, ports_in_use) + + while True: + question = f"Configure {client.display_name} for port" + port_input = get_number_input(question, min_count=80, default=port) + + if port_input not in ports_in_use: + client_settings: WebUiSettings = settings[client.name] + client_settings.port = port_input + settings.save() + + return port_input + + Logger.print_error("This port is already in use. Please select another one.") def get_next_free_port(ports_in_use: List[int]) -> int: