1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# Web WiFi Setup Plan
## Overview
Move WiFi configuration from on-display touchscreen UI to a web-based setup page
served by the captive portal. The display becomes portrait-only, showing QR codes
and status info. No more landscape rotation, on-screen keyboard, or touch-driven
WiFi setup.
## Architecture
### Display (portrait 320x480 only)
| State | When | Content |
|-------|------|---------|
| BOOT | Startup | WiFi QR + "TollGate" title + SSID + status |
| READY (unconfigured) | No STA network | AP WiFi QR + SSID + "http://AP_IP/setup" |
| READY (configured) | STA connected | QR cycling (WiFi↔Portal) + balance/clients/price |
| PAYMENT_RECEIVED | After payment | "ACCESS GRANTED" + amount + time (3s then→READY) |
| ERROR | No upstream | WiFi QR + "NO UPSTREAM" + SSID + setup URL |
### Captive Portal (new endpoints)
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/setup` | GET | WiFi setup HTML page (only when unconfigured) |
| `/wifi/scan` | GET | Trigger scan, return `[{ssid,rssi,secured}]` JSON |
| `/wifi/connect` | POST | Take `{ssid,password}`, save config, connect |
| `/wifi/status` | GET | Return `{connected,ip,ssid}` |
### Files Removed from Build (kept on disk)
- `main/touch.c` / `touch.h`
- `main/keyboard.c` / `keyboard.h`
- `main/wifi_setup.c` / `wifi_setup.h`
### Files Modified
- `main/display.c` — Strip WiFi setup state, rotation, offscreen; add setup URL text
- `main/display.h` — Remove `DISPLAY_WIFI_SETUP`, `display_enter_wifi_setup()`
- `main/tollgate_main.c` — Remove WiFi setup auto-enter, add display state for unconfigured
- `main/captive_portal.c` — Add WiFi scan/connect/status endpoints + `/setup` HTML
- `main/captive_portal.h` — Expose captive_portal_is_setup_available()
- `components/axs15231b/axs15231b.c` — Remove offscreen buffer
- `components/axs15231b/include/axs15231b.h` — Remove `axs15231b_set_offscreen()`
- `main/CMakeLists.txt` — Remove touch/keyboard/wifi_setup sources
## Checklist
### Phase 1: Strip display and driver
- [x] Remove offscreen buffer from `axs15231b.c` and `axs15231b.h`
- [x] Strip `display.c` — remove WiFi setup state, rotation, keyboard/touch imports
- [x] Update `display.h` — remove `DISPLAY_WIFI_SETUP`, `display_enter_wifi_setup()`
- [x] Add setup URL text to READY (unconfigured) and ERROR screens
- [x] Remove WiFi setup auto-enter from `tollgate_main.c`
- [x] Add WiFi QR code to BOOT screen (scan to connect)
- [x] Add WiFi QR code to ERROR screen
### Phase 2: Add web WiFi setup
- [x] Add `/wifi/scan` endpoint to `captive_portal.c`
- [x] Add `/wifi/connect` endpoint to `captive_portal.c`
- [x] Add `/wifi/status` endpoint to `captive_portal.c`
- [x] Add `/setup` HTML page with scan list + connect form
- [x] Gate `/setup` behind `network_count == 0`
### Phase 3: Build configuration
- [x] Remove touch.c, keyboard.c, wifi_setup.c from `main/CMakeLists.txt`
### Phase 4: Testing and fixes
- [x] `make test-unit` passes
- [x] Build succeeds (`idf.py build`)
- [x] Flash to Board C, verify portrait display shows setup URL
- [x] Fix: display stuck at BOOT when WiFi configured but unreachable
- Added `s_total_retries` counter (MAX_TOTAL_RETRIES=10)
- Transitions to DISPLAY_ERROR after all retries exhausted
- [x] WiFi QR code visible on BOOT and ERROR screens (hardware verified)
- [x] Write integration test `tests/integration/wifi_setup.mjs`
- [x] Pushed to `ngit.orangesync.tech` (commits `aa58b47`..`402f4f2`)
### Phase 5: Playwright E2E for `/setup` page
- [ ] Plan test scenarios for `/setup` page (requires unconfigured board)
- [ ] Write `tests/e2e/wifi-setup.spec.mjs`
- Test: `/setup` returns HTML with scan button when `network_count == 0`
- Test: `/wifi/scan` returns JSON array of APs
- Test: `/wifi/connect` rejects invalid JSON
- Test: `/wifi/connect` rejects missing SSID
- Test: `/wifi/status` returns `{connected, ip, ssid}`
- Test: `/setup` redirects to `/` when WiFi already configured
- Test: full flow — scan → select AP → enter password → connect
- [ ] Add `make test-wifi-setup` target to Makefile
- [ ] Run E2E test against live board with erased SPIFFS
## Commits
| Hash | Message |
|------|---------|
| `aa58b47` | feat: web-based WiFi setup via captive portal, portrait-only display |
| `2e65cdf` | fix: transition display to ERROR after WiFi retries exhausted |
| `cf4ac1b` | feat: add WiFi QR code to BOOT and ERROR screens |
| `402f4f2` | docs: update web WiFi setup plan checklist with progress |
|