Chapter 99: Network Diagnostics and Troubleshooting

Chapter Objectives

After completing this chapter, you will be able to:

  • Understand common networking problems and a layered approach to diagnosing them.
  • Utilize ESP-IDF logging effectively for network issue identification.
  • Employ standard diagnostic tools like ping with your ESP32.
  • Retrieve and interpret Wi-Fi specific diagnostic information (RSSI, disconnection reasons).
  • Diagnose issues at the IP, TCP, and UDP layers.
  • Implement basic error checking and logging for socket-based communication.
  • Understand how external tools like Wireshark can aid in ESP32 network troubleshooting.
  • Identify and resolve common network configuration and connectivity mistakes.
  • Apply these diagnostic skills to various ESP32 variants.

Introduction

As your ESP32 projects become more interconnected, relying on Wi-Fi, Ethernet, or other network protocols, the ability to diagnose and troubleshoot network issues becomes paramount. Network problems can be elusive, stemming from a variety of sources such as incorrect configurations, environmental factors, remote server issues, or bugs in your application code. Without a systematic approach and the right tools, resolving these issues can be a frustrating and time-consuming endeavor.

This chapter provides a comprehensive guide to network diagnostics and troubleshooting on ESP32 devices using the ESP-IDF. We will explore common networking problems, introduce a layered diagnostic methodology, and delve into practical techniques using ESP-IDF features, logging mechanisms, and standard network tools. By mastering these skills, you’ll be better equipped to build robust and reliable networked ESP32 applications.

Theory

Troubleshooting network issues effectively requires a combination of understanding how networks operate, knowing what tools are available, and applying a logical process of elimination.

Common Networking Problems

ESP32 devices can encounter a range of networking problems:

  1. Connectivity Issues:
    • Failure to connect to a Wi-Fi network (incorrect SSID/password, authentication issues).
    • Failure to obtain an IP address (DHCP server problems, IP address conflicts).
    • Inability to reach the gateway or external hosts (routing issues, DNS failures).
    • Intermittent disconnections.
  2. Performance Issues:
    • Slow data transfer rates.
    • High latency in communication.
    • Packet loss.
  3. Application-Layer Issues:
    • Failure to connect to specific services (e.g., MQTT broker, HTTP server, NTP server).
    • Incorrect data being sent or received.
    • Timeouts waiting for responses.
  4. Security Issues:
    • TLS handshake failures (certificate issues, cipher suite mismatches).
    • Authentication failures with network services.
Problem Category Specific Problem Common Symptoms
Connectivity Issues Failure to connect to Wi-Fi Incorrect SSID/password errors, authentication failures, no connection established. Device cannot find AP.
Connectivity Issues Failure to obtain an IP address Device connects to Wi-Fi but has no IP, or uses APIPA (169.254.x.x). DHCP server problems, IP address conflicts.
Connectivity Issues Inability to reach gateway or external hosts Device has IP but cannot ping gateway, DNS, or internet sites. Routing issues, DNS server failures.
Connectivity Issues Intermittent disconnections Wi-Fi connection drops unpredictably. Weak signal (low RSSI), interference, AP issues.
Performance Issues Slow data transfer rates Application data exchange is sluggish. Network congestion, poor signal quality, inefficient code.
Performance Issues High latency in communication Noticeable delays in request-response cycles. Network distance, congestion, server processing time.
Performance Issues Packet loss Data packets are not reaching their destination. Network congestion, interference, faulty hardware.
Application-Layer Issues Failure to connect to specific services Cannot establish connection with MQTT broker, HTTP server, NTP server, etc. Incorrect server address/port, service down, firewall.
Application-Layer Issues Incorrect data being sent or received Application behaves unexpectedly due to malformed or wrong data. Serialization/deserialization errors, protocol mismatches.
Application-Layer Issues Timeouts waiting for responses Application hangs or fails waiting for server reply. Server overload, network latency, incorrect timeout settings.
Security Issues TLS handshake failures Cannot establish secure connections (HTTPS, MQTTS). Certificate validation problems, cipher suite mismatches, incorrect time on device.
Security Issues Authentication failures with network services ESP32 rejected by service due to bad credentials or tokens. Incorrect API keys, usernames/passwords.

A Layered Approach to Diagnostics

Network communication is typically modeled in layers (e.g., the OSI model or TCP/IP model). A layered approach to troubleshooting helps isolate the problem:

  1. Physical Layer (Layer 1 – OSI):
    • ESP32 Context: Antenna connection, power supply to the ESP32 and Wi-Fi module, RF interference.
    • Diagnostics: Visual inspection, checking for obvious hardware damage. For RF issues, signal strength (RSSI) is a key indicator.
  2. Data Link Layer (Layer 2 – OSI):
    • ESP32 Context (Wi-Fi): Wi-Fi association and authentication with the Access Point (AP). MAC address filtering.
    • ESP32 Context (Ethernet): Link status, MAC address.
    • Diagnostics: Wi-Fi scan results, connection events (association, authentication, disconnection reasons), RSSI, AP BSSID and channel. Ethernet link status LEDs (if applicable on the module/PHY).
  3. Network Layer (Layer 3 – OSI):
    • ESP32 Context (IP): IP addressing (DHCP or static), subnet mask, gateway configuration, DNS resolution.
    • Diagnostics: Checking assigned IP address, gateway, DNS server addresses. Using ping to test reachability of gateway and other hosts.
  4. Transport Layer (Layer 4 – OSI):
    • ESP32 Context (TCP/UDP): Socket creation, connection establishment (TCP), port numbers, data transmission and reception.
    • Diagnostics: Socket error codes (errno), connection timeouts, netstat-like information (if available or logged), packet counters for TCP retransmissions.
  5. Application Layer (Layer 7 – OSI):
    • ESP32 Context: Protocol-specific logic (HTTP, MQTT, SNTP, WebSockets), message formatting, server responses.
    • Diagnostics: Application-level logs, protocol-specific error codes, verifying correct server addresses and ports, checking data payloads.
