mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-24 23:07:17 +00:00
IPv6 support for Ethernet (ESP32)
This commit is contained in:
parent
de408921ec
commit
2f1b2ec5fd
@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
|
||||
### Added
|
||||
- Serial Modbus transmit enable GPIOs to all modbus energy drivers and modbus bridge (#17247)
|
||||
- Berry crypto module, with AES_GCM by default and EC_CC25519 optional
|
||||
- IPv6 support for Ethernet (ESP32)
|
||||
|
||||
### Breaking Changed
|
||||
|
||||
|
@ -808,6 +808,7 @@
|
||||
#define D_LOG_UPLOAD "UPL: " // Upload
|
||||
#define D_LOG_UPNP "UPP: " // UPnP
|
||||
#define D_LOG_WIFI "WIF: " // Wifi
|
||||
#define D_LOG_ETH "ETH: " // Ethernet
|
||||
#define D_LOG_ZIGBEE "ZIG: " // Zigbee
|
||||
#define D_LOG_TCP "TCP: " // TCP bridge
|
||||
#define D_LOG_BERRY "BRY: " // Berry scripting language
|
||||
|
@ -828,11 +828,20 @@ void CmndStatus(void)
|
||||
ResponseAppend_P(PSTR(",\"Ethernet\":{\"" D_CMND_HOSTNAME "\":\"%s\",\""
|
||||
D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_GATEWAY "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\",\""
|
||||
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
|
||||
D_JSON_MAC "\":\"%s\"}"),
|
||||
D_JSON_MAC "\":\"%s\""
|
||||
|
||||
#if LWIP_IPV6
|
||||
",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\""
|
||||
#endif // LWIP_IPV6
|
||||
"}"),
|
||||
EthernetHostname(),
|
||||
(uint32_t)EthernetLocalIP(), Settings->eth_ipv4_address[1], Settings->eth_ipv4_address[2],
|
||||
Settings->eth_ipv4_address[3], Settings->eth_ipv4_address[4],
|
||||
EthernetMacAddress().c_str());
|
||||
EthernetMacAddress().c_str()
|
||||
#if LWIP_IPV6
|
||||
,EthernetGetIPv6().c_str(), EthernetGetIPv6LinkLocal().c_str()
|
||||
#endif // LWIP_IPV6
|
||||
);
|
||||
#endif // USE_ETHERNET
|
||||
ResponseAppend_P(PSTR(",\"" D_CMND_WEBSERVER "\":%d,\"HTTP_API\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"),
|
||||
Settings->webserver, Settings->flag5.disable_referer_chk, Settings->sta_config, WifiGetOutputPower().c_str());
|
||||
|
@ -466,21 +466,34 @@ void WifiSetState(uint8_t state)
|
||||
}
|
||||
|
||||
#if LWIP_IPV6
|
||||
//
|
||||
// Scan through all interfaces to find a global or local IPv6 address
|
||||
// Arg:
|
||||
// is_local: is the address Link-Local (true) or Global (false)
|
||||
// if_type: possible values are "st" for Wifi STA, "en" for Ethernet, "lo" for localhost (not useful)
|
||||
static String WifiFindIPv6(bool is_local, const char * if_type = "st") {
|
||||
for (netif* intf = netif_list; intf != nullptr; intf = intf->next) {
|
||||
if (intf->name[0] == if_type[0] && intf->name[1] == if_type[1]) {
|
||||
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
ip_addr_t *ipv6 = &intf->ip6_addr[i];
|
||||
if (IP_IS_V6_VAL(*ipv6) && !ip_addr_isloopback(ipv6) && ((bool)ip_addr_islinklocal(ipv6) == is_local)) {
|
||||
return IPAddress46(ipv6).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
// Returns only IPv6 global address (no loopback and no link-local)
|
||||
String WifiGetIPv6(void)
|
||||
{
|
||||
for (auto a : addrList) {
|
||||
if(!ip_addr_isloopback((ip_addr_t*)a.addr()) && !a.isLocal() && a.isV6()) return a.toString();
|
||||
}
|
||||
return "";
|
||||
return WifiFindIPv6(false, "st");
|
||||
}
|
||||
|
||||
String WifiGetIPv6LinkLocal(void)
|
||||
{
|
||||
for (auto a : addrList) {
|
||||
if(!ip_addr_isloopback((ip_addr_t*)a.addr()) && a.isLocal() && a.isV6()) return a.toString();
|
||||
}
|
||||
return "";
|
||||
return WifiFindIPv6(true, "st");
|
||||
}
|
||||
|
||||
// add an IPv6 link-local address to all netif
|
||||
@ -493,16 +506,18 @@ void CreateLinkLocalIPv6(void)
|
||||
#endif // ESP32
|
||||
}
|
||||
|
||||
//
|
||||
void WifiDumpAddressesIPv6(void)
|
||||
{
|
||||
for (auto a: addrList)
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("IF='%s' index=%d legacy=%d IPv4=%d local=%d addr='%s'"),
|
||||
a.ifname().c_str(),
|
||||
a.ifnumber(),
|
||||
a.isLegacy(),
|
||||
a.addr().isV4(),
|
||||
a.addr().isLocal(),
|
||||
a.toString().c_str());
|
||||
for (netif* intf = netif_list; intf != nullptr; intf = intf->next) {
|
||||
if (!ip_addr_isany_val(intf->ip_addr)) AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv4 %s", intf->name[0], intf->name[1], IPAddress46(intf->ip_addr).toString().c_str());
|
||||
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||
if (!ip_addr_isany_val(intf->ip6_addr[i]))
|
||||
AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv6 %s %s", intf->name[0], intf->name[1],
|
||||
IPAddress46(intf->ip6_addr[i]).toString().c_str(),
|
||||
ip_addr_islinklocal(&intf->ip6_addr[i]) ? "local" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // LWIP_IPV6=1
|
||||
|
||||
@ -738,7 +753,7 @@ void WifiConnect(void)
|
||||
{
|
||||
if (!Settings->flag4.network_wifi) { return; }
|
||||
|
||||
#ifdef ESP32
|
||||
#if defined(ESP32) && !defined(FIRMWARE_MINIMAL)
|
||||
static bool wifi_event_registered = false;
|
||||
if (!wifi_event_registered) {
|
||||
WiFi.onEvent(WifiEvents); // register event listener only once
|
||||
@ -895,6 +910,7 @@ bool WifiHostByName(const char* aHostname, IPAddress& aResult) {
|
||||
if (WiFi.hostByName(aHostname, aResult)) {
|
||||
// Host name resolved
|
||||
if (0xFFFFFFFF != (uint32_t)aResult) {
|
||||
AddLog(LOG_LEVEL_DEBUG, "WIF: Resolving '%s' (%s)", aHostname, aResult.toString().c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -903,6 +919,7 @@ bool WifiHostByName(const char* aHostname, IPAddress& aResult) {
|
||||
uint32_t dns_address = (!TasmotaGlobal.global_state.eth_down) ? Settings->eth_ipv4_address[3] : Settings->ipv4_address[3];
|
||||
DnsClient.begin((IPAddress)dns_address);
|
||||
if (1 == DnsClient.getHostByName(aHostname, aResult)) {
|
||||
AddLog(LOG_LEVEL_DEBUG, "WIF: Resolving '%s' (%s)", aHostname, aResult.toString().c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1076,16 +1093,19 @@ void WifiEvents(arduino_event_t *event) {
|
||||
ip_addr_t ip_addr6;
|
||||
ip_addr_copy_from_ip6(ip_addr6, event->event_info.got_ip6.ip6_info.ip);
|
||||
IPAddress46 addr(ip_addr6);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: IPv6 %s %s"), addr.isLocal() ? PSTR("Link-Local") : PSTR("Global"), addr.toString().c_str());
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv6 %s %s"),
|
||||
event->event_id == ARDUINO_EVENT_ETH_GOT_IP6 ? "ETH" : "WIF",
|
||||
addr.isLocal() ? PSTR("Local") : PSTR("Global"), addr.toString().c_str());
|
||||
}
|
||||
break;
|
||||
#endif // LWIP_IPV6
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
{
|
||||
ip_addr_t ip_addr4;
|
||||
ip_addr_copy_from_ip4(ip_addr4, event->event_info.got_ip.ip_info.ip);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: IPv4 %_I, mask %_I, gateway %_I"),
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv4 %_I, mask %_I, gateway %_I"),
|
||||
event->event_id == ARDUINO_EVENT_ETH_GOT_IP ? "ETH" : "WIF",
|
||||
event->event_info.got_ip.ip_info.ip.addr,
|
||||
event->event_info.got_ip.ip_info.netmask.addr,
|
||||
event->event_info.got_ip.ip_info.gw.addr);
|
||||
|
@ -2362,11 +2362,11 @@ void HandleInformation(void)
|
||||
#if LWIP_IPV6
|
||||
String ipv6_addr = WifiGetIPv6();
|
||||
if (ipv6_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Global }2%s"), ipv6_addr.c_str());
|
||||
WSContentSend_P(PSTR("}1 IPv6 Global (wifi)}2%s"), ipv6_addr.c_str());
|
||||
}
|
||||
ipv6_addr = WifiGetIPv6LinkLocal();
|
||||
if (ipv6_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Link-Local }2%s"), ipv6_addr.c_str());
|
||||
WSContentSend_P(PSTR("}1 IPv6 Local (wifi)}2%s"), ipv6_addr.c_str());
|
||||
}
|
||||
#endif // LWIP_IPV6 = 1
|
||||
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
|
||||
@ -2387,6 +2387,16 @@ void HandleInformation(void)
|
||||
WSContentSend_P(PSTR("}1<hr/>}2<hr/>"));
|
||||
}
|
||||
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? PSTR(".local") : "");
|
||||
#if LWIP_IPV6
|
||||
String ipv6_eth_addr = EthernetGetIPv6();
|
||||
if (ipv6_eth_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Global (eth)}2%s"), ipv6_eth_addr.c_str());
|
||||
}
|
||||
ipv6_eth_addr = EthernetGetIPv6LinkLocal();
|
||||
if (ipv6_eth_addr != "") {
|
||||
WSContentSend_P(PSTR("}1 IPv6 Local (eth)}2%s"), ipv6_eth_addr.c_str());
|
||||
}
|
||||
#endif // LWIP_IPV6 = 1
|
||||
WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), EthernetMacAddress().c_str());
|
||||
WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (eth)}2%_I"), (uint32_t)EthernetLocalIP());
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ extern "C" {
|
||||
#endif
|
||||
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
|
||||
be_map_insert_str(vm, "mac", WiFi.macAddress().c_str());
|
||||
be_map_insert_str(vm, "ip", WiFi.localIP().toString().c_str());
|
||||
be_map_insert_str(vm, "ip", IPAddress46((uint32_t)WiFi.localIP()).toString().c_str()); // quick fix for IPAddress bug
|
||||
show_rssi = true;
|
||||
}
|
||||
if (show_rssi) {
|
||||
@ -252,8 +252,18 @@ extern "C" {
|
||||
#ifdef USE_ETHERNET
|
||||
if (static_cast<uint32_t>(EthernetLocalIP()) != 0) {
|
||||
be_map_insert_str(vm, "mac", EthernetMacAddress().c_str());
|
||||
be_map_insert_str(vm, "ip", EthernetLocalIP().toString().c_str());
|
||||
be_map_insert_str(vm, "ip", IPAddress46((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug
|
||||
}
|
||||
#if LWIP_IPV6
|
||||
String ipv6_addr = EthernetGetIPv6();
|
||||
if (ipv6_addr != "") {
|
||||
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
|
||||
}
|
||||
ipv6_addr = EthernetGetIPv6LinkLocal();
|
||||
if (ipv6_addr != "") {
|
||||
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
be_pop(vm, 1);
|
||||
be_return(vm);
|
||||
|
@ -85,19 +85,28 @@
|
||||
char eth_hostname[sizeof(TasmotaGlobal.hostname)];
|
||||
uint8_t eth_config_change;
|
||||
|
||||
void EthernetEvent(WiFiEvent_t event) {
|
||||
switch (event) {
|
||||
void EthernetEvent(arduino_event_t *event) {
|
||||
switch (event->event_id) {
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION));
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH D_ATTEMPTING_CONNECTION));
|
||||
ETH.setHostname(eth_hostname);
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED " at %dMbps%s"),
|
||||
ETH.linkSpeed(), (ETH.fullDuplex()) ? " Full Duplex" : "");
|
||||
#if LWIP_IPV6
|
||||
ETH.enableIpV6(); // enable Link-Local
|
||||
#endif
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ETH D_CONNECTED " at %dMbps%s, Mac %s, Hostname %s"),
|
||||
ETH.linkSpeed(), (ETH.fullDuplex()) ? " Full Duplex" : "",
|
||||
ETH.macAddress().c_str(), eth_hostname
|
||||
);
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG, D_LOG_ETH "ETH.enableIpV6() -> %i", ETH.enableIpV6());
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %_I, Hostname %s"),
|
||||
ETH.macAddress().c_str(), (uint32_t)ETH.localIP(), eth_hostname);
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "Mac %s, IPAddress %_I, Hostname %s"),
|
||||
// ETH.macAddress().c_str(), (uint32_t)ETH.localIP(), eth_hostname);
|
||||
Settings->eth_ipv4_address[1] = (uint32_t)ETH.gatewayIP();
|
||||
Settings->eth_ipv4_address[2] = (uint32_t)ETH.subnetMask();
|
||||
if (0 == Settings->eth_ipv4_address[0]) { // At this point ETH.dnsIP() are NOT correct unless DHCP
|
||||
@ -107,15 +116,18 @@ void EthernetEvent(WiFiEvent_t event) {
|
||||
TasmotaGlobal.rules_flag.eth_connected = 1;
|
||||
TasmotaGlobal.global_state.eth_down = 0;
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("ETH: Disconnected"));
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ETH "Disconnected"));
|
||||
TasmotaGlobal.rules_flag.eth_disconnected = 1;
|
||||
TasmotaGlobal.global_state.eth_down = 1;
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Stopped"));
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "Stopped"));
|
||||
TasmotaGlobal.global_state.eth_down = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -130,10 +142,21 @@ void EthernetSetIp(void) {
|
||||
Settings->eth_ipv4_address[4]); // IPAddress dns2
|
||||
}
|
||||
|
||||
// Returns only IPv6 global address (no loopback and no link-local)
|
||||
String EthernetGetIPv6(void)
|
||||
{
|
||||
return WifiFindIPv6(false, "en");
|
||||
}
|
||||
|
||||
String EthernetGetIPv6LinkLocal(void)
|
||||
{
|
||||
return WifiFindIPv6(true, "en");
|
||||
}
|
||||
|
||||
void EthernetInit(void) {
|
||||
if (!Settings->flag4.network_ethernet) { return; }
|
||||
if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: No ETH MDC and/or ETH MDIO GPIO defined"));
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "No ETH MDC and/or ETH MDIO GPIO defined"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -180,7 +203,7 @@ void EthernetInit(void) {
|
||||
delay(1);
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
if (!ETH.begin(Settings->eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings->eth_type, (eth_clock_mode_t)Settings->eth_clk_mode)) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error"));
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_ETH "Bad PHY type or init error"));
|
||||
return;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user