abe9b764c7
- Add flutter_libserialport dependency (pubspec.yaml) - New ParpCodec: XOR-checksum NMEA parser + command builders for all PARP sentences - New ConcentradorService: manages two independent COM ports (RX-OUT broadcast, TX-IN commands) at 115200/8N1; auto-fires onConnectionChanged on link drop - AutopilotState: dual-mode operation (demo timer OR live serial); connectToSerial / disconnectSerial; command methods (engage/disengage/adjustSetpoint) forward to ConcentradorService when connected; falls back to demo on disconnect - New PortSettingsScreen (/settings/ports): RX+TX dropdowns populated from SerialPort.availablePorts, persisted in SharedPreferences; Connect/Disconnect buttons with error display and snackbar feedback - main.dart: auto-connect to saved ports on startup (silent fail → demo mode); registers /settings/ports route - CockpitScreen: gear icon replaced with PopupMenuButton (Puertos COM / Apariencia) AR_electronics — AR-Autopilot Project
71 lines
2.2 KiB
Dart
71 lines
2.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import 'data/autopilot_state.dart';
|
|
import 'theme/theme_provider.dart';
|
|
import 'screens/cockpit/cockpit_screen.dart';
|
|
import 'screens/settings/appearance_settings.dart';
|
|
import 'screens/settings/port_settings_screen.dart';
|
|
|
|
// SharedPreferences keys — must match port_settings_screen.dart
|
|
const _kRxKey = 'port.rx';
|
|
const _kTxKey = 'port.tx';
|
|
|
|
Future<void> main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// Load persisted theme before first frame.
|
|
final themeProvider = await AutopilotThemeProvider.load();
|
|
|
|
// Create state object early so we can attempt auto-connect.
|
|
final autopilotState = AutopilotState();
|
|
|
|
// Attempt to reconnect to the last-used COM ports silently.
|
|
// If the ports are not available (hardware unplugged, different PC, etc.)
|
|
// the exception is swallowed and the UI stays in demo mode.
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final rxPort = prefs.getString(_kRxKey);
|
|
final txPort = prefs.getString(_kTxKey);
|
|
if (rxPort != null && txPort != null) {
|
|
await autopilotState.connectToSerial(rxPort: rxPort, txPort: txPort);
|
|
}
|
|
} catch (_) {
|
|
// Hardware not available — stay in demo mode.
|
|
}
|
|
|
|
runApp(
|
|
MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider<AutopilotThemeProvider>.value(
|
|
value: themeProvider,
|
|
),
|
|
ChangeNotifierProvider<AutopilotState>.value(
|
|
value: autopilotState,
|
|
),
|
|
],
|
|
child: const ArAutopilotApp(),
|
|
),
|
|
);
|
|
}
|
|
|
|
class ArAutopilotApp extends StatelessWidget {
|
|
const ArAutopilotApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
title: 'AR-Autopilot',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: ThemeData(useMaterial3: true),
|
|
initialRoute: CockpitScreen.routeName,
|
|
routes: {
|
|
CockpitScreen.routeName: (_) => const CockpitScreen(),
|
|
AppearanceSettingsScreen.routeName: (_) => const AppearanceSettingsScreen(),
|
|
PortSettingsScreen.routeName: (_) => const PortSettingsScreen(),
|
|
},
|
|
);
|
|
}
|
|
}
|