Network API

About

The Network API provides a unified, object-oriented interface for managing multiple network interfaces on ESP32 devices. The Network Manager acts as a central coordinator that manages Wi-Fi (Station and Access Point modes), Ethernet, and PPP interfaces, providing a consistent API regardless of the underlying network technology.

Key Features:

  • Unified Interface Management: Single API for all network types (Wi-Fi, Ethernet, PPP)

  • Event-Driven Architecture: Centralized event handling through NetworkEvents

  • Multiple Interface Support: Simultaneous operation of multiple network interfaces

  • Default Interface Selection: Automatic or manual selection of the default network interface

  • IPv4 and IPv6 Support: Full support for both IP protocol versions

  • Network Communication Classes: Unified Client, Server, and UDP classes that work with any interface

Architecture

The Network library follows a tree-like hierarchical structure:

NetworkManager (NetworkEvents)
│
├── NetworkInterface (Base Class)
│   │
│   ├── Wi-Fi
│   │   ├── STAClass WiFi.STA (Station Mode)
│   │   └── APClass WiFi.AP (Access Point Mode)
│   │
│   ├── Ethernet
│   │   └── ETHClass ETH
│   │
│   └── PPP
│       └── PPPClass PPP
│
└── Network Communication
    ├── NetworkClient
    ├── NetworkServer
    └── NetworkUdp

Class Hierarchy:

  • NetworkManager: Extends NetworkEvents and Printable. Manages all network interfaces and provides global network functions.

  • NetworkEvents: Provides event callback registration and handling for all network events.

  • NetworkInterface: Base class that all network interfaces extend. Provides common functionality for IP configuration, status checking, and network information.

  • Interface Implementations: * STAClass: Wi-Fi Station (client) mode * APClass: Wi-Fi Access Point mode * ETHClass: Ethernet interface * PPPClass: Point-to-Point Protocol (modem/cellular)

Network Manager

The NetworkManager class (global instance: Network) is the central coordinator for all network interfaces. It extends NetworkEvents to provide event handling capabilities and implements Printable for status output.

Initialization

bool begin();

Initializes the Network Manager and the underlying ESP-IDF network interface system. This must be called before using any network interfaces. Returns true on success, false on failure.

Example:

#include "Network.h"

void setup() {
  Serial.begin(115200);
  Network.begin();  // Initialize Network Manager
}

Check if Online

bool isOnline();

Check if the device is online by verifying if any network interface (except AP) has an assigned IPv4 or global IPv6 address. Returns true if such interface has been found, false if no interface has assigned IP.

Example:

#include "Network.h"

void setup() {
  Serial.begin(115200);
  Network.begin();  // Initialize Network Manager

  // Connect to WiFi AP
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");

  // Wait for WiFi to connect
  while (!WiFi.STA.hasIP()) {
    delay(500);
  }

  if (Network.isOnline()) {
    Serial.println("Network is Online");
  }
}

Default Interface Management

bool setDefaultInterface(NetworkInterface &ifc);
NetworkInterface *getDefaultInterface();

Sets or gets the default network interface. The default interface is used for network operations when no specific interface is specified.

Example:

#include "Network.h"
#include "WiFi.h"

void setup() {
  Network.begin();
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");

  // Wait for WiFi to connect
  while (!WiFi.STA.hasIP()) {
    delay(500);
  }

  // Set WiFi as default interface
  Network.setDefaultInterface(WiFi.STA);

  // Get current default interface
  NetworkInterface *defaultIf = Network.getDefaultInterface();
  Serial.print("Default interface: ");
  Serial.println(defaultIf->impl_name());
}

Hostname Management

static const char *getHostname();
static bool setHostname(const char *hostname);
static bool hostname(const String &aHostname);

Gets or sets the system hostname. The hostname is used for network identification and mDNS.

Example:

// Set hostname
Network.setHostname("my-esp32-device");

// Get hostname
const char *hostname = Network.getHostname();
Serial.println(hostname);

DNS Resolution

int hostByName(const char *aHostname, IPAddress &aResult);

