connection settings cleanup and mock test added. removed bluetooth implementation
This commit is contained in:
@@ -1,110 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../transport/bluetooth/bluetooth_classic_transport.dart';
|
||||
import '../../transport/bluetooth/bluetooth_device_info.dart';
|
||||
import '../../transport/link_transport.dart';
|
||||
import 'database_provider.dart';
|
||||
|
||||
/// App-lebenslanger Bluetooth-Classic-Transport (Doku Kommunikationsschicht
|
||||
/// Abschnitt 3), verdrahtet gegen die gemerkte Geraete-MAC in den
|
||||
/// Einstellungen. Bewusst nicht autoDispose: die Verbindung soll bestehen
|
||||
/// bleiben, waehrend zwischen Fly- und Plan-Modus gewechselt wird, und erst
|
||||
/// beim Verlassen des Fly-Modus explizit getrennt werden (Doku 3,
|
||||
/// Robustheit: "Verbindung beim Verlassen des Fly-Modus sauber schliessen").
|
||||
final bluetoothTransportProvider = Provider<BluetoothClassicTransport>((ref) {
|
||||
final settingsRepo = ref.watch(appSettingsRepositoryProvider);
|
||||
final transport = BluetoothClassicTransport(
|
||||
getRememberedAddress: settingsRepo.loadConnectionDeviceAddress,
|
||||
rememberAddress: settingsRepo.setConnectionDeviceAddress,
|
||||
);
|
||||
ref.onDispose(transport.dispose);
|
||||
return transport;
|
||||
});
|
||||
|
||||
/// Reaktiver [LinkState] des Bluetooth-Transports fuer die Oberflaeche
|
||||
/// (Verbindungsindikator, Abnahmekriterium: "Zustand jederzeit sichtbar").
|
||||
final linkStateProvider = StreamProvider<LinkState>((ref) {
|
||||
final transport = ref.watch(bluetoothTransportProvider);
|
||||
return transport.state;
|
||||
});
|
||||
|
||||
/// Grund des zuletzt gemeldeten [LinkState.error] (Doku 3, Robustheit: "Grund
|
||||
/// mitfuehren und in der Oberflaeche anzeigen"). Wird bei jedem neuen
|
||||
/// LinkState neu ausgelesen, da der Transport ihn synchron mitfuehrt.
|
||||
final linkErrorReasonProvider = Provider<LinkErrorReason?>((ref) {
|
||||
ref.watch(linkStateProvider);
|
||||
return ref.watch(bluetoothTransportProvider).lastErrorReason;
|
||||
});
|
||||
|
||||
/// Gekoppelte Geraete fuer die manuelle Auswahlliste (Doku 3.2c). Wird bei
|
||||
/// jedem [LinkState]-Wechsel neu geladen, damit eine frisch angeschlossene
|
||||
/// Kopplung (ueber den "Geraet koppeln"-Knopf) ohne expliziten Reload
|
||||
/// auftaucht.
|
||||
final bondedDevicesProvider = FutureProvider<List<BluetoothDeviceInfo>>((ref) {
|
||||
ref.watch(linkStateProvider);
|
||||
return ref.watch(bluetoothTransportProvider).listBondedDevices();
|
||||
});
|
||||
|
||||
/// Ein Eintrag im Verbindungsprotokoll (Doku 7: "einfache Textansicht der
|
||||
/// letzten Ereignisse ... spart im Feld viel Ratearbeit").
|
||||
class ConnectionLogEntry {
|
||||
const ConnectionLogEntry(this.timestamp, this.message);
|
||||
|
||||
final DateTime timestamp;
|
||||
final String message;
|
||||
}
|
||||
|
||||
/// Verbindungsprotokoll + Paketzaehler (Doku 7). Haengt sich an den
|
||||
/// LinkState- und den Rohdaten-Stream des Transports, damit auch ohne
|
||||
/// MSP-Decoder schon sichtbar ist, dass ueberhaupt Bytes ankommen.
|
||||
class ConnectionLogNotifier extends Notifier<List<ConnectionLogEntry>> {
|
||||
static const _maxEntries = 50;
|
||||
|
||||
StreamSubscription<LinkState>? _stateSub;
|
||||
StreamSubscription<void>? _dataSub;
|
||||
int _packetCount = 0;
|
||||
|
||||
int get packetCount => _packetCount;
|
||||
|
||||
@override
|
||||
List<ConnectionLogEntry> build() {
|
||||
final transport = ref.watch(bluetoothTransportProvider);
|
||||
_stateSub?.cancel();
|
||||
_dataSub?.cancel();
|
||||
_packetCount = 0;
|
||||
_stateSub = transport.state.listen(_onStateChanged);
|
||||
_dataSub = transport.incoming.listen((_) => _packetCount++);
|
||||
ref.onDispose(() {
|
||||
_stateSub?.cancel();
|
||||
_dataSub?.cancel();
|
||||
});
|
||||
return const [];
|
||||
}
|
||||
|
||||
void _onStateChanged(LinkState linkState) {
|
||||
final transport = ref.read(bluetoothTransportProvider);
|
||||
final message = switch (linkState) {
|
||||
LinkState.disconnected => 'Disconnected',
|
||||
LinkState.connecting => 'Connecting...',
|
||||
LinkState.connected =>
|
||||
'Connected${transport.connectedDevice != null ? ' (${transport.connectedDevice!.displayName})' : ''}',
|
||||
LinkState.error =>
|
||||
'Error: ${transport.lastErrorMessage ?? transport.lastErrorReason?.name ?? 'unknown'}',
|
||||
};
|
||||
_append(message);
|
||||
}
|
||||
|
||||
void _append(String message) {
|
||||
final entry = ConnectionLogEntry(DateTime.now(), message);
|
||||
final next = [...state, entry];
|
||||
state = next.length > _maxEntries
|
||||
? next.sublist(next.length - _maxEntries)
|
||||
: next;
|
||||
}
|
||||
}
|
||||
|
||||
final connectionLogProvider =
|
||||
NotifierProvider<ConnectionLogNotifier, List<ConnectionLogEntry>>(
|
||||
ConnectionLogNotifier.new);
|
||||
@@ -11,11 +11,8 @@ import 'wifi_connection_provider.dart';
|
||||
|
||||
/// 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.
|
||||
/// sonst (ConnectionType.mock, oder solange die Einstellungen noch nicht
|
||||
/// geladen sind) der Mock fuer UI-Entwicklung/Testphase ohne Hardware.
|
||||
///
|
||||
/// connectionType wird reaktiv beobachtet (ref.watch), nicht nur einmalig
|
||||
/// gelesen - beim ersten App-Start ist connectionSettingsProvider oft noch
|
||||
|
||||
Reference in New Issue
Block a user