---
title: OSI Model Layers
---
graph TB

        Start("Troubleshooting Flow<br>Start Bottom-Up or Top-Down<br>based on symptoms"):::primary_start

        PhyL["<b>Physical Layer</b><br>(Antenna, RF, Cable, Power)<br><br><b>Key Checks:</b><br>- Antenna connection secure?<br>- ESP32 powered adequately?<br>- Obvious hardware damage?<br>- RF interference sources nearby?"]:::process_nodes
        LinkL["<b>Data Link Layer</b><br>(Wi-Fi: MAC, Association, Auth; Ethernet: Link Status)<br><br><b>Key Checks (Wi-Fi):</b><br>- Correct SSID/Password?<br>- AP visible in scan?<br>- Association & Authentication successful?<br>- RSSI value (signal strength)?<br>- Disconnection reason codes?<br>- MAC filtering on AP?<br><b>Key Checks (Ethernet):</b><br>- Link LED status (if available)?<br>- Cable connected properly?"]:::process_nodes
        NetL["<b>Network Layer</b><br>(IP, ICMP, ARP, Routing, DNS Client)<br><br><b>Key Checks:</b><br>- IP address assigned (DHCP/Static)?<br>- Subnet mask correct?<br>- Gateway IP correct & reachable (ping)?<br>- DNS server(s) configured & reachable (ping)?<br>- Can ping local devices?<br>- Can ping external hosts by IP?"]:::process_nodes
        TransL["<b>Transport Layer</b><br>(TCP, UDP - Sockets)<br><br><b>Key Checks:</b><br>- Socket creation successful?<br>- <code style='font-family:monospace; background-color: #E0E0E0; padding: 1px 3px; border-radius: 3px;'>connect()</code> (TCP) successful?<br>- <code style='font-family:monospace; background-color: #E0E0E0; padding: 1px 3px; border-radius: 3px;'>send()</code>/<code style='font-family:monospace; background-color: #E0E0E0; padding: 1px 3px; border-radius: 3px;'>recv()</code> behavior?<br>- Port numbers correct & not blocked?<br>- <code style='font-family:monospace; background-color: #E0E0E0; padding: 1px 3px; border-radius: 3px;'>errno</code> for socket errors (e.g., ECONNREFUSED, ETIMEDOUT)?"]:::process_nodes
        AppL["<b>Application Layer</b><br>(HTTP, MQTT, SNTP, Custom Protocols)<br><br><b>Key Checks:</b><br>- Application logs for errors?<br>- Correct server address/hostname & port?<br>- Protocol-specific error codes?<br>- Data payload format correct?<br>- Server responding as expected?<br>- TLS handshake issues (for secure protocols)?"]:::process_nodes

        Start --> PhyL
        PhyL --> LinkL
        LinkL --> NetL
        NetL --> TransL
        TransL --> AppL
        AppL --> Solution{Problem Identified & Solved?}:::end_success
        
        PhyL -- Issue Found --> FixPhy{Address Physical Issue}:::check_validation
        LinkL -- Issue Found --> FixLink{Address Link Issue}:::check_validation
        NetL -- Issue Found --> FixNet{Address Network Issue}:::check_validation
        TransL -- Issue Found --> FixTrans{Address Transport Issue}:::check_validation
        AppL -- Issue Found --> FixApp{Address Application Issue}:::check_validation

        FixPhy --> Solution
        FixLink --> Solution
        FixNet --> Solution
        FixTrans --> Solution
        FixApp --> Solution


    classDef primary_start fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6
    classDef process_nodes fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF
    classDef end_success fill:#D1FAE5,stroke:#059669,stroke-width:2px,color:#065F46
    classDef decision_nodes fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E
    classDef check_validation fill:#FEE2E2,stroke:#DC2626,stroke-width:1px,color:#991B1B

Start troubleshooting from the bottom layer up (or top-down if the symptoms strongly suggest an application issue). For example, if you can’t connect to an MQTT server (Application Layer), first check if you have an IP address (Network Layer), then if you’re connected to Wi-Fi (Data Link Layer).

ESP-IDF Logging for Networking

The ESP-IDF uses a logging library (esp_log.h) that is invaluable for diagnostics. Different components log messages with varying verbosity levels (Error, Warn, Info, Debug, Verbose). You can configure log levels per component via menuconfig or at runtime.

Key Components for Network Logging:

  • wifi: Logs related to Wi-Fi scanning, connection, authentication, disconnections, etc. Setting this to “Verbose” during Wi-Fi issues can be very revealing.
  • tcpip_adapter (older IDF) / esp_netif (newer IDF): Logs related to the network interface, IP address acquisition (DHCP), and general IP stack events.
  • LWIP: The underlying TCP/IP stack. Can provide very detailed (and often cryptic) logs about TCP connections, UDP packets, ICMP, etc. Useful for deep dives but can be overwhelming.
  • esp-tls: For TLS/SSL connection issues (HTTPS, MQTTS, WSS). Provides details on handshake failures, certificate problems.
  • HTTP_CLIENT, MQTT_CLIENT, ESP_WEBSOCKET_CLIENT, SNTP: Protocol-specific client libraries will have their own logs.
  • Your Application Tag: Use ESP_LOGx(YOUR_TAG, ...) extensively in your own networking code.
