mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 16:38:16 +01:00
Improve dualstack and IPv6 support (#5449)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
5e04914a11
commit
f73518dbeb
26 changed files with 300 additions and 140 deletions
|
@ -22,7 +22,7 @@ CONFIG_SCHEMA = cv.All(
|
|||
async def to_code(config):
|
||||
if CORE.is_esp32 or CORE.is_libretiny:
|
||||
# https://github.com/esphome/AsyncTCP/blob/master/library.json
|
||||
cg.add_library("esphome/AsyncTCP-esphome", "2.0.1")
|
||||
cg.add_library("esphome/AsyncTCP-esphome", "2.1.3")
|
||||
elif CORE.is_esp8266:
|
||||
# https://github.com/esphome/ESPAsyncTCP
|
||||
cg.add_library("esphome/ESPAsyncTCP-esphome", "2.0.0")
|
||||
|
|
|
@ -141,9 +141,13 @@ void ESP32ImprovComponent::loop() {
|
|||
|
||||
std::vector<std::string> urls = {ESPHOME_MY_LINK};
|
||||
#ifdef USE_WEBSERVER
|
||||
auto ip = wifi::global_wifi_component->wifi_sta_ip();
|
||||
for (auto &ip : wifi::global_wifi_component->wifi_sta_ip_addresses()) {
|
||||
if (ip.is_ip4()) {
|
||||
std::string webserver_url = "http://" + ip.str() + ":" + to_string(USE_WEBSERVER_PORT);
|
||||
urls.push_back(webserver_url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::vector<uint8_t> data = improv::build_rpc_response(improv::WIFI_SETTINGS, urls);
|
||||
this->send_response_(data);
|
||||
|
|
|
@ -119,10 +119,10 @@ void EthernetComponent::setup() {
|
|||
ESPHL_ERROR_CHECK(err, "ETH event handler register error");
|
||||
err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &EthernetComponent::got_ip_event_handler, nullptr);
|
||||
ESPHL_ERROR_CHECK(err, "GOT IP event handler register error");
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
err = esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &EthernetComponent::got_ip6_event_handler, nullptr);
|
||||
ESPHL_ERROR_CHECK(err, "GOT IP6 event handler register error");
|
||||
#endif /* ENABLE_IPV6 */
|
||||
ESPHL_ERROR_CHECK(err, "GOT IPv6 event handler register error");
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
/* start Ethernet driver state machine */
|
||||
err = esp_eth_start(this->eth_handle_);
|
||||
|
@ -165,20 +165,6 @@ void EthernetComponent::loop() {
|
|||
this->state_ = EthernetComponentState::CONNECTING;
|
||||
this->start_connect_();
|
||||
}
|
||||
#if ENABLE_IPV6
|
||||
else if (this->got_ipv6_) {
|
||||
esp_ip6_addr_t ip6_addr;
|
||||
if (esp_netif_get_ip6_global(this->eth_netif_, &ip6_addr) == 0 &&
|
||||
esp_netif_ip6_get_addr_type(&ip6_addr) == ESP_IP6_ADDR_IS_GLOBAL) {
|
||||
ESP_LOGCONFIG(TAG, "IPv6 Addr (Global): " IPV6STR, IPV62STR(ip6_addr));
|
||||
} else {
|
||||
esp_netif_get_ip6_linklocal(this->eth_netif_, &ip6_addr);
|
||||
ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(ip6_addr));
|
||||
}
|
||||
|
||||
this->got_ipv6_ = false;
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -234,10 +220,28 @@ float EthernetComponent::get_setup_priority() const { return setup_priority::WIF
|
|||
|
||||
bool EthernetComponent::can_proceed() { return this->is_connected(); }
|
||||
|
||||
network::IPAddress EthernetComponent::get_ip_address() {
|
||||
network::IPAddresses EthernetComponent::get_ip_addresses() {
|
||||
network::IPAddresses addresses;
|
||||
esp_netif_ip_info_t ip;
|
||||
esp_netif_get_ip_info(this->eth_netif_, &ip);
|
||||
return network::IPAddress(&ip.ip);
|
||||
esp_err_t err = esp_netif_get_ip_info(this->eth_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);
|
||||
}
|
||||
#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(this->eth_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;
|
||||
}
|
||||
|
||||
void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event, void *event_data) {
|
||||
|
@ -269,20 +273,33 @@ void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base
|
|||
|
||||
void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data) {
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||
const esp_netif_ip_info_t *ip_info = &event->ip_info;
|
||||
ESP_LOGV(TAG, "[Ethernet event] ETH Got IP " IPSTR, IP2STR(&ip_info->ip));
|
||||
global_eth_component->got_ipv4_address_ = true;
|
||||
#if USE_NETWORK_IPV6
|
||||
global_eth_component->connected_ = global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT;
|
||||
#else
|
||||
global_eth_component->connected_ = true;
|
||||
ESP_LOGV(TAG, "[Ethernet event] ETH Got IP (num=%" PRId32 ")", event_id);
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
}
|
||||
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data) {
|
||||
ESP_LOGV(TAG, "[Ethernet event] ETH Got IP6 (num=%" PRId32 ")", event_id);
|
||||
global_eth_component->got_ipv6_ = true;
|
||||
ip_event_got_ip6_t *event = (ip_event_got_ip6_t *) event_data;
|
||||
ESP_LOGV(TAG, "[Ethernet event] ETH Got IPv6: " IPV6STR, IPV62STR(event->ip6_info.ip));
|
||||
global_eth_component->ipv6_count_ += 1;
|
||||
global_eth_component->connected_ =
|
||||
global_eth_component->got_ipv4_address_ && (global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT);
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
void EthernetComponent::start_connect_() {
|
||||
global_eth_component->got_ipv4_address_ = false;
|
||||
#if USE_NETWORK_IPV6
|
||||
global_eth_component->ipv6_count_ = 0;
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
this->connect_begin_ = millis();
|
||||
this->status_set_warning();
|
||||
|
||||
|
@ -334,12 +351,12 @@ void EthernetComponent::start_connect_() {
|
|||
if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED) {
|
||||
ESPHL_ERROR_CHECK(err, "DHCPC start error");
|
||||
}
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
err = esp_netif_create_ip6_linklocal(this->eth_netif_);
|
||||
if (err != ESP_OK) {
|
||||
ESPHL_ERROR_CHECK(err, "IPv6 local failed");
|
||||
ESPHL_ERROR_CHECK(err, "Enable IPv6 link local failed");
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
}
|
||||
|
||||
this->connect_begin_ = millis();
|
||||
|
@ -362,18 +379,15 @@ void EthernetComponent::dump_connect_params_() {
|
|||
ESP_LOGCONFIG(TAG, " DNS1: %s", network::IPAddress(dns_ip1).str().c_str());
|
||||
ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2).str().c_str());
|
||||
|
||||
#if ENABLE_IPV6
|
||||
if (this->ipv6_count_ > 0) {
|
||||
esp_ip6_addr_t ip6_addr;
|
||||
esp_netif_get_ip6_linklocal(this->eth_netif_, &ip6_addr);
|
||||
ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(ip6_addr));
|
||||
|
||||
if (esp_netif_get_ip6_global(this->eth_netif_, &ip6_addr) == 0 &&
|
||||
esp_netif_ip6_get_addr_type(&ip6_addr) == ESP_IP6_ADDR_IS_GLOBAL) {
|
||||
ESP_LOGCONFIG(TAG, "IPv6 Addr (Global): " IPV6STR, IPV62STR(ip6_addr));
|
||||
#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(this->eth_netif_, if_ip6s);
|
||||
assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES);
|
||||
for (int i = 0; i < count; i++) {
|
||||
ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(if_ip6s[i]));
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class EthernetComponent : public Component {
|
|||
void set_clk_mode(emac_rmii_clock_mode_t clk_mode, emac_rmii_clock_gpio_t clk_gpio);
|
||||
void set_manual_ip(const ManualIP &manual_ip);
|
||||
|
||||
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);
|
||||
bool powerdown();
|
||||
|
@ -87,8 +87,8 @@ class EthernetComponent : public Component {
|
|||
|
||||
bool started_{false};
|
||||
bool connected_{false};
|
||||
bool got_ipv4_address_{false};
|
||||
#if LWIP_IPV6
|
||||
bool got_ipv6_{false};
|
||||
uint8_t ipv6_count_{0};
|
||||
#endif /* LWIP_IPV6 */
|
||||
EthernetComponentState state_{EthernetComponentState::STOPPED};
|
||||
|
|
|
@ -12,19 +12,30 @@ namespace ethernet_info {
|
|||
class IPAddressEthernetInfo : public PollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update() override {
|
||||
auto ip = ethernet::global_eth_component->get_ip_address();
|
||||
if (ip != this->last_ip_) {
|
||||
this->last_ip_ = ip;
|
||||
this->publish_state(network::IPAddress(ip).str());
|
||||
auto ips = ethernet::global_eth_component->get_ip_addresses();
|
||||
if (ips != this->last_ips_) {
|
||||
this->last_ips_ = ips;
|
||||
this->publish_state(ips[0].str());
|
||||
uint8_t sensor = 0;
|
||||
for (auto &ip : ips) {
|
||||
if (ip.is_set()) {
|
||||
if (this->ip_sensors_[sensor] != nullptr) {
|
||||
this->ip_sensors_[sensor]->publish_state(ip.str());
|
||||
sensor++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float get_setup_priority() const override { return setup_priority::ETHERNET; }
|
||||
std::string unique_id() override { return get_mac_address() + "-ethernetinfo"; }
|
||||
void dump_config() override;
|
||||
void add_ip_sensors(uint8_t index, text_sensor::TextSensor *s) { this->ip_sensors_[index] = s; }
|
||||
|
||||
protected:
|
||||
network::IPAddress last_ip_;
|
||||
network::IPAddresses last_ips_;
|
||||
std::array<text_sensor::TextSensor *, 5> ip_sensors_;
|
||||
};
|
||||
|
||||
} // namespace ethernet_info
|
||||
|
|
|
@ -18,17 +18,25 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
{
|
||||
cv.Optional(CONF_IP_ADDRESS): text_sensor.text_sensor_schema(
|
||||
IPAddressEsthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC
|
||||
).extend(cv.polling_component_schema("1s"))
|
||||
)
|
||||
.extend(cv.polling_component_schema("1s"))
|
||||
.extend(
|
||||
{
|
||||
cv.Optional(f"address_{x}"): text_sensor.text_sensor_schema(
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
)
|
||||
for x in range(5)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def setup_conf(config, key):
|
||||
if key in config:
|
||||
conf = config[key]
|
||||
var = await text_sensor.new_text_sensor(conf)
|
||||
await cg.register_component(var, conf)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
await setup_conf(config, CONF_IP_ADDRESS)
|
||||
if conf := config.get(CONF_IP_ADDRESS):
|
||||
ip_info = await text_sensor.new_text_sensor(config[CONF_IP_ADDRESS])
|
||||
await cg.register_component(ip_info, config[CONF_IP_ADDRESS])
|
||||
for x in range(5):
|
||||
if sensor_conf := conf.get(f"address_{x}"):
|
||||
sens = await text_sensor.new_text_sensor(sensor_conf)
|
||||
cg.add(ip_info.add_ip_sensors(x, sens))
|
||||
|
|
|
@ -21,8 +21,13 @@ std::string ImprovBase::get_formatted_next_url_() {
|
|||
// Ip address
|
||||
pos = this->next_url_.find("{{ip_address}}");
|
||||
if (pos != std::string::npos) {
|
||||
std::string ip = network::get_ip_address().str();
|
||||
copy.replace(pos, 14, ip);
|
||||
for (auto &ip : network::get_ip_addresses()) {
|
||||
if (ip.is_ip4()) {
|
||||
std::string ipa = ip.str();
|
||||
copy.replace(pos, 14, ipa);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
|
|
|
@ -155,9 +155,13 @@ std::vector<uint8_t> ImprovSerialComponent::build_rpc_settings_response_(improv:
|
|||
urls.push_back(this->get_formatted_next_url_());
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
auto ip = wifi::global_wifi_component->wifi_sta_ip();
|
||||
for (auto &ip : wifi::global_wifi_component->wifi_sta_ip_addresses()) {
|
||||
if (ip.is_ip4()) {
|
||||
std::string webserver_url = "http://" + ip.str() + ":" + to_string(USE_WEBSERVER_PORT);
|
||||
urls.push_back(webserver_url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::vector<uint8_t> data = improv::build_rpc_response(command, urls, false);
|
||||
return data;
|
||||
|
|
|
@ -91,8 +91,13 @@ void MQTTClientComponent::send_device_info_() {
|
|||
this->publish_json(
|
||||
topic,
|
||||
[](JsonObject root) {
|
||||
auto ip = network::get_ip_address();
|
||||
root["ip"] = ip.str();
|
||||
uint8_t index = 0;
|
||||
for (auto &ip : network::get_ip_addresses()) {
|
||||
if (ip.is_set()) {
|
||||
root["ip" + (index == 0 ? "" : esphome::to_string(index))] = ip.str();
|
||||
index++;
|
||||
}
|
||||
}
|
||||
root["name"] = App.get_name();
|
||||
#ifdef USE_API
|
||||
root["port"] = api::global_api_server->get_port();
|
||||
|
@ -159,14 +164,13 @@ void MQTTClientComponent::start_dnslookup_() {
|
|||
this->dns_resolve_error_ = false;
|
||||
this->dns_resolved_ = false;
|
||||
ip_addr_t addr;
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
#if USE_NETWORK_IPV6
|
||||
err_t err = dns_gethostbyname_addrtype(this->credentials_.address.c_str(), &addr,
|
||||
MQTTClientComponent::dns_found_callback, this, LWIP_DNS_ADDRTYPE_IPV6_IPV4);
|
||||
#else
|
||||
err_t err = dns_gethostbyname_addrtype(this->credentials_.address.c_str(), &addr,
|
||||
MQTTClientComponent::dns_found_callback, this, LWIP_DNS_ADDRTYPE_IPV4);
|
||||
#endif
|
||||
#ifdef USE_ESP8266
|
||||
err_t err = dns_gethostbyname(this->credentials_.address.c_str(), &addr,
|
||||
esphome::mqtt::MQTTClientComponent::dns_found_callback, this);
|
||||
#endif
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
switch (err) {
|
||||
case ERR_OK: {
|
||||
// Got IP immediately
|
||||
|
|
|
@ -5,6 +5,7 @@ from esphome.components.esp32 import add_idf_sdkconfig_option
|
|||
|
||||
from esphome.const import (
|
||||
CONF_ENABLE_IPV6,
|
||||
CONF_MIN_IPV6_ADDR_COUNT,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
|
@ -16,12 +17,14 @@ IPAddress = network_ns.class_("IPAddress")
|
|||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_ENABLE_IPV6, default=False): cv.boolean,
|
||||
cv.Optional(CONF_MIN_IPV6_ADDR_COUNT, default=0): cv.positive_int,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
cg.add_define("ENABLE_IPV6", config[CONF_ENABLE_IPV6])
|
||||
cg.add_define("USE_NETWORK_IPV6", config[CONF_ENABLE_IPV6])
|
||||
cg.add_define("USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT])
|
||||
if CORE.using_esp_idf:
|
||||
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6])
|
||||
add_idf_sdkconfig_option(
|
||||
|
|
|
@ -77,6 +77,13 @@ struct IPAddress {
|
|||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
IPAddress(esp_ip4_addr_t *other_ip) { memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(esp_ip4_addr_t)); }
|
||||
IPAddress(esp_ip_addr_t *other_ip) {
|
||||
#if LWIP_IPV6
|
||||
memcpy((void *) &ip_addr_, (void *) other_ip, sizeof(ip_addr_));
|
||||
#else
|
||||
memcpy((void *) &ip_addr_, (void *) &other_ip->u_addr.ip4, sizeof(ip_addr_));
|
||||
#endif
|
||||
}
|
||||
operator esp_ip_addr_t() const {
|
||||
esp_ip_addr_t tmp;
|
||||
#if LWIP_IPV6
|
||||
|
@ -128,5 +135,7 @@ struct IPAddress {
|
|||
ip_addr_t ip_addr_;
|
||||
};
|
||||
|
||||
using IPAddresses = std::array<IPAddress, 5>;
|
||||
|
||||
} // namespace network
|
||||
} // namespace esphome
|
||||
|
|
|
@ -37,14 +37,14 @@ bool is_disabled() {
|
|||
return false;
|
||||
}
|
||||
|
||||
network::IPAddress get_ip_address() {
|
||||
network::IPAddresses get_ip_addresses() {
|
||||
#ifdef USE_ETHERNET
|
||||
if (ethernet::global_eth_component != nullptr)
|
||||
return ethernet::global_eth_component->get_ip_address();
|
||||
return ethernet::global_eth_component->get_ip_addresses();
|
||||
#endif
|
||||
#ifdef USE_WIFI
|
||||
if (wifi::global_wifi_component != nullptr)
|
||||
return wifi::global_wifi_component->get_ip_address();
|
||||
return wifi::global_wifi_component->get_ip_addresses();
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ bool is_connected();
|
|||
bool is_disabled();
|
||||
/// Get the active network hostname
|
||||
std::string get_use_address();
|
||||
IPAddress get_ip_address();
|
||||
IPAddresses get_ip_addresses();
|
||||
|
||||
} // namespace network
|
||||
} // namespace esphome
|
||||
|
|
|
@ -10,15 +10,15 @@ namespace socket {
|
|||
Socket::~Socket() {}
|
||||
|
||||
std::unique_ptr<Socket> socket_ip(int type, int protocol) {
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
return socket(AF_INET6, type, protocol);
|
||||
#else
|
||||
return socket(AF_INET, type, protocol);
|
||||
#endif
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
}
|
||||
|
||||
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) {
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
if (addrlen < sizeof(sockaddr_in6)) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
|
@ -47,11 +47,11 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::stri
|
|||
server->sin_addr.s_addr = inet_addr(ip_address.c_str());
|
||||
server->sin_port = htons(port);
|
||||
return sizeof(sockaddr_in);
|
||||
#endif
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
}
|
||||
|
||||
socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port) {
|
||||
#if ENABLE_IPV6
|
||||
#if USE_NETWORK_IPV6
|
||||
if (addrlen < sizeof(sockaddr_in6)) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
|
@ -73,7 +73,7 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po
|
|||
server->sin_addr.s_addr = ESPHOME_INADDR_ANY;
|
||||
server->sin_port = htons(port);
|
||||
return sizeof(sockaddr_in);
|
||||
#endif
|
||||
#endif /* USE_NETWORK_IPV6 */
|
||||
}
|
||||
} // namespace socket
|
||||
} // namespace esphome
|
||||
|
|
|
@ -32,8 +32,12 @@ void WakeOnLanButton::press_action() {
|
|||
bool end_status = false;
|
||||
IPAddress broadcast = IPAddress(255, 255, 255, 255);
|
||||
#ifdef USE_ESP8266
|
||||
begin_status = this->udp_client_.beginPacketMulticast(broadcast, 9,
|
||||
IPAddress((ip_addr_t) esphome::network::get_ip_address()), 128);
|
||||
for (auto ip : esphome::network::get_ip_addresses()) {
|
||||
if (ip.is_ip4()) {
|
||||
begin_status = this->udp_client_.beginPacketMulticast(broadcast, 9, ip, 128);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ESP32
|
||||
begin_status = this->udp_client_.beginPacket(broadcast, 9);
|
||||
|
|
|
@ -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 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,9 +746,15 @@ 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) {
|
||||
|
|
|
@ -37,7 +37,16 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
{
|
||||
cv.Optional(CONF_IP_ADDRESS): text_sensor.text_sensor_schema(
|
||||
IPAddressWiFiInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC
|
||||
).extend(cv.polling_component_schema("1s")),
|
||||
)
|
||||
.extend(cv.polling_component_schema("1s"))
|
||||
.extend(
|
||||
{
|
||||
cv.Optional(f"address_{x}"): text_sensor.text_sensor_schema(
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
)
|
||||
for x in range(5)
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_SCAN_RESULTS): text_sensor.text_sensor_schema(
|
||||
ScanResultsWiFiInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC
|
||||
).extend(cv.polling_component_schema("60s")),
|
||||
|
@ -65,9 +74,15 @@ async def setup_conf(config, key):
|
|||
|
||||
|
||||
async def to_code(config):
|
||||
await setup_conf(config, CONF_IP_ADDRESS)
|
||||
await setup_conf(config, CONF_SSID)
|
||||
await setup_conf(config, CONF_BSSID)
|
||||
await setup_conf(config, CONF_MAC_ADDRESS)
|
||||
await setup_conf(config, CONF_SCAN_RESULTS)
|
||||
await setup_conf(config, CONF_DNS_ADDRESS)
|
||||
if conf := config.get(CONF_IP_ADDRESS):
|
||||
wifi_info = await text_sensor.new_text_sensor(config[CONF_IP_ADDRESS])
|
||||
await cg.register_component(wifi_info, config[CONF_IP_ADDRESS])
|
||||
for x in range(5):
|
||||
if sensor_conf := conf.get(f"address_{x}"):
|
||||
sens = await text_sensor.new_text_sensor(sensor_conf)
|
||||
cg.add(wifi_info.add_ip_sensors(x, sens))
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/text_sensor/text_sensor.h"
|
||||
#include "esphome/components/wifi/wifi_component.h"
|
||||
#include <array>
|
||||
|
||||
namespace esphome {
|
||||
namespace wifi_info {
|
||||
|
@ -10,18 +11,29 @@ namespace wifi_info {
|
|||
class IPAddressWiFiInfo : public PollingComponent, public text_sensor::TextSensor {
|
||||
public:
|
||||
void update() override {
|
||||
auto ip = wifi::global_wifi_component->wifi_sta_ip();
|
||||
if (ip != this->last_ip_) {
|
||||
this->last_ip_ = ip;
|
||||
this->publish_state(ip.str());
|
||||
auto ips = wifi::global_wifi_component->wifi_sta_ip_addresses();
|
||||
if (ips != this->last_ips_) {
|
||||
this->last_ips_ = ips;
|
||||
this->publish_state(ips[0].str());
|
||||
uint8_t sensor = 0;
|
||||
for (auto &ip : ips) {
|
||||
if (ip.is_set()) {
|
||||
if (this->ip_sensors_[sensor] != nullptr) {
|
||||
this->ip_sensors_[sensor]->publish_state(ip.str());
|
||||
sensor++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
std::string unique_id() override { return get_mac_address() + "-wifiinfo-ip"; }
|
||||
void dump_config() override;
|
||||
void add_ip_sensors(uint8_t index, text_sensor::TextSensor *s) { this->ip_sensors_[index] = s; }
|
||||
|
||||
protected:
|
||||
network::IPAddress last_ip_;
|
||||
network::IPAddresses last_ips_;
|
||||
std::array<text_sensor::TextSensor *, 5> ip_sensors_;
|
||||
};
|
||||
|
||||
class DNSAddressWifiInfo : public PollingComponent, public text_sensor::TextSensor {
|
||||
|
|
|
@ -449,6 +449,7 @@ CONF_MIN_FANNING_RUN_TIME = "min_fanning_run_time"
|
|||
CONF_MIN_HEATING_OFF_TIME = "min_heating_off_time"
|
||||
CONF_MIN_HEATING_RUN_TIME = "min_heating_run_time"
|
||||
CONF_MIN_IDLE_TIME = "min_idle_time"
|
||||
CONF_MIN_IPV6_ADDR_COUNT = "min_ipv6_addr_count"
|
||||
CONF_MIN_LENGTH = "min_length"
|
||||
CONF_MIN_LEVEL = "min_level"
|
||||
CONF_MIN_POWER = "min_power"
|
||||
|
|
|
@ -116,7 +116,7 @@ lib_deps =
|
|||
WiFi ; wifi,web_server_base,ethernet (Arduino built-in)
|
||||
Update ; ota,web_server_base (Arduino built-in)
|
||||
${common:arduino.lib_deps}
|
||||
esphome/AsyncTCP-esphome@1.2.2 ; async_tcp
|
||||
esphome/AsyncTCP-esphome@2.1.3 ; async_tcp
|
||||
WiFiClientSecure ; http_request,nextion (Arduino built-in)
|
||||
HTTPClient ; http_request,nextion (Arduino built-in)
|
||||
ESPmDNS ; mdns (Arduino built-in)
|
||||
|
|
Loading…
Reference in a new issue