upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/SESSION_NOTES.md
diff options
context:
space:
mode:
authorYour Name <you@example.com>2026-05-19 13:14:48 +0530
committerYour Name <you@example.com>2026-05-19 13:14:48 +0530
commitfe6aa9663d4cdabdc6e71db6068f8cd9e3739ffe (patch)
tree8cadb07243c07a6b3fa9453b239c9ac5cb02b454 /SESSION_NOTES.md
parent77031f06a9a87320d011f501590985161d1eb305 (diff)
feat: WiFi beacon price discovery via Vendor IE (two-board verified)
Price discovery allows TollGate ESP32 boards to advertise their per-step price via WiFi Vendor-Specific Information Elements (OUI 0xC0FFEE) in beacon and probe response frames. Nearby boards passively scan and build a market view of competing TollGates without requiring internet access. Features: - beacon_price.c/h: 26-byte packed Vendor IE payload (price, step, metric, mint_hash, geohash, npub_hash), injected via esp_wifi_set_vendor_ie() - market.c/h: Passive WiFi scan receiver, vendor IE callback parsing, BSSID-correlated market entries, effective price ranking - GET /market API endpoint: JSON market snapshot with discovered entries - AP-only services: beacon + market + API start on WIFI_EVENT_AP_START, independent of STA connectivity - STA reconnect fix: 2s delay between retries creates scan windows; s_sta_connecting guard prevents double-connect - write-config-ap-only-a/b Makefile targets for STA-less testing - market_tick() in main loop, client price comparison logging Hardware verified: both boards discover each other via Vendor IE beacons. Board A sees TollGate-C0E9CA (RSSI=-30), Board B sees TollGate-B96D80 (RSSI=-25). test-market.mjs: 9/9, test-price-discovery.mjs: 7/7 per board. Unit tests: 45 new assertions across test_beacon_price (28) and test_market (17). All 15 test suites pass. ESP-IDF build clean for ESP32-S3.
Diffstat (limited to 'SESSION_NOTES.md')
-rw-r--r--SESSION_NOTES.md141
1 files changed, 141 insertions, 0 deletions
diff --git a/SESSION_NOTES.md b/SESSION_NOTES.md
new file mode 100644
index 0000000..a8edb3f
--- /dev/null
+++ b/SESSION_NOTES.md
@@ -0,0 +1,141 @@
1# Session Notes — Price Discovery Hardware Integration
2
3## Date: 2026-05-18
4
5## Summary
6
7The price discovery feature (WiFi Vendor IE beacon advertising) is fully implemented and unit-tested. Hardware integration testing is blocked by two issues: (1) ESP32 boards failing to associate with the upstream WiFi router (reason 211 = NO_AP_FOUND), and (2) competing LLM sessions in other worktrees continuously reflashing the boards.
8
9## Commits on `feature/price-discovery`
10
11| Hash | Description |
12|------|-------------|
13| `ba8af3a` | Initial price discovery implementation |
14| `5f69aaa` | Integration tests + Makefile targets |
15| `a68fc46` | Unit test fixes |
16| `dd253f0` | ESP-IDF build fixes (format specifiers, symlinks) |
17| `c99deaa` | Per-board hardware mutex in Makefile |
18| `4e4576c` | write-config targets, SPIFFS image generation |
19| `5b36dba` | WiFi disconnect reason code logging |
20| `bc57c4e` | WiFi country code set to DE for EU regulatory compliance |
21
22## Key Findings
23
24### 1. WiFi STA Connectivity Failure (reason=211)
25
26**Symptom:** Both ESP32 boards report `WIFI_REASON_NO_AP_FOUND` (reason 211) when scanning for `EnterSSID-2.4GHz`. The laptop sees the router at 100% signal strength on channel 10.
27
28**Observations:**
29- Board B successfully obtained STA IP once during this session (CVM relay connections logged)
30- After the other session reflashed the board, STA connectivity was lost again
31- The same firmware that worked earlier stopped working after a reflash cycle
32- Both boards' APs (TollGate-B96D80, TollGate-C0E9CA) are visible to the laptop at 99-100% signal
33
34**Potential causes:**
35- **APSTA co-channel limitation:** ESP32 AP is on channel 1, router on channel 10. In APSTA mode, the ESP32 may have reduced scan sensitivity on non-AP channels
36- **USB power instability:** CH340 USB-serial adapters cause unreliable flashing (frequent "chip stopped responding" errors on Board A)
37- **esptool stub leaving board in download mode:** After flash, `--after hard_reset` via RTS pin doesn't always boot the app. USB device authorized toggle needed
38- **Multiple LLM sessions competing for hardware:** Other worktrees (`esp32-tollgate-arch`, `esp32-tollgate-display`, main `esp32-tollgate`) flash boards concurrently, overwriting our firmware within seconds
39
40**What we fixed:**
41- Added `esp_wifi_set_country_code("DE")` — was missing, defaults to CN which limits EU channels/power
42- Added disconnect reason code to log output for debugging
43
44### 2. Board A Hardware Issues
45
46Board A (MAC `94:a9:90:2e:37:7c`) has persistent problems:
47- Flash operations frequently fail with "chip stopped responding" or "StopIteration"
48- After esptool flash, board enters download mode (`boot:0x0 DOWNLOAD`) instead of app mode
49- Requires USB device authorized toggle to recover
50- The AGENTS.md in the main repo confirms: *"Board A WiFi is broken — hardware issue confirmed: WIFI_REASON_AUTH_EXPIRED on all APs"*
51
52### 3. Port Instability
53
54Board ports re-enumerate after every USB reset:
55- Typical mapping: Board A=ACM0, Board B=ACM1, Board C=ACM2
56- After USB reset: ports shift unpredictably (ACM0→ACM3, ACM1→ACM0, etc.)
57- The Makefile defaults (`PORT_A ?= /dev/ttyACM1`, `PORT_B ?= /dev/ttyACM2`) are often wrong
58- Must always verify with `esptool.py --port <port> chip_id` before flashing
59- The `boards.env` file uses stable `/dev/serial/by-id/` paths but Makefile uses raw `/dev/ttyACM*`
60
61### 4. Multi-Session Hardware Conflict
62
63Three other LLM sessions operate simultaneously:
64- `esp32-tollgate` (main repo) — flashes both boards with main-branch firmware
65- `esp32-tollgate-arch` — flashes Board A with architecture branch firmware
66- `esp32-tollgate-display` — flashes Board C with display branch firmware
67
68These sessions do not coordinate via the lock system. Even with locks held, other sessions bypass them by calling `esptool.py` directly. Our firmware was overwritten multiple times during testing — confirmed by seeing `mint.minibits.cash` (other session's default) instead of `testnut.cashu.space` (our config).
69
70### 5. SPIFFS Config Verification
71
72SPIFFS partition survives firmware flashes (different partition offsets):
73- Firmware: `0x0` (bootloader), `0x8000` (partition table), `0x10000` (app)
74- SPIFFS: `0x410000` (storage partition)
75- Read-back confirmed our config is correctly written (`testnut.cashu.space`, `price_per_step: 21`)
76- But the other session's firmware may also write its own SPIFFS, overwriting ours
77
78## Successful Tests
79
80### Single-board market test (Board B)
81- `GET /market` returns valid JSON with `entries: []` (no neighbors discovered)
82- `GET /` returns correct TollGate event with our config values
83- 4/4 tests passed
84
85### Single-board market test (Board A)
86- Same as above, 4/4 tests passed
87- Required workaround for Board A's flash issues (USB reset between flash and boot)
88
89### Unit tests
90- All 13 test suites pass (45 new assertions across `test_beacon_price` + `test_market`)
91- `make test-unit` passes cleanly
92
93## Recommendations for Next Session
94
951. **Coordinate with other sessions** — agree on exclusive hardware windows or add lock-checking to all flash paths
962. **Use `/dev/serial/by-id/` paths** — update Makefile `PORT_A`/`PORT_B` to use stable by-id symlinks
973. **Test with boards physically closer to router** — eliminate RF as a variable
984. **Consider starting services without STA** — modify `start_services()` to start beacon + market + API even without STA IP, so price discovery can be tested in isolation
995. **Use `--no-stub` esptool mode** — the stub leaves boards in download mode; direct flash without stub may be more reliable
100
101## Additional Finding: CVM set_config Overwrites Runtime Config
102
103The CVM (ContextVM) server receives `set_config` MCP commands via Nostr relay. When a `set_config` command arrives (e.g., changing `mint_url` or `price_per_step`), it modifies the in-memory config. This explains why the API returns `mint.minibits.cash` and `price_per_step: 1` even though our SPIFFS has `testnut.cashu.space` and `price_per_step: 21`. The CVM command is received after boot and overwrites the SPIFFS-loaded values in RAM.
104
105This also means **our firmware IS running on the board** (confirmed by market scan log messages), but the CVM is changing the visible config values. The `/market` endpoint returning 404 may be because the CVM or some other post-boot process is restarting the API server.
106
107## AP-Only Services
108
109Added `start_ap_services()` which starts tollgate_api, beacon_price, and market scanner on `WIFI_EVENT_AP_START` — independent of STA connectivity. This allows testing price discovery without internet access. Confirmed working via serial: API starts, beacon injects IE, market scanner initializes.
110
111### /market 404 Investigation
112
113The `/market` endpoint returns 404 even when our firmware is confirmed running via serial. Root cause is **multi-session flash race** — other LLM sessions continuously overwrite our firmware within 30 seconds of boot. Key evidence:
114- Serial shows `TollGate API started on port 2121` and `Market scanner initialized` (our firmware)
115- HTTP `/whoami` and `/usage` work (return correct data)
116- HTTP `/market` returns "Nothing matches the given URI" (handler not registered)
117- HTTP `/` returns `mint.minibits.cash` instead of `testnut.cashu.space`
118- Debug `>>>` log markers added to handlers never appear in serial
119
120The discrepancy between serial (our firmware) and HTTP (other firmware) is explained by a **reflash during the 15-30 second wait** between boot verification and HTTP testing. The board reboots with the other session's firmware silently.
121
122### Confirmed via Serial (Our Firmware)
123```
124I (1874) tollgate_api: TollGate API started on port 2121
125I (1878) beacon_price: Built IE: price=21 sats, step=60000, metric=milliseconds
126I (1886) beacon_price: Price advertising started (beacon + probe response)
127I (1893) market: Market scanner initialized
128I (1896) tollgate_main: === AP-only services started (no STA) ===
129```
130
131### ESP32 APSTA Channel Behavior (Confirmed from ESP-IDF docs)
132From `esp-idf/docs/en/api-guides/wifi.rst:1684`:
133> In station/AP-coexistence mode, the home channel of AP and station must be the same. The station's home channel is always in priority. The AP switches using Channel Switch Announcement (CSA).
134
135AP channel mismatch (AP=0/auto, router=10) is **NOT** the cause of reason=211. The ESP32 scans all channels regardless.
136
137### Fixes Applied
1381. `market_tick()`: Update `last_scan_ms` on scan failure — prevents 1-second retry spam
1392. `market_tick()`: Log failure count, suppress after 3 failures (every 30th thereafter)
1403. `config.c`: AP channel default changed from 1 to 0 (auto-select)
1414. `tollgate_api.c`: Debug logging on `/market` and `/` handlers, check registration return