MotorSignal-App/lib/features/settings/diagnostics_screen.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')),
],
),
);
}
}