96 lines
4.5 KiB
Dart
96 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../../services/telemetry_service.dart';
|
|
|
|
class DiagnosticsScreen extends ConsumerWidget {
|
|
const DiagnosticsScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final telemetryAsync = ref.watch(telemetryStreamProvider);
|
|
final t = telemetryAsync.value;
|
|
|
|
final gpsAccuracy = t?.gpsAccuracy;
|
|
String gpsHealthText = 'No Fix (Unavailable)';
|
|
Color gpsHealthColor = Colors.redAccent;
|
|
if (gpsAccuracy != null) {
|
|
if (gpsAccuracy <= 15.0) {
|
|
gpsHealthText = 'Healthy (${gpsAccuracy.toStringAsFixed(1)}m)';
|
|
gpsHealthColor = Colors.greenAccent;
|
|
} else if (gpsAccuracy <= 35.0) {
|
|
gpsHealthText = 'Degraded (${gpsAccuracy.toStringAsFixed(1)}m)';
|
|
gpsHealthColor = Colors.amberAccent;
|
|
} else {
|
|
gpsHealthText = 'Poor (${gpsAccuracy.toStringAsFixed(1)}m)';
|
|
gpsHealthColor = Colors.redAccent;
|
|
}
|
|
}
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('Sensor Diagnostics')),
|
|
body: t == null
|
|
? const Center(child: CircularProgressIndicator())
|
|
: ListView(
|
|
padding: const EdgeInsets.all(16.0),
|
|
children: [
|
|
_buildMetric('Timestamp', t.timestamp.toIso8601String()),
|
|
const Divider(),
|
|
const Text('Sensor Health & Signal', style: TextStyle(color: Colors.cyanAccent, fontWeight: FontWeight.bold)),
|
|
_buildHealthMetric('GPS Signal', gpsHealthText, gpsHealthColor),
|
|
_buildHealthMetric('IMU / Accelerometer', t.accelX != null ? 'Active' : 'No Data', t.accelX != null ? Colors.greenAccent : Colors.redAccent),
|
|
_buildHealthMetric('Compass / Gyro', t.heading != null ? 'Active' : 'No Data', t.heading != null ? Colors.greenAccent : Colors.redAccent),
|
|
const Divider(),
|
|
const Text('GPS Data', style: TextStyle(color: Colors.cyanAccent, fontWeight: FontWeight.bold)),
|
|
_buildMetric('GPS Accuracy', gpsAccuracy != null ? '±${gpsAccuracy.toStringAsFixed(1)} m' : 'N/A'),
|
|
_buildMetric('Latitude', t.latitude?.toStringAsFixed(6) ?? 'N/A'),
|
|
_buildMetric('Longitude', t.longitude?.toStringAsFixed(6) ?? 'N/A'),
|
|
_buildMetric('Altitude', t.altitude != null ? '${t.altitude!.toStringAsFixed(1)} m' : 'N/A'),
|
|
_buildMetric('Speed', t.speed != null ? '${t.speed!.toStringAsFixed(1)} MPH' : 'N/A'),
|
|
_buildMetric('Heading', t.heading != null ? '${t.heading!.toStringAsFixed(1)}°' : 'N/A'),
|
|
const Divider(),
|
|
const Text('IMU & G-Force Data', style: TextStyle(color: Colors.cyanAccent, fontWeight: FontWeight.bold)),
|
|
_buildMetric('Accel X (m/s²)', t.accelX?.toStringAsFixed(3) ?? 'N/A'),
|
|
_buildMetric('Accel Y (m/s²)', t.accelY?.toStringAsFixed(3) ?? 'N/A'),
|
|
_buildMetric('Accel Z (m/s²)', t.accelZ?.toStringAsFixed(3) ?? 'N/A'),
|
|
_buildMetric('Longitudinal G', t.longitudinalG != null ? '${t.longitudinalG!.toStringAsFixed(3)} G' : 'N/A'),
|
|
_buildMetric('Lateral G', t.lateralG != null ? '${t.lateralG!.toStringAsFixed(3)} G' : 'N/A'),
|
|
_buildMetric('Lean Angle', t.leanAngle != null ? '${t.leanAngle!.toStringAsFixed(2)}°' : 'N/A'),
|
|
_buildMetric('Pitch Angle', t.pitchAngle != null ? '${t.pitchAngle!.toStringAsFixed(2)}°' : 'N/A'),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildHealthMetric(String label, String status, Color statusColor) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(label, style: const TextStyle(color: Colors.white70)),
|
|
Row(
|
|
children: [
|
|
Icon(Icons.circle, color: statusColor, size: 10),
|
|
const SizedBox(width: 6),
|
|
Text(status, style: TextStyle(fontWeight: FontWeight.bold, color: statusColor)),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildMetric(String label, String value) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(label, style: const TextStyle(color: Colors.white70)),
|
|
Text(value, style: const TextStyle(fontWeight: FontWeight.bold, fontFamily: 'monospace')),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|