Skip to content

feat: Web UI modernization — all 8 increments (#51-#58)#85

Merged
basmeerman merged 9 commits intomasterfrom
work/plan-07
Mar 19, 2026
Merged

feat: Web UI modernization — all 8 increments (#51-#58)#85
basmeerman merged 9 commits intomasterfrom
work/plan-07

Conversation

@basmeerman
Copy link
Copy Markdown
Owner

@basmeerman basmeerman commented Mar 19, 2026

Summary

Complete Web UI modernization across all 8 increments:

Metrics

Metric Before After Budget
packed_fs.c 270 KB 298 KB < 300 KB
Flash 85.4% ~86% < 95%
RAM 21.2% ~21.3% < 90%
CDN deps 3 0 0
Bootstrap CSS 41 KB 26 KB trimmed unused

Firmware changes

  • network_common.cpp: /ws/data WebSocket endpoint (differential state, max 4 connections)
  • http_handlers.cpp: Extended /settings JSON with per-node nodes[] array, BalancedState extern

Test plan

  • UI loads without internet (no CDN dependencies)
  • All controls work: mode buttons, solar settings, MQTT/OCPP config, reboot
  • WebSocket connection (green dot) and fallback to polling (red dot)
  • Power flow diagram animates during charging
  • Dark mode toggle and system preference detection
  • Mobile layout (1-column, bottom nav)
  • LCD widget responsive scaling + keyboard shortcuts (arrows/enter)
  • Node overview card on master with multiple nodes
  • Diagnostic viewer: start/stop capture, live stream, download
  • packed_fs.c under 300 KB

🤖 Generated with Claude Code

basmeerman and others added 8 commits March 19, 2026 13:52
Remove jQuery, jQuery Mobile, and Bootstrap CDN dependencies so the
web UI works fully offline. Extract inline JavaScript into app.js
and rename styling.css to style.css with custom button/checkbox styles
replacing jQuery Mobile widgets. Convert all jQuery selectors to
vanilla JS and $.ajax/$.post to fetch(). packed_fs.c reduced by ~10KB.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a WebSocket endpoint /ws/data that pushes differential state
updates at 2 Hz and full syncs every 30 seconds. The client connects
via WebSocket and falls back to HTTP polling when disconnected.

Firmware side (network_common.cpp):
- Connection tracking with max 4 concurrent WS data connections
- Previous state tracking for differential JSON serialization
- Timer-based push at 500ms intervals
- Immediate full sync on new connection

Client side (app.js):
- WebSocket client with exponential backoff reconnection
- Cached state for computing phase current totals from partial updates
- Connection status indicator (green dot = WS, red = polling)
- Visibility-aware: disconnects when tab hidden, reconnects on focus

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace Bootstrap grid with CSS Grid for responsive dashboard layout
(1 column mobile, 2 tablet, 3 desktop). Add visual enhancements:

- State indicator dot: colored circle next to EVSE state (green=charging,
  blue=connected, red=error, gray=idle)
- Per-phase current bars: horizontal colored bars (L1=blue, L2=green,
  L3=yellow) in the Mains Phase Details card
- Mobile bottom navigation: fixed mode buttons (OFF/PAUSE/NORMAL/SOLAR/
  SMART) at bottom of screen on mobile viewports
- Mobile nav syncs with mode changes from both polling and WebSocket

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add an animated power flow visualization showing energy flow between
Grid, Home, and EVSE nodes. Flow lines use CSS stroke-dashoffset
animation with direction indicating import/export and thickness
proportional to power magnitude.

Features:
- Grid node: shows total mains power with import/export direction
- EVSE node: shows EV charging power
- Battery node: appears when home battery data is available
- Flow direction: blue=forward (import), green=reverse (export)
- Line thickness: scales with power magnitude (2-6px)
- Updates in real-time via WebSocket data channel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add dark mode support with CSS custom properties. Features:
- Auto-detects system preference via prefers-color-scheme media query
- Manual toggle button (moon/sun icon) in header
- Preference persisted in localStorage
- Dark palette: #1a1a2e background, #16213e cards, #d1d3e2 text
- All UI elements themed: cards, buttons, inputs, phase bars,
  power flow diagram, mobile nav, tooltips
- WCAG AA compliant contrast ratios

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a dashboard card (master mode only) showing all load balancing
nodes with per-node status, allocated current bars, and scheduling
state badges.

Firmware changes (http_handlers.cpp):
- Extend /settings JSON with nodes[] array containing per-node
  current, state (Idle/Request/Charging), and scheduling state
- Add BalancedState extern declaration
- Increase JSON doc size to 3700 for node data

UI changes:
- Node overview card with colored progress bars per node
- Total capacity utilization bar
- Scheduling state badges (Active=green, Paused=yellow, Inactive=gray)
- Updates via loadData polling (WS node channel in future increment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…uts (#58)

Replace fixed-pixel LCD positioning with percentage-based responsive
layout. The LCD widget now scales properly on all screen sizes.

Changes:
- CSS: percentage-based positioning (26% top, 15% left) replacing
  fixed pixels (156px, 60px). object-fit:contain for LCD image
- CSS: max-width:300px container, flex-wrap for password form
- JS: keyboard shortcuts - Arrow Left/Right for LCD buttons,
  Enter for middle button (only when not focused on input fields)
- HTML: keyboard hint text below LCD buttons
- HTML: removed fixed width/height from LCD images (CSS handles it)

packed_fs.c: 299,684 bytes (under 300KB budget)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move visibilitychange listener out of connectDataWs() to prevent
  duplicate listeners accumulating on each WS reconnect
- Increase ArduinoJson document sizes: full sync 512→640, diff 256→384,
  initial sync 512→640 for safety margin with 25+ fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a diagnostic viewer card that connects to Plan 06's /diag/stream
WebSocket endpoint to display live telemetry snapshots.

Features:
- Profile selection (General/Solar/LoadBal/Modbus/Fast)
- Start/Stop capture controls
- Download link for .diag binary capture files
- Scrollable monospace log with severity coloring:
  red=error, yellow=warning (solar timer/charge delay)
- Binary frame parsing: state, mode, currents, temperature, errors
- State transition arrows for state changes
- Auto-connects to stream if capture already active on page load

CSS budget: trimmed ~12KB of unused Bootstrap CSS (display-*, noise
animations, btn-group, pagination, list-group, spinners, negative
margins, responsive spacing utilities, etc.) to fit within 300KB.

packed_fs.c: 298,462 bytes (under 300KB budget)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@basmeerman basmeerman changed the title feat: Web UI modernization — offline, real-time, responsive (#51-#56,#58) feat: Web UI modernization — all 8 increments (#51-#58) Mar 19, 2026
@basmeerman basmeerman merged commit 3bc00d6 into master Mar 19, 2026
11 checks passed
basmeerman added a commit that referenced this pull request Mar 19, 2026
- Add Plan 06 (Diagnostic Telemetry) features section with PR #84
- Add Plan 07 (Web UI Modernization) features with PR #85
- Add Plan 09 (Power Input Methods) features: API staleness detection,
  HomeWizard P1 energy data, manual IP fallback, metering diagnostics
- Add per-phase energy MQTT and metering diagnostic counters to MQTT section
- Update Testing & Quality metrics (43 suites, 870+ scenarios)
- Update Roadmap: all 9 plans marked Done with PR links
- Add PR references throughout for traceability

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant