1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-26 12:43:48 +00:00

[openthread] Fix OTA by populating CORE.address with device's mDNS address (#11095)

Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
Daniel Stiner
2025-10-22 14:07:01 -07:00
committed by GitHub
parent 1c67a61945
commit f2de8df556
6 changed files with 34 additions and 9 deletions

View File

@@ -99,7 +99,11 @@ const std::string &get_use_address() {
return wifi::global_wifi_component->get_use_address(); return wifi::global_wifi_component->get_use_address();
#endif #endif
#if !defined(USE_ETHERNET) && !defined(USE_MODEM) && !defined(USE_WIFI) #ifdef USE_OPENTHREAD
return openthread::global_openthread_component->get_use_address();
#endif
#if !defined(USE_ETHERNET) && !defined(USE_MODEM) && !defined(USE_WIFI) && !defined(USE_OPENTHREAD)
// Fallback when no network component is defined (e.g., host platform) // Fallback when no network component is defined (e.g., host platform)
static const std::string empty; static const std::string empty;
return empty; return empty;

View File

@@ -8,8 +8,10 @@ from esphome.components.esp32 import (
) )
from esphome.components.mdns import MDNSComponent, enable_mdns_storage from esphome.components.mdns import MDNSComponent, enable_mdns_storage
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID, CONF_USE_ADDRESS
from esphome.core import CORE
import esphome.final_validate as fv import esphome.final_validate as fv
from esphome.types import ConfigType
from .const import ( from .const import (
CONF_DEVICE_TYPE, CONF_DEVICE_TYPE,
@@ -108,6 +110,12 @@ _CONNECTION_SCHEMA = cv.Schema(
) )
def _validate(config: ConfigType) -> ConfigType:
if CONF_USE_ADDRESS not in config:
config[CONF_USE_ADDRESS] = f"{CORE.name}.local"
return config
def _require_vfs_select(config): def _require_vfs_select(config):
"""Register VFS select requirement during config validation.""" """Register VFS select requirement during config validation."""
# OpenThread uses esp_vfs_eventfd which requires VFS select support # OpenThread uses esp_vfs_eventfd which requires VFS select support
@@ -126,11 +134,13 @@ CONFIG_SCHEMA = cv.All(
), ),
cv.Optional(CONF_FORCE_DATASET): cv.boolean, cv.Optional(CONF_FORCE_DATASET): cv.boolean,
cv.Optional(CONF_TLV): cv.string_strict, cv.Optional(CONF_TLV): cv.string_strict,
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
} }
).extend(_CONNECTION_SCHEMA), ).extend(_CONNECTION_SCHEMA),
cv.has_exactly_one_key(CONF_NETWORK_KEY, CONF_TLV), cv.has_exactly_one_key(CONF_NETWORK_KEY, CONF_TLV),
cv.only_with_esp_idf, cv.only_with_esp_idf,
only_on_variant(supported=[VARIANT_ESP32C6, VARIANT_ESP32H2]), only_on_variant(supported=[VARIANT_ESP32C6, VARIANT_ESP32H2]),
_validate,
_require_vfs_select, _require_vfs_select,
) )
@@ -155,6 +165,7 @@ async def to_code(config):
enable_mdns_storage() enable_mdns_storage()
ot = cg.new_Pvariable(config[CONF_ID]) ot = cg.new_Pvariable(config[CONF_ID])
cg.add(ot.set_use_address(config[CONF_USE_ADDRESS]))
await cg.register_component(ot, config) await cg.register_component(ot, config)
srp = cg.new_Pvariable(config[CONF_SRP_ID]) srp = cg.new_Pvariable(config[CONF_SRP_ID])

View File

@@ -252,6 +252,12 @@ void OpenThreadComponent::on_factory_reset(std::function<void()> callback) {
ESP_LOGD(TAG, "Waiting on Confirmation Removal SRP Host and Services"); ESP_LOGD(TAG, "Waiting on Confirmation Removal SRP Host and Services");
} }
// set_use_address() is guaranteed to be called during component setup by Python code generation,
// so use_address_ will always be valid when get_use_address() is called - no fallback needed.
const std::string &OpenThreadComponent::get_use_address() const { return this->use_address_; }
void OpenThreadComponent::set_use_address(const std::string &use_address) { this->use_address_ = use_address; }
} // namespace openthread } // namespace openthread
} // namespace esphome } // namespace esphome

View File

@@ -33,11 +33,15 @@ class OpenThreadComponent : public Component {
void on_factory_reset(std::function<void()> callback); void on_factory_reset(std::function<void()> callback);
void defer_factory_reset_external_callback(); void defer_factory_reset_external_callback();
const std::string &get_use_address() const;
void set_use_address(const std::string &use_address);
protected: protected:
std::optional<otIp6Address> get_omr_address_(InstanceLock &lock); std::optional<otIp6Address> get_omr_address_(InstanceLock &lock);
bool teardown_started_{false}; bool teardown_started_{false};
bool teardown_complete_{false}; bool teardown_complete_{false};
std::function<void()> factory_reset_external_callback_; std::function<void()> factory_reset_external_callback_;
std::string use_address_;
}; };
extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)

View File

@@ -636,11 +636,9 @@ class EsphomeCore:
if self.config is None: if self.config is None:
raise ValueError("Config has not been loaded yet") raise ValueError("Config has not been loaded yet")
if CONF_WIFI in self.config: for network_type in (CONF_WIFI, CONF_ETHERNET, CONF_OPENTHREAD):
return self.config[CONF_WIFI][CONF_USE_ADDRESS] if network_type in self.config:
return self.config[network_type][CONF_USE_ADDRESS]
if CONF_ETHERNET in self.config:
return self.config[CONF_ETHERNET][CONF_USE_ADDRESS]
if CONF_OPENTHREAD in self.config: if CONF_OPENTHREAD in self.config:
return f"{self.name}.local" return f"{self.name}.local"

View File

@@ -571,9 +571,11 @@ class TestEsphomeCore:
assert target.address == "4.3.2.1" assert target.address == "4.3.2.1"
def test_address__openthread(self, target): def test_address__openthread(self, target):
target.name = "test-device"
target.config = {} target.config = {}
target.config[const.CONF_OPENTHREAD] = {} target.config[const.CONF_OPENTHREAD] = {
const.CONF_USE_ADDRESS: "test-device.local"
}
target.name = "test-device"
assert target.address == "test-device.local" assert target.address == "test-device.local"