lte service (backend) and ui handling

This commit is contained in:
Mikkeli Matlock
2026-02-09 02:36:03 +09:00
parent 12a0d58800
commit 47b3427e63
5 changed files with 261 additions and 3 deletions

View File

@@ -37,6 +37,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
// WebSocket stream subscriptions
StreamSubscription<ArduinoData>? _arduinoSub;
StreamSubscription<GpsData>? _gpsSub;
StreamSubscription<LteData>? _lteSub;
StreamSubscription<WsConnectionState>? _connectionSub;
// Pi temperature - direct file read (safety critical)
@@ -114,6 +115,13 @@ class _DashboardScreenState extends State<DashboardScreen> {
});
});
// Subscribe to LTE data stream
_lteSub = WebSocketService.instance.lteStream.listen((data) {
setState(() {
_lteSignal = data.signal;
});
});
// Subscribe to connection state
_connectionSub = WebSocketService.instance.connectionStream.listen((state) {
setState(() {
@@ -151,8 +159,11 @@ class _DashboardScreenState extends State<DashboardScreen> {
_wsState = WebSocketService.instance.connectionState;
// Placeholder: LTE signal (TODO: wire up when LTE service exists)
_lteSignal = null;
// Init from cached LTE data
final cachedLte = WebSocketService.instance.latestLte;
if (cachedLte != null) {
_lteSignal = cachedLte.signal;
}
// DEBUG: flip-flop theme + navigator every 2s
TestFlipFlopService.instance.start(navigatorKey: _navigatorKey);
@@ -163,6 +174,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
_piTempTimer?.cancel();
_arduinoSub?.cancel();
_gpsSub?.cancel();
_lteSub?.cancel();
_connectionSub?.cancel();
TestFlipFlopService.instance.stop();
super.dispose();

View File

@@ -58,6 +58,25 @@ class GpsData {
}
}
/// Data from LTE modem (signal quality, connection state)
class LteData {
final bool? connected;
final int? signal; // 0-100 percent
final String? operator_;
final String? accessTech;
LteData({this.connected, this.signal, this.operator_, this.accessTech});
factory LteData.fromJson(Map<String, dynamic> json) {
return LteData(
connected: json['connected'] as bool?,
signal: (json['signal'] as num?)?.toInt(),
operator_: json['operator'] as String?,
accessTech: json['access_tech'] as String?,
);
}
}
/// HTTP client for Flask backend - fire-and-forget async fetch, sync cache return
///
/// Follows the same pattern as PiIO: never blocks UI, always returns cached data.

View File

@@ -65,11 +65,13 @@ class WebSocketService {
// Latest values for sync access (backward compat)
ArduinoData? _latestArduino;
GpsData? _latestGps;
LteData? _latestLte;
BackendStatus? _latestStatus;
// Stream controllers
late StreamController<ArduinoData> _arduinoController;
late StreamController<GpsData> _gpsController;
late StreamController<LteData> _lteController;
late StreamController<BackendStatus> _statusController;
late StreamController<CommandAck> _ackController;
late StreamController<BackendAlert> _alertController;
@@ -83,6 +85,7 @@ class WebSocketService {
void _setupStreams() {
_arduinoController = StreamController<ArduinoData>.broadcast();
_gpsController = StreamController<GpsData>.broadcast();
_lteController = StreamController<LteData>.broadcast();
_statusController = StreamController<BackendStatus>.broadcast();
_ackController = StreamController<CommandAck>.broadcast();
_alertController = StreamController<BackendAlert>.broadcast();
@@ -107,6 +110,9 @@ class WebSocketService {
/// Stream of GPS updates
Stream<GpsData> get gpsStream => _gpsController.stream;
/// Stream of LTE status updates
Stream<LteData> get lteStream => _lteController.stream;
/// Stream of backend status updates
Stream<BackendStatus> get statusStream => _statusController.stream;
@@ -139,6 +145,9 @@ class WebSocketService {
/// Latest GPS data (may be null if not yet received)
GpsData? get latestGps => _latestGps;
/// Latest LTE data (may be null if not yet received)
LteData? get latestLte => _latestLte;
/// Latest backend status
BackendStatus? get latestStatus => _latestStatus;
@@ -208,6 +217,15 @@ class WebSocketService {
}
});
_socket!.on('lte', (data) {
if (data is Map<String, dynamic>) {
final lte = LteData.fromJson(data);
_latestLte = lte;
_lteController.add(lte);
_log('lte: ${lte.signal ?? "-"}% ${lte.operator_ ?? "-"} ${lte.accessTech ?? "-"}');
}
});
_socket!.on('status', (data) {
if (data is Map<String, dynamic>) {
final status = BackendStatus(
@@ -323,6 +341,7 @@ class WebSocketService {
disconnect();
_arduinoController.close();
_gpsController.close();
_lteController.close();
_statusController.close();
_ackController.close();
_alertController.close();