โก Embedded Firmware Architecture
IntelliKeep firmware spans two radically different operational domains: the low-power, event-driven sleep loop on the ESP32-C3 tag, and the always-on, multi-tasking FreeRTOS gateway stack on the ESP32-S3 base station hub.
1. BLE Tag Firmware Lifecycle
Early prototype iterations utilized a connection-oriented GATT architecture where the tag advertised, waited for a base station connection handshake, and exchanged cryptographic acknowledgments. While technically functional, maintaining connections extended tag awake times to 2.5โ4.0 seconds per wake cycle, draining the coin-cell battery in weeks.
The final production firmware transitioned to an optimized non-connectable, broadcast-only beacon model. The tag simply wakes, transmits a short burst of non-connectable undirected advertisements carrying vital telemetry, and returns to deep sleep in under 300 ms. Presence inference and missing evaluation are delegated entirely to the base station and cloud backend.
Tag Execution Timeline (270 ms Wake Cycle)
MCU wakes from RTC timer (5-minute cadence), optical comparator tamper interrupt (GPIO pin change), or NFC field detection. The RISC-V core configures system clocks and restores NVS configuration.
To avoid spending high battery power on ADC sampling every 5 minutes, battery voltage is sampled only every 12th cycle (once per hour) using the switched MOSFET divider and cached in RTC fast memory.
The radio synthesizer boots and transmits the 5-byte manufacturer data payload (Company ID 0x1337) across standard BLE advertising channels 37, 38, and 39 at 20 ms intervals.
Peripherals are powered down, RF synthesizer disabled, RTC timer re-armed for 300 seconds, and the ESP32-C3 enters deep sleep (< 5 ยตA draw).
2. Base Station Hub Firmware (ESP32-S3)
The base station runs an asynchronous multi-threaded software stack on ESP-IDF / FreeRTOS. It is structured into modular subsystems located under components/:
Continuous active NimBLE discovery engine. Filters incoming advertising packets by company identifier 0x1337.
Manages local NVS registered tag table. Updates runtime cache of RSSI, battery, tamper status, and last-seen epoch.
Formats and publishes real-time JSON telemetry payloads to local brokers on topic intellikeep/base/<MAC>.
HTTPS client handling cloud self-registration, 15-second heartbeat synchronization, observation posting, and alert dispatch.
Captive onboarding SoftAP (IK-Base-Setup) and DNS intercept engine for initial headless network provisioning.
Embedded HTTP server hosting a local browser-based device dashboard and administrative JSON REST endpoints.
FreeRTOS Task Decomposition
To ensure real-time responsiveness without packet loss, responsibilities are split across independent FreeRTOS priority tasks:
| Task / Timer Name | Execution Cadence | Stack / Priority | Functional Description |
|---|---|---|---|
ble_scanner |
Continuous (100% duty) | 4 KB / Priority 5 | Continuous active scanning with itvl = window = 0x0130 (~190 ms). Intercepts 0x1337 beacon packets with zero inter-window gap. |
missing_monitor |
Periodic (Every 30 s) | 3 KB / Priority 3 | Scans local whitelist table. If a tag's last-seen timestamp exceeds the 11-minute grace window, flags state as Missing and dispatches alert. |
server_hb |
Periodic (Every 15 s) | 8 KB / Priority 3 | Executes HTTPS GET to /api/v1/base/info. Synchronizes base name, updates tag whitelist, and checks remote action flags (factory reset, reboot). |
wifi_monitor |
Periodic (Every 30 s) | 3 KB / Priority 2 | Monitors station connection state. Implements exponential backoff on disconnects and triggers SoftAP fallback if network remains unavailable. |
dns_cap |
Event-driven (SoftAP) | 2 KB / Priority 1 | Captive portal DNS server listening on UDP port 53. Redirects all HTTP requests to the base station setup IP (192.168.4.1). |
Non-Volatile Storage (NVS) Schema
The base station functions as a stateful gateway. System configuration, Wi-Fi credentials, API keys, and registered tag lists are persisted in flash NVS partitions so the hub recovers completely after power loss without requiring cloud re-provisioning:
| Namespace | Key Name(s) | Data Type | Contents / Description |
|---|---|---|---|
ikcfg |
wifi_ssid, wifi_pass |
String | Target 2.4 GHz Wi-Fi network SSID and WPA2/WPA3 passphrase. |
ikcfg |
app_user, app_upass |
String | Owner username and bcrypt password hash for local web UI login. |
ikcfg |
base_name |
String | Human-readable location identifier (e.g., "Main Cabin Living Room"). |
ikcfg |
mqtt_uri, mqtt_user, mqtt_pass |
String | Optional local MQTT broker URI (e.g., mqtt://192.168.1.100:1883) and credentials. |
ikcfg |
srv_key |
String | Unique 32-character base station cloud API key (X-API-Key). |
ikwhite |
m00 .. m31 |
String | BLE MAC address slots for up to 32 enrolled tags (e.g., "AA:BB:CC:DD:EE:FF"). |
ikwhite |
n00 .. n31 |
String | Friendly asset name corresponding to each MAC slot (e.g., "Sony Bravia 65"). |
iktoken |
token |
String | Short-lived cryptographic enrollment token for pairing verification. |
SoftAP Onboarding Portal
When booting without valid network credentials, the base station initializes a 802.11 b/g/n Access Point named IK-Base-Setup on channel 1.
// Intercept all domain resolutions and return 192.168.4.1
static void dns_recv_cb(void *arg, struct udp_pcb *upcb, struct pbuf *p,
const ip_addr_t *addr, u16_t port) {
dns_header_t *dns_hdr = (dns_header_t *)p->payload;
dns_hdr->flags = htons(0x8180); // Response, No Error
// Append Answer record pointing to 192.168.4.1
udp_sendto(upcb, reply_pbuf, addr, port);
}
Operating systems (iOS, Android, Windows, macOS) detect captive state and open the configuration page directly. The user selects an existing Wi-Fi network, enters the network password, assigns the base station name, and submits. The hub records the parameters to ikcfg in NVS and immediately restarts in Station mode.
Embedded Local Status UI
Even if internet access is interrupted or the cloud backend is unavailable, the base station provides an independent local management interface served directly from the ESP32 on port 80:
- Real-Time Tag Table: Live RSSI, battery percentages, tamper indicators, and seconds since last check-in.
- Manual Tag Registration: Form to manually whitelist new tag MAC addresses and friendly names.
- Transport Configuration: Update local MQTT broker parameters and cloud server URL.
- Factory Reset & Diagnostics: Clear NVS tables, trigger re-provisioning mode, and download diagnostic serial logs.