# 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