Flutter Real-Time communication using MQTT

Chetan Gaikwad
4 min readDec 4, 2022

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

--

--