Component Tag Description Typical Log Content When to Enable Verbose
wifi ESP-IDF Wi-Fi driver Scanning results, connection attempts, authentication steps, association status, disconnection events and reasons, AP info. When diagnosing Wi-Fi connectivity, stability, or performance issues. Very revealing for connection failures.
tcpip_adapter (older IDF) / esp_netif (newer IDF) Network interface management layer Interface initialization, IP address acquisition (DHCP client logs), IP address changes, interface status (up/down). When troubleshooting IP address assignment problems or general network interface issues.
LWIP LightWeight IP (TCP/IP stack) Detailed TCP connection states (SYN, ACK, FIN), UDP packet handling, ICMP messages, memory allocation within the stack. Can be very verbose. For deep dives into TCP/UDP connection problems, packet loss, or unexpected network behavior. Use cautiously due to volume.
esp-tls ESP-IDF TLS/SSL library TLS handshake process, certificate validation details, cipher suite negotiation, SSL errors. When diagnosing issues with secure connections like HTTPS, MQTTS, WSS (e.g., handshake failures).
HTTP_CLIENT ESP-IDF HTTP Client library HTTP request headers, response headers, status codes, connection management. When debugging issues related to HTTP/HTTPS requests made by the ESP32.
MQTT_CLIENT ESP-IDF MQTT Client library MQTT connection status, publish/subscribe messages, keep-alive pings, error codes. When troubleshooting MQTT connectivity or message delivery problems.
SNTP ESP-IDF SNTP client library Time synchronization attempts, server responses, errors during sync. When diagnosing issues with network time synchronization.
Your_App_Tag Custom tag for your application code Application state, variable values, function entry/exit points, custom error messages related to networking logic. Always. Use extensively in your own networking code to provide context and trace application flow.

To configure log levels:

  1. Run idf.py menuconfig (or idf.py menuconfig in VS Code terminal).
  2. Navigate to Component config -> Log output.
  3. Set the Default log verbosity.
  4. You can also set per-tag log levels under Component config -> Log output -> Maximum log verbosity for TAGs.

Common Diagnostic Tools & Techniques

  • ping (Packet Internet Groper):
    • Concept: Sends ICMP Echo Request packets to a target host and waits for ICMP Echo Reply packets. It’s a fundamental tool to test IP-level connectivity and measure round-trip time.
    • Usage:
      • From an external host to ESP32: If your ESP32 has an IP address, you can ping it from a computer on the same network. The ESP32’s LwIP stack will respond to pings by default.
      • From ESP32 to an external host: The ESP-IDF provides an esp_ping component. You can use it to ping the gateway, a DNS server, or any internet host to verify outbound connectivity.
    • Interpretation:
      • Successful replies: Basic IP connectivity is working. Note the round-trip time.
      • Request timed out: ESP32 is unreachable, host is down, firewall is blocking ICMP, or routing issues.
      • Destination host unreachable: Often indicates a routing problem closer to the source or that the ESP32 doesn’t have a valid route.
---
title: ESP Ping Process
---
sequenceDiagram
    actor UserApp as ESP32 Application
    participant esp_ping as esp_ping Component
    participant LwIP as LwIP Stack (ESP32)
    participant TargetHost as Target Host (e.g., Gateway / 8.8.8.8)

    UserApp->>esp_ping: esp_ping_new_session(config, callbacks)
    activate esp_ping
    esp_ping-->>UserApp: ping_handle
    UserApp->>esp_ping: esp_ping_start(ping_handle)
    esp_ping->>LwIP: Prepare ICMP Echo Request
    activate LwIP

    loop For each ping in count
        LwIP->>TargetHost: ICMP Echo Request (Seq=N, Data)
        activate TargetHost
        alt Successful Reply
            TargetHost-->>LwIP: ICMP Echo Reply (Seq=N, Data, TTL)
     
            LwIP-->>esp_ping: Notify: Ping Success (RTT, TTL, etc.)
            esp_ping-->>UserApp: Callback: cmd_ping_on_success()
        else Timeout
            Note over TargetHost, LwIP: No reply within timeout_ms
            deactivate TargetHost
            LwIP-->>esp_ping: Notify: Ping Timeout
            esp_ping-->>UserApp: Callback: cmd_ping_on_timeout()
        end
    end
    
    LwIP-->>esp_ping: Notify: Ping session ended
    deactivate LwIP
    esp_ping-->>UserApp: Callback: cmd_ping_on_end()
    UserApp->>esp_ping: esp_ping_delete_session(ping_handle)
    deactivate esp_ping
  • Wi-Fi Diagnostics:
    • RSSI (Received Signal Strength Indicator): Measures the power level of the Wi-Fi signal received by the ESP32.
      • esp_wifi_sta_get_ap_info(&ap_info) can retrieve ap_info.rssi.
      • Values closer to 0 dBm are stronger (e.g., -30 dBm is excellent, -50 dBm is very good, -70 dBm is okay, -80 dBm is weak, -90 dBm is often unusable).
      • Low RSSI can cause disconnections and slow performance.
    • Disconnection Reasons: The Wi-Fi event WIFI_EVENT_STA_DISCONNECTED provides a wifi_event_sta_disconnected_t structure containing a reason code. These codes (defined in esp_wifi_types.h) are crucial for understanding why a disconnection occurred (e.g., WIFI_REASON_AUTH_FAIL, WIFI_REASON_NO_AP_FOUND, WIFI_REASON_BEACON_TIMEOUT).
    • Channel and BSSID: Knowing the channel the AP is on and its BSSID (MAC address) can help diagnose interference or roaming issues. esp_wifi_sta_get_ap_info() also provides this.
    • Wi-Fi Sniffing (Advanced): Using another device with Wireshark in monitor mode to capture raw Wi-Fi frames can help diagnose low-level association/authentication problems.

Wi-Fi Diagnostics Metrics

