01 · Overview

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.

1
Wake

Timer or button press wakes the board from deep sleep.

2
Connect

Joins Wi-Fi and queries the SacMap API over HTTPS.

3
Decide

Lua script interprets the response: win, loss, live, or no game.

4
Celebrate

LED animation + optional buzzer, then back to deep sleep.

02 · Architecture

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 Sleep field. 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.

03 · Security

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.

04 · Hacking

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. Return CELEBRATE (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

ModuleFunctionsDescription
httpget(url), request(opts)HTTPS requests; body auto-parses JSON
ledset_rgb(r,g,b), off()PWM LED control (0–255 per channel)
buzzertone(hz), off()Passive buzzer; non-blocking
timesleep_ms(ms)Blocking delay for animations
loginfo(), 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