diff --git a/esphome/components/sendspin/sendspin_hub.cpp b/esphome/components/sendspin/sendspin_hub.cpp index d27c5672eb6..04426b8b1da 100644 --- a/esphome/components/sendspin/sendspin_hub.cpp +++ b/esphome/components/sendspin/sendspin_hub.cpp @@ -3,6 +3,9 @@ #ifdef USE_ESP32 #include "esphome/components/network/util.h" +#ifdef USE_ETHERNET +#include "esphome/components/ethernet/ethernet_component.h" +#endif #ifdef USE_WIFI #include "esphome/components/wifi/wifi_component.h" #endif @@ -63,7 +66,7 @@ void SendspinHub::dump_config() { "Sendspin Hub:\n" " Client ID: %s\n" " Task stack in PSRAM: %s", - get_mac_address_pretty_into_buffer(mac_buf), YESNO(this->task_stack_in_psram_)); + get_client_id_into_buffer(mac_buf), YESNO(this->task_stack_in_psram_)); } // --- Delegating methods --- @@ -89,11 +92,23 @@ void SendspinHub::update_state(sendspin::SendspinClientState state) { } } +const char *SendspinHub::get_client_id_into_buffer(std::span buf) { + // The server matches client_id against the L2 source MAC of the device's multicast traffic. + // ESP-IDF derives the ethernet MAC as base+3 by default on ESP32-S3, so we cannot use the + // eFuse base MAC when ethernet is the active interface. +#ifdef USE_ETHERNET + if (ethernet::global_eth_component != nullptr) { + return ethernet::global_eth_component->get_eth_mac_address_pretty_into_buffer(buf); + } +#endif + return get_mac_address_pretty_into_buffer(buf); +} + sendspin::SendspinClientConfig SendspinHub::build_client_config_() { sendspin::SendspinClientConfig config; char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; - config.client_id = get_mac_address_pretty_into_buffer(mac_buf); + config.client_id = SendspinHub::get_client_id_into_buffer(mac_buf); config.name = App.get_friendly_name(); config.product_name = App.get_name(); config.manufacturer = "ESPHome"; diff --git a/esphome/components/sendspin/sendspin_hub.h b/esphome/components/sendspin/sendspin_hub.h index 12fbf156ea6..c6b1ed97f74 100644 --- a/esphome/components/sendspin/sendspin_hub.h +++ b/esphome/components/sendspin/sendspin_hub.h @@ -35,7 +35,9 @@ namespace esphome::sendspin_ { /// without each subcomponent having to pick a priority independently. Children run /// one step later than hub so they can assume hub's setup() has already completed. namespace sendspin_priority { -inline constexpr float HUB = esphome::setup_priority::PROCESSOR; +// AFTER_WIFI so the hub runs after the wifi/ethernet drivers are up and we can read the active +// interface's MAC for client_id. +inline constexpr float HUB = esphome::setup_priority::AFTER_WIFI; inline constexpr float CHILD = HUB - 1.0f; } // namespace sendspin_priority @@ -149,6 +151,10 @@ class SendspinHub final : public Component, /// @brief Builds the SendspinClientConfig from ESPHome configuration and platform info. sendspin::SendspinClientConfig build_client_config_(); + /// @brief Writes the active network interface's MAC into @p buf and returns its data pointer. + /// Uses the ethernet MAC if ethernet is configured, otherwise the base MAC (used by wifi). + static const char *get_client_id_into_buffer(std::span buf); + // --- SendspinClientListener overrides --- void on_group_update(const sendspin::GroupUpdateObject &group) override; diff --git a/tests/components/sendspin/test-ethernet.esp32-idf.yaml b/tests/components/sendspin/test-ethernet.esp32-idf.yaml new file mode 100644 index 00000000000..069e397d992 --- /dev/null +++ b/tests/components/sendspin/test-ethernet.esp32-idf.yaml @@ -0,0 +1,9 @@ +ethernet: + type: OPENETH + +psram: + mode: quad + +sendspin: + id: sendspin_hub_id + task_stack_in_psram: true