Metric How to Obtain (ESP-IDF) Interpretation / Significance
RSSI (Received Signal Strength Indicator) Call esp_wifi_sta_get_ap_info(&ap_info), then access ap_info.rssi. Measures Wi-Fi signal power received by ESP32. Values closer to 0 dBm are stronger (e.g., -30dBm: Excellent, -50dBm: Very Good, -70dBm: Okay, -80dBm: Weak, -90dBm: Unusable). Low RSSI leads to disconnections and slow performance.
Disconnection Reason Code From WIFI_EVENT_STA_DISCONNECTED event data (wifi_event_sta_disconnected_t* structure, member reason). Numeric code (defined in esp_wifi_types.h) indicating why Wi-Fi disconnected. Crucial for diagnosing connection drops (e.g., WIFI_REASON_AUTH_FAIL, WIFI_REASON_NO_AP_FOUND, WIFI_REASON_BEACON_TIMEOUT).
Channel Call esp_wifi_sta_get_ap_info(&ap_info), then access ap_info.primary (primary channel). The Wi-Fi channel the AP is operating on. Helps diagnose interference issues if multiple APs use overlapping channels.
BSSID (Basic Service Set Identifier) Call esp_wifi_sta_get_ap_info(&ap_info), then access ap_info.bssid. The MAC address of the Access Point ESP32 is connected to. Useful for identifying the specific AP in environments with multiple APs (e.g., mesh networks, multiple APs with same SSID) or diagnosing roaming issues.
Wi-Fi Scan Results Use esp_wifi_scan_start() and retrieve results with esp_wifi_scan_get_ap_records(). Lists nearby APs, their SSIDs, RSSI, security types, and channels. Helps verify if the target AP is visible and its reported parameters match expectations.
  • IP Layer Diagnostics:
    • IP Address, Netmask, Gateway: Verify these are correctly assigned (via DHCP or static configuration).
      • esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
    • DNS Server Addresses: If domain name resolution fails, check the configured DNS servers.
      • esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns_info)
    • ARP Table (Conceptual): While not directly exposed easily, issues with ARP (Address Resolution Protocol) can prevent communication with local devices even if IP settings seem correct.
Parameter How to Obtain (ESP-IDF Function) Importance / What to Check
IP Address esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) -> ip_info.ip The unique address of the ESP32 on the network. Essential for any IP-based communication. Verify it’s assigned (not 0.0.0.0) and within the expected network range. Check for IP conflicts.
Subnet Mask (Netmask) esp_netif_get_ip_info(…) -> ip_info.netmask Defines the local network segment. Must be consistent with the network configuration. Incorrect netmask can prevent communication with some hosts.
Gateway Address esp_netif_get_ip_info(…) -> ip_info.gw The IP address of the router used to reach hosts outside the local network. Must be a valid, reachable IP on the local segment. Ping the gateway to test reachability.
DNS Server Addresses esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns_info) -> dns_info.ip IP addresses of Domain Name System servers used to resolve hostnames (e.g., “google.com”) to IP addresses. If DNS resolution fails, check these are correctly configured (via DHCP or static) and reachable (ping them). Primary (ESP_NETIF_DNS_MAIN) and Secondary (ESP_NETIF_DNS_BACKUP) may be configured.
ARP Table (Conceptual) Not directly exposed via a simple API for full table dump. LwIP handles ARP internally. Address Resolution Protocol maps IP addresses to MAC addresses on the local network. Issues (rare) can prevent communication with local devices even if IP settings seem correct. Symptoms: cannot ping local devices by IP.
  • Socket Level Diagnostics:
    • Many socket functions (e.g., connect, send, recv) return -1 on error and set the errno variable.
    • Common errno values:
      • ECONNREFUSED: No service listening on the remote port, or a firewall rejected the connection.
      • ETIMEDOUT: Connection attempt timed out (no response from server) or send/recv timeout.
      • EHOSTUNREACH: Destination host cannot be reached (routing issue).
      • ENETUNREACH: Network is unreachable.
      • EADDRINUSE: Trying to bind to a local address/port that is already in use.
    • Always check the return values of socket functions and print strerror(errno) for a human-readable error message.
Symbolic Name (errno) Common Cause ESP32 Context / Example
ECONNREFUSED Connection refused by remote host. No service is listening on the specified port, or a firewall actively rejected the connection. ESP32 tries to connect to a server (e.g., HTTP, MQTT) on a port where no service is running, or a firewall blocks it.
ETIMEDOUT Connection attempt timed out (no response from server). Can also occur on send/recv if a timeout is set and no data is transferred. Remote server is down, unreachable, or not responding. Network latency is too high. Firewall silently dropping packets. ESP32 trying to connect to an IP that doesn’t exist or is offline.
EHOSTUNREACH Destination host cannot be reached. Often a routing problem. The network or host is known, but there’s no route to it. ESP32’s gateway is misconfigured or down. Intermediate router in the path to the destination is down. Target host is on a known network but is itself offline.
ENETUNREACH Network is unreachable. A more general issue than EHOSTUNREACH, indicating no route to the entire network segment of the target. ESP32 has no Wi-Fi connection, no IP address, or a major network outage prevents reaching the destination network.
EADDRINUSE Address already in use. Trying to bind() a socket to a local address/port that is already in use by another socket. ESP32 application tries to start a TCP server (e.g., HTTP server) on a port that’s already occupied by another server instance or system service.
EINPROGRESS Operation now in progress. For non-blocking sockets, a connect() call may return this, indicating the connection is being established asynchronously. When using non-blocking sockets, this is an expected intermediate state, not an error. Use select() or poll() to check for connection completion.
EAGAIN or EWOULDBLOCK Resource temporarily unavailable. For non-blocking sockets, indicates that a recv() or send() operation would block. Normal behavior for non-blocking I/O when no data is ready to be read or the send buffer is full. Retry the operation later.
ENOBUFS No buffer space available. The system ran out of memory for network buffers. High network load, memory leaks in the application, or insufficient memory allocated to the LwIP stack.
  • Using Wireshark (External Tool):
    • Wireshark is a powerful network protocol analyzer. It captures network packets and displays them in detail.
    • How it helps with ESP32:
      • If ESP32 is in AP mode, you can run Wireshark on a computer connected to the ESP32’s AP to capture traffic from/to other clients connected to the ESP32.
      • If ESP32 is a station, you might need a managed switch with port mirroring capabilities to capture its traffic.
      • Alternatively, if the issue is with a specific server, run Wireshark on that server or another client interacting with it.
    • What to look for: TCP handshake issues (SYN, SYN-ACK, ACK), retransmissions, application-layer protocol correctness (HTTP headers, MQTT packets), TLS handshake details.
