The Internet of Things (IoT) is rapidly transforming the way we interact with devices and systems around us. Combining Flutter, a versatile UI toolkit, with MQTT, a lightweight messaging protocol, offers a powerful solution for building connected IoT applications. This article explores how to leverage Flutter and MQTT to create robust, real-time IoT applications.
What is MQTT?
MQTT (Message Queuing Telemetry Transport) is a lightweight, publish-subscribe network protocol that transports messages between devices. It’s ideal for IoT applications because it’s designed for low-bandwidth, high-latency, and unreliable networks. MQTT operates on top of the TCP/IP protocol.
What is Flutter?
Flutter is Google’s UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase. Flutter is known for its fast development, expressive UI, and native performance.
Why Combine Flutter and MQTT for IoT?
- Real-time Communication: MQTT enables real-time communication between IoT devices and applications.
- Cross-platform Development: Flutter allows you to build apps for multiple platforms (iOS, Android, web) from a single codebase.
- Lightweight: MQTT is designed for low-bandwidth environments, perfect for IoT devices with limited resources.
- Scalability: MQTT brokers can handle a large number of connected devices.
How to Build an IoT Application with Flutter and MQTT
Here’s a step-by-step guide on building an IoT application using Flutter and MQTT:
Step 1: Set up Your Development Environment
- Install Flutter: Follow the official Flutter installation guide for your operating system: https://flutter.dev/docs/get-started/install
- Install Dart: Dart comes bundled with Flutter, so no separate installation is required.
- Choose an IDE: Use Android Studio, VS Code, or your preferred IDE with Flutter and Dart plugins installed.
Step 2: Create a New Flutter Project
Open your terminal and run the following command to create a new Flutter project:
flutter create iot_flutter_app
Navigate to the project directory:
cd iot_flutter_app
Step 3: Add MQTT Client Dependency
Add the mqtt_client
package to your pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
mqtt_client: ^9.7.0 # Use the latest version
Run flutter pub get
to install the dependency.
Step 4: Implement MQTT Client Logic in Flutter
Create a Dart file (e.g., mqtt_service.dart
) to handle MQTT client connection, subscription, and message processing.
import 'dart:async';
import 'dart:io';
import 'package:mqtt_client/mqtt_server_client.dart';
class MQTTService {
final String server;
final String clientId;
final String topic;
MqttServerClient? client;
MQTTService({
required this.server,
required this.clientId,
required this.topic,
});
Future connect() async {
client = MqttServerClient(server, clientId);
client!.port = 1883; // MQTT port
client!.logging = true;
client!.onConnected = onConnected;
client!.onDisconnected = onDisconnected;
client!.onSubscribed = onSubscribed;
client!.onSubscribeFail = onSubscribeFail;
client!.pongCallback = pong;
final connMess = MqttConnectMessage()
.withClientIdentifier(clientId)
.withWillTopic('willtopic') // If you set this up on the broker, it will announce
.withWillMessage('My Will message')
.startCleanSession() // Non persistent session for testing
.withQos(MqttQos.atLeastOnce);
print('EXAMPLE::Mosquitto client connecting....');
client!.connectionMessage = connMess;
try {
await client!.connect();
} on NoConnectionException catch (e) {
// Raised if the broker rejects the connection due
// to an incorrect client identifier, password or username.
print('EXAMPLE::client exception - $e');
client!.disconnect();
} on SocketException catch (e) {
// Raised if the socket cannot be created.
print('EXAMPLE::socket exception - $e');
client!.disconnect();
}
return client!;
}
void subscribe() {
print('EXAMPLE::Subscribing to the $topic topic');
client!.subscribe(topic, MqttQos.atLeastOnce);
client!.updates!.listen((List>? c) {
final recMess = c![0].payload as MqttPublishMessage;
final pt =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
print(
'EXAMPLE::Change notification:: topic is <${c[0].topic}>, payload is <$pt>');
print('');
});
}
void publish(String message) {
final builder = MqttClientPayloadBuilder();
builder.addString(message);
client!.publishMessage(topic, MqttQos.exactlyOnce, builder.payload!);
}
void disconnect() {
client!.disconnect();
}
// callbacks
void onConnected() {
print('EXAMPLE::Mosquitto client connected');
}
void onDisconnected() {
print('EXAMPLE::Mosquitto client disconnected');
}
void onSubscribed(String topic) {
print('EXAMPLE::Subscribed topic: $topic');
}
void onSubscribeFail(String topic) {
print('EXAMPLE::Failed to subscribe $topic');
}
void pong() {
print('EXAMPLE::Ping response client callback invoked');
}
}
Step 5: Create the UI in Flutter
In your main.dart
file, build the UI that connects to the MQTT broker, subscribes to a topic, and displays the received messages.
import 'package:flutter/material.dart';
import 'mqtt_service.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter MQTT App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'MQTT Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
String _message = 'No message';
late MQTTService _mqttService;
@override
void initState() {
super.initState();
_mqttService = MQTTService(
server: 'test.mosquitto.org', // Replace with your MQTT broker address
clientId: 'flutter_client',
topic: 'flutter_topic', // Replace with your MQTT topic
);
_connectAndSubscribe();
}
Future _connectAndSubscribe() async {
await _mqttService.connect();
_mqttService.subscribe();
_mqttService.client!.updates!.listen((List>? c) {
final recMess = c![0].payload as MqttPublishMessage;
final pt =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
setState(() {
_message = pt;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Message from MQTT:',
),
Text(
'$_message',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
);
}
@override
void dispose() {
_mqttService.disconnect();
super.dispose();
}
}
Step 6: Configure MQTT Broker
For testing purposes, you can use a public MQTT broker such as test.mosquitto.org
. For production, it’s recommended to set up your own MQTT broker (e.g., Mosquitto, EMQX) for security and reliability.
Step 7: Test Your Application
Run your Flutter application on a device or emulator. Publish messages to the subscribed topic using an MQTT client (e.g., MQTT.fx) or another IoT device. The Flutter application should display the received messages in real time.
Code Explanation
- MQTTService: This class handles MQTT client connection, subscription, publishing, and disconnection.
- connect(): Connects to the MQTT broker using the provided server and client ID.
- subscribe(): Subscribes to the specified MQTT topic and listens for incoming messages.
- publish(): Publishes a message to the MQTT topic.
- onConnected(), onDisconnected(), onSubscribed(): Callback functions to handle MQTT client events.
- MyHomePage: Flutter UI component that displays the received MQTT messages.
- _connectAndSubscribe(): Asynchronously connects to the MQTT broker and subscribes to the topic upon initialization.
Best Practices for Building IoT Applications with Flutter and MQTT
- Secure Your MQTT Broker: Use TLS/SSL for secure communication and implement authentication.
- Handle Disconnections: Implement logic to handle MQTT disconnections and reconnect automatically.
- Optimize Message Payloads: Use lightweight data formats like JSON or Protocol Buffers to minimize bandwidth usage.
- Implement Error Handling: Add robust error handling to gracefully handle unexpected errors and exceptions.
- Test Thoroughly: Test your application under various network conditions and device configurations.
Conclusion
Building IoT applications with Flutter and MQTT offers a compelling combination of cross-platform development and real-time communication. By following the steps outlined in this article and adhering to best practices, you can create efficient, scalable, and robust IoT solutions that harness the power of Flutter’s UI capabilities and MQTT’s lightweight messaging protocol.