Embedded Systems / IoT / Social Device / Interactive Badge

Joke Box

Joke Box is the original version of what evolved into the BLE Badge — an interactive, WiFi-enabled smart badge/display device built on the LilyGO T...

Joke Box

Category: Embedded Systems / IoT / Social Device / Interactive Badge
Platform: LilyGO T-Display-S3 (ESP32-S3)
Framework: Arduino via PlatformIO | C++
Status: Active — Production Ready


Project Overview

Joke Box is the original version of what evolved into the BLE Badge — an interactive, WiFi-enabled smart badge/display device built on the LilyGO T-Display-S3. It serves as a social interaction device that broadcasts a WiFi hotspot allowing nearby people to send jokes and messages directly to its screen via a captive web portal.

The device fetches live jokes from the JokeAPI, downloads mood-matched wallpaper images, and uses Bluetooth Low Energy (BLE) ambient scanning to determine the "mood" of the surrounding environment — automatically switching between calm anime-style artwork ("Zen" mode) and urban cyberpunk imagery ("Cyberpunk" mode) based on how many BLE devices are detected nearby.

Unlike the later BLE Badge evolution, Joke Box connects to a home WiFi network (via WiFiManager) before switching to simultaneous AP+STA mode, enabling both internet connectivity and local interaction concurrently.


Core Features

Live Joke Fetching

  • Fetches jokes from the JokeAPI v2 (jokeapi.dev) — family-friendly filter applied (excludes NSFW, religious, political, racist, sexist, and explicit content)
  • Supports both single-line jokes and two-part setup/delivery format jokes
  • Dynamic font sizing: shorter jokes render in large Font4, longer jokes in smaller Font2 to fit the display
  • Display label: "Haha.exe"

BLE Ambient Mood Detection

  • Performs a 2-second passive BLE scan every 15 seconds using NimBLE
  • If more than 15 BLE devices are detected: mood switches to "Cyberpunk" → fetches urban/dark aesthetic images from LoremFlickr
  • If 15 or fewer BLE devices: mood is "Zen" → fetches anime-style artwork from nekos.best API v2
  • Mood is displayed on screen as part of the wallpaper screen header

Captive Portal Web Interface

  • Broadcasts WiFi AP: "Joke of the Day (Send a Joke)" (open network, no password)
  • All connecting devices (iOS, Android, Windows) are automatically redirected to a styled cyberpunk web portal
  • Portal features:
    • Text input form to send a joke or message directly to the badge display
    • WebSocket connection for real-time bidirectional communication
    • Sample jokes section for inspiration
    • Branded neon/terminal aesthetic with teal/cyan colour scheme

ESP-NOW Peer-to-Peer Messaging

  • Simultaneously listens for ESP-NOW broadcast packets on the current WiFi channel
  • Incoming ESP-NOW messages are displayed as an "Override" interrupt screen
  • Device can also broadcast outgoing jokes to all nearby ESP-NOW peers via the long-press button action

Message Handling

  • Received messages (from web portal or ESP-NOW) display for 60 seconds before reverting to auto mode
  • Sends a "retaliation joke" broadcast to all WebSocket clients when the hardware button is held for 3+ seconds

Multi-Mode Display System

Mode Trigger Description
AUTO Default Cycles: 6x wallpapers, then 2x jokes, then repeat
WALLPAPER (IMG) Button cycle Continuous wallpaper fetching every 30s
JOKES Button cycle Continuous joke fetching from JokeAPI every 30s
INFO (Neural Link) Button cycle Shows WiFi SSID and connection instructions

Battery Monitoring

  • ADC reading of LiPo voltage from GPIO 4
  • Percentage displayed in bottom-right corner of every screen frame

Power Management

  • Holding GPIO 14 (power button) for 2 seconds initiates graceful shutdown
  • TFT sleep command sent, backlight turned off, WiFi disconnected, ESP32 enters deep sleep
  • GPIO 14 LOW signal configured as wake-up trigger

Technical Architecture

Component Detail
MCU ESP32-S3 @ 240 MHz
Display ST7789 IPS — 170x320 pixels (portrait orientation)
Display Library TFT_eSPI
JPEG Decoder TJpg_Decoder (hardware-accelerated JPEG rendering)
BLE Stack NimBLE-Arduino (passive scanning)
Web Server ESPAsyncWebServer (non-blocking)
WebSocket AsyncWebSocket at /ws
Captive Portal DNSServer wildcard redirect
Peer-to-Peer ESP-NOW broadcast (all 0xFF peer address)
WiFi Mode Concurrent AP+STA (WIFI_AP_STA)
Image Buffer 150KB PSRAM-allocated JPEG buffer
JSON ArduinoJson (DynamicJsonDocument)
First-Run Config WiFiManager captive portal (SmartBadge Setup AP)

API Integrations

Service Endpoint Purpose
JokeAPI v2 jokeapi.dev/joke/Programming,Miscellaneous Live joke fetching
nekos.best API v2 nekos.best/api/v2/neko Zen mode anime wallpapers
LoremFlickr loremflickr.com/170/320/cyberpunk Cyberpunk mood images
wsrv.nl wsrv.nl/?url=...&output=jpg&w=170&h=320 Image proxy, resize, convert

Difference From BLE Badge (Later Iteration)

Feature Joke Box (Original) BLE Badge (Evolution)
WiFi Setup WiFiManager (home WiFi) AP-only (no home WiFi needed)
Jokes Source JokeAPI v2 (live, internet) Local hardcoded joke bank
Oracle Feature Not present Full Oracle prediction system
Arcade Games Not present DX-Ball + Space Invaders
Typing Indicator Not present Radar animation while user types
Security Awareness Not present Full tabbed cybersecurity guides
Score Reporting Not present WebSocket game score display

Joke Box is the earlier, simpler design; BLE Badge is the fully evolved successor with significantly more features.


Hardware Pins

Pin GPIO Function
Power Enable 15 Display power rail enable
LCD Backlight 38 TFT backlight control
Battery ADC 4 LiPo voltage sensing (1:2 divider)
Boot Button 0 Mode cycling / ESP-NOW broadcast
Power Button 14 Hold 2s to enter deep sleep

Security Notes

  • No user data is stored — messages are displayed and immediately discarded from memory
  • No tracking, cookies, analytics, or account systems
  • Open network portal by design — social interaction device
  • Input length capped at 150 characters to prevent memory exhaustion
Return to Projects