%% Suggested Placement: In Chapter 99, under "Theory", section "Common Diagnostic Tools & Techniques", 
%% subsection "Using Wireshark (External Tool)", after the "How it helps with ESP32:" part.

graph TD
    subgraph "Wireshark for ESP32 Traffic Analysis Scenarios"




        Scenario2["<b>Scenario 2: ESP32 in Station (STA) Mode</b><br>ESP32 connects to an existing Wi-Fi network"]:::primary_start
            ESP32_STA["ESP32 (STA Mode)<br>Gets IP from RouterAP"]:::process_nodes
            RouterAP["Wi-Fi Router / AP"]:::decision_nodes
            InternetServer["Remote Server (Internet)"]:::process_nodes
            
            subgraph "Capture Methods"
                direction LR
                MethodA["<b>A: Port Mirroring (SPAN)</b><br>If Router/Switch supports it"]
                    ManagedSwitch["Managed Switch<br>(with Port Mirroring)"]:::decision_nodes
                    WiresharkHostA["Computer with Wireshark<br>(Connected to Mirror Port)"]:::check_validation_nodes
                    RouterAP --> ManagedSwitch
                    ESP32_STA -- Wi-Fi --> RouterAP
                    ManagedSwitch -- "Mirrors ESP32_STA's Traffic" --> WiresharkHostA
                
                MethodB["<b>B: Wireshark on Server</b><br>If ESP32 communicates with a specific server you control"]
                    WiresharkHostB["Server (e.g., MQTT Broker, HTTP Server)<br>Runs Wireshark"]:::check_validation_nodes
                    ESP32_STA -- "Network Traffic" --> WiresharkHostB
                
                MethodC["<b>C: Wireshark on another Client (Limited)</b><br>Captures broadcast/multicast or traffic to itself"]
                    OtherClientSTA["Another Client on same Wi-Fi<br>Runs Wireshark"]:::check_validation_nodes
                    ESP32_STA -- "Broadcast/Multicast or direct to OtherClientSTA" --> OtherClientSTA

            end
            Scenario2 --> ESP32_STA
            ESP32_STA -- "Network Traffic" --> RouterAP
            RouterAP -- "Network Traffic" --> InternetServer

            Scenario1["<b>Scenario 1: ESP32 in AP Mode</b><br>ESP32 acts as an Access Point"]:::primary_start
            ESP32_AP["ESP32 (AP Mode)<br>IP: 192.168.4.1 (example)"]:::process_nodes
            ClientDevice["Client Device (Laptop/Phone)<br>Wi-Fi connected to ESP32_AP<br>Runs Wireshark"]:::check_validation_nodes
            OtherClient["Another Client (Optional)<br>Connected to ESP32_AP"]:::process_nodes

            Scenario1 --> ESP32_AP
            ClientDevice -- "Wi-Fi Traffic (to/from ESP32_AP & OtherClient)" --> ClientDevice
            ESP32_AP -- "Serves Data" --- OtherClient
            ESP32_AP -- "Serves Data" --- ClientDevice
            
            
    end

    classDef primary_start fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6
    classDef process_nodes fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF
    classDef decision_nodes fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E
    classDef check_validation_nodes fill:#FEE2E2,stroke:#DC2626,stroke-width:1px,color:#991B1B
    classDef end_success fill:#D1FAE5,stroke:#059669,stroke-width:2px,color:#065F46

ESP-IDF esp_ping Component

The esp_ping component allows the ESP32 to send ICMP echo requests.

Key steps:

  1. Initialize ping session configuration (esp_ping_config_t).
  2. Set target IP address, count, interval, timeout.
  3. Define callback functions for success, timeout, and end of session.
  4. Start the ping session (esp_ping_start()).
  5. Stop the session when done (esp_ping_stop()).

This is demonstrated in the practical examples.

Practical Examples

Example 1: Using esp_ping to Check Connectivity

This example shows how to use the esp_ping component to ping a known host (e.g., Google’s DNS server 8.8.8.8) after connecting to Wi-Fi.

1. Project Setup and CMakeLists.txt:

In your main component’s CMakeLists.txt:

Plaintext
idf_component_register(SRCS "main.c"
                    INCLUDE_DIRS "."
                    REQUIRES esp_wifi esp_event esp_log nvs_flash netif_stack esp_netif esp_ping lwip)

Enable CONFIG_LWIP_MAX_PING_PAYLOAD_SIZE in menuconfig if you need larger ping payloads (default is often enough).

2. main.c Implementation:

C
#include <stdio.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_ping.h"
#include "ping/ping_sock.h" // For esp_ping_callbacks_t
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#define WIFI_SSID      "YOUR_WIFI_SSID"
#define WIFI_PASS      "YOUR_WIFI_PASSWORD"
#define PING_TARGET_IP "8.8.8.8" // Google's Public DNS

static const char *TAG = "PING_EXAMPLE";
static SemaphoreHandle_t wifi_connected_sem;

// Ping callback functions
static void cmd_ping_on_success(esp_ping_handle_t hdl, void *args) {
    uint8_t ttl;
    uint16_t seqno;
    uint32_t elapsed_time, recv_len;
    ip_addr_t target_addr;
    esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
    esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
    esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
    esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
    esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
    ESP_LOGI(TAG, "%lu bytes from %s icmp_seq=%u ttl=%u time=%lu ms",
             (unsigned long)recv_len, ipaddr_ntoa((const ip_addr_t*)&target_addr), seqno, ttl, (unsigned long)elapsed_time);
}

static void cmd_ping_on_timeout(esp_ping_handle_t hdl, void *args) {
    uint16_t seqno;
    ip_addr_t target_addr;
    esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
    esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
    ESP_LOGW(TAG, "From %s icmp_seq=%u timeout", ipaddr_ntoa((const ip_addr_t*)&target_addr), seqno);
}

