diff --git a/esphome/__main__.py b/esphome/__main__.py index 70d5cacd72..e1f683397f 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -398,28 +398,27 @@ def check_permissions(port: str): def upload_program( config: ConfigType, args: ArgsProtocol, devices: list[str] -) -> int | str: +) -> tuple[int, str | None]: host = devices[0] try: module = importlib.import_module("esphome.components." + CORE.target_platform) if getattr(module, "upload_program")(config, args, host): - return 0 + return 0, host except AttributeError: pass if get_port_type(host) == "SERIAL": check_permissions(host) + + exit_code = 1 if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266): file = getattr(args, "file", None) - return upload_using_esptool(config, host, file, args.upload_speed) + exit_code = upload_using_esptool(config, host, file, args.upload_speed) + elif CORE.target_platform == PLATFORM_RP2040 or CORE.is_libretiny: + exit_code = upload_using_platformio(config, host) + # else: Unknown target platform, exit_code remains 1 - if CORE.target_platform in (PLATFORM_RP2040): - return upload_using_platformio(config, host) - - if CORE.is_libretiny: - return upload_using_platformio(config, host) - - return 1 # Unknown target platform + return exit_code, host if exit_code == 0 else None ota_conf = {} for ota_item in config.get(CONF_OTA, []): @@ -553,7 +552,7 @@ def command_upload(args: ArgsProtocol, config: ConfigType) -> int | None: purpose="uploading", ) - exit_code = upload_program(config, args, devices) + exit_code, _ = upload_program(config, args, devices) if exit_code == 0: _LOGGER.info("Successfully uploaded program.") else: @@ -610,19 +609,11 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None: purpose="uploading", ) - # Try each device for upload until one succeeds - successful_device: str | None = None - for device in devices: - _LOGGER.info("Uploading to %s", device) - exit_code = upload_program(config, args, device) - if exit_code == 0: - _LOGGER.info("Successfully uploaded program.") - successful_device = device - break - if len(devices) > 1: - _LOGGER.warning("Failed to upload to %s", device) - - if successful_device is None: + exit_code, successful_device = upload_program(config, args, devices) + if exit_code == 0: + _LOGGER.info("Successfully uploaded program.") + else: + _LOGGER.warning("Failed to upload to %s", devices) return exit_code if args.no_logs: diff --git a/esphome/espota2.py b/esphome/espota2.py index d83f25a303..3d25af985b 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -310,7 +310,7 @@ def perform_ota( def run_ota_impl_( remote_host: str | list[str], remote_port: int, password: str, filename: str -) -> int: +) -> tuple[int, str | None]: # Handle both single host and list of hosts try: # Resolve all hosts at once for parallel DNS resolution @@ -344,21 +344,22 @@ def run_ota_impl_( perform_ota(sock, password, file_handle, filename) except OTAError as err: _LOGGER.error(str(err)) - return 1 + return 1, None finally: sock.close() - return 0 + # Successfully uploaded to sa[0] + return 0, sa[0] _LOGGER.error("Connection failed.") - return 1 + return 1, None def run_ota( remote_host: str | list[str], remote_port: int, password: str, filename: str -) -> int: +) -> tuple[int, str | None]: try: return run_ota_impl_(remote_host, remote_port, password, filename) except OTAError as err: _LOGGER.error(err) - return 1 + return 1, None