ESP32 Node
AUS001 N1–N5
MQTT pub
8883 TLS
DNS
mqtt.equilibriumfan.com
β†’ 147.182.221.185
Droplet
Mosquitto
+ bridge.py
REST
Supabase
hvac_telemetry
bridge_health
Streamlit
Community Cloud
dashboard
NodeSiteLive FWLast SeenOTAStatus
Loading…
Loading issues…
GitHub
src/main.cpp
CI: ota_ci_check.py
push/tag
ota.equilibriumfan.com
nginx + Let's Encrypt
firmware binary
MQTT trigger
ESP32
esp_https_ota()
node-specific topic
no retain
ScriptWhat it doesStatus
session_init.pySession brief β€” fleet roster, live FW from Supabase, open GitHub issues. Run at session start.βœ“ synced
health_check.pyScheduled health report via GitHub Actions (11:15 UTC / 6:15 AM CDT). Rogue droplet cron at 12 PM CDT.⚠ sched conflict
ota_ci_check.pyCI guard: binary ≀ slot, struct ≀ 512B, stack β‰₯ 12288, watermark β‰₯ 2048.βœ“ committed
ota_host.pyLab OTA host for bench testing. Not the production nginx vhost.βœ“ committed
equisim_gauntlet.pyHIL simulation β€” scenarios 1–68.βœ“ committed
fleet_preflight_audit.pyPre-flight check before any OTA push.βœ“ committed
check_firmware_size.pyValidates binary size vs partition slot.βœ“ committed
simulate_ble_capture.pyBLE advertisement simulation for EquiSync RF learning.βœ“ committed
New Node Commissioning
  • Same session: USB, Streamlit, this dashboard
  • Banner first, then capture the BLE MAC
  • Add the node_id to AUS_NODES and redeploy Pages
  • Bench 010 stays on hvac_telemetry_bench
  • Full procedure: docs/NODE_COMMISSIONING.md
Initial Flash (USB)
  • Physical USB-C to node
  • PlatformIO upload via Cursor / CLI
  • Sets FW_VERSION in NVS
  • Required: N2 + bench 010 β†’ v4.5.16
EquiSync RF Learning
  • Hold GPIO35 at power-on β†’ learn mode
  • BLE advertisement from remote
  • Stored in NVS
  • simulate_ble_capture.py for bench test
OTA Update
  • Merge β†’ CI runs ota_ci_check.py
  • fleet_preflight_audit.py before trigger
  • Node-specific MQTT topic, no retain
  • Confirm via session_init
HIL Bench (010)
  • Site EQBNTV, table hvac_telemetry_bench
  • equisim_gauntlet.py β€” scenarios 1–68
  • Validate watermark β‰₯ 2048
  • USB flash needed β†’ v4.5.16
5-Party Ballot
  • Required: any threshold, pin, state-edge change
  • Open questions only β€” no A/B/C options
  • All 5 parties respond before merge
  • Label: needs-ballot
  • After merge: update AI.md + docs/TEN_COMMANDMENTS.md
Commit Rules
  • Every main.cpp commit β†’ bump FW_VERSION
  • kOffTroughRiseF = 1.2Β°F β€” Tier 3 to change
  • Node-specific OTA only, never fleet topic
  • static_assert(ota_status_t ≀ 512B)
  • otaWorker stack β‰₯ 12288
  • Post-ballot: update AI.md + TEN_COMMANDMENTS.md same session
Claude Web
Architecture Β· audit Β· review Β· diagrams
Gemini
Independent review Β· adversarial check
Claude Code
Code execution Β· CI Β· commits
Cursor
Active coding Β· file edits Β· droplet SSH
Steve
Final authority Β· site access Β· USB flash
πŸ””
Change health check notification time β€” rogue droplet cron fires at 12 PM CDT. Run crontab -l + systemctl list-timers, reschedule to 6 AM CDT (11:00 UTC). Set up email on the morning GitHub Actions brief.
HIGH
🌐
CNAME for dashboard.equilibriumfan.com β€” Pages project is live at equilibrium-dashboard-98s.pages.dev. Add a proxied CNAME dashboard β†’ equilibrium-dashboard-98s.pages.dev. The Wrangler token cannot write DNS.
HIGH
πŸ—„
Ballot: Supabase anon RLS policy β€” grant anon SELECT on node_id, fw, created_at in hvac_telemetry (engine=v4) and hvac_telemetry_bench (node 010). Fleet rows stay empty until this passes. After it passes, replace AUS_NODES with a distinct node_id query.
HIGH
πŸ”Œ
USB flash N2 β†’ v4.5.16 β€” AUS001-N2 is on the v4.5.11 stack canary. Physical USB-C required. Do not OTA N2.
MED
πŸ”¬
USB flash bench 010 β†’ v4.5.16 β€” HIL bench is behind the field image. USB flash only. Reads stay on hvac_telemetry_bench.
MED
⏳
Task D: fleet_baseline.json workflow β€” ballot pending β€” YAML written, not yet committed. Manual dispatch would update one existing node entry and commit. Waiting on a 5-party ballot before adding .github/workflows/.
MED
πŸ“‹
Update fleet_baseline.json β€” approved Austin baseline still lags the image running in the field. No hardcoded versions in static docs. The Task D workflow is the intended update path.
MED
βœ…
Cloudflare sources tracked β€” issues-worker.js, wrangler-issues.toml, and README-issues-worker.md are on main at 0e81e47.
DONE
βœ…
Pages dashboard deployed β€” static HTML is on Cloudflare Pages at equilibrium-dashboard-98s.pages.dev. Custom domain still needs the CNAME above.
DONE
βœ…
Doc consolidation β€” AI.md and docs/TEN_COMMANDMENTS.md are the onboarding pair. CLAUDE.md, .cursorrules, and SESSION_QUICKSTART.md are stubs.
DONE