Matthias Nott
9 days ago 1bf6e76e31383aef77e42943fc2caf350cf7e096
lib/services/trace_service.dart
....@@ -1,4 +1,10 @@
1
+import 'dart:convert';
2
+
13 import 'package:flutter/foundation.dart';
4
+import 'package:mqtt_client/mqtt_client.dart';
5
+import 'package:mqtt_client/mqtt_server_client.dart';
6
+
7
+import 'mqtt_service.dart';
28
39 /// A single trace entry capturing a message-handling event.
410 class TraceEntry {
....@@ -22,17 +28,28 @@
2228 /// Captures message-handling events from MQTT, chat screen, and other
2329 /// components. The buffer is capped at [maxEntries] (default 200).
2430 /// Works in both debug and release builds.
31
+///
32
+/// When an MqttService is attached via [attachMqtt], trace entries are
33
+/// automatically published to the server on `pailot/control/in` so they
34
+/// can be read from the daemon log.
2535 class TraceService {
2636 TraceService._();
2737 static final TraceService instance = TraceService._();
2838
2939 static const int maxEntries = 200;
3040 final List<TraceEntry> _entries = [];
41
+ MqttService? _mqtt;
42
+
43
+ /// Attach an MQTT service for auto-publishing traces to the server.
44
+ void attachMqtt(MqttService mqtt) {
45
+ _mqtt = mqtt;
46
+ }
3147
3248 /// All entries, oldest first.
3349 List<TraceEntry> get entries => List.unmodifiable(_entries);
3450
3551 /// Add a trace entry. Oldest entry is evicted once the buffer is full.
52
+ /// If MQTT is attached and connected, the entry is also published to the server.
3653 void addTrace(String event, String details) {
3754 _entries.add(TraceEntry(
3855 timestamp: DateTime.now(),
....@@ -43,6 +60,28 @@
4360 _entries.removeAt(0);
4461 }
4562 debugPrint('[TRACE] $event — $details');
63
+
64
+ // Auto-publish to server if MQTT is connected
65
+ _publishTrace(event, details);
66
+ }
67
+
68
+ void _publishTrace(String event, String details) {
69
+ final mqtt = _mqtt;
70
+ if (mqtt == null || !mqtt.isConnected) return;
71
+ try {
72
+ final payload = jsonEncode({
73
+ 'type': 'command',
74
+ 'command': 'app_trace',
75
+ 'event': event,
76
+ 'details': details,
77
+ 'ts': DateTime.now().millisecondsSinceEpoch,
78
+ });
79
+ final builder = MqttClientPayloadBuilder();
80
+ builder.addString(payload);
81
+ mqtt.publishRaw('pailot/control/in', builder.payload!, MqttQos.atMostOnce);
82
+ } catch (_) {
83
+ // Non-fatal — don't let trace logging break the app
84
+ }
4685 }
4786
4887 /// Clear all entries.