Resolves a hostname to an IP address using DNS. Returns 1 on success, error code on failure.

Example:

IPAddress ip;
if (Network.hostByName("www.example.com", ip) == 1) {
  Serial.print("Resolved IP: ");
  Serial.println(ip);
}

MAC Address

uint8_t *macAddress(uint8_t *mac);
String macAddress();

Gets the MAC address of the default network interface.

Example:

uint8_t mac[6];
Network.macAddress(mac);
Serial.print("MAC: ");
for (int i = 0; i < 6; i++) {
  if (i > 0) Serial.print(":");
  Serial.print(mac[i], HEX);
}
Serial.println();

// Or as String
String macStr = Network.macAddress();
Serial.println(macStr);

Network Events

The NetworkEvents class provides a centralized event handling system for all network-related events. NetworkManager extends NetworkEvents, so you can register event callbacks directly on the Network object.

Event Types

Network events are defined in arduino_event_id_t enum:

Ethernet Events: * ARDUINO_EVENT_ETH_START * ARDUINO_EVENT_ETH_STOP * ARDUINO_EVENT_ETH_CONNECTED * ARDUINO_EVENT_ETH_DISCONNECTED * ARDUINO_EVENT_ETH_GOT_IP * ARDUINO_EVENT_ETH_LOST_IP * ARDUINO_EVENT_ETH_GOT_IP6

Wi-Fi Station Events: * ARDUINO_EVENT_WIFI_STA_START * ARDUINO_EVENT_WIFI_STA_STOP * ARDUINO_EVENT_WIFI_STA_CONNECTED * ARDUINO_EVENT_WIFI_STA_DISCONNECTED * ARDUINO_EVENT_WIFI_STA_GOT_IP * ARDUINO_EVENT_WIFI_STA_LOST_IP * ARDUINO_EVENT_WIFI_STA_GOT_IP6

Wi-Fi AP Events: * ARDUINO_EVENT_WIFI_AP_START * ARDUINO_EVENT_WIFI_AP_STOP * ARDUINO_EVENT_WIFI_AP_STACONNECTED * ARDUINO_EVENT_WIFI_AP_STADISCONNECTED * ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED * ARDUINO_EVENT_WIFI_AP_GOT_IP6

PPP Events: * ARDUINO_EVENT_PPP_START * ARDUINO_EVENT_PPP_STOP * ARDUINO_EVENT_PPP_CONNECTED * ARDUINO_EVENT_PPP_DISCONNECTED * ARDUINO_EVENT_PPP_GOT_IP * ARDUINO_EVENT_PPP_LOST_IP * ARDUINO_EVENT_PPP_GOT_IP6

Registering Event Callbacks

Three types of callback functions are supported:

1. Simple Event Callback (Event ID only):

typedef void (*NetworkEventCb)(arduino_event_id_t event);
network_event_handle_t onEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);

2. Functional Callback (Event ID and Info):

typedef std::function<void(arduino_event_id_t event, arduino_event_info_t info)> NetworkEventFuncCb;
network_event_handle_t onEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);

3. System Callback (Event Structure):

typedef void (*NetworkEventSysCb)(arduino_event_t *event);
network_event_handle_t onEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);

Example - Simple Callback:

void onNetworkEvent(arduino_event_id_t event) {
  Serial.print("Network event: ");
  Serial.println(NetworkEvents::eventName(event));

  if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) {
    Serial.println("WiFi connected!");
  }
}

void setup() {
  Network.begin();
  Network.onEvent(onNetworkEvent);
}

Example - Functional Callback with Event Info:

void setup() {
  Network.begin();

  Network.onEvent([](arduino_event_id_t event, arduino_event_info_t info) {
    if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) {
      Serial.print("IP Address: ");
      Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
      Serial.print("Gateway: ");
      Serial.println(IPAddress(info.got_ip.ip_info.gw.addr));
    }
  });
}

Example - System Callback:

