Matthias Nott
2026-04-01 3e19d6917ff245863be43a39a76daa7010ecda6f
lib/services/mqtt_service.dart
....@@ -5,6 +5,7 @@
55 import 'package:crypto/crypto.dart';
66
77 import 'package:bonsoir/bonsoir.dart';
8
+import 'package:connectivity_plus/connectivity_plus.dart';
89 import 'package:flutter/foundation.dart';
910 import 'package:flutter/widgets.dart';
1011 import 'package:path_provider/path_provider.dart' as pp;
....@@ -50,6 +51,8 @@
5051 bool _intentionalClose = false;
5152 String? _clientId;
5253 String? _lastDiscoveredHost;
54
+ StreamSubscription? _connectivitySub;
55
+ List<ConnectivityResult>? _lastConnectivity;
5356 StreamSubscription? _updatesSub;
5457
5558 // Message deduplication
....@@ -103,6 +106,36 @@
103106
104107 _intentionalClose = false;
105108 _setStatus(ConnectionStatus.connecting);
109
+
110
+ // Start listening for network changes (WiFi↔cellular, VPN connect/disconnect)
111
+ _connectivitySub ??= Connectivity().onConnectivityChanged.listen((results) {
112
+ if (_lastConnectivity != null && !_intentionalClose) {
113
+ final changed = results.length != _lastConnectivity!.length ||
114
+ !results.every((r) => _lastConnectivity!.contains(r));
115
+ if (changed) {
116
+ _mqttLog('MQTT: network changed: ${results.map((r) => r.name).join(",")} — forcing reconnect');
117
+ // Force disconnect and reconnect on new network
118
+ final client = _client;
119
+ if (client != null) {
120
+ _intentionalClose = true;
121
+ client.autoReconnect = false;
122
+ try { client.disconnect(); } catch (_) {}
123
+ _client = null;
124
+ _updatesSub?.cancel();
125
+ _updatesSub = null;
126
+ _intentionalClose = false;
127
+ }
128
+ _lastDiscoveredHost = null; // Clear cached discovery — subnet may have changed
129
+ connectedHost = null;
130
+ connectedVia = null;
131
+ _setStatus(ConnectionStatus.reconnecting);
132
+ Future.delayed(const Duration(milliseconds: 500), () {
133
+ if (!_intentionalClose) connect();
134
+ });
135
+ }
136
+ }
137
+ _lastConnectivity = results;
138
+ });
106139
107140 // Load trusted cert fingerprint for TOFU verification
108141 if (_trustedFingerprint == null) await _loadTrustedFingerprint();
....@@ -724,6 +757,8 @@
724757 _intentionalClose = true;
725758 _updatesSub?.cancel();
726759 _updatesSub = null;
760
+ _connectivitySub?.cancel();
761
+ _connectivitySub = null;
727762
728763 try {
729764 _client?.disconnect();