From 16893f9606d43171992199cf2529f3774a226b84 Mon Sep 17 00:00:00 2001
From: Matthias Nott <mnott@mnsoft.org>
Date: Sun, 22 Mar 2026 18:57:15 +0100
Subject: [PATCH] fix: MQTT port matches config, keyboard dismiss on drawer, debug logging

---
 lib/services/mqtt_service.dart |   32 +++++++++++++++++++++++++-------
 1 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/lib/services/mqtt_service.dart b/lib/services/mqtt_service.dart
index 3f3afcb..9f5526e 100644
--- a/lib/services/mqtt_service.dart
+++ b/lib/services/mqtt_service.dart
@@ -1,7 +1,9 @@
 import 'dart:async';
 import 'dart:convert';
+import 'dart:io';
 
 import 'package:flutter/widgets.dart';
+import 'package:path_provider/path_provider.dart' as pp;
 import 'package:mqtt_client/mqtt_client.dart';
 import 'package:mqtt_client/mqtt_server_client.dart';
 import 'package:shared_preferences/shared_preferences.dart';
@@ -11,8 +13,15 @@
 import 'websocket_service.dart' show ConnectionStatus;
 import 'wol_service.dart';
 
-/// MQTT port — standard unencrypted MQTT.
-const int mqttPort = 1883;
+// Debug log to file (survives release builds)
+Future<void> _mqttLog(String msg) async {
+  try {
+    final dir = await pp.getApplicationDocumentsDirectory();
+    final file = File('${dir.path}/mqtt_debug.log');
+    final ts = DateTime.now().toIso8601String().substring(11, 19);
+    await file.writeAsString('[$ts] $msg\n', mode: FileMode.append);
+  } catch (_) {}
+}
 
 /// MQTT client for PAILot, replacing WebSocketService.
 ///
@@ -56,8 +65,10 @@
     if (_clientId != null) return _clientId!;
     final prefs = await SharedPreferences.getInstance();
     var id = prefs.getString('mqtt_client_id');
-    if (id == null) {
-      id = 'pailot-${const Uuid().v4()}';
+    // Regenerate if old format (too long for MQTT 3.1.1)
+    if (id == null || id.length > 23) {
+      // MQTT 3.1.1 client IDs: max 23 chars, alphanumeric
+      id = 'pailot${const Uuid().v4().replaceAll('-', '').substring(0, 16)}';
       await prefs.setString('mqtt_client_id', id);
     }
     _clientId = id;
@@ -88,19 +99,23 @@
     for (final host in hosts) {
       if (_intentionalClose) return;
 
+      _mqttLog('MQTT: trying $host:${config.port}');
       try {
         final connected = await _tryConnect(
           host,
           clientId,
           timeout: host == hosts.first && hosts.length > 1 ? 2500 : 5000,
         );
+        _mqttLog('MQTT: $host result=$connected');
         if (connected) return;
-      } catch (_) {
+      } catch (e) {
+        _mqttLog('MQTT: $host error=$e');
         continue;
       }
     }
 
     // All hosts failed
+    debugPrint('MQTT: all hosts failed');
     _setStatus(ConnectionStatus.disconnected);
     onError?.call('Failed to connect to MQTT broker');
   }
@@ -117,11 +132,11 @@
 
   Future<bool> _tryConnect(String host, String clientId, {int timeout = 5000}) async {
     try {
-      final client = MqttServerClient.withPort(host, clientId, mqttPort);
+      final client = MqttServerClient.withPort(host, clientId, config.port);
       client.keepAlivePeriod = 30;
       client.autoReconnect = true;
       client.connectTimeoutPeriod = timeout;
-      client.logging(on: false);
+      client.logging(on: true);
 
       client.onConnected = _onConnected;
       client.onDisconnected = _onDisconnected;
@@ -140,7 +155,9 @@
 
       client.connectionMessage = connMessage;
 
+      _mqttLog('MQTT: connecting to $host:${config.port} as $clientId');
       final result = await client.connect();
+      _mqttLog('MQTT: connect result=${result?.state}');
       if (result?.state == MqttConnectionState.connected) {
         _client = client;
         return true;
@@ -148,6 +165,7 @@
       client.disconnect();
       return false;
     } catch (e) {
+      _mqttLog('MQTT: connect exception=$e');
       return false;
     }
   }

--
Gitblit v1.3.1