Flutter Real-Time communication using MQTT
Real-Time communication plays an important role in this connected world of devices.
I was working on one of my side projects in which I was required to implement Real-Time communication to track Real-Time positions of vehicles using an app. After a lot of research, MQTT seems to be the perfect fit for the job.
This article cover
- Introduction to MQTT
- Concepts and Terminologies related to MQTT
- Advantage over HTTP
- Installation and Permission
- Implementing MQTT operations like
1. Connect
2. Publish
3. Subscribe
4. Unsubscribe
5. Disconnect - Usage and Conclusion
By the end of this article, you will learn how to implement real-time communication in your flutter app so that multiple devices communicate with each other in real time.
MQTT (Message Queue Telemetry Transport)
What is MQTT?
MQTT is a machine-to-machine (M2M)/”Internet of Things” connectivity protocol.
Used for simple communication between multiple devices with a simple messaging protocol in RealTime.
Some of the related concepts
- Publish: Sending a message.
- Subscribe: Receiving a message
- Broker: The broker is responsible for distributing messages to interested clients based on the topic of a message.
- Topic: A topic is a UTF-8 string, which the broker uses to filter messages for each connected client. A topic consists of one or more topic levels. Each topic level is separated by a forward slash. eg: global/demo
Some of the broker server tasks are
- Receive all messages
- Filter and rectify the interesting subscriber
- send/publish a message to all subscriber
Why not HTTP for this purpose?
- No Good solution for push and Quality of service
- Require more bandwidth
- Acting as host requires more battery(To listen for incoming requests and server)
- more battery
MQTT communication architecture
MQTT advantages
- Pub-Sub protocol
- Limited Bandwidth, It is designed for connections to remote locations where a “small code footprint” is required or the network bandwidth is limited
- The binary format requires less bandwidth
- Less battery
In this post, we will learn the following things
- Dependency required
- Permissions and Tag required
- Connecting and Disconnecting to the Broker server
- Publishing, Subscribing, and Unsubscribing to a topic
Let’s jump into code how to implement MQTT in Flutter
I am using mqtt_client library.
dependencies:
mqtt_client: ^9.7.2
I am creating a class MqttHandler to manage all the MQTT operations and just pass the received data
Initializing the client object
MqttServerClient client = MqttServerClient.withPort(
SERVER_URL,
CLIENT_IDENTIFIER,
PORT_NUMBER
);
Note: It’s important to remember that the client ID must be unique for every client connecting to the broker, so you will need to generate it not just hard code a random value of the will ever be more than one instance of the code running.
Referance: Stackoverflow
Register all the callbacks and functions
client.logging(on: true);
client.onConnected = onConnected;
client.onDisconnected = onDisconnected;
client.onUnsubscribed = onUnsubscribed;
client.onSubscribed = onSubscribed;
client.onSubscribeFail = onSubscribeFail;
client.pongCallback = pong;
client.keepAlivePeriod = 60;
client.logging(on: true);
client.setProtocolV311();
void onConnected() {
print('MQTT_LOGS:: Connected');
}
void onDisconnected() {
print('MQTT_LOGS:: Disconnected');
}
void onSubscribed(String topic) {
print('MQTT_LOGS:: Subscribed topic: $topic');
}
void onSubscribeFail(String topic) {
print('MQTT_LOGS:: Failed to subscribe $topic');
}
void onUnsubscribed(String? topic) {
print('MQTT_LOGS:: Unsubscribed topic: $topic');
}
void pong() {
print('MQTT_LOGS:: Ping response client callback invoked');
}
Connect
final connMessage = MqttConnectMessage()
.withWillTopic('willtopic')
.withWillMessage('Will message')
.startClean()
.withWillQos(MqttQos.atLeastOnce);
print('MQTT_LOGS::Mosquitto client connecting....');
client.connectionMessage = connMessage;
try {
await client.connect();
} catch (e) {
print('Exception: $e');
client.disconnect();
}
if (client.connectionStatus!.state == MqttConnectionState.connected) {
print('MQTT_LOGS::Mosquitto client connected');
} else {
print(
'MQTT_LOGS::ERROR Mosquitto client connection failed - disconnecting, status is ${client.connectionStatus}');
client.disconnect();
}
Subscribing to a topic
print('MQTT_LOGS::Subscribing to the test/lol topic');
const topic = 'test/sample';
client.subscribe(topic, MqttQos.atMostOnce);
client.updates!.listen((List<MqttReceivedMessage<MqttMessage?>>? c) {
final recMess = c![0].payload as MqttPublishMessage;
final pt =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
data.value = pt;
print(
'MQTT_LOGS:: New data arrived: topic is <${c[0].topic}>, payload is $pt');
print('');
});
Publishing a message
void publishMessage(String message) {
const pubTopic = 'test/sample';
final builder = MqttClientPayloadBuilder();
builder.addString(message);
if (client.connectionStatus?.state == MqttConnectionState.connected) {
client.publishMessage(pubTopic, MqttQos.atMostOnce, builder.payload!);
}
}
Reference to the final class:
Now let's set up a widget to call this class and display the value received on the sample topic
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
MqttHandler mqttHandler = MqttHandler();
@override
void initState() {
super.initState();
mqttHandler.connect();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sample Code'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Data received:',
style: TextStyle(color: Colors.black, fontSize: 25)),
ValueListenableBuilder<String>(
builder: (BuildContext context, String value, Widget? child) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('$value',
style: TextStyle(
color: Colors.deepPurpleAccent, fontSize: 35))
],
);
},
valueListenable: mqttHandler.data,
)
],
),
),
);
}
}
Result:
GitHub repository:
Let’s get connected
For any query, suggestion, or improvement on my blog ping me
- My portfolio: https://droid-learn.com/
- Medium profile → https://medium.com/@gaikwadchetan93
- GitHub → https://github.com/gaikwadChetan93
- LinkedIn → https://www.linkedin.com/in/chetan-gaikwad-10426383/