90 lines
2.7 KiB
Dart
90 lines
2.7 KiB
Dart
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;
|
|
double _heading = 0;
|
|
double _batteryPercent = 100;
|
|
|
|
@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), (_) {
|
|
// Kurs dreht sich langsam weiter statt fest zu stehen, damit die
|
|
// Rotation des Drohnen-Markers (DroneMarkerIcon) auch ohne Hardware
|
|
// sichtbar ueberprueft werden kann (Doku 9: UI-Entwicklung ohne
|
|
// Hardware).
|
|
_heading = (_heading + 5) % 360;
|
|
// Langsam sinkender Akkustand, damit die Anzeige auch ohne Hardware
|
|
// sichtbar auf Werteaenderungen reagiert (Doku 9).
|
|
_batteryPercent = (_batteryPercent - 0.1).clamp(0, 100);
|
|
_telemetryController?.add(TelemetryFrame(
|
|
lat: 52.5,
|
|
lon: 13.4,
|
|
hasFix: true,
|
|
numSat: 12,
|
|
altitudeM: 120,
|
|
speedMs: 18,
|
|
headingDeg: _heading,
|
|
armed: _armed,
|
|
batteryPercent: _batteryPercent.round(),
|
|
linkQuality: 95,
|
|
flightMode: _activeWaypointIndex != null
|
|
? 'Waypoint mission (en route)'
|
|
: 'Idle',
|
|
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;
|
|
}
|