How it works
SacMap connects to your Wi-Fi, checks the SacMap API for Kings game results, and lights up the LED when they win. No app, no cloud account, no subscription.
Timer or button press wakes the board from deep sleep.
Joins Wi-Fi and queries the SacMap API over HTTPS.
Lua script interprets the response: win, loss, live, or no game.
LED animation + optional buzzer, then back to deep sleep.
Software architecture
Deep sleep cycle
The ESP32-S3 spends almost all its time in deep sleep, drawing microamps. Three events can wake it:
- Timer — the API tells SacMap how many seconds to sleep via the
Sleepfield. Adaptive: shorter during live games, longer during off-hours. - Celebrate button — replays the last win celebration immediately. No Wi-Fi needed.
- Check button — forces a full connectivity check and reports status via LEDs. Diagnostic only, never auto-celebrates.
USB configuration
All settings live on a FAT32 USB thumbdrive in a file called config.txt. On first boot (or when you press the Check button), SacMap reads the drive:
wifi_name = "MyNetwork"
wifi_password = "s3cr3t"
color_red = 102
color_green = 0
color_blue = 204
buzzer_enabled = false
buzzer_notes = {
{ "G4", 125 },
{ "C5", 125 },
{ "E5", 125 },
{ "G5", 400 },
}
NVS caching
After the first read, configuration is cached in the ESP32's non-volatile storage (NVS). Subsequent timer wakes skip USB entirely — the 5V boost converter stays off, saving power. Press the Check button to force a re-read from USB.
Battery life
Powered by 2× AA batteries. A power-gated 5V boost converter only activates for USB reads and LED celebrations. Between checks, the board draws single-digit microamps in deep sleep.
Security & privacy
WiFi credentials stay local
Your SSID and password live on the USB thumbdrive and in on-chip NVS. They are only used to connect to your router — never transmitted to any server.
HTTPS only
All API requests use HTTPS with a bundled certificate store. No plaintext HTTP, no self-signed certs.
No telemetry
SacMap makes exactly one outbound request per check: sacmap.art. No analytics, no tracking, no cloud account.
No app required
Configuration is a text file on a USB drive. No phone app, no Bluetooth pairing, no account creation.
Extensibility
SacMap runs a Lua 5.5 VM on the ESP32-S3. All game-check and celebration logic lives in logic.lua on the USB drive. Edit the file, re-insert the drive, and press Check — no firmware reflash needed.
Script hooks
Your script must define two functions:
check()— called on timer and Check-button wakes. ReturnCELEBRATE(0) for a win,ERROR(-1) on failure, or a positive number of seconds to sleep.celebrate()— called after a win or when the Celebrate button is pressed. Run your LED animation and buzzer song here.
Available modules
| Module | Functions | Description |
|---|---|---|
http | get(url), request(opts) | HTTPS requests; body auto-parses JSON |
led | set_rgb(r,g,b), off() | PWM LED control (0–255 per channel) |
buzzer | tone(hz), off() | Passive buzzer; non-blocking |
time | sleep_ms(ms) | Blocking delay for animations |
log | info(), warn(), error() | Logs to serial console |
Example: custom celebration
function celebrate()
for i = 1, 3 do
led.set_rgb(config.color_red, config.color_green, config.color_blue)
if config.buzzer_enabled then buzzer.tone(523) end
time.sleep_ms(300)
led.off()
buzzer.off()
time.sleep_ms(200)
end
led.set_rgb(config.color_red, config.color_green, config.color_blue)
end
Example: track a different team or API
function check()
local resp, err = http.get("https://your-api.example.com/score")
if not resp then return ERROR end
if resp.body.winner == "my_team" then return CELEBRATE end
return resp.body.next_check or 3600
end