A Flutter app that runs next to DJI Fly without the DJI SDK. It receives the aircraft's Remote ID (Bluetooth, BT5, Wi-Fi NaN and Beacon) in a foreground service, streams the paired aircraft to the hub over /ws/device, and turns take-off to landing into a logbook entry filed through /api/flights, queued when offline. Covers phases A0-A3 of the Fly Agent plan; needs no server change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
1.6 KiB
Dart
54 lines
1.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'api/api.dart';
|
|
import 'pilot_location.dart';
|
|
import 'rid/rid_service.dart';
|
|
import 'services.dart';
|
|
import 'session/session_controller.dart';
|
|
import 'theme.dart';
|
|
import 'ui/login_page.dart';
|
|
import 'ui/shell.dart';
|
|
import 'uplink/uplink.dart';
|
|
|
|
/// PilotVault Fly Agent: runs next to DJI Fly and never controls the aircraft.
|
|
/// It listens to the aircraft's Remote ID broadcast, streams the paired
|
|
/// aircraft's position to PilotVault, and files the flight in the logbook.
|
|
/// See REA/DJI Fly/PilotVault_FlyAgentApp_Plan.md for the phase plan.
|
|
Future<void> main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
final Api api = Api();
|
|
final RidService rid = RidService();
|
|
final PilotLocation pilot = PilotLocation();
|
|
final Uplink uplink = Uplink(rid: rid, pilot: pilot);
|
|
final SessionController sessions = SessionController(api: api, rid: rid);
|
|
await api.init();
|
|
await rid.init();
|
|
await sessions.init();
|
|
runApp(Services(
|
|
api: api,
|
|
rid: rid,
|
|
pilot: pilot,
|
|
uplink: uplink,
|
|
sessions: sessions,
|
|
child: const AgentApp(),
|
|
));
|
|
}
|
|
|
|
class AgentApp extends StatelessWidget {
|
|
const AgentApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final Api api = Services.of(context).api;
|
|
return MaterialApp(
|
|
title: 'PV Fly Agent',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: PV.theme(),
|
|
home: ListenableBuilder(
|
|
listenable: api,
|
|
builder: (BuildContext context, _) => api.isAuthed ? const AgentShell() : const LoginPage(),
|
|
),
|
|
);
|
|
}
|
|
}
|