Erweiterungen
This commit is contained in:
367
MQTT_QUICK_REFERENCE.md
Normal file
367
MQTT_QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,367 @@
|
||||
# MQTT Quick Reference - Client Migration
|
||||
|
||||
## 🚨 Kritische Änderungen
|
||||
|
||||
### Port-Änderung (WICHTIG!)
|
||||
```
|
||||
Alt: mqtt-2.assecutor.de:1883
|
||||
Neu: mqtt-2.assecutor.de:42099
|
||||
```
|
||||
|
||||
### Authentifizierung (NEU!)
|
||||
```
|
||||
Username: app
|
||||
Password: apppwd
|
||||
```
|
||||
|
||||
### Timeout-Erhöhung
|
||||
```
|
||||
Connection Timeout: 60 Sekunden (vorher 30s)
|
||||
Keep-Alive: 60 Sekunden (vorher 30s)
|
||||
```
|
||||
|
||||
## 📋 Flutter/Dart Code-Snippets
|
||||
|
||||
### 1. Verbindung herstellen
|
||||
|
||||
```dart
|
||||
import 'package:mqtt_client/mqtt_client.dart';
|
||||
import 'package:mqtt_client/mqtt_server_client.dart';
|
||||
|
||||
Future<MqttServerClient> connectToMqtt(String clientId) async {
|
||||
final client = MqttServerClient.withPort(
|
||||
'mqtt-2.assecutor.de',
|
||||
clientId,
|
||||
42099, // NEUER PORT!
|
||||
);
|
||||
|
||||
client.keepAlivePeriod = 60;
|
||||
client.connectTimeoutPeriod = 60000;
|
||||
client.autoReconnect = true;
|
||||
client.setProtocolV311();
|
||||
|
||||
final connMessage = MqttConnectMessage()
|
||||
.withClientIdentifier(clientId)
|
||||
.authenticateAs('app', 'apppwd') // NEU: Authentifizierung
|
||||
.withWillQos(MqttQos.atLeastOnce)
|
||||
.startClean()
|
||||
.keepAliveFor(60);
|
||||
|
||||
client.connectionMessage = connMessage;
|
||||
|
||||
await client.connect();
|
||||
return client;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Message Envelope (NEU!)
|
||||
|
||||
```dart
|
||||
class MessageEnvelope {
|
||||
final String messageId;
|
||||
final DateTime timestamp;
|
||||
final String topic;
|
||||
final Map<String, dynamic> payload;
|
||||
final bool requiresAck;
|
||||
final int retryCount;
|
||||
final DateTime? expiresAt;
|
||||
|
||||
MessageEnvelope({
|
||||
required this.messageId,
|
||||
required this.timestamp,
|
||||
required this.topic,
|
||||
required this.payload,
|
||||
this.requiresAck = true,
|
||||
this.retryCount = 0,
|
||||
this.expiresAt,
|
||||
});
|
||||
|
||||
factory MessageEnvelope.fromJson(Map<String, dynamic> json) {
|
||||
return MessageEnvelope(
|
||||
messageId: json['messageId'],
|
||||
timestamp: DateTime.parse(json['timestamp']),
|
||||
topic: json['topic'],
|
||||
payload: json['payload'],
|
||||
requiresAck: json['requiresAck'] ?? true,
|
||||
retryCount: json['retryCount'] ?? 0,
|
||||
expiresAt: json['expiresAt'] != null
|
||||
? DateTime.parse(json['expiresAt'])
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'messageId': messageId,
|
||||
'timestamp': timestamp.toIso8601String(),
|
||||
'topic': topic,
|
||||
'payload': payload,
|
||||
'requiresAck': requiresAck,
|
||||
'retryCount': retryCount,
|
||||
if (expiresAt != null) 'expiresAt': expiresAt!.toIso8601String(),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Nachricht senden
|
||||
|
||||
```dart
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
Future<void> sendMessage(
|
||||
MqttServerClient client,
|
||||
String clientId,
|
||||
String messageType,
|
||||
Map<String, dynamic> payload,
|
||||
) async {
|
||||
final envelope = MessageEnvelope(
|
||||
messageId: Uuid().v4(),
|
||||
timestamp: DateTime.now(),
|
||||
topic: '/server/$clientId/$messageType',
|
||||
payload: payload,
|
||||
requiresAck: true,
|
||||
);
|
||||
|
||||
final builder = MqttClientPayloadBuilder();
|
||||
builder.addString(jsonEncode(envelope.toJson()));
|
||||
|
||||
client.publishMessage(
|
||||
envelope.topic,
|
||||
MqttQos.exactlyOnce,
|
||||
builder.payload!,
|
||||
);
|
||||
}
|
||||
|
||||
// Beispiel-Verwendung:
|
||||
await sendMessage(
|
||||
client,
|
||||
'app-user-123',
|
||||
'task_completed',
|
||||
{
|
||||
'taskId': '456',
|
||||
'status': 'completed',
|
||||
'completedAt': DateTime.now().toIso8601String(),
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 4. Nachricht empfangen
|
||||
|
||||
```dart
|
||||
void setupMessageListener(MqttServerClient client, String clientId) {
|
||||
// Subscribe zu allen relevanten Topics
|
||||
client.subscribe('/client/$clientId/#', MqttQos.exactlyOnce);
|
||||
client.subscribe('/ack/client/$clientId/#', MqttQos.exactlyOnce);
|
||||
|
||||
client.updates!.listen((List<MqttReceivedMessage<MqttMessage>> messages) {
|
||||
for (var message in messages) {
|
||||
final topic = message.topic;
|
||||
final payloadString = MqttPublishPayload.bytesToStringAsString(
|
||||
(message.payload as MqttPublishMessage).payload.message,
|
||||
);
|
||||
|
||||
try {
|
||||
final json = jsonDecode(payloadString);
|
||||
|
||||
// Prüfen ob Envelope-Format
|
||||
if (json.containsKey('messageId') && json.containsKey('payload')) {
|
||||
final envelope = MessageEnvelope.fromJson(json);
|
||||
|
||||
// Nachricht verarbeiten
|
||||
handleEnvelopeMessage(envelope);
|
||||
|
||||
// ACK senden wenn erforderlich
|
||||
if (envelope.requiresAck) {
|
||||
sendAck(client, envelope.messageId, true);
|
||||
}
|
||||
} else {
|
||||
// Legacy-Format
|
||||
handleLegacyMessage(topic, json);
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error processing message: $e');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Acknowledgment senden (NEU!)
|
||||
|
||||
```dart
|
||||
class AcknowledgmentMessage {
|
||||
final String messageId;
|
||||
final DateTime timestamp;
|
||||
final String status;
|
||||
final String? errorMessage;
|
||||
|
||||
AcknowledgmentMessage({
|
||||
required this.messageId,
|
||||
required this.timestamp,
|
||||
required this.status,
|
||||
this.errorMessage,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'messageId': messageId,
|
||||
'timestamp': timestamp.toIso8601String(),
|
||||
'status': status,
|
||||
if (errorMessage != null) 'errorMessage': errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
void sendAck(
|
||||
MqttServerClient client,
|
||||
String messageId,
|
||||
bool success,
|
||||
[String? errorMessage]
|
||||
) {
|
||||
final ack = AcknowledgmentMessage(
|
||||
messageId: messageId,
|
||||
timestamp: DateTime.now(),
|
||||
status: success ? 'SUCCESS' : 'FAILED',
|
||||
errorMessage: errorMessage,
|
||||
);
|
||||
|
||||
final topic = '/ack/server/$messageId';
|
||||
final builder = MqttClientPayloadBuilder();
|
||||
builder.addString(jsonEncode(ack.toJson()));
|
||||
|
||||
client.publishMessage(
|
||||
topic,
|
||||
MqttQos.exactlyOnce,
|
||||
builder.payload!,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Topic-Struktur (unverändert)
|
||||
|
||||
### Client → Server
|
||||
```
|
||||
/server/{clientId}/task_completed
|
||||
/server/{clientId}/login
|
||||
/server/{clientId}/message
|
||||
/server/{clientId}/jobs/assigned
|
||||
```
|
||||
|
||||
### Server → Client
|
||||
```
|
||||
/client/{clientId}/jobs/assigned
|
||||
/client/{clientId}/message
|
||||
/client/{clientId}/task_update
|
||||
```
|
||||
|
||||
### Acknowledgments
|
||||
```
|
||||
Client → Server: /ack/server/{messageId}
|
||||
Server → Client: /ack/client/{clientId}/{messageId}
|
||||
```
|
||||
|
||||
## 🔍 Debugging
|
||||
|
||||
### Verbindung testen
|
||||
|
||||
```dart
|
||||
Future<void> testConnection() async {
|
||||
try {
|
||||
final client = await connectToMqtt('test-${Uuid().v4()}');
|
||||
|
||||
if (client.connectionStatus!.state == MqttConnectionState.connected) {
|
||||
print('✅ Connection successful!');
|
||||
|
||||
// Test-Nachricht senden
|
||||
await sendMessage(
|
||||
client,
|
||||
'test-client',
|
||||
'test',
|
||||
{'message': 'Hello from client'},
|
||||
);
|
||||
|
||||
print('✅ Test message sent!');
|
||||
} else {
|
||||
print('❌ Connection failed: ${client.connectionStatus}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('❌ Error: $e');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Häufige Fehler
|
||||
|
||||
#### 1. Connection Timeout
|
||||
```
|
||||
Fehler: TimeoutException after 60 seconds
|
||||
Lösung:
|
||||
- Prüfen Sie, ob Port 42099 erreichbar ist
|
||||
- Firewall-Einstellungen überprüfen
|
||||
- Netzwerkverbindung testen
|
||||
```
|
||||
|
||||
#### 2. Authentication Failed
|
||||
```
|
||||
Fehler: Connection refused
|
||||
Lösung:
|
||||
- Username: 'app'
|
||||
- Password: 'apppwd'
|
||||
- Stellen Sie sicher, dass authenticateAs() aufgerufen wird
|
||||
```
|
||||
|
||||
#### 3. Message not received
|
||||
```
|
||||
Fehler: Keine Nachrichten empfangen
|
||||
Lösung:
|
||||
- Subscription überprüfen: client.subscribe('/client/$clientId/#', ...)
|
||||
- Listener registriert: client.updates!.listen(...)
|
||||
- Topic-Format korrekt: /client/{clientId}/{messageType}
|
||||
```
|
||||
|
||||
## 📦 Dependencies
|
||||
|
||||
### pubspec.yaml
|
||||
```yaml
|
||||
dependencies:
|
||||
mqtt_client: ^10.2.0
|
||||
uuid: ^4.0.0
|
||||
```
|
||||
|
||||
## ✅ Migration Checklist
|
||||
|
||||
- [ ] Port auf 42099 geändert
|
||||
- [ ] Authentifizierung hinzugefügt (app/apppwd)
|
||||
- [ ] Connection-Timeout auf 60s erhöht
|
||||
- [ ] Keep-Alive auf 60s gesetzt
|
||||
- [ ] MessageEnvelope-Klasse implementiert
|
||||
- [ ] AcknowledgmentMessage-Klasse implementiert
|
||||
- [ ] Envelope-basiertes Senden implementiert
|
||||
- [ ] Envelope-basiertes Empfangen implementiert
|
||||
- [ ] ACK-Handling implementiert
|
||||
- [ ] Fehlerbehandlung für ACKs implementiert
|
||||
- [ ] Verbindung getestet
|
||||
- [ ] Nachrichtenversand getestet
|
||||
- [ ] Nachrichtenempfang getestet
|
||||
|
||||
## 🔗 Weitere Dokumentation
|
||||
|
||||
- **Detaillierte Migration**: `MQTT_MIGRATION_GUIDE.md`
|
||||
- **Changelog**: `CHANGELOG_MQTT.md`
|
||||
- **Architektur**: `MESSAGING_LAYER.md`
|
||||
- **API-Referenz**: `MQTT_README.md`
|
||||
|
||||
## 💡 Best Practices
|
||||
|
||||
1. **Eindeutige Client-IDs**: Verwenden Sie stabile, geräte-spezifische IDs
|
||||
2. **Fehlerbehandlung**: Implementieren Sie Retry-Logik für fehlgeschlagene Verbindungen
|
||||
3. **ACK-Timeout**: Warten Sie maximal 30 Sekunden auf ACKs
|
||||
4. **Message-Expiry**: Prüfen Sie `expiresAt` vor der Verarbeitung
|
||||
5. **Logging**: Loggen Sie alle Verbindungsereignisse für Debugging
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
Bei Problemen:
|
||||
1. Logs auf Client- und Server-Seite prüfen
|
||||
2. Netzwerk-Konnektivität testen (Port 42099)
|
||||
3. MQTT-Client-Tool verwenden (z.B. MQTT Explorer)
|
||||
4. Dokumentation konsultieren
|
||||
|
||||
Reference in New Issue
Block a user