Preserve Flutter mirror-os codebase
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# Mirror OS
|
||||
|
||||
Smart mirror app platform built with Flutter for a hacked Lululemon Mirror (BOE panel + Vizio driver board + Raspberry Pi 4).
|
||||
|
||||
## Architecture
|
||||
|
||||
Melos mono-repo with two apps sharing packages:
|
||||
|
||||
- `apps/display` — Flutter Linux desktop app, runs fullscreen on Pi 4 (1080x1920 portrait)
|
||||
- `apps/remote` — Flutter mobile app (iOS/Android), phone remote control
|
||||
- `packages/mirror_protocol` — WebSocket message types and serialization
|
||||
- `packages/mirror_core` — Shared business logic, API clients (workout-player, YouTube)
|
||||
- `packages/mirror_ui` — Dark theme, shared widgets, animations
|
||||
- `services/` — Python sidecars for voice (OpenWakeWord + Whisper) and motion (PIR/GPIO)
|
||||
- `deploy/` — Pi setup scripts, systemd units, labwc compositor config
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Flutter SDK 3.24+ (stable channel)
|
||||
- Dart SDK 3.5+
|
||||
- Melos: `dart pub global activate melos`
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
melos bootstrap
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Run display app (macOS/Linux desktop for development)
|
||||
cd apps/display && flutter run -d macos
|
||||
|
||||
# Run remote app on iOS simulator
|
||||
cd apps/remote && flutter run
|
||||
|
||||
# Run both and test WebSocket communication:
|
||||
# 1. Start display app (starts WS server on :9090)
|
||||
# 2. Start remote app, connect to localhost:9090
|
||||
|
||||
# Analyze all packages
|
||||
melos run analyze
|
||||
|
||||
# Format all packages
|
||||
melos run format
|
||||
```
|
||||
|
||||
## Hardware
|
||||
|
||||
- **Panel**: BOE DV430FHM-NN5, 43" 1080p IPS, portrait orientation (1080x1920)
|
||||
- **Driver board**: Vizio mainboard (HDMI passthrough → LVDS → panel)
|
||||
- **Compute**: Raspberry Pi 4 (4GB)
|
||||
- **Control**: Phone over same WiFi network
|
||||
- **Rotation**: Pi handles via `wlr-randr --output HDMI-A-1 --transform 90`
|
||||
|
||||
## Communication
|
||||
|
||||
Display app runs a WebSocket server on port 9090. Phone remote connects as a client.
|
||||
|
||||
Protocol: JSON messages, typed via sealed Dart classes in `mirror_protocol` package.
|
||||
- Server → Client: `StateSync` (full state on connect), `StatePatch` (deltas)
|
||||
- Client → Server: `NavigateCommand`, `PlaybackCommand`, `WorkoutCommand`
|
||||
|
||||
## External Services
|
||||
|
||||
- **Workout Player**: http://192.168.86.172:8091 — REST API for video library, streaming, progress
|
||||
- **OpenWeather**: API key needed for dashboard weather widget
|
||||
- **Google Calendar**: OAuth for dashboard calendar widget
|
||||
- **Plex**: Local server on same LAN
|
||||
|
||||
## Build for Pi 4
|
||||
|
||||
```bash
|
||||
# On the Pi (with Flutter installed):
|
||||
cd apps/display
|
||||
flutter build linux --release
|
||||
|
||||
# Output: build/linux/arm64/release/bundle/
|
||||
# Deploy: rsync bundle to /opt/mirror-os/display/ on the Pi
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Unit tests
|
||||
melos exec -- dart test
|
||||
|
||||
# Integration: start display app, connect remote, verify state sync
|
||||
```
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
- Riverpod for state management (no code generation needed for basic use)
|
||||
- Single `DisplayState` as source of truth on the Pi, broadcast to all remotes
|
||||
- media_kit (mpv) for media playback with V4L2 hardware decoding
|
||||
- Python sidecars for voice/motion (communicate via Unix domain sockets)
|
||||
- No touch input on mirror — all interaction via phone remote
|
||||
Reference in New Issue
Block a user