SeaPulse is a full-stack IoT system that integrates ESP32 firmware, a Flask + PostgreSQL backend, and a Leaflet.js dashboard to track and visualize real-time GPS and environmental data out at sea. I created this project to send real-time data to my family members during sailing races.
esp32-boat-tracker/
├── backend/
│ ├── app.py
│ ├── render.yaml
│ ├── requirements.txt
├── firmware/
│ ├── include/
│ │ ├── config.h.example
│ │ ├── sensors.h
│ ├── src/
│ │ ├── main.cpp
│ │ ├── sensors.cpp
│ ├── platformio.ini
├── web/
│ ├── css/
│ │ ├── styles.css
│ ├── js/
│ │ ├── api.js
│ │ ├── app.js
│ │ ├── chart.js
│ │ └── map.js
│ └── index.html
├── .gitignore
├── LICENSE
└── README.md
SeaPulse is composed of three primary layers:
- Firmware Layer (ESP32): Collects GPS and environmental sensor data and transmits telemetry to the backend.
- Backend Layer (Flask + PostgreSQL): Receives, validates, and stores incoming telemetry via a RESTful API.
- Visualization Layer (Web Dashboard): Fetches processed data from the backend and visualizes real-time and historical information using maps and charts.
1) The ESP32 collects GPS position and environmental sensor readings at a fixed interval (currently every 5 seconds).
2) Sensor data is packaged into a JSON payload and transmitted to the backend via an HTTP POST request.
3) The Flask backend validates the incoming payload, assigns a server-side timestamp, and inserts the data into a PostgreSQL database.
4) The web dashboard periodically issues HTTP GET requests to retrieve the latest telemetry data.
5) Retrieved data is rendered on the dashboard as a live GPS track on a map and as time-series charts for environmental metrics.
The hardware layer is centered around an ESP32 microcontroller responsible for data acquisition and network communication.
- ESP32: The main controller. Handles sensor interfacing, GPS parsing, and Wi-Fi communication.
- GPS Module (NEO-6M / NEO-7M): Provides real-time latitude and longitude data for tracking.
- Environmental Sensor (BME280): Measures ambient conditions such as temperature, humidity, and pressure.
- External GPS Antenna: Improves satellite reception and position accuracy.
The backend is a Flask-based web service responsible for ingesting telemetry data, persisting it, and serving it to the web dashboard.
- Flask REST API: Exposes endpoints for receiving telemetry from the ESP32 and for serving processed data to the frontend.
- Data Validation & Processing: Incoming payloads are validated and timestamped server-side before storage.
- PostgreSQL Database (Supabase): Stores time-series GPS and sensor telemetry with automatic pruning of data older than 7 days.
- Deployment: The Flask service is hosted on Render, with database credentials managed via an environment variable.
The web dashboard provides a real-time view of the boat’s position and environmental conditions through an interactive map and renderable charts.
- Displays the boat’s current location and recent track using Leaflet.js
- Visualizes historical sensor data with time-series charts
- Periodically fetches telemetry from the backend using REST API endpoints
- Updates map markers, paths, and statistics dynamically on the client side
Below are two screenshots from an early on-water test. My buddy and I were just cruising around.
Data Types supported: Temperature, Humidity, Pressure, and Track.
Time Ranges supported: 1 day, 3 days, and 7 days.
SeaPulse is designed to be safely open-sourced while protecting live deployments.
- Device Authentication: Telemetry uploads are protected using a device ingest key sent via a custom HTTP header. Only authorized ESP32 devices can submit data.
- Secret Management: Wi-Fi credentials, ingest keys, and database credentials are never committed to the repository. All secrets are injected via ignored configuration files or environment variables.
- CORS Restrictions: Browser-based access to API endpoints is restricted to the official dashboard origin.
- Input Validation: Incoming requests are validated server-side to prevent malformed or abusive payloads.
- Dashboard Authentication: Restrict dashboard access to authenticated users.
- Dashboard UI: Improve mobile responsiveness and layout scaling across screen sizes.
- Per-Device Keys: Support multiple ingest keys to allow multiple devices with individual revocation.
- Rate Limiting: Add server-side rate limiting to protect against excessive or abusive requests.
- Encryption at Rest: Explore database-level encryption strategies for stored telemetry.
- Offline Buffering: Allow the ESP32 to cache telemetry when Wi-Fi is unavailable and replay it on reconnect.