static void cmd_ping_on_end(esp_ping_handle_t hdl, void *args) {
    uint32_t transmitted;
    uint32_t received;
    uint32_t total_time_ms;
    esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
    esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
    esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
    ESP_LOGI(TAG, "%lu packets transmitted, %lu received, time %lums",
             (unsigned long)transmitted, (unsigned long)received, (unsigned long)total_time_ms);
    esp_ping_delete_session(hdl); // Important: delete session after use
}

static void start_pinging(void) {
    esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG();
    
    ip_addr_t target_addr;
    ipaddr_aton(PING_TARGET_IP, &target_addr); // Convert string to IP address
    ping_config.target_addr = target_addr;
    ping_config.count = 5; // Send 5 pings
    ping_config.interval_ms = 1000; // 1 second interval
    ping_config.timeout_ms = 1000; // 1 second timeout per ping

    esp_ping_callbacks_t cbs = {
        .on_ping_success = cmd_ping_on_success,
        .on_ping_timeout = cmd_ping_on_timeout,
        .on_ping_end = cmd_ping_on_end,
        .cb_args = NULL // Optional arguments for callbacks
    };

    esp_ping_handle_t ping_handle;
    esp_err_t ret = esp_ping_new_session(&ping_config, &cbs, &ping_handle);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to create ping session: %s", esp_err_to_name(ret));
        return;
    }

    ret = esp_ping_start(ping_handle);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to start ping session: %s", esp_err_to_name(ret));
        esp_ping_delete_session(ping_handle); // Clean up if start fails
    }
    ESP_LOGI(TAG, "Pinging %s...", PING_TARGET_IP);
}

// Wi-Fi Event Handler (from Chapter 98)
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                               int32_t event_id, void* event_data) {
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        ESP_LOGI(TAG, "Disconnected from Wi-Fi. Retrying...");
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "Got IP address: " IPSTR, IP2STR(&event->ip_info.ip));
        xSemaphoreGive(wifi_connected_sem);
    }
}

// Wi-Fi Initialization (from Chapter 98)
void wifi_init_sta(void) {
    wifi_connected_sem = xSemaphoreCreateBinary();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));
    wifi_config_t wifi_config = { .sta = { .ssid = WIFI_SSID, .password = WIFI_PASS }};
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );
}

void app_main(void) {
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    wifi_init_sta();

    ESP_LOGI(TAG, "Waiting for Wi-Fi connection...");
    if(xSemaphoreTake(wifi_connected_sem, portMAX_DELAY) == pdTRUE) {
        ESP_LOGI(TAG, "Wi-Fi Connected.");
        start_pinging();
    } else {
        ESP_LOGE(TAG, "Failed to connect to Wi-Fi.");
    }
    // Ping session runs, callbacks handle results.
}

3. Build, Flash, and Observe:

  • Replace Wi-Fi credentials.
  • After connecting to Wi-Fi, the ESP32 will attempt to ping 8.8.8.8.
  • Observe the serial monitor for ping results (success or timeout) and the final summary.

Example 2: Retrieving Wi-Fi Diagnostics (RSSI, Disconnection Reason)

This example shows how to get the RSSI of the connected AP and log disconnection reasons.

C
#include <stdio.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#define WIFI_SSID      "YOUR_WIFI_SSID"
#define WIFI_PASS      "YOUR_WIFI_PASSWORD"

static const char *TAG = "WIFI_DIAG_EXAMPLE";
static SemaphoreHandle_t wifi_connected_sem;
static bool is_connected = false;

static const char* wifi_disconnect_reason_str(wifi_err_reason_t reason) {
    // Refer to esp_wifi_types.h for all reasons
    switch (reason) {
        case WIFI_REASON_UNSPECIFIED: return "UNSPECIFIED";
        case WIFI_REASON_AUTH_EXPIRE: return "AUTH_EXPIRE";
        case WIFI_REASON_AUTH_LEAVE: return "AUTH_LEAVE";
        case WIFI_REASON_ASSOC_EXPIRE: return "ASSOC_EXPIRE";
        // ... many more reasons
        case WIFI_REASON_BEACON_TIMEOUT: return "BEACON_TIMEOUT";
        case WIFI_REASON_NO_AP_FOUND: return "NO_AP_FOUND";
        case WIFI_REASON_AUTH_FAIL: return "AUTH_FAIL";
        case WIFI_REASON_ASSOC_FAIL: return "ASSOC_FAIL";
        case WIFI_REASON_HANDSHAKE_TIMEOUT: return "HANDSHAKE_TIMEOUT";
        default: return "UNKNOWN";
    }
}

static void wifi_event_handler_diag(void* arg, esp_event_base_t event_base,
                               int32_t event_id, void* event_data) {
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data;
        ESP_LOGW(TAG, "Wi-Fi disconnected! Reason: %d (%s)", 
                 disconnected->reason, wifi_disconnect_reason_str(disconnected->reason));
        is_connected = false;
        // Attempt to reconnect
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ESP_LOGI(TAG, "Wi-Fi connected, IP obtained.");
        is_connected = true;
        xSemaphoreGive(wifi_connected_sem);
    }
}

void wifi_init_sta_diag(void) {
    // ... (Same as wifi_init_sta in Example 1, but use wifi_event_handler_diag) ...
    wifi_connected_sem = xSemaphoreCreateBinary();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler_diag, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler_diag, NULL, NULL));
    wifi_config_t wifi_config = { .sta = { .ssid = WIFI_SSID, .password = WIFI_PASS }};
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );
}

static void print_wifi_info_task(void *pvParameters) {
    wifi_ap_record_t ap_info;
    while(1) {
        if (is_connected) {
            esp_err_t ret = esp_wifi_sta_get_ap_info(&ap_info);
            if (ret == ESP_OK) {
                ESP_LOGI(TAG, "Connected to SSID: %s, BSSID: "MACSTR", Channel: %d, RSSI: %d dBm",
                         ap_info.ssid, MAC2STR(ap_info.bssid), ap_info.primary, ap_info.rssi);
            } else {
                ESP_LOGE(TAG, "Failed to get AP info: %s", esp_err_to_name(ret));
            }
        } else {
            ESP_LOGI(TAG, "Wi-Fi not connected.");
        }
        vTaskDelay(pdMS_TO_TICKS(5000)); // Print every 5 seconds
    }
}

