msp over wifi implemented
This commit is contained in:
@@ -1,16 +1,37 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../transport/connection_type.dart';
|
||||
import '../../transport/flight_controller_link.dart';
|
||||
import '../../transport/mock/mock_flight_controller_link.dart';
|
||||
import '../../transport/msp/msp_flight_controller_link.dart';
|
||||
import 'connection_settings_provider.dart';
|
||||
import 'wifi_connection_provider.dart';
|
||||
|
||||
/// FlightControllerLink fuer den Fly-Modus (Doku 3.1) - aktuell fest auf den
|
||||
/// Mock verdrahtet, bis ein echter Transport (MSP, Doku 4.19) existiert.
|
||||
/// FlightControllerLink fuer den Fly-Modus (Doku 3.1): bei WLAN als
|
||||
/// gewaehlter Verbindungsart ein echter MSP-Link ueber den UDP-Transport,
|
||||
/// sonst (Bluetooth/5G/USB, oder solange die Einstellungen noch nicht
|
||||
/// geladen sind) weiterhin der Mock fuer UI-Entwicklung ohne Hardware -
|
||||
/// Bluetooth ist auf der eingesetzten mLRS-Bruecke ohnehin nicht moeglich
|
||||
/// (Doku Kommunikationsschicht v2, Abschnitt 1), 5G/USB sind noch nicht
|
||||
/// umgesetzt.
|
||||
///
|
||||
/// connectionType wird bewusst per ref.read() einmalig beim Eintritt in den
|
||||
/// Fly-Modus gelesen, nicht reaktiv beobachtet - sonst wuerde jede
|
||||
/// Einstellungsaenderung waehrend des Flugs (z.B. Tippen im
|
||||
/// SSID-Praefix-Feld, das ueberall im Settings-Screen ein
|
||||
/// `ref.invalidate(connectionSettingsProvider)` ausloest) einen Neuaufbau
|
||||
/// dieses Providers samt Trennen/Neuverbinden des Transports ausloesen.
|
||||
///
|
||||
/// autoDispose: verbindet erst, wenn der Fly-Screen tatsaechlich beobachtet
|
||||
/// wird, und trennt/stoppt den Mock-Ticker wieder, sobald niemand mehr
|
||||
/// zuhoert (z.B. Rueckkehr in den Plan-Modus) statt endlos im Hintergrund
|
||||
/// wird, und trennt sich wieder (Doku Abschnitt 8: "Verlassen des
|
||||
/// Fly-Modus gibt den Netz-Request frei"), sobald niemand mehr zuhoert
|
||||
/// (z.B. Rueckkehr in den Plan-Modus) statt endlos im Hintergrund
|
||||
/// weiterzulaufen.
|
||||
final flightControllerLinkProvider = Provider.autoDispose<FlightControllerLink>((ref) {
|
||||
final link = MockFlightControllerLink();
|
||||
final connectionType = ref.read(connectionSettingsProvider).value?.connectionType;
|
||||
final FlightControllerLink link = connectionType == ConnectionType.wifi
|
||||
? MspFlightControllerLink(transport: ref.watch(wifiTransportProvider))
|
||||
: MockFlightControllerLink();
|
||||
ref.onDispose(link.disconnect);
|
||||
return link;
|
||||
});
|
||||
|
||||
@@ -149,7 +149,7 @@ class FlyScreen extends ConsumerWidget {
|
||||
width: 28,
|
||||
height: 28,
|
||||
alignment: Alignment.center,
|
||||
child: const DroneMarkerIcon(),
|
||||
child: DroneMarkerIcon(headingDeg: telemetry.headingDeg),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
|
||||
@@ -1,15 +1,84 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Live-Positionsmarker der Drohne im Fly-Modus (Doku 3.10) - noch ohne
|
||||
/// Peilungsanzeige, da TelemetryFrame aktuell keinen Kurs (heading)
|
||||
/// mitliefert (nur MockFlightControllerLink, siehe Doku 4.19).
|
||||
/// Live-Positionsmarker der Drohne im Fly-Modus (Doku 3.10), Papierflieger-
|
||||
/// Form aus design/B_paperplane.svg - nativ als [CustomPainter] statt als
|
||||
/// SVG-Asset nachgebaut (Format bewusst geaendert: die drei Pfade sind
|
||||
/// einfache Dreiecke, eine zusaetzliche SVG-Renderer-Abhaengigkeit lohnt sich
|
||||
/// dafuer nicht, siehe auch mountain_peak_icon.dart/wind_arrow_icon.dart fuer
|
||||
/// dasselbe Muster). Zeigt unrotiert (Spitze nach oben) bei fehlendem
|
||||
/// [headingDeg], sonst im Uhrzeigersinn um den Kurs ueber Grund gedreht.
|
||||
class DroneMarkerIcon extends StatelessWidget {
|
||||
const DroneMarkerIcon({super.key, this.size = 22});
|
||||
const DroneMarkerIcon({super.key, this.size = 28, this.headingDeg});
|
||||
|
||||
final double size;
|
||||
|
||||
/// Kurs ueber Grund in Grad (0 = Norden, im Uhrzeigersinn) aus
|
||||
/// TelemetryFrame.headingDeg.
|
||||
final double? headingDeg;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Icon(Icons.airplanemode_active, color: const Color(0xFF4D9DFF), size: size);
|
||||
return Transform.rotate(
|
||||
angle: (headingDeg ?? 0) * math.pi / 180,
|
||||
child: CustomPaint(
|
||||
size: Size.square(size),
|
||||
painter: const _PaperPlanePainter(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PaperPlanePainter extends CustomPainter {
|
||||
const _PaperPlanePainter();
|
||||
|
||||
// 1:1 aus design/B_paperplane.svg uebernommene Koordinaten (viewBox
|
||||
// 0 0 200 200): Spitze oben, zwei Fluegel unten, Heckkerbe dazwischen.
|
||||
static const _viewBoxSize = 200.0;
|
||||
static const _nose = Offset(100, 22);
|
||||
static const _rightWing = Offset(164, 172);
|
||||
static const _tailNotch = Offset(100, 138);
|
||||
static const _leftWing = Offset(36, 172);
|
||||
static const _rightFill = Color(0xFFFF2E93);
|
||||
static const _leftFill = Color(0xFFB01464);
|
||||
static const _strokeWidth = 7.0;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final scale = size.width / _viewBoxSize;
|
||||
Offset s(Offset p) => p * scale;
|
||||
|
||||
final rightHalf = Path()
|
||||
..moveTo(s(_nose).dx, s(_nose).dy)
|
||||
..lineTo(s(_rightWing).dx, s(_rightWing).dy)
|
||||
..lineTo(s(_tailNotch).dx, s(_tailNotch).dy)
|
||||
..close();
|
||||
final leftHalf = Path()
|
||||
..moveTo(s(_nose).dx, s(_nose).dy)
|
||||
..lineTo(s(_leftWing).dx, s(_leftWing).dy)
|
||||
..lineTo(s(_tailNotch).dx, s(_tailNotch).dy)
|
||||
..close();
|
||||
|
||||
canvas.drawPath(rightHalf, Paint()..color = _rightFill);
|
||||
canvas.drawPath(leftHalf, Paint()..color = _leftFill);
|
||||
|
||||
final outline = Path()
|
||||
..moveTo(s(_nose).dx, s(_nose).dy)
|
||||
..lineTo(s(_rightWing).dx, s(_rightWing).dy)
|
||||
..lineTo(s(_tailNotch).dx, s(_tailNotch).dy)
|
||||
..lineTo(s(_leftWing).dx, s(_leftWing).dy)
|
||||
..close();
|
||||
canvas.drawPath(
|
||||
outline,
|
||||
Paint()
|
||||
..color = Colors.white
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = _strokeWidth * scale
|
||||
..strokeJoin = StrokeJoin.round,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant _PaperPlanePainter oldDelegate) => false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user