Open Dilbert66 opened 3 months ago
Any logs? I have tested it on C3 and S3 and no issues.
I'm doing a few more tests. I suspect it's a custom component I'm loading that is affecting it as when I use a barebones config, the ota component loads fine in safe mode. I will post more info later.
Ok, found the culprit. I thought I had commented that out when testing. Anyhow it's an on_begin action under the ota that's causing the failure:
ota:
password: !secret ota_password
platform: esphome
on_begin:
switch.turn_off: connection_status_switch
ok, i see what is happening. When a trigger event is added, the preprocessing delays adding the ota component to the components queue which happesn after the safe_mode return .
// ota.esphome:
// platform: esphome
// password: !secret 'ota_password'
// on_begin:
// - then:
// - switch.turn_off:
// id: connection_status_switch
// type_id: switch__turnoffaction_id
// automation_id: automation_id_3
// trigger_id: ota_otastarttrigger_id
// id: esphome_esphomeotacomponent_id
// version: 2
// port: 3232
esphome_esphomeotacomponent_id = new esphome::ESPHomeOTAComponent();
ota_otastarttrigger_id = new ota::OTAStartTrigger(esphome_esphomeotacomponent_id);
automation_id_3 = new Automation<>(ota_otastarttrigger_id);
### on a no trigger setup, the ota component setup is normally done here and added to the queue. But since in this case, it happens later in the process after the "should_enter_safe_mode" check, it never gets added to the queue and thus is not seen in the safe_mode reboot.
// safe_mode:
// id: safe_mode_safemodecomponent_id
// boot_is_good_after: 1min
// disabled: false
// num_attempts: 10
// reboot_timeout: 5min
safe_mode_safemodecomponent_id = new safe_mode::SafeModeComponent();
safe_mode_safemodecomponent_id->set_component_source("safe_mode");
App.register_component(safe_mode_safemodecomponent_id);
if (safe_mode_safemodecomponent_id->should_enter_safe_mode(10, 300000, 60000)) return;
In the "esphome\ota\__init__.py" file, moving the await for the ota_to_code trigger setup after the component registration fixes the issue on my system as shown below:
@coroutine_with_priority(52.0)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await ota_to_code(var, config) <------- move this line to
cg.add(var.set_port(config[CONF_PORT]))
if CONF_PASSWORD in config:
cg.add(var.set_auth_password(config[CONF_PASSWORD]))
cg.add_define("USE_OTA_PASSWORD")
cg.add_define("USE_OTA_VERSION", config[CONF_VERSION])
await cg.register_component(var, config)
<----- here
The problem
Latest changes related to safe_mode and OTA configuration seems to have broken the ability to do an OTA update if the device goes into safe_mode (either manually via a switch or via 10 failed boot attempts) when there is an on_begin action specified for the ota: I keep getting connection refused. When the on_begin section is on, the esphome.ota component does not load (no log dump display) during transition to safe_mode. The esphome.ota does show up fine and ota works when the offending on_begin is removed.
My safe mode and ota config options:
Which version of ESPHome has the issue?
2024.6.2
What type of installation are you using?
Home Assistant Add-on
Which version of Home Assistant has the issue?
Core: 2024.6.4
What platform are you using?
ESP32
Board
ESP32-c3 and esp32-d1 mini
Component causing the issue
OTA and safe_mode
Example YAML snippet
No response
Anything in the logs that might be useful for us?
No response
Additional information
No response