Skip to main content

Local Grill Monitoring Setup

1.

System ExecutiveOverview: Summary & Architecture Overview

The Local Grill Monitoring Setup provides a 100% self-hosted, cloud-free telemetry and historical graphing pipeline for the FireBoard 2 (FBX2-GJ8RC3JRD) multi-6-probe grill thermometer,thermometer. feedingAn internal Seeed Studio XIAO ESP32-C3 (switched on/off automatically by an IRLB8721PBF N-Channel MOSFET driven from the FireBoard's [Pin 35: TXD0] pad) reads all probe channels over Bluetooth Low Energy GATT and posts live webupdates dashboardover hostedWi-Fi onto ul at https://grill.drheck.dev (http://10.0.0.3:8088/api/ingest).

Why

1. anBench InternalWiring BLE-to-Wi-Fi& BridgeFlashing Was Required

    Closed Local Network Surface: Packet capture and full 65,535-port TCP/UDP nmap scans against the FireBoard 2Guide (10.0.0.71Seeed Studio XIAO ESP32-C3 + IRLB8721PBF) confirmed

    1.1 the stock firmware exposes zero local listening ports and initiates outbound TLS 1.2 connections exclusively to FireBoard Cloud (fireboard.io) with strict server certificate verification (CA pinning) and SNI checks.

    Locked Factory Silicon (eFuses): Direct hardware interrogationBill of the on-board Espressif ESP32-WROVER-EMaterials (MGN8R8) over its internal 6-pin 1.27mm UART bootloader interface proved that FireBoard permanently burned all hardware security eFuses at the factory:BOM)
    • Flash Encryption (FLASH_CRYPT_CNT = 127)Microcontroller: All 7 bits of FLASH_CRYPT_CNT (0b1111111) are burned (Write-Protected), permanently locking flash encryption on and preventing plaintext re-flashing.
    Download Mode Crypto Disabled (DISABLE_DL_ENCRYPT = True, DISABLE_DL_DECRYPT = True): The ROM bootloader is physically barred by silicon eFuse from encrypting new plaintext images or decrypting existing flash contents over UART (esptool). Secure Boot v1 (ABS_DONE_0 = True): Only firmware images signed with FireBoard's private ECDSA key (BLK2, read/write protected) are executed by the ROM bootloader. Silent UART Console (MTDO Strapped Low + ESP_LOG_NONE): Both the ROM bootloader (ets_printf) and application firmware (NVS encrypted at 0x9000) emit 0 bytes on UART0 during normal boot. Unauthenticated Local BLE GATT Stream: Even when Wi-Fi is completely unconfigured (e.g., after an on-device Factory Reset) or blocked at the router, the FireBoard 2 continuously advertises a Bluetooth Low Energy (BLE) GATT service that streams real-time JSON temperatures for all 6 probe channels (c2f780ec-45e1-452b-a879-327e3140d1f1) as soon as a single byte (0x01) is written to its control characteristic (c2f780ec-45e1-452b-a879-327e3140d1e8).

    Solution Architecture

    A thumb-sized Seeed Studio XIAO ESP32-C3 (with$21\text{ anmm} \times 17.5\text{ mm}$, built-in Li-Ion battery pads on underside + external U.FL flexibleantenna socket).

    External Antenna: Included Seeed U.FL (IPEX) 2.4 GHz flexible dipole sticker antenna and(snap anonto the XIAO's ANT socket before powering on; adhere inside the plastic FireBoard shell away from the metal Li-Ion pouch cell). Power Switch MOSFET: IRLB8721PBF TO-220 Logic-Level N-Channel logic-levelMOSFET ($V_{\text{GS(th)}} = 1.35\text{ V–}2.35\text{ V}$, $R_{\text{DS(on)}} \approx 0.013\text{ }\Omega$ at $V_{\text{GS}} = 3.3\text{ V}$). Resistors (1/4W 1% Metal Film):
      1x 100kΩ (Required): Gate pull-down resistor between MOSFET Pin 1 (Gate) automaticand powerPin switch)3 is(Source mounted/ insideGND) so the MOSFET snaps 100% shut ($0.000\text{ mA}$ standby drain) the instant the FireBoard 2turns enclosure:
        off. Automatic2x Power100kΩ Sync(Optional — for Battery % Telemetry): 50/50 voltage divider (0.000 mABAT+ Standby$\longrightarrow$ Drain)XIAO A0 $\longrightarrow$ XIAO GND).

        1.2 Step-by-Step Pin Connections

        MOSFET Pin Orientation (IRLB8721PBF):: TheHold the MOSFET Gate is driven bywith the FireBoard'sblack printed label facing you and the metal heatsink tab facing away (legs pointing down). From left to right, the 3 legs are:
        • Pin 1 (Left Leg): Gate (G) — Trigger input ($3.3\text{ V}$ ON / $0.0\text{ V}$ OFF)
        • Pin 2 (Middle Leg): Drain (D) — Switched ground going to XIAO BAT-
        • Pin 3 (Right Leg): Source (S) — True ground going to FireBoard Battery - (GND)

        Required Connections (4 Wires + 1x 100kΩ Resistor)

          FireBoard Battery + (Red) $\longrightarrow$ XIAO underside BAT+ pad. FireBoard Battery - (GND) $\longrightarrow$ MOSFET Pin 3 (Right Leg, Source). MOSFET Pin 2 (Middle Leg, Drain) $\longrightarrow$ XIAO underside BAT- pad. FireBoard 6-pin header top-left pad ([Pin 35: TXD0]) debug$\longrightarrow$ padMOSFET Pin 1 (Left Leg, Gate), AND solder 1x 100kΩ resistor between MOSFET Pin 1 (3.3VGate) and MOSFET Pin 3 (Source / GND).

          Optional Battery % Sense Divider (2x 100kΩ when the FireBoard is ON, 0.0V when the FireBoard is OFF). Turning the FireBoard 2Resistors on or off automatically powers the internalPin XIAOA0)

          ESP32-C3
            Solder 1x 100kΩ on or off with zero parasitic battery drain. BLE-to-Wi-Fi Bridgeresistor (~/git/grill-syncR1): Withinfrom 3FireBoard seconds of boot, theBattery + (BAT+) to XIAO ESP32-C3Pin A0 connects(top-left pin next to the FireBoardUSB-C port, GPIO2). Solder 1x 100kΩ resistor (R2) from XIAO Pin A0 to XIAO GND (or BAT-). (If omitted, the firmware automatically detects $<1.5\text{ V}$ on A0, disables the software low-battery sleep cutoff, and reports 100% battery to the dashboard).

            1.3 Complete Wiring Schematic

              FIREBOARD 2 overMAIN BLEPCB GATT/ BATTERY                   IRLB8721PBF MOSFET              SEEED XIAO ESP32-C3
              ==============================                   (Label Facing You)              ===================
            
              1S Li-Ion Battery (+) [3.7V-4.2V] ---------------------------------------------> Underside [BAT+] Pad
                                                                   |
                                                                [100kΩ] (Optional R1)
                                                                   |
                                                                   +-------------------------> Top-Left Pin [A0 / GPIO2]
                                                                   |
                                                                [100kΩ] (Optional R2)
                                                                   |
                                                                   v
              6-Pin Header [35 TXD0] (3.3V ON) ------------> Pin 1 [Gate (G) - Left]
                                                                   |
                                                                [100kΩ] (Pull-Down to GND)
                                                                   |
              1S Li-Ion Battery (-) / [GND] ---------------> Pin 3 [Source (S) - Right]
                                                                   
                                                             Pin 2 [Drain (D) - Middle] -----> Underside [BAT-] Pad
            

            Why Power Connects to the Underside BAT+ / BAT- Pads (Not the Top 5V Pin): On the Seeed Studio XIAO ESP32-C3, the top 5V (2VBUS) cmpin awaypasses insidethrough thea shell),protection sendsSchottky diode ($\Delta V_{\text{diode}} \approx 0.34\text{ V}$) before feeding the 0x01XC6206P332MR start$3.3\text{ command,V}$ readsLDO ($\Delta V_{\text{drop}} \approx 0.25\text{ V}$), requiring at least $3.85\text{ V}$ on 5V before the $3.3\text{ V}$ rail sags. Soldering to the underside BAT+ pad bypasses the Schottky diode and feeds the LDO directly ($V_{\text{min}} = 3.30\text{ V} + 0.25\text{ V} = 3.55\text{ V}$), running cleanly across the entire $3.5\text{ V–}4.2\text{ V}$ discharge curve of the 1S Li-Ion batterycell.

            voltage

            $$V_{\text{ADC}} via= A0V_{\text{BAT}} \times \frac{R_2}{R_1 + R_2} = \frac{V_{\text{BAT}}}{2.0}, \qquad I_{\text{divider}} = \frac{4.2\text{ V}}{200\text{ k}\Omega} = 21\text{ }\mu\text{A}$$

            1.4 Building, Flashing & Bench Testing (GPIO2PlatformIO),

              Snap the U.FL antenna onto the XIAO ESP32-C3 before powering on. Copy include/secrets.example.h to include/secrets.h in ~/git/grill-sync and POSTsset liveyour probe2.4 temperatures every 5 seconds overGHz Wi-Fi credentials:
              #define WIFI_SSID "Your_2.4GHz_WiFi_SSID"
              #define WIFI_PASSWORD "Your_WiFi_Password"
              
              Compile, flash over USB-C, and open the live serial monitor (115200 baud):
              $ pio run -t upload -t monitor
              
              Turn on the FireBoard 2 nearby with a probe plugged into Channel 1. Within 5 seconds, the serial console outputs:
              === FireBoard 2 BLE -> Wi-Fi Sync (XIAO ESP32-C3) ===
              [WiFi] Connected, IP: 10.0.0.x
              [BLE] Found FireBoard (94:54:c5:f7:1c:fa, RSSI -42 dBm)
              [BLE] Connected to FireBoard 2
              [BLE] Subscribed and sent 0x01 start command
              [BLE] Ch 1: 72.5 F
              [HTTP] POST http://10.0.0.3:8088/api/ingest -> 200
              
              (https://grill.drheck.dev).

              2. FireBoard 2 Hardware Forensics & PCB Pinout Reference

              2.1 Internal ESP32-WROVER-E Photograph & Pin Labels

              ESP32.jpg FireBoard 2 ESP32-WROVER-E Pinout

              RecoveredFigure Device1: & Silicon Identity (esptool / espefuse)

              Property Value Notes Device Hostname / Serial FBX2-GJ8RC3JRD FireBoard 2 Extremeinternal / Standard 6-Channel Controller MCU Module ESP32-WROVER-E (MGN8R8) 8module MBand Quad-SPIunpopulated Flash6-pin (a1:4017)1.27mm +UART 8bootloader MBheader PSRAMwith verified pin Siliconnumbers. Die Revision ESP32-D0WD-V3 (revision v3.1) Dual-Core Xtensa LX6 @ 240 MHz, 40 MHz crystal Wi-Fi STA MAC (Base) 94:54:c5:f7:1c:f8 Reserved as 10.0.0.71 in ~/git/router_config/dhcpd.conf on danknasty Wi-Fi SoftAP MAC (Base + 1) 94:54:c5:f7:1c:f9 Used only during initial mobile app Wi-Fi setup Bluetooth LE MAC (Base + 2) 94:54:c5:f7:1c:fa Always active whenever the FireBoard

              2.2 is powered on

              Battery Pack 1S Li-Ion Pouch Cell (3.7V nominal, 4.20V full) Charged via USB-C PD/5V charging circuit on main board

              Unpopulated 6-Pin 1.27mm (0.050") Debug Header Pinout

              Located immediately adjacent tobelow the ESP32-WROVER-E module on the main PCB. All pads arewere verified by continuity against the castellated ESP32-WROVER-E pins:

                    TOP ROW (Closer to ESP32 bottom edge)
                 +----------------+----------------+----------------+
                 |  [Pin 35] *    |  [Pin 25]      |  [GND]         |
                 |  UART0 TXD0    |  GPIO0 (BOOT)  |  Ground        |
                 |  (Right #23)   |  (Right #14)   |  (Shield/1/15) |
                 +----------------+----------------+----------------+
                 |  [Pin 34]      |  [Pin 3]       |  [Pin 24]      |
                 |  UART0 RXD0    |  EN / RST      |  GPIO2 (Strap) |
                 |  (Right #22)   |  (Left #3)     |  (Right #13)   |
                 +----------------+----------------+----------------+
                    BOTTOM ROW (Closer to PCB edge)
              
                 * [Pin 35: TXD0] (top-left pad) outputs 3.30V when FireBoard is ON
                   and 0.00V when FireBoard is OFF — wire this pad to MOSFET Pin 1 (Gate).
              
              Header Pad ESP32 Module Pin Function Voltage (FireBoard ON) Voltage (FireBoard OFF) Notes
              [35 TXD0] Pin 35 (Right #23) GPIO1 / U0TXD $3.3030\text{ VV}$ (Idle High) $0.0000\text{ VV}$ IdealUsed as the $3.3V3\text{ logicV}$ ON/OFF trigger for the IRLB8721PBF MOSFET Pin 1 (Gate)
              [34 RXD0] Pin 34 (Right #22) GPIO3 / U0RXD $3.3030\text{ VV}$ $0.0000\text{ VV}$ UART0 receive input
              [25 IO0] Pin 25 (Right #14) GPIO0 (Boot Strap) $3.3030\text{ VV}$ $0.0000\text{ VV}$ Hold at 0V$0\text{ V}$ (GND) while pulsing [3 RST] to enter UART Download Mode
              [3 RST] Pin 3 (Left #3) CHIP_PU (EN / RST) $3.3030\text{ VV}$ $0.0000\text{ VV}$ Active-low hardware reset (0V$0\text{ V}$ resets ESP32)
              [24 IO2] Pin 24 (Right #13) GPIO2 (Boot Strap) $0.0000\text{ VV}$ $0.0000\text{ VV}$ Must be low/floating to enter serial bootloader
              [GND] Pins 1, 15, 38, 39 Common Ground $0.0000\text{ VV}$ $0.0000\text{ VV}$ Connected to ESP32 RF shield can and battery negative (-)

              Additional Module Reference Pad: Left #2 (Pin 2: 3V3) carries the regulated $3.3030\text{ VV}$ rail when the FireBoard is powered on and drops to $0.0000\text{ VV}$ when powered off.

              Hardware2.3 Recovered Device & Silicon Identity (esptool / espefuse)

              Property Value Notes Device Hostname / Serial FBX2-GJ8RC3JRD FireBoard 2 6-Channel Thermometer MCU Module ESP32-WROVER-E (MGN8R8) 8 MB Quad-SPI Flash (a1:4017) + 8 MB PSRAM Silicon Die Revision ESP32-D0WD-V3 (revision v3.1) Dual-Core Xtensa LX6 @ $240\text{ MHz}$, $40\text{ MHz}$ crystal Wi-Fi STA MAC (Base) 94:54:c5:f7:1c:f8 Reserved as 10.0.0.71 in ~/git/router_config/dhcpd.conf on danknasty Wi-Fi SoftAP MAC (Base + 1) 94:54:c5:f7:1c:f9 Used only during initial mobile app Wi-Fi setup Bluetooth LE MAC (Base + 2) 94:54:c5:f7:1c:fa Always active whenever the FireBoard 2 is powered on Battery Pack 1S Li-Ion Pouch Cell ($3.7\text{ V}$ nominal, $4.20\text{ V}$ full) Charged via USB-C 5V charging circuit on main board

              2.4 Why the Stock Firmware Could Not Be Redirected or Replaced

                Closed Local Network Surface: Full 65,535-port TCP/UDP nmap scans and packet captures against 10.0.0.71 confirmed the stock firmware listens on zero local ports and initiates outbound TLS 1.2 connections exclusively to FireBoard Cloud (fireboard.io) with strict CA certificate verification and SNI checks. Locked Factory Silicon (eFuses): Interrogation over the 6-pin UART bootloader header proved all hardware security eFuses are permanently burned:
                  Flash Encryption (FLASH_CRYPT_CNT = 127 / 0b1111111): All 7 bits burned and write-protected; plaintext flashing renders the chip unbootable. UART Crypto Disabled (DISABLE_DL_ENCRYPT = True, DISABLE_DL_DECRYPT = True): The ROM bootloader is physically barred from encrypting new images or decrypting flash over UART. Secure Boot v1 (ABS_DONE_0 = True): Only images signed with FireBoard's private key (BLOCK2, read/write protected) are booted. Silent UART Console (MTDO Strapped Low + ESP_LOG_NONE): Zero application log bytes are emitted on UART0 during normal boot.
                  Click to expand full ESP32-D0WD-V3 Security eFuseseFuse Register Dump (espefuse summary)summary)
                  FLASH_CRYPT_CNT        (BLOCK0) = 127 R/- (0b1111111)  [Flash encryption permanently enabled; odd bit count = 7; Write-Protected]
                  FLASH_CRYPT_CONFIG     (BLOCK0) = 15  R/W (0xf)        [Full AES flash encryption tweak configuration]
                  ABS_DONE_0             (BLOCK0) = True R/W             [Secure Boot V1 permanently enforced on boot]
                  DISABLE_DL_ENCRYPT     (BLOCK0) = True R/W             [UART bootloader flash encryption disabled]
                  DISABLE_DL_DECRYPT     (BLOCK0) = True R/W             [UART bootloader flash decryption disabled]
                  DISABLE_DL_CACHE       (BLOCK0) = True R/W             [UART bootloader MMU flash cache disabled]
                  JTAG_DISABLE           (BLOCK0) = True R/W             [Hardware JTAG debugging permanently disabled]
                  CONSOLE_DEBUG_DISABLE  (BLOCK0) = True R/W             [ROM BASIC fallback console disabled]
                  BLOCK1 (Flash Key)              = ?? ?? ... -/-        [256-bit AES Flash Encryption Key: Read & Write Protected]
                  BLOCK2 (Secure Boot Key)        = ?? ?? ... -/-        [256-bit Secure Boot Key: Read & Write Protected]
                  

                  3. FireBoard 2 BLE GATT Protocol Reference

                  Zero Cloud Dependency: The FireBoard 2 exposes an unauthenticated Bluetooth Low EnergyBLE GATT service thatserver remains active regardless of Wi-Fi state:state, including after an on-device Factory Reset that wipes Wi-Fi credentials.

                  GATT Attribute UUID / Value Properties Description
                  FIREBOARD_DATA_CHAR_UUID c2f780ec-45e1-452b-a879-327e3140d1f1 Notify Streams UTF-8 JSON temperature packets every 3–5s per active probe channel
                  FIREBOARD_CONTROL_CHAR_UUID c2f780ec-45e1-452b-a879-327e3140d1e8 Write Writing single byte 0x01 starts the notification stream on d1f1
                  FIREBOARD_START_STREAM_BYTE 0x01 (b'\x01') 1 Byte Must be written after enabling notifications (CCCD) on d1f1

                  BLE Handshake & Notification Payload Format

                  1. Scan & Connect: Connect to BLE MAC 94:54:c5:f7:1c:fa (or any device matching prefix 94:54:c5:f7:1c: / name FBX). No pairing PIN or bond is required.
                  2. Subscribe: Enable GATT notifications on c2f780ec-45e1-452b-a879-327e3140d1f1.
                  3. Start Stream: Write 0x01 (1 byte, with response) to c2f780ec-45e1-452b-a879-327e3140d1e8.
                  4. Parse JSON Notifications: The FireBoard immediately begins emitting UTF-8 JSON notifications for each connected thermistor probe (channel 1 through 6):
                    {
                      "channel": 1,
                      "temp": 225.4,
                      "degreetype": 2,
                      "date": "2026-09-25T13:28T20:30:00Z"
                    }
                    
                    • channel: Probe port number (1..6).
                    • temp: Floating-point temperature (null or <= 0 when unplugged).
                    • degreetype: 2 = Fahrenheit (°F), 1 = Celsius (°C).

                  4. Internal Hardware Mod: Seeed Studio XIAO ESP32-C3 + IRLB8721PBF Power Switch

                  Bill of Materials (BOM)

                    Microcontroller: Seeed Studio XIAO ESP32-C3 (21 mm x 17.5 mm, built-in Li-Ion battery pads on underside + external U.FL antenna connector). External Antenna: Included Seeed U.FL (IPEX) 2.4 GHz flexible dipole sticker antenna (adhered to the inside of the plastic FireBoard shell away from the metal battery pouch for strong Wi-Fi range outdoors). Power Switch MOSFET: IRLB8721PBF TO-220 Logic-Level N-Channel MOSFET (Vgs(th) = 1.35V–2.35V, Rds(on) ≈ 0.013 Ω at Vgs = 3.3V). Looking at the front label of the IRLB8721PBF with the metal tab facing away from you, the pins from left to right are:
                      Pin 1 (Left): Gate (G) Pin 2 (Middle): Drain (D) Pin 3 (Right): Source (S) Resistors (1/4W 1% Metal Film):
                        1x 100kΩ: Gate pull-down resistor between MOSFET Pin 1 (Gate) and Pin 3 (Source / GND). Ensures the MOSFET snaps 100% shut (0.000 mA) the instant the FireBoard turns off. 1x 1kΩ–10kΩ (optional): Series current-limiting resistor between FireBoard [35 TXD0] and MOSFET Pin 1 (Gate). 2x 100kΩ (optional): 50/50 voltage divider across BAT+ -> XIAO A0 (GPIO2) -> XIAO GND so the dashboard displays exact battery percentage (0–100%) and enters deep sleep below 3.25V.

                        Why Power Goes to the Underside BAT+ / BAT- Pads (Not the 5V Pin)

                          On the Seeed Studio XIAO ESP32-C3, the top 5V (VBUS) pin passes through a protection Schottky diode (~0.34V voltage drop) before feeding the XC6206P332MR 3.3V LDO (~0.25V dropout), requiring at least ~3.85V on 5V before 3.3V sags. By contrast, the underside BAT+ pad bypasses the VBUS Schottky diode and feeds the 3.3V LDO directly (3.3V + 0.25V = 3.55V full regulation down to 3.25V empty), allowing the XIAO to run across the entire usable 3.5V–4.2V discharge curve of the FireBoard's 1S Li-Ion battery—and automatically recharge whenever USB-C is plugged into the FireBoard!

                          Complete Wiring Schematic

                            FIREBOARD 2 MAIN PCB / BATTERY                   IRLB8721PBF MOSFET              SEEED XIAO ESP32-C3
                            ==============================                   ==================              ===================
                          
                            1S Li-Ion Battery (+) [3.7V-4.2V] ---------------------------------------------> Underside [BAT+] Pad
                                                                                 |
                                                                              [100kΩ] (Optional R1)
                                                                                 |
                                                                                 +-------------------------> Pin [A0 / GPIO2]
                                                                                 |
                                                                              [100kΩ] (Optional R2)
                                                                                 |
                                                                                 v
                            6-Pin Header [35 TXD0] (3.3V ON) ---[10kΩ]---> Pin 1 [Gate (G)]
                                                                                 |
                                                                              [100kΩ] (Pull-Down)
                                                                                 |
                            1S Li-Ion Battery (-) / [GND] ---------------> Pin 3 [Source (S)]
                                                                                 
                                                                           Pin 2 [Drain (D)] --------------> Underside [BAT-] Pad
                          

                          5. Firmware Repository (~/git/grill-sync) & Magic Constants Reference(include/config.h)

                          The firmware and verification tools live in /usr/local/google/home/luket/git/grill-sync. All hardware, BLE protocol, ADC resistor, and network "magic" constants are isolated in a single, self-documenting header file: include/config.h (with Wi-Fi credentials in gitignored include/secrets.h).

                          Repository Layout

                          • platformio.ini — PlatformIO configuration targeting seeed_xiao_esp32c3 (huge_app.csv 3.1 MB partition table, NimBLE-Arduino, ArduinoJson).
                          • include/config.h — Central configuration file containing all network URLs, MAC addresses, BLE GATT UUIDs, start byte (0x01), resistor divider values, and voltage thresholds.
                          • include/secrets.example.h / include/secrets.h — Local Wi-Fi credentials (WIFI_SSID, WIFI_PASSWORD) and optional local overrides.
                          • src/main.cpp — Non-blocking BLE GATT client, JSON parser, battery monitor, and HTTP POST transmitter.
                          • tools/verify_ble.py — Standalone Python (bleak) BLE client for Linux hosts to test the FireBoard 2 BLE stream and dashboard ingestion before soldering the microcontroller.

                          Complete Reference of Constants in include/config.h

                          Constant Default Value Purpose & When to Change
                          INGEST_URL "http://10.0.0.3:8088/api/ingest" Target HTTP POST URL on host ul (10.0.0.3 portports 8088 and 8000). Change if ul's LAN IP (10.0.0.3) or container port (8088) ever changes, or set to "https://grill.drheck.dev/api/ingest".
                          HTTP_POST_INTERVAL_MS 5000UL (5s) How frequently the XIAO posts temperature snapshots to ul.
                          WIFI_CONNECT_TIMEOUT_MS 10000UL (10s) Maximum time spent waiting for Wi-Fi association per attempt.
                          FIREBOARD_DEVICE_ID "FBX2-GJ8RC3JRD" Device ID reported in JSON payloads to ul.
                          FIREBOARD_WIFI_MAC "94:54:c5:f7:1c:f8" Base / Wi-Fi MAC of the FireBoard 2 (assigned static IP 10.0.0.71 in ~/git/router_config/dhcpd.conf on danknasty).
                          FIREBOARD_BLE_MAC "94:54:c5:f7:1c:fa" Bluetooth LE MAC of the FireBoard 2 (Base MAC + 2). Change if pairing with a replacement FireBoard unit.
                          FIREBOARD_MAC_PREFIX "94:54:c5:f7:1c:" OUI/prefix matched during BLE scanning.
                          FIREBOARD_LOCK_TO_MAC 0 Set to 1 to only connect to FIREBOARD_BLE_MAC, or 0 to also connect to any nearby device advertising "FBX" / "FireBoard".
                          FIREBOARD_DATA_CHAR_UUID "c2f780ec-45e1-452b-a879-327e3140d1f1" FireBoard 2 BLE GATT Notify characteristic that outputs JSON temperature readings.
                          FIREBOARD_CONTROL_CHAR_UUID "c2f780ec-45e1-452b-a879-327e3140d1e8" FireBoard 2 BLE GATT Write characteristic that starts the stream when 0x01 is written.
                          FIREBOARD_START_STREAM_BYTE 0x01 Magic wake byte written to FIREBOARD_CONTROL_CHAR_UUID upon BLE connect.
                          FIREBOARD_MAX_CHANNELS 6 Maximum probe channel index (Channels 1..6).
                          FIREBOARD_PROBE_STALE_MS 30000UL (30s) Time without a BLE notification before a channel is considered unplugged.
                          PIN_BATTERY_ADC A0 (GPIO2) XIAO pin reading the midpoint of the battery voltage divider.
                          VOLTAGE_DIVIDER_R1_OHMS 100000.0f (100kΩ$100\text{ k}\Omega$) Upper resistor from BAT+ to A0. Update if using e.g. 220kΩ.
                          VOLTAGE_DIVIDER_R2_OHMS 100000.0f (100kΩ$100\text{ k}\Omega$) Lower resistor from A0 to GND.
                          ADC_CALIBRATION_FACTOR 1.000f Multiplier to fine-tune the ADC reading against a multimeter measurement.
                          BATTERY_FULL_VOLTS 4.15f Voltage mapped to 100% battery on the dashboard.
                          BATTERY_EMPTY_VOLTS 3.30f Voltage mapped to 0% battery on the dashboard.
                          BATTERY_LOW_CUTOFF_VOLTS 3.25f Software safety threshold ($3.25V25\text{ V}$) that puts the XIAO into deep sleep if the MOSFET switch is not present.

                          6.5. Dashboard Infrastructure Reference on Host ul (https://grill.drheck.dev)

                          Component Path / Address Details
                          Public URL (SSO Protected) https://grill.drheck.dev (https://fireboard.drheck.dev) Protected by Authentik ForwardAuth (Grill Monitor (FireBoard 2) application tile in user portal)
                          Unauthenticated Ingest API http://10.0.0.3:8088/api/ingest / http://10.0.0.3:8000/api/ingest / https://grill.drheck.dev/api/ingest Accepts POST JSON ({"device_id": "FBX2-GJ8RC3JRD", "battery": 95, "rssi": -42, "probes": {"1": 225.4, "2": 165.2}})
                          Docker Compose & App Source /srv/data/docker/grill/docker-compose.yml, /srv/data/docker/grill/app/main.app.py Docker container grill running FastAPI + SQLite (WAL mode) + Chart.js live/historical multi-channel dashboard
                          Persistent SQLite Database /srv/data/docker/grill/data/grill.db Stores historical temperature series (1h, 3h, 6h, 12h, 24h, 48h views)
                          Dedicated Docker ULA IPv6 fd77:7777:5010:0:1337:f1ac:d00d:fb02 (Port 8000) Bound on eth77 (10.0.0.3:8088 and 10.0.0.3:8000 mapped on IPv4 LAN for the XIAO ESP32-C3)
                          DNS Configuration ~/git/router_config/unbound.conf & update_dns.py Local Unbound (10.0.0.100 / fd77:7777:5010::1337:f1ac:d00d:aaaa) on danknasty + public deSEC IPv6 GUA sync Nginx Site Config /etc/nginx/sites-available/grill Proxies / with Authentik ForwardAuth and /api/ingest with auth_request off Backup & Restore Scripts ~/git/backups/ul/scripts/grill_backup, grill_restore shellcheck-verified backups with par2 create -r10 parity archives in /data/backups/services/grill/