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, andArduinoJson.h. - Flutter App: Written in Dart, utilizing Material 3 UI,
providerfor state management,web_socket_channelfor WebSockets, andhttpfor 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
- HTTP Server (Port 80):
- Exposes a
/healthendpoint returning a 200 OK status ({"status": "ok"}). This allows the Flutter app to verify connectivity before attempting a WebSocket connection.
- Exposes a
- 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
Providerpackage to globally expose theEsp32Service. - 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:
-
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_heapanduptimeupdates from the ESP32. - Message Card: Contains a text field to send custom text messages to the ESP32 via WebSocket.
-
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, andACCESS_WIFI_STATE. - Added
android:usesCleartextTraffic="true"to the<application>tag to allow unencrypted local HTTP/WS traffic to192.168.4.1.
4. How to Run & Test
- Flash the ESP32:
- Open
esp32/esp32.inoin the Arduino IDE. - Install the
WebSocketsby Markus Sattler andArduinoJsonlibraries. - Flash the code to your ESP32-S3.
- Open
- Connect the Mobile Device:
- Open your phone's Wi-Fi settings.
- Connect to the
ESP32_APnetwork.
- Run the App:
- Run
flutter runto build and deploy the app to your phone. - The app should automatically negotiate the connection, allowing you to view telemetry and toggle the LED!
- Run
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.