UI improvements for telemetry debugging

This commit is contained in:
Constantin Leue
2026-08-02 20:21:21 +02:00
parent 6cfb82bd77
commit f42d997d4c
7 changed files with 272 additions and 190 deletions
@@ -35,6 +35,16 @@ final wifiLinkErrorReasonProvider = Provider<LinkErrorReason?>((ref) {
return ref.watch(wifiTransportProvider).lastErrorReason;
});
/// Reaktive tatsaechliche SSID des verbundenen Netzes (Doku: "connected
/// pille soll den WiFi-Namen anzeigen") - eigener Stream statt Ableitung aus
/// [wifiLinkStateProvider], weil Android die SSID fuer WifiNetworkSpecifier-
/// Netze oft erst nachtraeglich liefert (siehe UdpTransport.connectedSsidChanges/
/// MlrsNetworkPlugin.kt), also ohne begleitenden LinkState-Wechsel.
final wifiConnectedSsidProvider = StreamProvider<String?>((ref) {
final transport = ref.watch(wifiTransportProvider);
return transport.connectedSsidChanges;
});
/// Zeigt an, ob gerade UDP-Pakete ankommen ("receiving"/"not receiving"),
/// unabhaengig vom (binaeren) Verbindungszustand - der Socket kann offen
/// sein (LinkState.connected), ohne dass die Gegenstelle tatsaechlich
@@ -82,6 +92,27 @@ final wifiStreamActivityProvider =
NotifierProvider<WifiStreamActivityNotifier, bool>(
WifiStreamActivityNotifier.new);
/// Reaktive Gesamtzahl empfangener UDP-Pakete seit Verbindungsaufbau - fuer
/// die "Receiving"-Pille und die Connection-Log-Ueberschrift, die beide bei
/// jedem Paket sofort aktualisiert werden sollen (anders als
/// [WifiConnectionLogNotifier], deren Log-Eintraege nur bei Zustands-
/// aenderungen bzw. neu gelernter Gegenstelle geschrieben werden).
class WifiPacketCountNotifier extends Notifier<int> {
StreamSubscription<void>? _dataSub;
@override
int build() {
final transport = ref.watch(wifiTransportProvider);
_dataSub?.cancel();
_dataSub = transport.incoming.listen((_) => state++);
ref.onDispose(() => _dataSub?.cancel());
return 0;
}
}
final wifiPacketCountProvider =
NotifierProvider<WifiPacketCountNotifier, int>(WifiPacketCountNotifier.new);
/// Ein Eintrag im WLAN-Verbindungsprotokoll (Doku 7).
class WifiConnectionLogEntry {
const WifiConnectionLogEntry(this.timestamp, this.message);
@@ -90,25 +121,22 @@ class WifiConnectionLogEntry {
final String message;
}
/// Verbindungsprotokoll + Paketzaehler fuer den WLAN-Transport, analog zu
/// [ConnectionLogNotifier] fuer Bluetooth.
/// Verbindungsprotokoll fuer den WLAN-Transport, analog zu
/// [ConnectionLogNotifier] fuer Bluetooth. Der Paketzaehler lebt separat in
/// [wifiPacketCountProvider] (reaktiv pro Paket, hier nur protokolliert).
class WifiConnectionLogNotifier
extends Notifier<List<WifiConnectionLogEntry>> {
static const _maxEntries = 50;
StreamSubscription<LinkState>? _stateSub;
StreamSubscription<void>? _dataSub;
int _packetCount = 0;
String? _lastLoggedPeer;
int get packetCount => _packetCount;
@override
List<WifiConnectionLogEntry> build() {
final transport = ref.watch(wifiTransportProvider);
_stateSub?.cancel();
_dataSub?.cancel();
_packetCount = 0;
_lastLoggedPeer = null;
_stateSub = transport.state.listen(_onStateChanged);
_dataSub = transport.incoming.listen((_) => _onPacket(transport));
@@ -116,11 +144,18 @@ class WifiConnectionLogNotifier
_stateSub?.cancel();
_dataSub?.cancel();
});
// Telemetrie-Start/-Stopp (ueber denselben 4s-Timeout wie die
// "Receiving"-Pille) als eigene Log-Zeile, statt jedes einzelne Paket zu
// protokollieren - sonst wuerde das Log bei ~7 Paketen/s sofort
// ueberlaufen.
ref.listen<bool>(wifiStreamActivityProvider, (previous, isReceiving) {
if (previous == isReceiving) return;
_append(isReceiving ? 'Receiving telemetry' : 'Telemetry stream stopped');
});
return const [];
}
void _onPacket(UdpTransport transport) {
_packetCount++;
// Gegenstelle wird aus dem ersten eingehenden Paket gelernt (Doku
// Kommunikationsschicht v2, Abschnitt 3/9) - nur beim ersten Mal bzw.
// bei Aenderung protokollieren, nicht pro Paket.