void onNetworkEventSys(arduino_event_t *event) {
  Serial.print("Event: ");
  Serial.println(NetworkEvents::eventName(event->event_id));

  if (event->event_id == ARDUINO_EVENT_WIFI_STA_GOT_IP) {
    IPAddress ip = IPAddress(event->event_info.got_ip.ip_info.ip.addr);
    Serial.print("Got IP: ");
    Serial.println(ip);
  }
}

void setup() {
  Network.begin();
  Network.onEvent(onNetworkEventSys);
}

Removing Event Callbacks

void removeEvent(NetworkEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(NetworkEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(NetworkEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
void removeEvent(network_event_handle_t event_handle);

Remove event callbacks by function pointer or by handle (recommended).

Example:

network_event_handle_t eventHandle;

void setup() {
  Network.begin();
  // Register and save handle
  eventHandle = Network.onEvent(onNetworkEvent);
}

void loop() {
  // Later, remove by handle
  Network.removeEvent(eventHandle);
}

Event Information

static const char *eventName(arduino_event_id_t id);

Returns a human-readable name for an event ID.

Example:

Serial.println(NetworkEvents::eventName(ARDUINO_EVENT_WIFI_STA_GOT_IP));
// Output: "WIFI_STA_GOT_IP"

Network Interface Base Class

The NetworkInterface class is the base class for all network interfaces (Wi-Fi STA, Wi-Fi AP, Ethernet, PPP). It provides common functionality for IP configuration, status checking, and network information retrieval.

All network interfaces inherit from NetworkInterface and can be used polymorphically.

IP Configuration

bool config(
  IPAddress local_ip = (uint32_t)0x00000000,
  IPAddress gateway = (uint32_t)0x00000000,
  IPAddress subnet = (uint32_t)0x00000000,
  IPAddress dns1 = (uint32_t)0x00000000,
  IPAddress dns2 = (uint32_t)0x00000000,
  IPAddress dns3 = (uint32_t)0x00000000
);
bool dnsIP(uint8_t dns_no, IPAddress ip);

Configures static IP address, gateway, subnet mask, and DNS servers. For server interfaces (Wi-Fi AP), dns1 is the DHCP lease range start and dns2 is the DNS server.

Example:

#include "Network.h"
#include "WiFi.h"

void setup() {
  Network.begin();

  // Configure static IP
  IPAddress local_ip(192, 168, 1, 100);
  IPAddress gateway(192, 168, 1, 1);
  IPAddress subnet(255, 255, 255, 0);
  IPAddress dns1(8, 8, 8, 8);
  IPAddress dns2(8, 8, 4, 4);

  WiFi.STA.begin();
  WiFi.STA.config(local_ip, gateway, subnet, dns1, dns2);
  WiFi.STA.connect("ssid", "password");
}

Hostname

const char *getHostname() const;
bool setHostname(const char *hostname) const;

Gets or sets the hostname for the specific interface.

Example:

WiFi.STA.setHostname("my-wifi-device");
Serial.println(WiFi.STA.getHostname());

Status Checking

bool started() const;
bool connected() const;
bool hasIP() const;
bool hasLinkLocalIPv6() const;
bool hasGlobalIPv6() const;
bool linkUp() const;

Check the status of the network interface.

Example:

if (WiFi.STA.started()) {
  Serial.println("WiFi interface started");
}

if (WiFi.STA.connected()) {
  Serial.println("WiFi connected");
}

if (WiFi.STA.hasIP()) {
  Serial.println("WiFi has IP address");
}

IPv6 Support

bool enableIPv6(bool en = true);

Enables or disables IPv6 support on the interface.

Example:

WiFi.STA.enableIPv6(true);

if (WiFi.STA.hasGlobalIPv6()) {
  IPAddress ipv6 = WiFi.STA.globalIPv6();
  Serial.print("Global IPv6: ");
  Serial.println(ipv6);
}

IP Address Information

IPAddress localIP() const;
IPAddress subnetMask() const;
IPAddress gatewayIP() const;
IPAddress dnsIP(uint8_t dns_no = 0) const;
IPAddress broadcastIP() const;
IPAddress networkID() const;
uint8_t subnetCIDR() const;
IPAddress linkLocalIPv6() const;  // IPv6 only
IPAddress globalIPv6() const;    // IPv6 only

Get IP address information from the interface.

Example:

Serial.print("Local IP: ");
Serial.println(WiFi.STA.localIP());

Serial.print("Subnet Mask: ");
Serial.println(WiFi.STA.subnetMask());

Serial.print("Gateway: ");
Serial.println(WiFi.STA.gatewayIP());

Serial.print("DNS: ");
Serial.println(WiFi.STA.dnsIP());

Serial.print("Broadcast: ");
Serial.println(WiFi.STA.broadcastIP());

Serial.print("Network ID: ");
Serial.println(WiFi.STA.networkID());

Serial.print("Subnet CIDR: /");
Serial.println(WiFi.STA.subnetCIDR());

MAC Address

uint8_t *macAddress(uint8_t *mac) const;
String macAddress() const;

Get the MAC address of the interface.

Example:

uint8_t mac[6];
WiFi.STA.macAddress(mac);
Serial.print("MAC: ");
for (int i = 0; i < 6; i++) {
  if (i > 0) Serial.print(":");
  Serial.print(mac[i], HEX);
}
Serial.println();

// Or as String
Serial.println(WiFi.STA.macAddress());

Default Interface

bool setDefault();
bool isDefault() const;

Set this interface as the default network interface, or check if it is the default.

Example:

// Set WiFi STA as default
WiFi.STA.setDefault();

// Check if it's default
if (WiFi.STA.isDefault()) {
  Serial.println("WiFi STA is the default interface");
}

Route Priority

int getRoutePrio() const;
int setRoutePrio(int prio);  // ESP-IDF 5.5+

Gets or sets the route priority for the interface. Higher priority interfaces are preferred for routing.

Example:

#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
// Set higher priority for Ethernet
ETH.setRoutePrio(100);
WiFi.STA.setRoutePrio(50);
#endif

Status Bits and Waiting

int getStatusBits() const;
int waitStatusBits(int bits, uint32_t timeout_ms) const;

Get current status bits or wait for specific status bits to be set.

Status Bits: * ESP_NETIF_STARTED_BIT: Interface has been started * ESP_NETIF_CONNECTED_BIT: Interface is connected * ESP_NETIF_HAS_IP_BIT: Interface has an IP address * ESP_NETIF_HAS_LOCAL_IP6_BIT: Interface has link-local IPv6 * ESP_NETIF_HAS_GLOBAL_IP6_BIT: Interface has global IPv6 * ESP_NETIF_WANT_IP6_BIT: Interface wants IPv6 * ESP_NETIF_HAS_STATIC_IP_BIT: Interface has static IP configuration

Example:

// Wait for WiFi STA to get IP address (with 10 second timeout)
if (WiFi.STA.waitStatusBits(ESP_NETIF_HAS_IP_BIT, 10000) & ESP_NETIF_HAS_IP_BIT) {
  Serial.println("WiFi STA got IP address!");
} else {
  Serial.println("Timeout waiting for IP address");
}

Interface Information

const char *ifkey() const;
const char *desc() const;
String impl_name() const;
int impl_index() const;
esp_netif_t *netif();

Get interface identification and description information.

Example:

Serial.print("Interface key: ");
Serial.println(WiFi.STA.ifkey());

Serial.print("Description: ");
Serial.println(WiFi.STA.desc());

Serial.print("Implementation name: ");
Serial.println(WiFi.STA.impl_name());

Serial.print("Implementation index: ");
Serial.println(WiFi.STA.impl_index());

Network Interface Implementations

Wi-Fi Station (STA)

The STAClass (accessed via WiFi.STA object) extends NetworkInterface and provides Wi-Fi Station (client) mode functionality.

Key Features: * Connect to Wi-Fi access points * Automatic reconnection * WPA2/WPA3 security support * Enterprise Wi-Fi support (WPA2-Enterprise) * Scanning for available networks

Example:

#include "WiFi.h"

void setup() {
  Network.begin();
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");

  while (WiFi.STA.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("Connected! IP: ");
  Serial.println(WiFi.STA.localIP());
}

For detailed Wi-Fi Station API documentation, see Wi-Fi API.

Wi-Fi Access Point (AP)

The APClass (accessed via WiFi.AP object) extends NetworkInterface and provides Wi-Fi Access Point mode functionality.

Key Features: * Create Wi-Fi access points * DHCP server for connected stations * Network Address Translation (NAT) * Captive portal support

Example:

#include "WiFi.h"

void setup() {
  Network.begin();
  WiFi.AP.begin();
  WiFi.AP.create("MyESP32AP", "password123");

  Serial.print("AP IP: ");
  Serial.println(WiFi.AP.localIP());
}

For detailed Wi-Fi AP API documentation, see Wi-Fi API.

Ethernet

The ETHClass (accessed via ETH object) extends NetworkInterface and provides Ethernet connectivity.

Key Features: * Support for multiple Ethernet PHY types * SPI-based and EMAC-based Ethernet controllers * Automatic link detection * Full-duplex operation

Example:

#include "ETH.h"

void setup() {
  Network.begin();
  ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_POWER, ETH_CLK_MODE);

  while (!ETH.hasIP()) {
    delay(500);
  }

  Serial.print("Ethernet IP: ");
  Serial.println(ETH.localIP());
}

For detailed Ethernet API documentation, see Ethernet.

PPP (Point-to-Point Protocol)

The PPPClass (accessed via PPP object) extends NetworkInterface and provides PPP connectivity, typically used with cellular modems.

Key Features: * Cellular modem support (SIM7000, SIM7600, BG96, etc.) * APN configuration * PIN code support * Hardware flow control

Example:

#include "PPP.h"

void setup() {
  Network.begin();
  PPP.begin(PPP_MODEM_SIM7600, 1, 115200);
  PPP.setApn("your.apn.here");

  while (!PPP.hasIP()) {
    delay(500);
  }

  Serial.print("PPP IP: ");
  Serial.println(PPP.localIP());
}

For detailed PPP API documentation, see the PPP library documentation.

Network Communication Classes

The Network library provides unified communication classes that work with any network interface: NetworkClient, NetworkServer, and NetworkUdp.

NetworkClient

The NetworkClient class provides TCP client functionality that works with any network interface.

Key Features: * Connect to TCP servers * Read/write data * Timeout configuration * Socket options

Example:

#include "Network.h"
#include "WiFi.h"

NetworkClient client;

void setup() {
  Network.begin();
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");
  while (WiFi.STA.status() != WL_CONNECTED) delay(500);

  if (client.connect("www.example.com", 80)) {
    client.println("GET / HTTP/1.1");
    client.println("Host: www.example.com");
    client.println();

    while (client.available()) {
      char c = client.read();
      Serial.print(c);
    }

    client.stop();
  }
}

NetworkServer

The NetworkServer class provides TCP server functionality that works with any network interface.

Key Features: * Accept incoming TCP connections * Multiple client support * Timeout configuration

Example:

#include "Network.h"
#include "WiFi.h"

NetworkServer server(80);

void setup() {
  Network.begin();
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");
  while (WiFi.STA.status() != WL_CONNECTED) delay(500);

  server.begin();
  Serial.print("Server started on: ");
  Serial.println(WiFi.STA.localIP());
}

void loop() {
  NetworkClient client = server.accept();
  if (client) {
    Serial.println("New client connected");
    client.println("Hello from ESP32!");
    client.stop();
  }
}

NetworkUdp

The NetworkUdp class provides UDP communication that works with any network interface.

Key Features: * Send/receive UDP packets * Multicast support * Remote IP and port information

Example:

#include "Network.h"
#include "WiFi.h"

NetworkUDP udp;

void setup() {
  Network.begin();
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");
  while (WiFi.STA.status() != WL_CONNECTED) delay(500);

  udp.begin(1234);
}

void loop() {
  int packetSize = udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet from: ");
    Serial.print(udp.remoteIP());
    Serial.print(":");
    Serial.println(udp.remotePort());

    char buffer[255];
    int len = udp.read(buffer, 255);
    if (len > 0) {
      buffer[len] = 0;
      Serial.println(buffer);
    }
  }
}

Multiple Interface Management

The Network Manager allows you to manage multiple network interfaces simultaneously and switch between them as needed.

Example - Multiple Interfaces:

#include "Network.h"
#include "WiFi.h"
#include "ETH.h"

void setup() {
  Network.begin();

  // Start Ethernet
  ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_POWER, ETH_CLK_MODE);

  // Start WiFi as backup
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");

  // Wait for either interface to connect
  while (!ETH.connected() && WiFi.STA.status() != WL_CONNECTED) {
    delay(500);
  }

  // Set the connected interface as default
  if (ETH.connected()) {
    Network.setDefaultInterface(ETH);
    Serial.println("Using Ethernet");
  } else if (WiFi.STA.status() == WL_CONNECTED) {
    Network.setDefaultInterface(WiFi.STA);
    Serial.println("Using WiFi");
  }
}

Example - Interface Priority:

void setup() {
  Network.begin();

  // Start both interfaces
  ETH.begin(...);
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");

  // Set route priorities (ESP-IDF 5.5+)
  #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
  ETH.setRoutePrio(100);  // Higher priority
  WiFi.STA.setRoutePrio(50);   // Lower priority
  #endif

  // Ethernet will be preferred for routing when both are connected
}

Event Handling Examples

Example - Monitor All Network Events:

#include "Network.h"

void onNetworkEvent(arduino_event_id_t event) {
  Serial.print("[Network Event] ");
  Serial.println(NetworkEvents::eventName(event));

  switch (event) {
    case ARDUINO_EVENT_WIFI_STA_GOT_IP:
      Serial.println("WiFi Station got IP!");
      break;
    case ARDUINO_EVENT_ETH_GOT_IP:
      Serial.println("Ethernet got IP!");
      break;
    case ARDUINO_EVENT_PPP_GOT_IP:
      Serial.println("PPP got IP!");
      break;
    default:
      break;
  }
}

void setup() {
  Serial.begin(115200);
  Network.begin();
  Network.onEvent(onNetworkEvent);
}

Example - Interface-Specific Event Handling:

#include "Network.h"
#include "WiFi.h"

void onWiFiEvent(arduino_event_id_t event, arduino_event_info_t info) {
  if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) {
    IPAddress ip = IPAddress(info.got_ip.ip_info.ip.addr);
    IPAddress gateway = IPAddress(info.got_ip.ip_info.gw.addr);
    IPAddress subnet = IPAddress(info.got_ip.ip_info.netmask.addr);

    Serial.println("WiFi Connected!");
    Serial.print("IP: ");
    Serial.println(ip);
    Serial.print("Gateway: ");
    Serial.println(gateway);
    Serial.print("Subnet: ");
    Serial.println(subnet);
  }
}

void setup() {
  Network.begin();
  Network.onEvent(onWiFiEvent, ARDUINO_EVENT_WIFI_STA_GOT_IP);
  WiFi.STA.begin();
  WiFi.STA.connect("ssid", "password");
}

Troubleshooting

Interface Not Starting: * Ensure Network.begin() is called before using any interface * Check that the interface-specific initialization is correct * Verify hardware connections (for Ethernet/PPP)

Default Interface Not Working: * Explicitly set the default interface using Network.setDefaultInterface() * Check interface status using started(), connected(), and hasIP() * Verify route priorities if using multiple interfaces

Events Not Firing: * Ensure Network.begin() is called to initialize the event system * Check that callbacks are registered before the events occur * Use NetworkEvents::eventName() to verify event IDs

IP Configuration Issues: * For static IP, ensure all parameters (IP, gateway, subnet) are provided * Check that the IP address is not already in use on the network * Verify DNS server addresses are correct

Multiple Interface Conflicts: * Set appropriate route priorities to control which interface is used * Use setDefaultInterface() to explicitly select the default * Monitor events to see which interface gets IP addresses first