upleb.uk

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

summaryrefslogtreecommitdiff
path: root/PRICING_DISCOVERY_PLAN.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 /PRICING_DISCOVERY_PLAN.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 'PRICING_DISCOVERY_PLAN.md')
-rw-r--r--PRICING_DISCOVERY_PLAN.md79
1 files changed, 79 insertions, 0 deletions
diff --git a/PRICING_DISCOVERY_PLAN.md b/PRICING_DISCOVERY_PLAN.md
new file mode 100644
index 0000000..3cf7742
--- /dev/null
+++ b/PRICING_DISCOVERY_PLAN.md
@@ -0,0 +1,79 @@
1# Price Discovery — Two-Board Cross-Discovery Plan
2
3## Goal
4
5Get `test-price-discovery.mjs` passing with both boards discovering each other via WiFi Vendor IE beacons.
6
7## Root Cause
8
9Cross-discovery never worked because of two compounding issues:
10
111. **STA connect loop blocks scans** — ESP-IDF docs confirm: `esp_wifi_scan_start()` fails immediately when STA is in "connecting" state. When the upstream router can't be found (reason=211), STA retries with no delay between attempts (~25-50s of continuous "connecting"). Market scanner can never start a scan during this window.
12
132. **Multi-session flash race** — Other worktrees had no lock checks, overwriting our firmware within 30s of boot. Now fixed.
14
15## Phases
16
17### Phase 1: Firmware fixes (no hardware needed)
18
19- [x] 1a. Add 2s delay before `esp_wifi_connect()` in disconnect handler (creates scan window)
20- [x] 1b. Guard `WIFI_EVENT_STA_START` against double-connect during retry loop
21- [x] 1c. Add `write-config-ap-only-a/b` Makefile targets (no `wifi_networks` in config)
22- [x] 1d. Update `test-price-discovery.mjs` with correct Board B IP
23- [x] 1e. Run `make test-unit` — must pass
24
25### Phase 2: Flash and verify both boards (hardware needed)
26
27- [x] 2a. Acquire locks on both boards (`make lock-a`, `make lock-b`)
28- [x] 2b. Build firmware (`make build`)
29- [x] 2c. Flash Board A with AP-only config (`make write-config-ap-only-a && make flash-a`)
30- [x] 2d. Flash Board B with AP-only config (`make write-config-ap-only-b && make flash-b`)
31- [x] 2e. Verify serial: both boards show AP services started, beacon IE injected, market initialized
32- [x] 2f. Wait 60s for scan cycle, verify `GET /market` returns valid JSON on both boards
33
34### Phase 3: Cross-discovery test (hardware needed)
35
36- [x] 3a. Verify Board A `/market` shows Board B entry (BSSID `3A:2A:EB:C0:E9:CA`, SSID TollGate-C0E9CA)
37- [x] 3b. Verify Board B `/market` shows Board A entry (BSSID `FE:08:F7:B9:6D:80`, SSID TollGate-B96D80)
38- [x] 3c. Run `test-price-discovery.mjs` — 7/7 passed (per board, sequential due to single WiFi adapter)
39- [x] 3d. Run `test-market.mjs` on both boards — 9/9 passed on both
40
41### Phase 4: STA-connected test (stretch, hardware + upstream router needed)
42
43- [ ] 4a. Flash with STA config (`write-config-a/b`)
44- [ ] 4b. Verify STA connects to upstream router
45- [ ] 4c. Verify cross-discovery still works with STA connected (background scan)
46- [ ] 4d. Run full test suite
47
48## Risk: vendor_ie_cb may not fire during scan
49
50**CONFIRMED: vendor_ie_cb fires during passive scan.** No fallback needed.
51
52Both boards successfully receive Vendor IEs from the other board's beacon frames during passive WiFi scan. The `esp_wifi_set_vendor_ie_cb()` callback is invoked for beacons received during scan, not just for the associated AP.
53
54## Results
55
56| Test | Result |
57|------|--------|
58| `make test-unit` | 17/17 passed |
59| `idf.py build` | Pass |
60| `test-market.mjs` Board A | 9/9 passed |
61| `test-market.mjs` Board B | 9/9 passed |
62| `test-price-discovery.mjs` Board A | 7/7 passed |
63| `test-price-discovery.mjs` Board B | 7/7 passed |
64
65### Cross-Discovery Data
66
67| Board | Sees | BSSID | SSID | RSSI | Price |
68|-------|------|-------|------|------|-------|
69| A (10.185.47.1) | Board B | `3A:2A:EB:C0:E9:CA` | TollGate-C0E9CA | -30 | 21 sats/step |
70| B (10.192.45.1) | Board A | `FE:08:F7:B9:6D:80` | TollGate-B96D80 | -25 | 21 sats/step |
71
72## Key Technical Details
73
74- **Vendor IE OUI:** `0xC0, 0xFF, 0xEE`
75- **IE type:** `0x01`
76- **Payload:** 26-byte packed struct (version, metric, price, step, mint_hash, geohash, npub_hash)
77- **Scan config:** passive, 120ms/channel, all channels
78- **Self-filter:** `npub_hash` comparison avoids processing own beacons
79- **AP-only mode:** No `wifi_networks` in config → STA never connects → scans always work