Implement Phase 7C local status dashboard
Add fixed status icons, OLED dimming and wake behavior, lowercase glyphs, and access-point metadata tracking. Update validation guidance, roadmap status, and provide an icon layout mockup with licensing.
This commit is contained in:
@@ -127,9 +127,18 @@ After boot, the OLED starts on the **OVERVIEW** page. A short previous/back pres
|
||||
3. **BROKER** — connected clients, current writer marker, pending output, and drop/event counters.
|
||||
4. **NETWORK SERVICES** — Wi-Fi state/RSSI/IP/AP state and HTTPS, WebSocket, and SSH service state.
|
||||
|
||||
Confirm that each page remains entirely within the blue content panel and that the yellow strip continuously shows compact serial/Wi-Fi/client/service state. The UI refreshes at 4 Hz maximum and is read-only: select (GPIO13) must not change a service, acquire/release a writer, inject serial data, or expose passwords, credentials, tickets, or key material.
|
||||
Confirm that each page remains entirely within the blue content panel. The yellow panel must retain the same fixed icon positions while pages change: serial, segmented Wi-Fi strength, USB, WebSocket, SSH, broker clients, and alert. Active icons are solid with a value below; inactive icon slots remain completely blank and omit their value. Confirm that page text uses readable upper/lowercase, separates items and values with colons, and displays the active station SSID or AP SSID with its channel on the Overview and Network pages.
|
||||
|
||||
With UART0, USB CDC, WebSocket, or SSH active, navigate pages and confirm that the display continues to update without disrupting serial traffic or UART0 recovery. Record a missing, stale, clipped, or implausible status value before Phase 7C is marked complete.
|
||||
The UI refreshes at 4 Hz maximum and is read-only: select (GPIO13) must not change a service, acquire/release a writer, inject serial data, or expose passwords, credentials, tickets, or key material. With UART0, USB CDC, WebSocket, and SSH active, navigate pages and confirm that the display continues to update without disrupting serial traffic or UART0 recovery.
|
||||
|
||||
For the OLED-aging policy, leave all three buttons untouched and verify:
|
||||
|
||||
1. At five minutes, display contrast drops to `1` while the contents remain present.
|
||||
2. At ten minutes, the OLED switches off.
|
||||
3. The first debounced press of any button wakes the OLED at contrast `127` without changing the current page.
|
||||
4. A subsequent previous/next press navigates normally and restarts the inactivity timers.
|
||||
|
||||
`debug display status` may verify an individual transition in a separate timing run. Every display diagnostic counts as activity and holds normal UI rendering for 30 seconds, so do not invoke it between the five- and ten-minute observations of one continuous run. Record a missing, stale, clipped, or implausible status value or incorrect dim/off/wake transition before Phase 7C is marked complete.
|
||||
|
||||
## Configuration A: data and handshake pairs
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1080" height="720" viewBox="0 0 1080 720" role="img" aria-labelledby="title description">
|
||||
<title id="title">Phase 7C compact icon status UI mockup</title>
|
||||
<desc id="description">Four 128 by 64 OLED page mockups with the same fixed-position yellow status icons and changing blue page content. Active icons are solid yellow with values beneath; inactive SSH and alert slots are blank.</desc>
|
||||
<defs>
|
||||
<style>
|
||||
.heading{fill:#d8e4ec;font:600 20px sans-serif}.note{fill:#93a8b6;font:14px sans-serif}.screen{fill:#010609;stroke:#668092;stroke-width:2}.yellowbg{fill:#191600}.divider{stroke:#77858d;stroke-opacity:.5;stroke-width:2}.active{fill:#ffd52e;stroke:#ffd52e}.blue{fill:#27c9ff;stroke:#27c9ff}.content{fill:#27c9ff;font:600 18px 'DejaVu Sans Mono',monospace}.value{fill:#ffd52e;font:600 14px 'DejaVu Sans Mono',monospace}.page{fill:#d8e4ec;font:600 17px sans-serif}
|
||||
</style>
|
||||
<!-- Official Material Design Icons usb path, @mdi/svg 7.4.47. -->
|
||||
<symbol id="usb" viewBox="0 0 24 24"><path d="M15,7V11H16V13H13V5H15L12,1L9,5H11V13H8V10.93C8.7,10.56 9.2,9.85 9.2,9C9.2,7.78 8.21,6.8 7,6.8C5.78,6.8 4.8,7.78 4.8,9C4.8,9.85 5.3,10.56 6,10.93V13A2,2 0 0,0 8,15H11V18.05C10.29,18.41 9.8,19.15 9.8,20A2.2,2.2 0 0,0 12,22.2A2.2,2.2 0 0,0 14.2,20C14.2,19.15 13.71,18.41 13,18.05V15H16A2,2 0 0,0 18,13V11H19V7H15Z"/></symbol>
|
||||
<symbol id="serial" viewBox="0 0 24 24"><path d="M5 3h14v5h3v13H2V8h3zm2 2v3h10V5zM5 11v7h14v-7zm2 2h2v2H7zm4 0h2v2h-2zm4 0h2v2h-2z"/></symbol>
|
||||
<symbol id="wifi" viewBox="0 0 24 24"><path d="M1 8q11-9 22 0l-2 3q-9-7-18 0zm5 6q6-5 12 0l-2 3q-4-3-8 0zm4 6a2 2 0 1 1 4 0z"/></symbol>
|
||||
<symbol id="web" viewBox="0 0 24 24"><path fill-rule="evenodd" d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20M4.3 9h3.1A16 16 0 0 1 9 4.7 8.1 8.1 0 0 0 4.3 9m-.2 6h3.3a16 16 0 0 1 0-6H4.3a8 8 0 0 0-.2 6m4.9 4.3A16 16 0 0 1 7.4 15H4.3A8.1 8.1 0 0 0 9 19.3M10 15h4a14 14 0 0 0 0-6h-4a14 14 0 0 0 0 6m1 4.9v-3h2v3a8 8 0 0 1-2 0m0-15.8v3h2v-3a8 8 0 0 0-2 0m4 15.2a16 16 0 0 0 1.6-4.3h3.1a8.1 8.1 0 0 1-4.7 4.3m1.6-10.3h3.1A8.1 8.1 0 0 0 15 4.7 16 16 0 0 1 16.6 9m.1 2a14 14 0 0 1 0 4h3.2a8 8 0 0 0 0-4z"/></symbol>
|
||||
<symbol id="ssh" viewBox="0 0 24 24"><path d="M2 3h20v18H2zm3 4 4 4-4 4 2 2 6-6-6-6zm8 8v2h6v-2z"/></symbol>
|
||||
<symbol id="clients" viewBox="0 0 24 24"><path d="M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8m7-1a3 3 0 1 0 0-6 3 3 0 0 0 0 6M2 21v-3c0-3 3-5 7-5s7 2 7 5v3zm14-8c4 0 6 2 6 5v3h-4v-3c0-2-1-4-3-5z"/></symbol>
|
||||
<symbol id="alert" viewBox="0 0 24 24"><path d="M12 2 1 22h22zm-1 7h2v7h-2zm0 9h2v2h-2z"/></symbol>
|
||||
<g id="status">
|
||||
<g class="active"><use href="#serial" x="12" y="4" width="30" height="30"/><use href="#wifi" x="80" y="4" width="30" height="30"/><use href="#usb" x="150" y="4" width="30" height="30"/><use href="#web" x="220" y="4" width="30" height="30"/><use href="#clients" x="360" y="4" width="30" height="30"/></g>
|
||||
|
||||
<text x="17" y="57" class="value">On</text><text x="91" y="57" class="value">6</text><text x="154" y="57" class="value">Wr</text><text x="231" y="57" class="value">1</text><text x="371" y="57" class="value">3</text>
|
||||
</g>
|
||||
</defs>
|
||||
<rect width="1080" height="720" fill="#0b1118"/><text x="540" y="34" text-anchor="middle" class="heading">Phase 7C — fixed icon dashboard and compact status pages</text><text x="540" y="57" text-anchor="middle" class="note">Yellow strip is identical on every page · inactive icon slots and their supplementary values remain blank</text>
|
||||
|
||||
<g transform="translate(62 98)"><text x="256" y="-16" text-anchor="middle" class="page">Overview</text><rect width="512" height="256" class="screen"/><rect width="512" height="64" class="yellowbg"/><line x1="0" y1="64" x2="512" y2="64" class="divider"/><use href="#status"/>
|
||||
<g class="blue"><use href="#serial" x="8" y="72" width="30" height="30"/><use href="#clients" x="8" y="104" width="30" height="30"/><use href="#wifi" x="8" y="136" width="30" height="30"/><use href="#web" x="8" y="200" width="30" height="30"/></g><text x="45" y="96" class="content">Serial:230400 8N1</text><text x="45" y="128" class="content">Clients:3 Wr:USB</text><text x="45" y="160" class="content">WiFi:LabNet Ch:6</text><text x="45" y="192" class="content">IP:192.168.1.42</text><text x="45" y="224" class="content">Web:1 SSH:0 USB:1</text></g>
|
||||
|
||||
<g transform="translate(592 98)"><text x="256" y="-16" text-anchor="middle" class="page">RS-232 / modem</text><rect width="512" height="256" class="screen"/><rect width="512" height="64" class="yellowbg"/><line x1="0" y1="64" x2="512" y2="64" class="divider"/><use href="#status"/>
|
||||
<g class="blue"><use href="#serial" x="8" y="72" width="30" height="30"/></g><text x="45" y="96" class="content">Mode:230400 8N1</text><text x="45" y="128" class="content">Flow:rts-cts</text><text x="45" y="160" class="content">DCD:0 DSR:1 CTS:1</text><text x="45" y="192" class="content">Valid:Yes RX:1.2M</text><text x="45" y="224" class="content">TX:633 Err:0</text></g>
|
||||
|
||||
<g transform="translate(62 438)"><text x="256" y="-16" text-anchor="middle" class="page">Broker clients</text><rect width="512" height="256" class="screen"/><rect width="512" height="64" class="yellowbg"/><line x1="0" y1="64" x2="512" y2="64" class="divider"/><use href="#status"/>
|
||||
<g class="blue"><use href="#usb" x="8" y="72" width="30" height="30"/><use href="#web" x="8" y="104" width="30" height="30"/><use href="#ssh" x="8" y="136" width="30" height="30"/></g><text x="45" y="96" class="content">Wr:USB Q:0</text><text x="45" y="128" class="content">Ob:web Q:0</text><text x="45" y="160" class="content">Ob:SSH Q:0</text><text x="45" y="224" class="content">Drop:0 Events:0</text></g>
|
||||
|
||||
<g transform="translate(592 438)"><text x="256" y="-16" text-anchor="middle" class="page">Network / services</text><rect width="512" height="256" class="screen"/><rect width="512" height="64" class="yellowbg"/><line x1="0" y1="64" x2="512" y2="64" class="divider"/><use href="#status"/>
|
||||
<g class="blue"><use href="#wifi" x="8" y="72" width="30" height="30"/><use href="#web" x="8" y="168" width="30" height="30"/><use href="#ssh" x="8" y="200" width="30" height="30"/></g><text x="45" y="96" class="content">WiFi:LabNet Ch:6</text><text x="45" y="128" class="content">IP:192.168.1.42</text><text x="45" y="160" class="content">AP:Off Clients:0</text><text x="45" y="192" class="content">HTTPS:On Web:1</text><text x="45" y="224" class="content">SSH:On Sessions:0</text></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
+10
-8
@@ -37,7 +37,7 @@ These constraints apply across all phases:
|
||||
| 5A | Authenticated HTTPS administration foundation | **Complete** |
|
||||
| 5B | Offline xterm.js WebSocket serial terminal | **Complete** |
|
||||
| 6 | Authenticated SSH serial transport | **Complete** |
|
||||
| 7 | Local display and button interface | **In progress (7C)** |
|
||||
| 7 | Local display and button interface | **In progress (7D)** |
|
||||
| 8 | Security and production hardening | **Planned** |
|
||||
| 9 | Authenticated, rollback-capable OTA | **Planned** |
|
||||
| 10 | BLE serial transport and provisioning evaluation | **Planned** |
|
||||
@@ -184,7 +184,7 @@ The order below is the current plan. Phase 7 is in progress; later phases remain
|
||||
|
||||
Add a standalone local status/control interface without making it a dependency of the serial core. The planning baseline uses a 128×64 dual-color monochrome I²C OLED sold with an SSD1315 controller. Phase 7A confirmed SSD1306-compatible operation, 7-bit I²C address `0x3c`, orientation, column mapping, contrast/inversion behavior, button inputs, and the physical color geometry on the selected hardware.
|
||||
|
||||
Phase 7A diagnostics and target-hardware electrical validation are complete. Phase 7B display-driver validation is complete; Phase 7 overall remains in progress (7C). Phases 7C through 7E are not complete.
|
||||
Phase 7A diagnostics and target-hardware electrical validation are complete. Phases 7B and 7C are complete; Phase 7 overall remains in progress (7D). Phases 7D and 7E are not complete.
|
||||
|
||||
#### Hardware baseline
|
||||
|
||||
@@ -196,9 +196,9 @@ Phase 7A diagnostics and target-hardware electrical validation are complete. Pha
|
||||
- Hardware verification established yellow rows 0–15 and blue rows 16–63. A narrow physical black divider separates the two regions even though row 15 is the final yellow addressable row and row 16 the first blue addressable row.
|
||||
- Keep assignments centralized in the board profile rather than scattering display or button GPIO assumptions through UI code.
|
||||
|
||||

|
||||

|
||||
|
||||
The persistent yellow strip is reserved for serial-service state, Wi-Fi strength, active USB/Web/SSH counts, current writer, total clients, and an alert indicator. Phase 7B must render it as a separate 128×16 status panel. The blue 128×48 content panel begins at row 16 and rotates through overview, RS-232, broker-client, and network/service pages; the physical black divider must remain visually clear. No password, Wi-Fi secret, private-key material, or routine credential data may appear on the display.
|
||||
The persistent yellow strip uses fixed-position serial, Wi-Fi-strength, USB, WebSocket, SSH, broker-client, and alert icons. Active icons are solid with a compact value below; inactive icon slots remain blank and show no value. The blue 128×48 content panel begins at row 16 and rotates through overview, RS-232, broker-client, and network/service pages; the physical black divider remains visually clear. No password, Wi-Fi secret, private-key material, or routine credential data may appear on the display.
|
||||
|
||||
#### Implementation sequence
|
||||
|
||||
@@ -207,23 +207,25 @@ The persistent yellow strip is reserved for serial-service state, Wi-Fi strength
|
||||
- The selected module acknowledged at 7-bit `0x3c` (8-bit `0x78` write / `0x79` read). A guarded full scan is retained for the dedicated local-UI bus; an absent display remains nonfatal and does not make the serial core dependent on the OLED.
|
||||
- Hardware validation passed for geometry, orientation, row/column addressing, contrast, inversion, button pull-ups/debounce/short-press/long-press/stuck behavior, and the color geometry: yellow rows 0–15, blue rows 16–63, with a physical black separator between the regions.
|
||||
2. **Phase 7B — Display driver — Complete**
|
||||
- The `local_display` service owns the local I²C bus, SSD1315-compatible panel, and framebuffer. It uses a static 1 KiB 128×64 framebuffer, a compact 5×7 uppercase/digit/punctuation renderer, and an internal mutex; do not add LVGL for this fixed monochrome UI.
|
||||
- The `local_display` service owns the local I²C bus, SSD1315-compatible panel, and framebuffer. It uses a static 1 KiB 128×64 framebuffer, a compact 5×7 upper/lowercase, digit, and punctuation renderer, and an internal mutex; do not add LVGL for this fixed monochrome UI.
|
||||
- Rendering treats the yellow 128×16 status panel (rows 0–15) and blue 128×48 content panel (rows 16–63) as separate panels so the physical divider remains clear.
|
||||
- Frame commits refresh only dirty 8-pixel pages. I²C runs at 100 kHz with bounded transactions.
|
||||
- The display bus initializes at boot; a known display is automatically initialized and cleared. A missing or unresponsive display is nonfatal and does not make the serial core dependent on it.
|
||||
- Target-hardware validation passed for initialization, all display diagnostic patterns, the rendered panel layout and physical divider, row 15/16 boundary, contrast, inversion, display-off/reinitialization, and button diagnostics. Observed contrast control has a useful brightness range of 1–255.
|
||||
3. **Phase 7C — Read-only status UI — Implemented; validation pending**
|
||||
3. **Phase 7C — Read-only status UI — Complete**
|
||||
- The low-priority `local_status_ui` owner task builds display state from copied public serial, Wi-Fi, broker, USB, WebSocket, HTTPS, and SSH snapshots. It does not parse CLI output, reach into transport internals, or become a broker client.
|
||||
- Previous/back and next short presses navigate overview, RS-232/modem, broker-client/writer, and network/service pages. Select has no state-changing action in this read-only phase.
|
||||
- The task polls and debounces the existing active-low button inputs and refreshes at 4 Hz maximum. It collects service snapshots before beginning a display frame, so no service or broker lock is held across an I²C transaction.
|
||||
- The yellow panel is page-independent and uses fixed icon slots. Wi-Fi strength is shown by segmented Wi-Fi bars; the USB glyph is derived from Pictogrammers Material Design Icons. Page text uses lowercase where appropriate, separates labels and values with colons, and shows the active station or AP SSID plus channel.
|
||||
- To reduce OLED aging, inactivity dims contrast to `1` after five minutes and switches the panel off after ten minutes. The first debounced button press restores contrast `127` and wakes without navigating.
|
||||
- A missing/unresponsive display is nonfatal; the task remains read-only and never acquires serial writer ownership.
|
||||
- Pending target-hardware validation: page navigation, each page's live snapshot values, concurrent USB/WebSocket/SSH operation while refreshing, and UART0 responsiveness.
|
||||
- Target-hardware validation passed for the four pages, fixed active-only status icons, lowercase layout, diagnostics hold, dim/off/wake behavior, all available concurrent client interfaces, UART0 recovery, and serial traffic from 9600 through 230400 baud.
|
||||
4. **Phase 7D — Local controls — Planned**
|
||||
- Add a shallow menu for safe serial, Wi-Fi, HTTPS, SSH, writer-release, display, and reboot actions through direct service APIs.
|
||||
- Require a visible confirmation screen and a timed select hold before stopping active services, revoking a writer, rebooting, or performing another disruptive action.
|
||||
- A local display is not a serial broker client and cannot silently acquire the writer lease.
|
||||
5. **Phase 7E — Reliability, persistence, and documentation — Planned**
|
||||
- Add contrast and optional dim/blank timeout settings to limit OLED burn-in without making the display necessary for recovery.
|
||||
- Make the implemented contrast dim/blank timeouts configurable and persistent without making the display necessary for recovery.
|
||||
- Validate display removal, I²C NACK/timeouts, stuck buttons, queue saturation, and repeated actions.
|
||||
- Re-run concurrent USB CDC, WebSocket, and SSH traffic while the UI refreshes and confirm UART0 remains responsive.
|
||||
- Update wiring, electrical-test, command-reference, and recovery documentation.
|
||||
|
||||
Reference in New Issue
Block a user