Files
dmc/app/lib/transport/link_transport.dart
T

80 lines
3.1 KiB
Dart

import 'dart:typed_data';
/// Transportzustand, protokollneutral (Doku Kommunikationsschicht Abschnitt 2).
enum LinkState { disconnected, connecting, connected, error }
/// Grund eines [LinkState.error] (Doku Abschnitt 3, Robustheit/Abnahme):
/// Bluetooth aus und Berechtigung abgelehnt brauchen jeweils einen eigenen,
/// erklaerenden Hinweis in der Oberflaeche statt eines generischen
/// "Verbindung fehlgeschlagen".
enum LinkErrorReason {
/// Bluetooth-Adapter ist aus. Kann ab Android 12 nicht mehr programmatisch
/// eingeschaltet werden - die Oberflaeche muss zu den Systemeinstellungen
/// verlinken.
bluetoothOff,
/// Berechtigung wurde abgelehnt, darf aber erneut angefragt werden.
permissionDenied,
/// Berechtigung wurde dauerhaft abgelehnt ("nicht mehr fragen"). Android
/// zeigt den Dialog kein zweites Mal - die Oberflaeche muss zu den
/// App-Einstellungen verlinken.
permissionDeniedPermanently,
/// Kein gekoppeltes Zielgeraet konnte automatisch bestimmt werden (weder
/// gemerkte MAC-Adresse noch ein Geraet mit "mLRS"-Praefix). Die
/// Oberflaeche muss eine Auswahlliste der gekoppelten Geraete anbieten.
deviceSelectionRequired,
/// Verbindungsaufbau zum bestimmten Geraet ist fehlgeschlagen oder wurde
/// getrennt.
connectionFailed,
/// Sonstiger, nicht naeher klassifizierter Fehler.
unknown,
}
/// Protokollneutrale Transportschnittstelle (Doku Kommunikationsschicht
/// Abschnitt 2). Alles oberhalb (MSP-Encoder/-Decoder) programmiert
/// ausschliesslich gegen diese Schnittstelle - kein Import von Bluetooth-
/// oder Netzwerkpaketen ausserhalb von transport/.
///
/// Implementierungen: BluetoothClassicTransport (MVP), UdpTransport
/// (spaeter, Doku Abschnitt 6), LoopbackTransport (Tests/Entwicklung ohne
/// Hardware).
abstract class LinkTransport {
Stream<Uint8List> get incoming;
Stream<LinkState> get state;
/// Grund des zuletzt gemeldeten [LinkState.error], oder null solange kein
/// Fehler aufgetreten ist bzw. nach erfolgreicher Verbindung.
LinkErrorReason? get lastErrorReason;
/// Freitext zum zuletzt gemeldeten Fehler, fuer Diagnose/Verbindungsprotokoll
/// (Doku Abschnitt 7). Nicht fuer die direkte Nutzeranzeige gedacht - dafuer
/// dient [lastErrorReason].
String? get lastErrorMessage;
Future<void> send(Uint8List data);
Future<void> connect();
Future<void> disconnect();
void dispose();
}
/// Wird von [LinkTransport.connect] geworfen, wenn der Verbindungsaufbau
/// vorab (also bevor ueberhaupt eine Socket-Verbindung versucht wird)
/// erkennbar scheitert - z.B. Bluetooth aus, Berechtigung fehlt, oder kein
/// Geraet automatisch bestimmbar. Der gleiche [reason] wird zeitgleich ueber
/// [LinkTransport.state]/[LinkTransport.lastErrorReason] gemeldet, damit
/// sowohl der aufrufende Code (durch Warten auf [LinkTransport.connect])
/// als auch reine Beobachter der Zustands-Streams reagieren koennen.
class LinkConnectException implements Exception {
const LinkConnectException(this.reason, this.message);
final LinkErrorReason reason;
final String message;
@override
String toString() => 'LinkConnectException($reason): $message';
}