Checklist to run AFTER the deploy, with a physical iPad connected to the same network as the server. Estimated time: 20 minutes.
Prerequisites
- [ ] Server deployed and working (see Pre-deploy)
- [ ] iPad connected to the same LAN as the server (192.168.1.0/24)
- [ ] Flutter app built and installed on the iPad (→ see Build Flutter App if not done yet)
- [ ] Working Flussonic stream URL for testing
1. Verify backend (2 min)
Open a browser on your Mac:
bash
# Device list — must return [] (requires the API key)
curl -H "X-API-Key: <API_KEY>" http://192.168.1.127/api/devices
# Link list — must return []
curl -H "X-API-Key: <API_KEY>" http://192.168.1.127/api/links
# License status (public endpoint, no key needed)
curl http://192.168.1.127/api/license
# Expected output: { "valid": true, "client": "Stadio Olimpico", ... }
# Swagger UI
open http://192.168.1.127/docs| Test | Expected result | ✅ |
|---|---|---|
| Backend responds on port 80 | HTTP 200 | ☐ |
| Valid license | valid: true | ☐ |
| Swagger UI accessible | Docs page | ☐ |
2. Verify Control Room UI (3 min)
Open the Control Room in the browser:
bash
open http://192.168.1.127/| Test | Expected result | ✅ |
|---|---|---|
| Basic Auth works | Login window appears | ☐ |
Login with regia / 1234 | Access granted | ☐ |
| Dashboard loads | Summary view without errors | ☐ |
| Sidebar shows all pages | Streams, Links, Devices, Events, License | ☐ |
| WS status is green | WebSocket connection established | ☐ |
| License page shows details | Client, expiry, days remaining | ☐ |
3. Verify iPad app (5 min)
| Test | How | Expected result | ✅ |
|---|---|---|---|
| App starts | Tap the iPad icon | Empty 3-slot screen (no errors) | ☐ |
| WS connection established | After startup | Connection status OK | ☐ |
| Device appears in Control Room | Go to Control Room → Devices | iPad appears in the list with heartbeat | ☐ |
4. Live stream test (5 min)
From the Control Room:
| Test | How | Expected result | ✅ |
|---|---|---|---|
| Create a link | Links → Add link: name, m3u8 URL | Link created with "inactive" status | ☐ |
| Test URL with Ping | Click 📡 on the created link | Shows time in ms (e.g. 342ms) or ERR | ☐ |
| Activate MAIN slot | Click "Activate on MAIN" | Link becomes active, MAIN slot occupied | ☐ |
| Video on iPad (MAIN) | Watch iPad | HLS stream starts in the MAIN slot | ☐ |
| Change MAIN link | Activate another link on MAIN | iPad switches to the new stream | ☐ |
| Free MAIN slot | Streams → Free MAIN | Video stops, slot free | ☐ |
| FEED and ALT | Repeat for FEED and ALT slots | All 3 slots work | ☐ |
5. DVR test (3 min)
| Test | How | Expected result | ✅ |
|---|---|---|---|
| DVR seek | Tap the DVR timeline | Video seeks to the selected position | ☐ |
| Go Live | Tap "Go Live" | Video returns to live instantly | ☐ |
| LIVE/DVR badge | Watch the badge at the top | LIVE (red) or DVR (blue) correct | ☐ |
6. Remote control test (3 min)
From the Control Room, Devices page:
| Test | How | Expected result | ✅ |
|---|---|---|---|
| Restart all | Expand device → click "Restart all" | iPad stops and restarts all 3 streams | ☐ |
| Stop MAIN | Expand device → ⏹ MAIN | The MAIN stream stops on the iPad | ☐ |
| Play MAIN | ▶ MAIN | The MAIN stream resumes | ☐ |
| Restart MAIN | 🔄 MAIN | The MAIN stream restarts | ☐ |
| Stop/Restart FEED/ALT | Repeat for FEED and ALT | They work like MAIN | ☐ |
7. Headphone audio test (2 min)
| Test | How | Expected result | ✅ |
|---|---|---|---|
| Default volume | Start a stream | Volume at 0 (silent) | ☐ |
| Connect Bluetooth headphones | Connect headphones to the iPad | Volume activates automatically | ☐ |
| Volume slider | Adjust with the volume control | Volume follows the slider | ☐ |
| Disconnect headphones | Disconnect headphones | Volume returns to 0 | ☐ |
8. Resilience test (3 min)
| Test | How | Expected result | ✅ |
|---|---|---|---|
| Server restart | pm2 restart zerolatency-live-player-api | iPad reconnects on its own | ☐ |
| iPad restart | Physically restart the iPad | App restarts, reconnects to the server | ☐ |
| Network disconnection | Turn off WiFi 10s, turn back on | iPad reconnects with exponential backoff | ☐ |
| Unreachable link | Activate a fake URL | iPad shows an error but does not crash | ☐ |
9. Multi-iPad test (if available)
| Test | How | Expected result | ✅ |
|---|---|---|---|
| 2 simultaneous iPads | Start the app on 2 iPads | Both appear in Control Room → Devices | ☐ |
| Stream switch on both | Activate MAIN link | Both iPads receive the new stream | ☐ |
| Ping on both | Watch status | Both synchronized | ☐ |
10. Final verification
bash
# All tests passed? Sign below.| Area | Status | Notes |
|---|---|---|
| Backend API | ☐ ✅ / ❌ | |
| Control Room UI | ☐ ✅ / ❌ | |
| iPad App | ☐ ✅ / ❌ | |
| Video streaming | ☐ ✅ / ❌ | |
| DVR | ☐ ✅ / ❌ | |
| Remote control | ☐ ✅ / ❌ | |
| Headphone audio | ☐ ✅ / ❌ | |
| Resilience | ☐ ✅ / ❌ | |
| Multi-iPad | ☐ ✅ / ❌ | |
| READY FOR LIVE | ☐ YES / ❌ |
Notes for the operator
- If a stream does not start, use Ping 📡 from the Control Room to verify the URL is reachable
- If an iPad disconnects, the Control Room shows
lastSeen— if it exceeds 60s, the device is offline - The Restart all button is an emergency crutch — use it only if a stream gets stuck
- Free a slot before assigning a new link to avoid conflicts
- The default Basic Auth password is
regia/1234(injectable at deploy time viaREGIA_HTPASSWD) — change it after the first test; withREGIA_PRESERVE=1the deploy does not overwrite it - The license expires on the indicated date — renew it BEFORE expiry or the server stops