Add Flutter project skeleton (Android-only MVP)
Five-layer architecture per DMC_Architektur_und_Design.md: FlightControllerLink abstraction (Mock + MSP stub), protocol-neutral mission domain layer, App-Mode state machine with Ready-to-Fly gate, Drift persistence schema, and placeholder UI screens wired via go_router. App icon generated from design/Y2_pink_dark.svg. Verified with flutter analyze and flutter test. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
62d655fe8e
commit
346fcc2183
@@ -0,0 +1,71 @@
|
||||
import 'dart:async';
|
||||
|
||||
import '../../domain/waypoint/flat_waypoint_list.dart';
|
||||
import '../flight_controller_link.dart';
|
||||
|
||||
/// Synthetische Telemetrie fuer UI-Entwicklung/Tests ohne Hardware oder SITL
|
||||
/// (Architektur-Doku 3.1).
|
||||
class MockFlightControllerLink implements FlightControllerLink {
|
||||
bool _armed = false;
|
||||
int? _activeWaypointIndex;
|
||||
StreamController<TelemetryFrame>? _telemetryController;
|
||||
Timer? _ticker;
|
||||
|
||||
@override
|
||||
FcCapabilities get capabilities => const FcCapabilities(
|
||||
supportsMultiMission: true,
|
||||
supportsInFlightUpload: false,
|
||||
maxWaypoints: 60,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> connect() async {
|
||||
_telemetryController = StreamController<TelemetryFrame>.broadcast();
|
||||
_ticker = Timer.periodic(const Duration(seconds: 1), (_) {
|
||||
_telemetryController?.add(TelemetryFrame(
|
||||
lat: 52.5,
|
||||
lon: 13.4,
|
||||
altitudeM: 120,
|
||||
speedMs: 18,
|
||||
armed: _armed,
|
||||
activeWaypointIndex: _activeWaypointIndex,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect() async {
|
||||
_ticker?.cancel();
|
||||
await _telemetryController?.close();
|
||||
_telemetryController = null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> uploadMission(FlatWaypointList mission) async {
|
||||
// iNAV/MAVLink erlauben Mission-Upload nur im unarmed-Zustand (Doku 4.5).
|
||||
if (_armed) {
|
||||
throw StateError('Mission-Upload verweigert: Drohne ist armed.');
|
||||
}
|
||||
_activeWaypointIndex = mission.waypoints.isEmpty ? null : 0;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setFlightMode(FlightMode mode) async {}
|
||||
|
||||
@override
|
||||
Future<void> arm() async {
|
||||
_armed = true;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<TelemetryFrame> subscribeTelemetry() {
|
||||
final controller = _telemetryController;
|
||||
if (controller == null) {
|
||||
throw StateError('subscribeTelemetry() vor connect() aufgerufen.');
|
||||
}
|
||||
return controller.stream;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int?> readActiveWaypointIndex() async => _activeWaypointIndex;
|
||||
}
|
||||
Reference in New Issue
Block a user