BLE Badge
BLE Badge is an advanced, interactive smart wearable badge built on the LilyGO T-Display-S3 (ESP32-S3). It is designed to operate as a fully self-c...
BLE Badge
Category: Embedded Systems / IoT / Social Computing / Wearable Technology
Platform: LilyGO T-Display-S3 (ESP32-S3)
Framework: Arduino via PlatformIO | C++
Status: Active — Production Ready
Project Overview
BLE Badge is an advanced, interactive smart wearable badge built on the LilyGO T-Display-S3 (ESP32-S3). It is designed to operate as a fully self-contained social and entertainment device — worn at conferences, hackathons, events, or simply as a conversation-starting piece of hardware art.
At its core, BLE Badge broadcasts a WiFi Access Point that nearby devices can connect to, enabling them to interact with the badge in real time through a captive web portal. The badge simultaneously scans for Bluetooth Low Energy (BLE) devices in the environment, uses that ambient signal density as a "mood sensor," and dynamically adapts its display content accordingly. It supports two-way communication via ESP-NOW (peer-to-peer WiFi messaging), a built-in WebSocket server for live updates, and a full arcade game system accessible from connected phones.
Core Features
Multi-Mode Display System
The badge operates across four selectable system modes:
| Mode | Description |
|---|---|
| AUTO | Automatically cycles: wallpaper images → jokes → wallpaper |
| WALLPAPER (IMG) | Continuously fetches and displays JPEG images from external APIs |
| JOKES | Cycles through fetched or locally stored jokes |
| INFO (Neural Link) | Displays connection instructions and WiFi details |
BLE Ambient Mood Detection
- Continuously scans the 2.4 GHz spectrum for nearby Bluetooth Low Energy devices
- If more than 15 BLE devices are detected in a 2-second scan window, the badge switches its wallpaper mood to "Cyberpunk" (fetches urban/dark aesthetic images from LoremFlickr)
- Below this threshold, the badge is in "Zen" mode (fetches soft anime-style images from nekos.best API)
- This creates an automatic, environment-reactive personality for the badge
Captive Portal Web Interface
- Badge broadcasts an open WiFi AP called "Joke of the Day (Send a Joke)"
- Any connecting device (iOS or Android) is automatically redirected to a cyberpunk-themed captive portal
- The portal includes:
- A text input to transmit custom jokes or messages directly to the badge screen
- An "Oracle" feature — consult the badge for a random philosophical prediction
- A built-in Arcade OS with two playable browser games (DX-Ball, Space Invaders)
- A Network Data Flow animated canvas visualisation showing data flowing through the system
- Tabbed cybersecurity awareness guides for both everyday users and advanced practitioners
ESP-NOW Peer-to-Peer Messaging
- Operates as both an ESP-NOW transmitter and receiver simultaneously
- Can receive joke payloads broadcast from other ESP32 devices on the same channel
- Incoming ESP-NOW messages are displayed as an "Override" screen on the badge
- Long-pressing the hardware button broadcasts a "retaliation joke" back to all connected WebSocket clients
WebSocket Real-Time Communication
- Full WebSocket server at
/wson port 80 - Supports live typing notifications (badge shows a radar animation while someone is composing a message)
- Game score reporting — browser-based arcade games send scores back to the badge via WebSocket
- Oracle prediction requests and replies over WebSocket
Dynamic JPEG Wallpaper System
- Downloads and renders full-resolution JPEG images directly to the TFT display
- PSRAM-backed 150KB image buffer for efficient memory management
- Images are fetched from external REST APIs and displayed using the TJpg_Decoder hardware-accelerated JPEG renderer
- Automatic fallback to locally stored Oracle predictions if offline
Oracle Prediction Engine
- Internal database of philosophical predictions and witty quotes
- Displayed locally on the badge screen in rotation
- Externally accessible via the WebSocket Oracle interface from connected browsers
Battery Monitoring
- Real-time battery voltage ADC reading
- Percentage display in the badge UI corner at all times
Power Management
- Deep sleep mode triggered by holding the GPIO 14 power button for 2 seconds
- Wakes on GPIO 14 low signal
- Clean shutdown sequence: TFT sleep command, backlight off, WiFi disconnect, deep sleep entry
Technical Architecture
| Component | Detail |
|---|---|
| MCU | ESP32-S3 @ 240 MHz |
| Display | ST7789 IPS — 170x320 pixels, 16-bit colour |
| Display Library | TFT_eSPI with TJpg_Decoder for JPEG rendering |
| BLE Stack | NimBLE-Arduino (passive scanning, low overhead) |
| Web Server | ESPAsyncWebServer (non-blocking, event-driven) |
| WebSocket | AsyncWebSocket on /ws endpoint |
| Captive Portal | DNSServer (wildcard DNS redirect) + CaptiveRequestHandler |
| Peer-to-Peer | ESP-NOW broadcast (MAC FF:FF:FF:FF:FF:FF) |
| Image Buffer | 150KB PSRAM-allocated ring buffer |
| JSON | ArduinoJson 6.x with streaming deserialization |
| Connectivity | WiFi AP + STA concurrent mode (WIFI_AP_STA) |
Hardware Specifications
| Pin | GPIO | Function |
|---|---|---|
| Power Enable | 15 | Must be HIGH for display power rail |
| LCD Backlight | 38 | PWM backlight control |
| Battery ADC | 4 | 1:2 voltage divider for LiPo sensing |
| Boot Button | 0 | Mode cycling / long press = retaliation broadcast |
| Power Button | 14 | Hold 2s for deep sleep / wake trigger |
API Integrations
| Service | Purpose |
|---|---|
| nekos.best API v2 | Zen mood wallpaper images (anime aesthetic) |
| LoremFlickr | Cyberpunk mood images (urban/dark aesthetic) |
| wsrv.nl | Image proxy and resize service (JPEG output, fit-contain) |
Arcade Games (Browser-Based)
Both games run entirely in the browser canvas and report high scores to the badge via WebSocket:
| Game | Controls |
|---|---|
| DX-Ball | Touch/drag paddle (landscape orientation required) |
| Space Invaders | Touch left/right to move, tap centre to fire |
Security & Privacy Design
- No user data stored at any time — messages are displayed and immediately discarded
- No analytics, cookies, or tracking of any kind
- Complete anonymity — no names, accounts, or identifiers
- Network intentionally air-gapped (AP-only when in message mode — no internet routing from connected clients)
- Input sanitisation: message payloads are truncated at 150 characters to prevent memory exhaustion attacks