A IOT Bot LogoA IOT Bot
Back to Projects
ESP32FlutterWebSocketsC++Dart

ESP32 & Flutter WebSockets Project

A real-time hardware telemetry and control application using ESP32 WebSockets and a Flutter mobile app.

October 4, 2026Level: Intermediate

ESP32 & Flutter WebSockets Project Documentation

This document provides full technical details of the Flutter + ESP32 WebSockets integration project, covering both the firmware (ESP32 side) and the mobile application (Flutter side).


1. Project Overview

The project is a real-time hardware telemetry and control application. The ESP32 acts as a Wi-Fi Access Point (AP) and runs a WebSocket server. The Flutter mobile app connects to this AP, negotiates a WebSocket connection, receives real-time telemetry (uptime, free heap), and sends control commands (turning an LED on/off).

Key Technologies

  • ESP32 Firmware: Written in C++ (Arduino Framework), utilizing WiFi.h, WebServer.h, WebSocketsServer.h, and ArduinoJson.h.
  • Flutter App: Written in Dart, utilizing Material 3 UI, provider for state management, web_socket_channel for WebSockets, and http for health checks.

2. ESP32 Firmware Side

The ESP32 acts as the core hardware peripheral and server. File: esp32/esp32.ino

2.1. Network Configuration

  • Mode: Wi-Fi Access Point (SoftAP).
  • SSID: ESP32_AP
  • Password: None (Open network).
  • IP Address: Fixed to 192.168.4.1 (Default Arduino ESP32 SoftAP IP).

2.2. Servers Hosted

  1. HTTP Server (Port 80):
    • Exposes a /health endpoint returning a 200 OK status ({"status": "ok"}). This allows the Flutter app to verify connectivity before attempting a WebSocket connection.
  2. WebSocket Server (Port 81):
    • Maintains persistent, full-duplex communication with the Flutter app.

2.3. WebSocket Payloads (JSON format)

The ESP32 parses incoming JSON payloads and broadcasts status updates at a regular interval (every 2 seconds).

Incoming Commands (App -> ESP32)

  • LED Control:
    { "type": "command", "led": true }
  • Custom Messages:
    { "type": "message", "text": "Hello ESP32!" }
  • Ping (Latency tracking): PING (String literal)

Outgoing Telemetry (ESP32 -> App)

  • Status Update (Broadcasted every 2s):
    { "uptime": 12345, "free_heap": 256000, "led": true }
  • Pong (Latency response): PONG (String literal)

3. Flutter Application Side

The Flutter app is designed to be highly resilient, handling sudden disconnects and network drops gracefully using exponential backoff.

3.1. App Architecture & State Management

  • State Management: Uses the Provider package to globally expose the Esp32Service.
  • Models (lib/models.dart):
    • DeviceStatus: Represents the latest telemetry from the ESP32 (uptime, heap, LED state).
    • LogMessage: Represents timestamped console logs for the debugging UI.

3.2. Core Service: Esp32Service (lib/esp32_service.dart)

This is the heart of the Flutter app logic.

  • Connection Lifecycle: Tracks connection states via EspConnectionState (disconnected, connecting, connected, error).
  • HTTP Pre-flight Check: Before connecting to the WebSocket, it polls http://192.168.4.1/health. This prevents the WebSocket library from hanging if the hardware is off.
  • WebSocket Channel: Connects to ws://192.168.4.1:81.
  • Auto-Reconnect with Exponential Backoff: If the connection drops unexpectedly, it automatically attempts to reconnect, doubling the delay between each failed attempt (e.g., 2s, 4s, 8s, up to 30s) to save battery and resources.
  • Ping/Pong Latency: The app has a ping() method that sends a literal "PING" to the ESP32. When the ESP32 replies with "PONG", the round-trip latency is calculated in milliseconds.

3.3. User Interface (UI)

The UI is built with Flutter's Material 3 design and utilizes a bottom navigation bar to switch between two main screens:

  1. Home Screen (lib/home_screen.dart):

    • Status Card: Displays current connection status (Connected, Disconnected, Error) and live latency.
    • Control Card: Contains a switch to toggle the ESP32's built-in LED on and off.
    • Telemetry Card: Displays live free_heap and uptime updates from the ESP32.
    • Message Card: Contains a text field to send custom text messages to the ESP32 via WebSocket.
  2. Console Screen (lib/console_screen.dart):

    • Acts as an in-app terminal/debugger.
    • Displays real-time logs from the Esp32Service, including JSON payloads received, connection attempts, errors, and custom messages.

3.4. Android Configuration (AndroidManifest.xml)

Because the ESP32 AP does not use SSL/HTTPS, specific configurations were required to allow local network traffic:

  • Permissions added for INTERNET, ACCESS_NETWORK_STATE, and ACCESS_WIFI_STATE.
  • Added android:usesCleartextTraffic="true" to the <application> tag to allow unencrypted local HTTP/WS traffic to 192.168.4.1.

4. How to Run & Test

  1. Flash the ESP32:
    • Open esp32/esp32.ino in the Arduino IDE.
    • Install the WebSockets by Markus Sattler and ArduinoJson libraries.
    • Flash the code to your ESP32-S3.
  2. Connect the Mobile Device:
    • Open your phone's Wi-Fi settings.
    • Connect to the ESP32_AP network.
  3. Run the App:
    • Run flutter run to build and deploy the app to your phone.
    • The app should automatically negotiate the connection, allowing you to view telemetry and toggle the LED!

5. AI Generation Prompt

Want to recreate this project quickly? Copy and paste the prompt below into your favorite AI assistant (like Claude, ChatGPT, or Gemini) to have it generate the entire codebase for you!

Act as an expert IoT developer and Flutter engineer. I want to build a local Wi-Fi telemetry and control system. Please write the complete code for two components: 1. ESP32 Firmware (C++ / Arduino IDE) - Create a SoftAP network called "ESP32_AP" with no password. - Run an HTTP server on port 80 with a `/health` endpoint that returns `{"status": "ok"}`. - Run a WebSocket server on port 81. - Every 2 seconds, broadcast a JSON payload containing `uptime` (millis), `free_heap` (ESP.getFreeHeap()), and `led` (boolean state of the built-in LED). - Listen for incoming JSON WebSocket messages. If `{"type": "command", "led": true/false}` is received, toggle the built-in LED accordingly. - Listen for a text message "PING" and immediately reply with "PONG". 2. Flutter Application (Dart) - Create a clean Material 3 UI with two tabs: Home (Controls/Telemetry) and Console (Logs). - Write an Esp32Service class using the `web_socket_channel` and `http` packages. - The service should first ping `http://192.168.4.1/health`. If successful, connect to `ws://192.168.4.1:81`. - Implement exponential backoff for auto-reconnecting if the WebSocket drops. - Parse the incoming JSON to display real-time Uptime and Free Heap on the Home screen. - Add a toggle switch on the Home screen that sends the LED command JSON to the ESP32. - Add a button to send a "PING" and measure/display the round-trip latency in milliseconds when "PONG" is received. - Log all connection events, errors, and raw JSON payloads to be displayed in the Console tab. Please provide the complete `esp32.ino` file, the Flutter `pubspec.yaml` dependencies, and the core Flutter Dart files (`main.dart`, `esp32_service.dart`, etc.) required to make this run.