void app_main(void) {
    // ... (NVS init) ...
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    wifi_init_sta_diag();

    ESP_LOGI(TAG, "Waiting for Wi-Fi connection...");
    if(xSemaphoreTake(wifi_connected_sem, portMAX_DELAY) == pdTRUE) {
        ESP_LOGI(TAG, "Wi-Fi connection established. Starting info task.");
        xTaskCreate(print_wifi_info_task, "wifi_info_task", 4096, NULL, 5, NULL);
    } else {
        ESP_LOGE(TAG, "Failed to connect to Wi-Fi initially.");
    }
}

Build, Flash, and Observe:

  • After connecting, the print_wifi_info_task will periodically log the SSID, BSSID, channel, and RSSI.
  • If you intentionally cause a disconnection (e.g., turn off your AP or enter wrong password after a while), you should see the disconnection reason logged.

Example 3: Basic Socket Error Checking (TCP Client)

This example demonstrates a simple TCP client connecting to a non-existent port to illustrate error handling.

C
#include <stdio.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "lwip/err.h"  // For err_t
#include "lwip/sockets.h" // For socket functions
#include "lwip/sys.h"
#include "lwip/netdb.h" // For gethostbyname
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#define WIFI_SSID      "YOUR_WIFI_SSID"
#define WIFI_PASS      "YOUR_WIFI_PASSWORD"
#define TARGET_HOST    "example.com"
#define TARGET_PORT    12345 // Unlikely to be open

static const char *TAG = "SOCKET_ERR_EXAMPLE";
static SemaphoreHandle_t wifi_connected_sem_sock; // Use a different name

// Wi-Fi Event Handler (can reuse from previous examples)
static void wifi_event_handler_sock(void* arg, esp_event_base_t event_base,
                               int32_t event_id, void* event_data) {
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xSemaphoreGive(wifi_connected_sem_sock);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect(); // Keep retrying
    }
}

// Wi-Fi Initialization (can reuse)
void wifi_init_sta_sock(void) {
    wifi_connected_sem_sock = xSemaphoreCreateBinary();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler_sock, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler_sock, NULL, NULL));
    wifi_config_t wifi_config = { .sta = { .ssid = WIFI_SSID, .password = WIFI_PASS }};
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );
}

static void tcp_client_task(void *pvParameters) {
    char rx_buffer[128];
    struct sockaddr_in dest_addr;

    // Resolve hostname
    const struct hostent *hp = gethostbyname(TARGET_HOST);
    if (hp == NULL) {
        ESP_LOGE(TAG, "Failed to resolve hostname '%s'. Error: %d (%s)", TARGET_HOST, h_errno, strerror(h_errno));
        vTaskDelete(NULL);
        return;
    }
    ESP_LOGI(TAG, "Resolved %s to IP: %s", TARGET_HOST, inet_ntoa(*((struct in_addr *)hp->h_addr_list[0])));

    dest_addr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr_list[0]))->s_addr;
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(TARGET_PORT);

    int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (sock < 0) {
        ESP_LOGE(TAG, "Unable to create socket: errno %d (%s)", errno, strerror(errno));
        vTaskDelete(NULL);
        return;
    }
    ESP_LOGI(TAG, "Socket created, attempting to connect to %s:%d...", TARGET_HOST, TARGET_PORT);

    // Set a timeout for connect
    struct timeval tv;
    tv.tv_sec = 5; // 5 seconds timeout
    tv.tv_usec = 0;
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));


    int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    if (err != 0) {
        ESP_LOGE(TAG, "Socket unable to connect: errno %d (%s)", errno, strerror(errno));
        // Common errors: ECONNREFUSED (port not open), ETIMEDOUT (host unreachable/firewall)
    } else {
        ESP_LOGI(TAG, "Successfully connected to %s:%d", TARGET_HOST, TARGET_PORT);
        // ... Send/Receive logic would go here ...
        // For this example, we just close if successful (which is unlikely for this port)
    }

    ESP_LOGI(TAG, "Shutting down socket and closing...");
    shutdown(sock, 0);
    close(sock);
    vTaskDelete(NULL);
}


void app_main(void) {
    // ... (NVS init) ...
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    wifi_init_sta_sock();
    if(xSemaphoreTake(wifi_connected_sem_sock, portMAX_DELAY) == pdTRUE) {
        xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL);
    }
}

Build, Flash, and Observe:

  • The task will attempt to connect to example.com on port 12345.
  • You should see an error message like “Socket unable to connect: errno 111 (Connection refused)” or a timeout, demonstrating how errno provides diagnostic information.

Variant Notes

  • ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6: These variants with built-in Wi-Fi will use similar diagnostic techniques for Wi-Fi and IP networking. Variants with Ethernet capabilities (e.g., some ESP32 modules with external PHY) would have Ethernet-specific link status and diagnostics. Hardware crypto acceleration in S2, S3, C3, C6 can be relevant if diagnosing TLS performance, but not primary for basic connectivity.
  • ESP32-H2: This variant uses IEEE 802.15.4 (Thread, Zigbee) and Bluetooth LE.
    • Network diagnostics for Thread/Zigbee involve different tools and concepts (e.g., link quality indicators (LQI), mesh routing analysis, PAN ID, channel). ESP-IDF might provide specific APIs or logging for these.
    • If IP connectivity is established over Thread (6LoWPAN via a border router), then IP-level tools like esp_ping (if adapted or available for that netif type) and socket error checking would still be relevant for the IP layer. However, the underlying Data Link and Physical layer diagnostics are specific to 802.15.4.
  • General: Resource constraints on smaller variants (e.g., ESP32-C3) might limit the verbosity of logging or the complexity of on-device diagnostic routines you can run simultaneously.

Common Mistakes & Troubleshooting Tips

Mistake / Issue Symptom(s) Troubleshooting / Solution
Forgetting to Check Return Codes / errno Network functions fail silently or behave unexpectedly. Difficult to diagnose the root cause. Application may crash or hang. Always check the return value of network functions (e.g., connect(), send(), recv(), esp_wifi_connect()). If an error is indicated (e.g., -1, or specific ESP_ERR_ codes), log errno (using strerror(errno) for a human-readable message) or the ESP-IDF error string (esp_err_to_name()).
Misconfigured Wi-Fi Credentials or AP Issues ESP32 fails to connect to Wi-Fi. Logs may show WIFI_REASON_AUTH_FAIL, WIFI_REASON_NO_AP_FOUND, or repeated connection attempts. Double-check SSID and password (case-sensitive). Verify AP security type (WPA2/WPA3) matches ESP32 config. Use esp_wifi_scan_start() to see if AP is visible and its reported security. Check AP logs if accessible. Ensure AP is not out of range or down. Check for MAC filtering on the AP.
DHCP Failures / Incorrect Static IP Configuration ESP32 connects to Wi-Fi but gets no IP address (or 0.0.0.0), or uses an APIPA address (169.254.x.x). IP_EVENT_STA_GOT_IP event not received. Cannot communicate on the network. DHCP: Ensure DHCP server on the network is operational and has available leases. Check network for DHCP conflicts.
Static IP: Verify static IP address, gateway, netmask, and DNS server addresses are all correct for the network segment and do not conflict with another device.
DNS Resolution Failures ESP32 can ping IP addresses but cannot connect to hostnames (e.g., “google.com”). Functions like gethostbyname() fail, possibly returning h_errno like HOST_NOT_FOUND. Verify DNS server configuration (obtained via DHCP or set statically using esp_netif_set_dns_info()). Try pinging the DNS server’s IP address to check reachability. Test resolving a known good hostname. Ensure ESP32 has proper internet gateway access.
Firewall Blocking ESP32 Traffic Connections to specific ports or hosts fail (e.g., ECONNREFUSED, ETIMEDOUT). ESP32 can ping some hosts but not others, or cannot reach specific services. Check firewalls on the local network (router), gateway, or remote server. Temporarily disable firewalls for testing (if safe and possible). Check firewall logs. Ensure required ports are open for outbound/inbound connections as needed by your application (e.g., port 80 for HTTP, 1883 for MQTT).
Insufficient Logging Difficult to pinpoint the source of a network problem. Generic failure messages without context. Increase log verbosity levels for relevant components (wifi, tcpip_adapter/esp_netif, LWIP, and protocol-specific tags like HTTP_CLIENT, MQTT_CLIENT) via menuconfig or runtime calls (esp_log_level_set()) when debugging. Add detailed ESP_LOGx() statements in your own application code.
Socket Programming Errors Unexpected socket behavior, data corruption, connection drops, or errors like EBADF (bad file descriptor). Ensure sockets are created correctly for the protocol (TCP/UDP). Check bind(), listen(), accept() logic for servers. Verify connect() parameters for clients. Handle short reads/writes. Close sockets properly when done (close(), shutdown()). Manage socket descriptors carefully.
Task Stack Overflow / Memory Issues Random crashes, reboots, or erratic behavior during network operations, especially with TLS or complex protocols. Network tasks, especially those involving TLS, can require significant stack space. Increase task stack size. Monitor free heap memory (esp_get_free_heap_size()) to detect memory leaks or exhaustion. Enable stack overflow detection in menuconfig.

Exercises

  1. Wi-Fi Disconnection Reason Analyzer:
    • Modify Example 2. Intentionally cause different Wi-Fi disconnection scenarios (e.g., turn off your AP, change AP password while ESP32 is connected, move ESP32 out of range).
    • Observe and log the disconnection reason codes reported by the WIFI_EVENT_STA_DISCONNECTED event. Try to map these codes to the actual cause.
  2. Gateway and DNS Ping Test:
    • Extend Example 1. After obtaining an IP address, retrieve the gateway and DNS server IP addresses using esp_netif_get_ip_info() and esp_netif_get_dns_info().
    • Implement logic to ping both the gateway and the primary DNS server. Log the results. This helps confirm basic network path viability.
  3. Simulate Socket Timeout:
    • Modify Example 3. Instead of a non-existent port, try to connect to a valid IP address on your network that you know isn’t running a TCP server on a specific port (e.g., another computer’s IP on a high, unused port).
    • Observe if the connect() call results in ETIMEDOUT rather than ECONNREFUSED. Discuss why the error might be different.
    • Experiment with different SO_RCVTIMEO and SO_SNDTIMEO values.
  4. Verbose Log Analysis (Conceptual):
    • Enable “Verbose” logging for the wifi and LWIP components in menuconfig.
    • Run any of the networking examples (e.g., HTTP client from Chapter 93 or MQTT client from Chapter 102).
    • Observe the flood of log messages. Try to identify messages related to:
      • Wi-Fi association steps.
      • DHCP address acquisition.
      • TCP connection establishment (SYN, ACK packets if visible in LWIP logs).
      • Application data packets.
    • (No code submission needed, this is an observation exercise).

Summary

  • Effective network troubleshooting on ESP32 involves a layered approach, from physical connectivity to application behavior.
  • ESP-IDF logging is a primary tool; enable verbose logging for relevant components (wifi, esp_netif, LWIP, protocol tags) during debugging.
  • The esp_ping component allows testing IP-level connectivity from the ESP32.
  • Wi-Fi diagnostics include checking RSSI, channel, BSSID, and especially disconnection reason codes.
  • For socket programming, always check return values and errno for errors like ECONNREFUSED or ETIMEDOUT.
  • External tools like Wireshark can provide deep insights into network traffic if you can capture packets from/to the ESP32.
  • Common issues often revolve around Wi-Fi credentials, IP configuration (DHCP/static), DNS resolution, and firewalls.
  • Variant-specific considerations apply, especially for ESP32-H2’s 802.15.4 networking.

Further Reading

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top