diff --git a/pi/backend/README.md b/pi/backend/README.md index f6e212c..69d1726 100644 --- a/pi/backend/README.md +++ b/pi/backend/README.md @@ -30,6 +30,8 @@ uv run flask --app main run --host 0.0.0.0 --port 5000 --reload ## API +### HTTP Endpoints + | Endpoint | Description | |----------|-------------| | `GET /health` | Health check, shows gpsd and Arduino connection status | @@ -38,6 +40,34 @@ uv run flask --app main run --host 0.0.0.0 --port 5000 --reload | `GET /arduino` | Latest Arduino telemetry (voltage, rpm, eng_temp, gear) | | `GET /arduino/history` | Last 100 buffered Arduino readings | +### WebSocket Events (socket.io) + +Real-time data is pushed over WebSocket. The UI connects once and receives streams. + +**Server → Client:** + +| Event | Description | +|-------|-------------| +| `arduino` | Real-time telemetry (voltage, rpm, roll, pitch, accel, etc.) | +| `gps` | GPS position updates | +| `status` | Connection status + `theme_switch` signal from GPIO | +| `alert` | System alerts | +| `ack` | Command acknowledgments | + +**Client → Server:** + +| Event | Description | +|-------|-------------| +| `button` | UI button presses (horn, light, indicators, hazard) | +| `emergency` | Emergency signal | + +### Throttling + +WebSocket data is rate-limited to prevent flooding: + +- **Arduino data**: 20Hz max +- **GPS data**: 1Hz max + ## Test from SSH ```bash diff --git a/pi/ui/lib/README.md b/pi/ui/lib/README.md index 0a297b9..598ccdc 100644 --- a/pi/ui/lib/README.md +++ b/pi/ui/lib/README.md @@ -22,11 +22,29 @@ All services use singleton pattern with `ServiceName.instance`. | Service | Role | |---------|------| | `ConfigService` | Loads `config.json`, exposes settings | -| `PiIO` | Pi hardware interface (CPU temp, future GPIO) | +| `WebSocketService` | socket.io client, streams for arduino/gps/connection/debug, auto-reconnect | +| `PiIO` | Pi hardware interface (CPU temp) | | `OverheatMonitor` | Polls temp, fires callback when threshold exceeded | | `ThemeService` | Dark/bright mode state, notifies listeners | | `TestFlipFlopService` | Debug: toggles theme + navigator emotion every 2s | +## Key Widgets + +| Widget | Purpose | +|--------|---------| +| `NavigatorWidget` | Animated character with emotion states (images precached at startup) | +| `AccelGraph` | Real-time accelerometer visualization with gravity compensation | +| `WhiskeyMark` | Gimbal-style horizon indicator using IMU roll/pitch | +| `SystemBar` | Top status bar (time, connection, Pi temp) | +| `StatBox` | Reusable metric display box | +| `DebugConsole` | Scrolling log overlay for diagnostics | + +## Notes + +- **Gravity compensation**: Accelerometer display subtracts 1g from Z-axis to show deviation from vertical +- **Navigator precaching**: All navigator images are loaded during splash screen to prevent frame drops +- **Theme switching**: Backend sends `theme_switch` via WebSocket status events (triggered by GPIO) + ## Theme System - `AppColors` — static color constants (dark/bright variants), auto-generated from JSON diff --git a/pi/ui/lib/widgets/accel_graph.dart b/pi/ui/lib/widgets/accel_graph.dart index a273614..7872974 100644 --- a/pi/ui/lib/widgets/accel_graph.dart +++ b/pi/ui/lib/widgets/accel_graph.dart @@ -151,7 +151,7 @@ class _AccelGraphState extends State { // Label Text( - 'ACCEL', + 'Acceleration', style: TextStyle( fontSize: fontSize * 0.8, fontWeight: FontWeight.w400, @@ -167,7 +167,9 @@ class _AccelGraphState extends State { String _formatAccel(double? force) { if (force == null) return '—°'; - return '${force.toStringAsFixed(1)}G'; + return '${ + force.toStringAsFixed(1) == '-0.0' ? '0.0' : force.toStringAsFixed(1) + }G'; } } diff --git a/pi/ui/lib/widgets/whiskey_mark.dart b/pi/ui/lib/widgets/whiskey_mark.dart index 5f92131..08593ff 100644 --- a/pi/ui/lib/widgets/whiskey_mark.dart +++ b/pi/ui/lib/widgets/whiskey_mark.dart @@ -85,7 +85,7 @@ class WhiskeyMark extends StatelessWidget { // Label Text( - 'ATTITUDE', + 'Attitude', style: TextStyle( fontSize: fontSize * 0.8, fontWeight: FontWeight.w400, diff --git a/scripts/README.md b/scripts/README.md index efac2fa..5f58e4b 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -46,6 +46,8 @@ Called automatically by `build.py`. Looks for theme matching `navigator` in `con | `pi_setup_backend.sh` | First-time Pi config for backend (uv, gpsd, systemd) | | `smartserow-ui.service.sample` | UI systemd unit template | | `smartserow-backend.service.sample` | Backend systemd unit template | +| `smartserow-ui.service` | Production UI systemd unit (gitignored, Pi-specific) | +| `smartserow-backend.service` | Production backend systemd unit (gitignored, Pi-specific) | ```bash # On the Pi - UI setup