camview: tell the client when the camera is unavailable
CI / Analyze & Test (push) Successful in 9s
CI / Debug APK (push) Successful in 25s

The server sends "camera unavailable" after 3 s without a frame and
"camera ok" when frames come; the app shows the notice instead of a
stale frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
This commit is contained in:
2026-10-12 16:11:03 +09:00
parent 85837363ee
commit 00d161e068
2 changed files with 42 additions and 11 deletions
+19 -2
View File
@@ -28,6 +28,9 @@ class CamView extends ChangeNotifier {
final _delays = <double>[];
String lastReply = '';
/// Whether the Orin has the camera: null until it says, then its last notice.
bool? available;
final _window = <(int, int)>[]; // (arrival µs, bytes) over the last second
final _clock = Stopwatch()..start();
@@ -55,6 +58,7 @@ class CamView extends ChangeNotifier {
timeout: const Duration(seconds: 3),
);
_s = s;
available = null;
status = 'connected';
notifyListeners();
await _read(s);
@@ -63,6 +67,7 @@ class CamView extends ChangeNotifier {
status = '$e'.split('\n').first;
}
_s = null;
frame = null; // a frame from a closed connection is not live
notifyListeners();
if (_running) await Future<void>.delayed(const Duration(seconds: 1));
}
@@ -92,7 +97,7 @@ class CamView extends ChangeNotifier {
final bytes = Uint8List.sublistView(data, off + 16, off + 16 + body);
off += 16 + body;
if (len == 0) {
lastReply = utf8.decode(bytes);
_onText(utf8.decode(bytes));
} else {
_onFrame(Uint8List.fromList(bytes), sentAt);
}
@@ -101,6 +106,16 @@ class CamView extends ChangeNotifier {
}
}
void _onText(String text) {
if (text == 'camera unavailable' || text == 'camera ok') {
available = text == 'camera ok';
if (available == false) frame = null; // never show a stale frame as live
} else {
lastReply = text;
}
notifyListeners();
}
void _onFrame(Uint8List jpeg, double sentAt) {
final now = _clock.elapsedMicroseconds;
_window.add((now, jpeg.length));
@@ -163,7 +178,9 @@ class _CamViewPageState extends State<CamViewPage> {
child: f == null
? Center(
child: Text(
cam.status,
cam.available == false
? 'Camera unavailable on the Orin'
: cam.status,
style: const TextStyle(color: Colors.white70),
),
)