[openthread] add poll period for mtd devices (#11374)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
rwrozelle
2025-11-05 22:57:31 -05:00
committed by GitHub
parent 895d76ca03
commit 26607713bb
6 changed files with 71 additions and 3 deletions

View File

@@ -9,7 +9,7 @@ from esphome.components.esp32 import (
from esphome.components.mdns import MDNSComponent, enable_mdns_storage
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID, CONF_USE_ADDRESS
from esphome.core import CORE
from esphome.core import CORE, TimePeriodMilliseconds
import esphome.final_validate as fv
from esphome.types import ConfigType
@@ -22,6 +22,7 @@ from .const import (
CONF_NETWORK_KEY,
CONF_NETWORK_NAME,
CONF_PAN_ID,
CONF_POLL_PERIOD,
CONF_PSKC,
CONF_SRP_ID,
CONF_TLV,
@@ -89,7 +90,7 @@ def set_sdkconfig_options(config):
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_SRP_CLIENT", True)
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_SRP_CLIENT_MAX_SERVICES", 5)
# TODO: Add suport for sleepy end devices
# TODO: Add suport for synchronized sleepy end devices (SSED)
add_idf_sdkconfig_option(f"CONFIG_OPENTHREAD_{config.get(CONF_DEVICE_TYPE)}", True)
@@ -113,6 +114,17 @@ _CONNECTION_SCHEMA = cv.Schema(
def _validate(config: ConfigType) -> ConfigType:
if CONF_USE_ADDRESS not in config:
config[CONF_USE_ADDRESS] = f"{CORE.name}.local"
device_type = config.get(CONF_DEVICE_TYPE)
poll_period = config.get(CONF_POLL_PERIOD)
if (
device_type == "FTD"
and poll_period
and poll_period > TimePeriodMilliseconds(milliseconds=0)
):
raise cv.Invalid(
f"{CONF_POLL_PERIOD} can only be used with {CONF_DEVICE_TYPE}: MTD"
)
return config
@@ -135,6 +147,7 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_FORCE_DATASET): cv.boolean,
cv.Optional(CONF_TLV): cv.string_strict,
cv.Optional(CONF_USE_ADDRESS): cv.string_strict,
cv.Optional(CONF_POLL_PERIOD): cv.positive_time_period_milliseconds,
}
).extend(_CONNECTION_SCHEMA),
cv.has_exactly_one_key(CONF_NETWORK_KEY, CONF_TLV),
@@ -167,6 +180,8 @@ async def to_code(config):
ot = cg.new_Pvariable(config[CONF_ID])
cg.add(ot.set_use_address(config[CONF_USE_ADDRESS]))
await cg.register_component(ot, config)
if (poll_period := config.get(CONF_POLL_PERIOD)) is not None:
cg.add(ot.set_poll_period(poll_period))
srp = cg.new_Pvariable(config[CONF_SRP_ID])
mdns_component = await cg.get_variable(config[CONF_MDNS_ID])

View File

@@ -6,6 +6,7 @@ CONF_MESH_LOCAL_PREFIX = "mesh_local_prefix"
CONF_NETWORK_NAME = "network_name"
CONF_NETWORK_KEY = "network_key"
CONF_PAN_ID = "pan_id"
CONF_POLL_PERIOD = "poll_period"
CONF_PSKC = "pskc"
CONF_SRP_ID = "srp_id"
CONF_TLV = "tlv"

View File

@@ -29,6 +29,23 @@ OpenThreadComponent *global_openthread_component = // NOLINT(cppcoreguidelines-
OpenThreadComponent::OpenThreadComponent() { global_openthread_component = this; }
void OpenThreadComponent::dump_config() {
ESP_LOGCONFIG(TAG, "Open Thread:");
#if CONFIG_OPENTHREAD_FTD
ESP_LOGCONFIG(TAG, " Device Type: FTD");
#elif CONFIG_OPENTHREAD_MTD
ESP_LOGCONFIG(TAG, " Device Type: MTD");
// TBD: Synchronized Sleepy End Device
if (this->poll_period > 0) {
ESP_LOGCONFIG(TAG, " Device is configured as Sleepy End Device (SED)");
uint32_t duration = this->poll_period / 1000;
ESP_LOGCONFIG(TAG, " Poll Period: %" PRIu32 "s", duration);
} else {
ESP_LOGCONFIG(TAG, " Device is configured as Minimal End Device (MED)");
}
#endif
}
bool OpenThreadComponent::is_connected() {
auto lock = InstanceLock::try_acquire(100);
if (!lock) {

View File

@@ -22,6 +22,7 @@ class OpenThreadComponent : public Component {
public:
OpenThreadComponent();
~OpenThreadComponent();
void dump_config() override;
void setup() override;
bool teardown() override;
float get_setup_priority() const override { return setup_priority::WIFI; }
@@ -35,6 +36,9 @@ class OpenThreadComponent : public Component {
const char *get_use_address() const;
void set_use_address(const char *use_address);
#if CONFIG_OPENTHREAD_MTD
void set_poll_period(uint32_t poll_period) { this->poll_period = poll_period; }
#endif
protected:
std::optional<otIp6Address> get_omr_address_(InstanceLock &lock);
@@ -46,6 +50,9 @@ class OpenThreadComponent : public Component {
// Stores a pointer to a string literal (static storage duration).
// ONLY set from Python-generated code with string literals - never dynamic strings.
const char *use_address_{""};
#if CONFIG_OPENTHREAD_MTD
uint32_t poll_period{0};
#endif
};
extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)

View File

@@ -105,6 +105,32 @@ void OpenThreadComponent::ot_main() {
esp_cli_custom_command_init();
#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
otLinkModeConfig link_mode_config = {0};
#if CONFIG_OPENTHREAD_FTD
link_mode_config.mRxOnWhenIdle = true;
link_mode_config.mDeviceType = true;
link_mode_config.mNetworkData = true;
#elif CONFIG_OPENTHREAD_MTD
if (this->poll_period > 0) {
if (otLinkSetPollPeriod(esp_openthread_get_instance(), this->poll_period) != OT_ERROR_NONE) {
ESP_LOGE(TAG, "Failed to set OpenThread pollperiod.");
}
uint32_t link_polling_period = otLinkGetPollPeriod(esp_openthread_get_instance());
ESP_LOGD(TAG, "Link Polling Period: %d", link_polling_period);
}
link_mode_config.mRxOnWhenIdle = this->poll_period == 0;
link_mode_config.mDeviceType = false;
link_mode_config.mNetworkData = false;
#endif
if (otThreadSetLinkMode(esp_openthread_get_instance(), link_mode_config) != OT_ERROR_NONE) {
ESP_LOGE(TAG, "Failed to set OpenThread linkmode.");
}
link_mode_config = otThreadGetLinkMode(esp_openthread_get_instance());
ESP_LOGD(TAG, "Link Mode Device Type: %s", link_mode_config.mDeviceType ? "true" : "false");
ESP_LOGD(TAG, "Link Mode Network Data: %s", link_mode_config.mNetworkData ? "true" : "false");
ESP_LOGD(TAG, "Link Mode RX On When Idle: %s", link_mode_config.mRxOnWhenIdle ? "true" : "false");
// Run the main loop
#if CONFIG_OPENTHREAD_CLI
esp_openthread_cli_create_task();

View File

@@ -2,7 +2,7 @@ network:
enable_ipv6: true
openthread:
device_type: FTD
device_type: MTD
channel: 13
network_name: OpenThread-8f28
network_key: 0xdfd34f0f05cad978ec4e32b0413038ff
@@ -11,3 +11,5 @@ openthread:
pskc: 0xc23a76e98f1a6483639b1ac1271e2e27
mesh_local_prefix: fd53:145f:ed22:ad81::/64
force_dataset: true
use_address: open-thread-test.local
poll_period: 20sec