mirror of
https://github.com/esphome/esphome.git
synced 2025-10-08 21:03:49 +01:00
Improve dualstack and IPv6 support (#5449)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
@@ -207,14 +207,13 @@ void WiFiComponent::set_fast_connect(bool fast_connect) { this->fast_connect_ =
|
||||
void WiFiComponent::set_btm(bool btm) { this->btm_ = btm; }
|
||||
void WiFiComponent::set_rrm(bool rrm) { this->rrm_ = rrm; }
|
||||
#endif
|
||||
|
||||
network::IPAddress WiFiComponent::get_ip_address() {
|
||||
network::IPAddresses WiFiComponent::get_ip_addresses() {
|
||||
if (this->has_sta())
|
||||
return this->wifi_sta_ip();
|
||||
return this->wifi_sta_ip_addresses();
|
||||
|
||||
#ifdef USE_WIFI_AP
|
||||
if (this->has_ap())
|
||||
return this->wifi_soft_ap_ip();
|
||||
return {this->wifi_soft_ap_ip()};
|
||||
#endif // USE_WIFI_AP
|
||||
|
||||
return {};
|
||||
@@ -412,7 +411,11 @@ void WiFiComponent::print_connect_params_() {
|
||||
return;
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " SSID: " LOG_SECRET("'%s'"), wifi_ssid().c_str());
|
||||
ESP_LOGCONFIG(TAG, " IP Address: %s", wifi_sta_ip().str().c_str());
|
||||
for (auto &ip : wifi_sta_ip_addresses()) {
|
||||
if (ip.is_set()) {
|
||||
ESP_LOGCONFIG(TAG, " IP Address: %s", ip.str().c_str());
|
||||
}
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " BSSID: " LOG_SECRET("%02X:%02X:%02X:%02X:%02X:%02X"), bssid[0], bssid[1], bssid[2], bssid[3],
|
||||
bssid[4], bssid[5]);
|
||||
ESP_LOGCONFIG(TAG, " Hostname: '%s'", App.get_name().c_str());
|
||||
|
@@ -258,7 +258,7 @@ class WiFiComponent : public Component {
|
||||
#endif
|
||||
|
||||
network::IPAddress get_dns_address(int num);
|
||||
network::IPAddress get_ip_address();
|
||||
network::IPAddresses get_ip_addresses();
|
||||
std::string get_use_address() const;
|
||||
void set_use_address(const std::string &use_address);
|
||||
|
||||
@@ -293,7 +293,7 @@ class WiFiComponent : public Component {
|
||||
});
|
||||
}
|
||||
|
||||
network::IPAddress wifi_sta_ip();
|
||||
network::IPAddresses wifi_sta_ip_addresses();
|
||||
std::string wifi_ssid();
|
||||
bssid_t wifi_bssid();
|
||||
|
||||
@@ -396,6 +396,10 @@ class WiFiComponent : public Component {
|
||||
bool rrm_{false};
|
||||
#endif
|
||||
bool enable_on_boot_;
|
||||
bool got_ipv4_address_{false};
|
||||
#if USE_NETWORK_IPV6
|
||||
uint8_t num_ipv6_addresses_{0};
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
Trigger<> *connect_trigger_{new Trigger<>()};
|
||||
Trigger<> *disconnect_trigger_{new Trigger<>()};
|
||||
|
@@ -131,7 +131,7 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||
// TODO: is this needed?
|
||||
#if LWIP_IPV6
|
||||
dns.type = IPADDR_TYPE_V4;
|
||||
#endif
|
||||
#endif /* LWIP_IPV6 */
|
||||
if (manual_ip->dns1.is_set()) {
|
||||
dns = manual_ip->dns1;
|
||||
dns_setserver(0, &dns);
|
||||
@@ -144,12 +144,36 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||
return true;
|
||||
}
|
||||
|
||||
network::IPAddress WiFiComponent::wifi_sta_ip() {
|
||||
network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() {
|
||||
if (!this->has_sta())
|
||||
return {};
|
||||
network::IPAddresses addresses;
|
||||
tcpip_adapter_ip_info_t ip;
|
||||
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip);
|
||||
return network::IPAddress(&ip.ip);
|
||||
esp_err_t err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGV(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err));
|
||||
// TODO: do something smarter
|
||||
// return false;
|
||||
} else {
|
||||
addresses[0] = network::IPAddress(&ip.ip);
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
ip6_addr_t ipv6;
|
||||
err = tcpip_adapter_get_ip6_global(TCPIP_ADAPTER_IF_STA, &ipv6);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGV(TAG, "esp_netif_get_ip6_gobal failed: %s", esp_err_to_name(err));
|
||||
} else {
|
||||
addresses[1] = network::IPAddress(&ipv6);
|
||||
}
|
||||
err = tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_STA, &ipv6);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGV(TAG, "esp_netif_get_ip6_linklocal failed: %s", esp_err_to_name(err));
|
||||
} else {
|
||||
addresses[2] = network::IPAddress(&ipv6);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
bool WiFiComponent::wifi_apply_hostname_() {
|
||||
@@ -440,9 +464,9 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
|
||||
buf[it.ssid_len] = '\0';
|
||||
ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf,
|
||||
format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode));
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
this->set_timeout(100, [] { WiFi.enableIpV6(); });
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -494,18 +518,26 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
|
||||
auto it = info.got_ip.ip_info;
|
||||
ESP_LOGV(TAG, "Event: Got IP static_ip=%s gateway=%s", format_ip4_addr(it.ip).c_str(),
|
||||
format_ip4_addr(it.gw).c_str());
|
||||
this->got_ipv4_address_ = true;
|
||||
#if USE_NETWORK_IPV6
|
||||
s_sta_connecting = this->num_ipv6_addresses_ < USE_NETWORK_MIN_IPV6_ADDR_COUNT;
|
||||
#else
|
||||
s_sta_connecting = false;
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
break;
|
||||
}
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: {
|
||||
auto it = info.got_ip6.ip6_info;
|
||||
ESP_LOGV(TAG, "Got IPv6 address=" IPV6STR, IPV62STR(it.ip));
|
||||
this->num_ipv6_addresses_++;
|
||||
s_sta_connecting = !(this->got_ipv4_address_ & (this->num_ipv6_addresses_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT));
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: {
|
||||
ESP_LOGV(TAG, "Event: Lost IP");
|
||||
this->got_ipv4_address_ = false;
|
||||
break;
|
||||
}
|
||||
case ESPHOME_EVENT_ID_WIFI_AP_START: {
|
||||
|
@@ -17,10 +17,8 @@ extern "C" {
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#include "lwip/apps/sntp.h"
|
||||
#if LWIP_IPV6
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#include <AddrList.h>
|
||||
#endif
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0)
|
||||
#include "LwipDhcpServer.h"
|
||||
#define wifi_softap_set_dhcps_lease(lease) dhcpSoftAP.set_dhcps_lease(lease)
|
||||
@@ -185,12 +183,15 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
network::IPAddress WiFiComponent::wifi_sta_ip() {
|
||||
network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() {
|
||||
if (!this->has_sta())
|
||||
return {};
|
||||
struct ip_info ip {};
|
||||
wifi_get_ip_info(STATION_IF, &ip);
|
||||
return network::IPAddress(&ip.ip);
|
||||
network::IPAddresses addresses;
|
||||
uint8_t index = 0;
|
||||
for (auto &addr : addrList) {
|
||||
addresses[index++] = addr.ipFromNetifNum();
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
bool WiFiComponent::wifi_apply_hostname_() {
|
||||
const std::string &hostname = App.get_name();
|
||||
@@ -327,17 +328,20 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_IPV6
|
||||
for (bool configured = false; !configured;) {
|
||||
#if USE_NETWORK_IPV6
|
||||
bool connected = false;
|
||||
while (!connected) {
|
||||
uint8_t ipv6_addr_count = 0;
|
||||
for (auto addr : addrList) {
|
||||
ESP_LOGV(TAG, "Address %s", addr.toString().c_str());
|
||||
if ((configured = !addr.isLocal() && addr.isV6())) {
|
||||
break;
|
||||
if (addr.isV6()) {
|
||||
ipv6_addr_count++;
|
||||
}
|
||||
}
|
||||
delay(500); // NOLINT
|
||||
connected = (ipv6_addr_count >= USE_NETWORK_MIN_IPV6_ADDR_COUNT);
|
||||
}
|
||||
#endif
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
if (ap.get_channel().has_value()) {
|
||||
ret = wifi_set_channel(*ap.get_channel());
|
||||
|
@@ -39,14 +39,11 @@ static const char *const TAG = "wifi_esp32";
|
||||
static EventGroupHandle_t s_wifi_event_group; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static QueueHandle_t s_event_queue; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static esp_netif_t *s_sta_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
#ifdef USE_WIFI_AP
|
||||
static esp_netif_t *s_ap_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
#endif // USE_WIFI_AP
|
||||
|
||||
static esp_netif_t *s_ap_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
#endif // USE_WIFI_AP
|
||||
static bool s_sta_started = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_sta_connected = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_sta_got_ip = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_ap_started = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_sta_connect_not_found = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
static bool s_sta_connect_error = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
@@ -66,9 +63,9 @@ struct IDFWiFiEvent {
|
||||
wifi_event_ap_probe_req_rx_t ap_probe_req_rx;
|
||||
wifi_event_bss_rssi_low_t bss_rssi_low;
|
||||
ip_event_got_ip_t ip_got_ip;
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
ip_event_got_ip6_t ip_got_ip6;
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
ip_event_ap_staipassigned_t ip_ap_staipassigned;
|
||||
} data;
|
||||
};
|
||||
@@ -92,7 +89,7 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi
|
||||
memcpy(&event.data.sta_disconnected, event_data, sizeof(wifi_event_sta_disconnected_t));
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
memcpy(&event.data.ip_got_ip, event_data, sizeof(ip_event_got_ip_t));
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_GOT_IP6) {
|
||||
memcpy(&event.data.ip_got_ip6, event_data, sizeof(ip_event_got_ip6_t));
|
||||
#endif
|
||||
@@ -411,7 +408,6 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
||||
// may be called from wifi_station_connect
|
||||
s_sta_connecting = true;
|
||||
s_sta_connected = false;
|
||||
s_sta_got_ip = false;
|
||||
s_sta_connect_error = false;
|
||||
s_sta_connect_not_found = false;
|
||||
|
||||
@@ -476,17 +472,29 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||
return true;
|
||||
}
|
||||
|
||||
network::IPAddress WiFiComponent::wifi_sta_ip() {
|
||||
network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() {
|
||||
if (!this->has_sta())
|
||||
return {};
|
||||
network::IPAddresses addresses;
|
||||
esp_netif_ip_info_t ip;
|
||||
esp_err_t err = esp_netif_get_ip_info(s_sta_netif, &ip);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGV(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err));
|
||||
// TODO: do something smarter
|
||||
// return false;
|
||||
} else {
|
||||
addresses[0] = network::IPAddress(&ip.ip);
|
||||
}
|
||||
return network::IPAddress(&ip.ip);
|
||||
#if USE_NETWORK_IPV6
|
||||
struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
|
||||
uint8_t count = 0;
|
||||
count = esp_netif_get_all_ip6(s_sta_netif, if_ip6s);
|
||||
assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES);
|
||||
for (int i = 0; i < count; i++) {
|
||||
addresses[i + 1] = network::IPAddress(&if_ip6s[i]);
|
||||
}
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
return addresses;
|
||||
}
|
||||
|
||||
bool WiFiComponent::wifi_apply_hostname_() {
|
||||
@@ -521,7 +529,7 @@ const char *get_auth_mode_str(uint8_t mode) {
|
||||
std::string format_ip4_addr(const esp_ip4_addr_t &ip) { return str_snprintf(IPSTR, 15, IP2STR(&ip)); }
|
||||
#if LWIP_IPV6
|
||||
std::string format_ip6_addr(const esp_ip6_addr_t &ip) { return str_snprintf(IPV6STR, 39, IPV62STR(ip)); }
|
||||
#endif
|
||||
#endif /* LWIP_IPV6 */
|
||||
const char *get_disconnect_reason_str(uint8_t reason) {
|
||||
switch (reason) {
|
||||
case WIFI_REASON_AUTH_EXPIRE:
|
||||
@@ -658,22 +666,23 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) {
|
||||
|
||||
} else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_STA_GOT_IP) {
|
||||
const auto &it = data->data.ip_got_ip;
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
esp_netif_create_ip6_linklocal(s_sta_netif);
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
ESP_LOGV(TAG, "Event: Got IP static_ip=%s gateway=%s", format_ip4_addr(it.ip_info.ip).c_str(),
|
||||
format_ip4_addr(it.ip_info.gw).c_str());
|
||||
s_sta_got_ip = true;
|
||||
this->got_ipv4_address_ = true;
|
||||
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
} else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_GOT_IP6) {
|
||||
const auto &it = data->data.ip_got_ip6;
|
||||
ESP_LOGV(TAG, "Event: Got IPv6 address=%s", format_ip6_addr(it.ip6_info.ip).c_str());
|
||||
#endif /* ENABLE_IPV6 */
|
||||
this->num_ipv6_addresses_++;
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
} else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_STA_LOST_IP) {
|
||||
ESP_LOGV(TAG, "Event: Lost IP");
|
||||
s_sta_got_ip = false;
|
||||
this->got_ipv4_address_ = false;
|
||||
|
||||
} else if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_SCAN_DONE) {
|
||||
const auto &it = data->data.sta_scan_done;
|
||||
@@ -737,8 +746,14 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) {
|
||||
}
|
||||
|
||||
WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() {
|
||||
if (s_sta_connected && s_sta_got_ip) {
|
||||
if (s_sta_connected && this->got_ipv4_address_) {
|
||||
#if USE_NETWORK_IPV6
|
||||
if (this->num_ipv6_addresses_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT) {
|
||||
return WiFiSTAConnectStatus::CONNECTED;
|
||||
}
|
||||
#else
|
||||
return WiFiSTAConnectStatus::CONNECTED;
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
}
|
||||
if (s_sta_connect_error) {
|
||||
return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
|
||||
|
@@ -81,7 +81,7 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||
return true;
|
||||
}
|
||||
|
||||
network::IPAddress WiFiComponent::wifi_sta_ip() {
|
||||
network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() {
|
||||
if (!this->has_sta())
|
||||
return {};
|
||||
return {WiFi.localIP()};
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
#include <AddrList.h>
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/hal.h"
|
||||
@@ -173,7 +174,14 @@ std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); }
|
||||
int8_t WiFiComponent::wifi_rssi() { return WiFi.RSSI(); }
|
||||
int32_t WiFiComponent::wifi_channel_() { return WiFi.channel(); }
|
||||
|
||||
network::IPAddress WiFiComponent::wifi_sta_ip() { return {(const ip_addr_t *) WiFi.localIP()}; }
|
||||
network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() {
|
||||
network::IPAddresses addresses;
|
||||
uint8_t index = 0;
|
||||
for (auto addr : addrList) {
|
||||
addresses[index++] = addr.ipFromNetifNum();
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {(const ip_addr_t *) WiFi.subnetMask()}; }
|
||||
network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {(const ip_addr_t *) WiFi.gatewayIP()}; }
|
||||
network::IPAddress WiFiComponent::wifi_dns_ip_(int num) {
|
||||
|
Reference in New Issue
Block a user