mirror of
https://github.com/esphome/esphome.git
synced 2025-09-17 10:42:21 +01:00
Merge branch 'fix_upload_run' into integration
This commit is contained in:
@@ -398,28 +398,29 @@ def check_permissions(port: str):
|
|||||||
|
|
||||||
def upload_program(
|
def upload_program(
|
||||||
config: ConfigType, args: ArgsProtocol, devices: list[str]
|
config: ConfigType, args: ArgsProtocol, devices: list[str]
|
||||||
) -> int | str:
|
) -> tuple[int, str | None]:
|
||||||
host = devices[0]
|
host = devices[0]
|
||||||
try:
|
try:
|
||||||
module = importlib.import_module("esphome.components." + CORE.target_platform)
|
module = importlib.import_module("esphome.components." + CORE.target_platform)
|
||||||
if getattr(module, "upload_program")(config, args, host):
|
if getattr(module, "upload_program")(config, args, host):
|
||||||
return 0
|
return 0, host
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if get_port_type(host) == "SERIAL":
|
if get_port_type(host) == "SERIAL":
|
||||||
check_permissions(host)
|
check_permissions(host)
|
||||||
|
|
||||||
|
exit_code = 1
|
||||||
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
|
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
|
||||||
file = getattr(args, "file", None)
|
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
|
||||||
|
pass
|
||||||
|
|
||||||
if CORE.target_platform in (PLATFORM_RP2040):
|
return exit_code, host if exit_code == 0 else None
|
||||||
return upload_using_platformio(config, host)
|
|
||||||
|
|
||||||
if CORE.is_libretiny:
|
|
||||||
return upload_using_platformio(config, host)
|
|
||||||
|
|
||||||
return 1 # Unknown target platform
|
|
||||||
|
|
||||||
ota_conf = {}
|
ota_conf = {}
|
||||||
for ota_item in config.get(CONF_OTA, []):
|
for ota_item in config.get(CONF_OTA, []):
|
||||||
@@ -560,7 +561,7 @@ def command_upload(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|||||||
purpose="uploading",
|
purpose="uploading",
|
||||||
)
|
)
|
||||||
|
|
||||||
exit_code = upload_program(config, args, devices)
|
exit_code, successful_device = upload_program(config, args, devices)
|
||||||
if exit_code == 0:
|
if exit_code == 0:
|
||||||
_LOGGER.info("Successfully uploaded program.")
|
_LOGGER.info("Successfully uploaded program.")
|
||||||
else:
|
else:
|
||||||
@@ -617,19 +618,11 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|||||||
purpose="uploading",
|
purpose="uploading",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Try each device for upload until one succeeds
|
exit_code, successful_device = upload_program(config, args, devices)
|
||||||
successful_device: str | None = None
|
if exit_code == 0:
|
||||||
for device in devices:
|
_LOGGER.info("Successfully uploaded program.")
|
||||||
_LOGGER.info("Uploading to %s", device)
|
else:
|
||||||
exit_code = upload_program(config, args, device)
|
_LOGGER.warning("Failed to upload to %s", devices)
|
||||||
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:
|
|
||||||
return exit_code
|
return exit_code
|
||||||
|
|
||||||
if args.no_logs:
|
if args.no_logs:
|
||||||
|
@@ -56,7 +56,7 @@ ISRInternalGPIOPin ESP32InternalGPIOPin::to_isr() const {
|
|||||||
auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
|
auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
arg->pin = this->get_pin_num();
|
arg->pin = this->get_pin_num();
|
||||||
arg->flags = gpio::FLAG_NONE;
|
arg->flags = gpio::FLAG_NONE;
|
||||||
arg->inverted = pin_flags_.inverted;
|
arg->inverted = this->pin_flags_.inverted;
|
||||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||||
arg->use_rtc = rtc_gpio_is_valid_gpio(this->get_pin_num());
|
arg->use_rtc = rtc_gpio_is_valid_gpio(this->get_pin_num());
|
||||||
if (arg->use_rtc)
|
if (arg->use_rtc)
|
||||||
@@ -69,23 +69,23 @@ void ESP32InternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpi
|
|||||||
gpio_int_type_t idf_type = GPIO_INTR_ANYEDGE;
|
gpio_int_type_t idf_type = GPIO_INTR_ANYEDGE;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case gpio::INTERRUPT_RISING_EDGE:
|
case gpio::INTERRUPT_RISING_EDGE:
|
||||||
idf_type = pin_flags_.inverted ? GPIO_INTR_NEGEDGE : GPIO_INTR_POSEDGE;
|
idf_type = this->pin_flags_.inverted ? GPIO_INTR_NEGEDGE : GPIO_INTR_POSEDGE;
|
||||||
break;
|
break;
|
||||||
case gpio::INTERRUPT_FALLING_EDGE:
|
case gpio::INTERRUPT_FALLING_EDGE:
|
||||||
idf_type = pin_flags_.inverted ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE;
|
idf_type = this->pin_flags_.inverted ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE;
|
||||||
break;
|
break;
|
||||||
case gpio::INTERRUPT_ANY_EDGE:
|
case gpio::INTERRUPT_ANY_EDGE:
|
||||||
idf_type = GPIO_INTR_ANYEDGE;
|
idf_type = GPIO_INTR_ANYEDGE;
|
||||||
break;
|
break;
|
||||||
case gpio::INTERRUPT_LOW_LEVEL:
|
case gpio::INTERRUPT_LOW_LEVEL:
|
||||||
idf_type = pin_flags_.inverted ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL;
|
idf_type = this->pin_flags_.inverted ? GPIO_INTR_HIGH_LEVEL : GPIO_INTR_LOW_LEVEL;
|
||||||
break;
|
break;
|
||||||
case gpio::INTERRUPT_HIGH_LEVEL:
|
case gpio::INTERRUPT_HIGH_LEVEL:
|
||||||
idf_type = pin_flags_.inverted ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL;
|
idf_type = this->pin_flags_.inverted ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gpio_set_intr_type(get_pin_num(), idf_type);
|
gpio_set_intr_type(this->get_pin_num(), idf_type);
|
||||||
gpio_intr_enable(get_pin_num());
|
gpio_intr_enable(this->get_pin_num());
|
||||||
if (!isr_service_installed) {
|
if (!isr_service_installed) {
|
||||||
auto res = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL3);
|
auto res = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL3);
|
||||||
if (res != ESP_OK) {
|
if (res != ESP_OK) {
|
||||||
@@ -94,31 +94,31 @@ void ESP32InternalGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpi
|
|||||||
}
|
}
|
||||||
isr_service_installed = true;
|
isr_service_installed = true;
|
||||||
}
|
}
|
||||||
gpio_isr_handler_add(get_pin_num(), func, arg);
|
gpio_isr_handler_add(this->get_pin_num(), func, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ESP32InternalGPIOPin::dump_summary() const {
|
std::string ESP32InternalGPIOPin::dump_summary() const {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
snprintf(buffer, sizeof(buffer), "GPIO%" PRIu32, static_cast<uint32_t>(pin_));
|
snprintf(buffer, sizeof(buffer), "GPIO%" PRIu32, static_cast<uint32_t>(this->pin_));
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32InternalGPIOPin::setup() {
|
void ESP32InternalGPIOPin::setup() {
|
||||||
gpio_config_t conf{};
|
gpio_config_t conf{};
|
||||||
conf.pin_bit_mask = 1ULL << static_cast<uint32_t>(pin_);
|
conf.pin_bit_mask = 1ULL << static_cast<uint32_t>(this->pin_);
|
||||||
conf.mode = flags_to_mode(flags_);
|
conf.mode = flags_to_mode(this->flags_);
|
||||||
conf.pull_up_en = flags_ & gpio::FLAG_PULLUP ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
|
conf.pull_up_en = this->flags_ & gpio::FLAG_PULLUP ? GPIO_PULLUP_ENABLE : GPIO_PULLUP_DISABLE;
|
||||||
conf.pull_down_en = flags_ & gpio::FLAG_PULLDOWN ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE;
|
conf.pull_down_en = this->flags_ & gpio::FLAG_PULLDOWN ? GPIO_PULLDOWN_ENABLE : GPIO_PULLDOWN_DISABLE;
|
||||||
conf.intr_type = GPIO_INTR_DISABLE;
|
conf.intr_type = GPIO_INTR_DISABLE;
|
||||||
gpio_config(&conf);
|
gpio_config(&conf);
|
||||||
if (flags_ & gpio::FLAG_OUTPUT) {
|
if (this->flags_ & gpio::FLAG_OUTPUT) {
|
||||||
gpio_set_drive_capability(get_pin_num(), get_drive_strength());
|
gpio_set_drive_capability(this->get_pin_num(), this->get_drive_strength());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32InternalGPIOPin::pin_mode(gpio::Flags flags) {
|
void ESP32InternalGPIOPin::pin_mode(gpio::Flags flags) {
|
||||||
// can't call gpio_config here because that logs in esp-idf which may cause issues
|
// can't call gpio_config here because that logs in esp-idf which may cause issues
|
||||||
gpio_set_direction(get_pin_num(), flags_to_mode(flags));
|
gpio_set_direction(this->get_pin_num(), flags_to_mode(flags));
|
||||||
gpio_pull_mode_t pull_mode = GPIO_FLOATING;
|
gpio_pull_mode_t pull_mode = GPIO_FLOATING;
|
||||||
if ((flags & gpio::FLAG_PULLUP) && (flags & gpio::FLAG_PULLDOWN)) {
|
if ((flags & gpio::FLAG_PULLUP) && (flags & gpio::FLAG_PULLDOWN)) {
|
||||||
pull_mode = GPIO_PULLUP_PULLDOWN;
|
pull_mode = GPIO_PULLUP_PULLDOWN;
|
||||||
@@ -127,14 +127,16 @@ void ESP32InternalGPIOPin::pin_mode(gpio::Flags flags) {
|
|||||||
} else if (flags & gpio::FLAG_PULLDOWN) {
|
} else if (flags & gpio::FLAG_PULLDOWN) {
|
||||||
pull_mode = GPIO_PULLDOWN_ONLY;
|
pull_mode = GPIO_PULLDOWN_ONLY;
|
||||||
}
|
}
|
||||||
gpio_set_pull_mode(get_pin_num(), pull_mode);
|
gpio_set_pull_mode(this->get_pin_num(), pull_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESP32InternalGPIOPin::digital_read() { return bool(gpio_get_level(get_pin_num())) != pin_flags_.inverted; }
|
bool ESP32InternalGPIOPin::digital_read() {
|
||||||
void ESP32InternalGPIOPin::digital_write(bool value) {
|
return bool(gpio_get_level(this->get_pin_num())) != this->pin_flags_.inverted;
|
||||||
gpio_set_level(get_pin_num(), value != pin_flags_.inverted ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
void ESP32InternalGPIOPin::detach_interrupt() const { gpio_intr_disable(get_pin_num()); }
|
void ESP32InternalGPIOPin::digital_write(bool value) {
|
||||||
|
gpio_set_level(this->get_pin_num(), value != this->pin_flags_.inverted ? 1 : 0);
|
||||||
|
}
|
||||||
|
void ESP32InternalGPIOPin::detach_interrupt() const { gpio_intr_disable(this->get_pin_num()); }
|
||||||
|
|
||||||
} // namespace esp32
|
} // namespace esp32
|
||||||
|
|
||||||
|
@@ -13,12 +13,12 @@ static_assert(GPIO_DRIVE_CAP_MAX <= 4, "gpio_drive_cap_t has too many values for
|
|||||||
|
|
||||||
class ESP32InternalGPIOPin : public InternalGPIOPin {
|
class ESP32InternalGPIOPin : public InternalGPIOPin {
|
||||||
public:
|
public:
|
||||||
void set_pin(gpio_num_t pin) { pin_ = static_cast<uint8_t>(pin); }
|
void set_pin(gpio_num_t pin) { this->pin_ = static_cast<uint8_t>(pin); }
|
||||||
void set_inverted(bool inverted) { pin_flags_.inverted = inverted; }
|
void set_inverted(bool inverted) { this->pin_flags_.inverted = inverted; }
|
||||||
void set_drive_strength(gpio_drive_cap_t drive_strength) {
|
void set_drive_strength(gpio_drive_cap_t drive_strength) {
|
||||||
pin_flags_.drive_strength = static_cast<uint8_t>(drive_strength);
|
this->pin_flags_.drive_strength = static_cast<uint8_t>(drive_strength);
|
||||||
}
|
}
|
||||||
void set_flags(gpio::Flags flags) { flags_ = flags; }
|
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void pin_mode(gpio::Flags flags) override;
|
void pin_mode(gpio::Flags flags) override;
|
||||||
@@ -27,11 +27,11 @@ class ESP32InternalGPIOPin : public InternalGPIOPin {
|
|||||||
std::string dump_summary() const override;
|
std::string dump_summary() const override;
|
||||||
void detach_interrupt() const override;
|
void detach_interrupt() const override;
|
||||||
ISRInternalGPIOPin to_isr() const override;
|
ISRInternalGPIOPin to_isr() const override;
|
||||||
uint8_t get_pin() const override { return pin_; }
|
uint8_t get_pin() const override { return this->pin_; }
|
||||||
gpio::Flags get_flags() const override { return flags_; }
|
gpio::Flags get_flags() const override { return this->flags_; }
|
||||||
bool is_inverted() const override { return pin_flags_.inverted; }
|
bool is_inverted() const override { return this->pin_flags_.inverted; }
|
||||||
gpio_num_t get_pin_num() const { return static_cast<gpio_num_t>(pin_); }
|
gpio_num_t get_pin_num() const { return static_cast<gpio_num_t>(this->pin_); }
|
||||||
gpio_drive_cap_t get_drive_strength() const { return static_cast<gpio_drive_cap_t>(pin_flags_.drive_strength); }
|
gpio_drive_cap_t get_drive_strength() const { return static_cast<gpio_drive_cap_t>(this->pin_flags_.drive_strength); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override;
|
void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override;
|
||||||
@@ -40,7 +40,7 @@ class ESP32InternalGPIOPin : public InternalGPIOPin {
|
|||||||
// - 3 bytes for members below
|
// - 3 bytes for members below
|
||||||
// - 1 byte padding for alignment
|
// - 1 byte padding for alignment
|
||||||
// - 4 bytes for vtable pointer
|
// - 4 bytes for vtable pointer
|
||||||
uint8_t pin_; // GPIO pin number (0-255, actual max ~48 on ESP32)
|
uint8_t pin_; // GPIO pin number (0-255, actual max ~54 on ESP32)
|
||||||
gpio::Flags flags_; // GPIO flags (1 byte)
|
gpio::Flags flags_; // GPIO flags (1 byte)
|
||||||
struct PinFlags {
|
struct PinFlags {
|
||||||
uint8_t inverted : 1; // Invert pin logic (1 bit)
|
uint8_t inverted : 1; // Invert pin logic (1 bit)
|
||||||
|
@@ -310,7 +310,7 @@ def perform_ota(
|
|||||||
|
|
||||||
def run_ota_impl_(
|
def run_ota_impl_(
|
||||||
remote_host: str | list[str], remote_port: int, password: str, filename: str
|
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
|
# Handle both single host and list of hosts
|
||||||
try:
|
try:
|
||||||
# Resolve all hosts at once for parallel DNS resolution
|
# Resolve all hosts at once for parallel DNS resolution
|
||||||
@@ -344,21 +344,22 @@ def run_ota_impl_(
|
|||||||
perform_ota(sock, password, file_handle, filename)
|
perform_ota(sock, password, file_handle, filename)
|
||||||
except OTAError as err:
|
except OTAError as err:
|
||||||
_LOGGER.error(str(err))
|
_LOGGER.error(str(err))
|
||||||
return 1
|
return 1, None
|
||||||
finally:
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
return 0
|
# Successfully uploaded to sa[0]
|
||||||
|
return 0, sa[0]
|
||||||
|
|
||||||
_LOGGER.error("Connection failed.")
|
_LOGGER.error("Connection failed.")
|
||||||
return 1
|
return 1, None
|
||||||
|
|
||||||
|
|
||||||
def run_ota(
|
def run_ota(
|
||||||
remote_host: str | list[str], remote_port: int, password: str, filename: str
|
remote_host: str | list[str], remote_port: int, password: str, filename: str
|
||||||
) -> int:
|
) -> tuple[int, str | None]:
|
||||||
try:
|
try:
|
||||||
return run_ota_impl_(remote_host, remote_port, password, filename)
|
return run_ota_impl_(remote_host, remote_port, password, filename)
|
||||||
except OTAError as err:
|
except OTAError as err:
|
||||||
_LOGGER.error(err)
|
_LOGGER.error(err)
|
||||||
return 1
|
return 1, None
|
||||||
|
Reference in New Issue
Block a user