Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Integrate IoT Device Controls into a FlutterFlow App

FlutterFlow apps control IoT devices through three main patterns: MQTT via the mqtt_client Custom Widget connecting to a broker like AWS IoT or HiveMQ, REST API calls if the device vendor provides one, or Firebase as a relay where the device reads commands from Firestore and publishes state back. Most home IoT devices lack public IP addresses, so a message broker or cloud relay is required rather than direct connections.

What you'll learn

  • How to connect a FlutterFlow app to an MQTT broker using the mqtt_client Flutter package
  • How to use Firebase Firestore as a real-time IoT command relay without a dedicated broker
  • How to call vendor REST APIs (Philips Hue, SmartThings) via FlutterFlow's API Manager
  • How to build a device dashboard with online/offline status, toggle switches, and sliders
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced9 min read90-120 minFlutterFlow Free+ (Custom Actions required)March 2026RapidDev Engineering Team
TL;DR

FlutterFlow apps control IoT devices through three main patterns: MQTT via the mqtt_client Custom Widget connecting to a broker like AWS IoT or HiveMQ, REST API calls if the device vendor provides one, or Firebase as a relay where the device reads commands from Firestore and publishes state back. Most home IoT devices lack public IP addresses, so a message broker or cloud relay is required rather than direct connections.

Connect FlutterFlow to IoT devices via MQTT, REST, or Firebase relay

IoT devices run on local networks or behind NAT, so they are not directly reachable from a mobile app over the internet. FlutterFlow solves this with three approaches: MQTT (a lightweight pub/sub protocol used by most IoT hardware), vendor REST APIs (Philips Hue, TP-Link Tapo, Samsung SmartThings), and Firebase Firestore as a bidirectional command relay. This tutorial covers all three patterns so you can pick the right one for your hardware. You will build a device dashboard with real-time status indicators, on/off toggle switches, and a brightness slider.

Prerequisites

  • A FlutterFlow project with Custom Actions enabled (any paid plan or free with custom code)
  • At least one IoT device or MQTT broker to test against (HiveMQ Cloud free tier works)
  • Basic understanding of FlutterFlow's Custom Action editor and Firestore Backend Queries
  • Firebase project connected to FlutterFlow if using the Firestore relay pattern

Step-by-step guide

1

Add mqtt_client to Pubspec Dependencies

In FlutterFlow, go to Custom Code (left navigation) → Pubspec Dependencies → Add Dependency. Enter mqtt_client with version ^10.0.0. Click Save. This package handles WebSocket and TCP connections to any MQTT broker. If you plan to use Bluetooth Low Energy instead of MQTT, add flutter_blue_plus ^1.31.0 here as well. After saving, click Compile Code to verify the package resolves correctly before writing any Custom Actions.

Expected result: Pubspec compiles without errors and mqtt_client is listed in the dependencies panel.

2

Create the MQTT Connect and Subscribe Custom Action

Go to Custom Code → Custom Actions → Add Action. Name it mqttConnect. Import statements at the top: import 'package:mqtt_client/mqtt_client.dart'; import 'package:mqtt_client/mqtt_server_client.dart';. Create an MqttServerClient with your broker host and a unique clientIdentifier (use Uuid().v4() from the uuid package). Set client.port = 8883 for TLS or 1883 for plain TCP. Set client.secure = true if using TLS. Call await client.connect(username, password) inside a try/catch. On connection, subscribe to your device topic: client.subscribe('home/lights/status', MqttQos.atLeastOnce). Listen to client.updates to receive incoming messages and update App State variables (deviceOnline, brightness, temperature). Store the client instance in a global variable so other Actions can publish to it.

Expected result: The Custom Action connects to the broker and begins streaming device state updates into App State variables.

3

Build the device dashboard UI

Create a new page named DeviceDashboard. Add a ListView widget and use Generate Dynamic Children bound to an App State variable deviceList (List of JSON, each item has id, name, online, brightness). Inside each list item, add: a Container row with a green or red Circle bound conditionally to item.online, a Text widget for item.name, a Switch widget with its value bound to item.online and its On Toggle calling a Custom Action mqttPublish with topic 'home/{id}/command' and payload '{"power": true/false}', and a Slider widget (visible only when item.online is true) bound to item.brightness and On Change Committed calling mqttPublish with payload '{"brightness": sliderValue}'. Call the mqttConnect action in the Page's On Page Load action flow.

Expected result: Dashboard displays device cards with live online/offline status, functional power toggles, and brightness sliders.

4

Use Firestore as a command relay (alternative to MQTT)

If your IoT device runs a firmware that can read from Firestore (ESP32 with Firebase Arduino SDK, for example), use Firestore as the message bus. Structure: collection devices, document per device with fields: power (Boolean), brightness (Integer), lastSeen (Timestamp), online (Boolean). In FlutterFlow, add a Backend Query on the DeviceDashboard page pointing to the devices collection with a real-time listener. Use Update Document actions from Switch and Slider widgets to write new values directly to the device document. The firmware polls or listens to Firestore changes, reads the command, actuates the hardware, then writes its current state back to the same document. This requires no MQTT broker — Firebase handles all message delivery.

Expected result: Toggling the FlutterFlow Switch updates the Firestore document, and the device firmware reads the change and responds within 1-2 seconds.

5

Integrate vendor REST APIs for commercial IoT platforms

Many consumer IoT platforms (Philips Hue, TP-Link Tapo, Samsung SmartThings) expose REST APIs. In FlutterFlow, go to API Manager → Add API Group. For Philips Hue: Base URL https://api.meethue.com/bridge/{bridgeId}, header Authorization: Bearer {hue_token}. Add API Calls: GET /lights (list lights with status), PUT /lights/{id}/state with body {"on": true, "bri": 200} for control. Store the hue_token in FlutterFlow Secrets (Settings → Secrets) and reference it in the header as [hue_token]. Use Backend Queries on your dashboard page to poll the lights state every 30 seconds. For SmartThings: Base URL https://api.smartthings.com/v1, header Authorization: Bearer {st_token}, endpoints GET /devices and POST /devices/{deviceId}/commands.

Expected result: The API Group tests successfully and returns your device list with current power and brightness state.

Complete working example

mqtt_connect_action.dart
1// Custom Action: mqttConnect
2// Add to Pubspec: mqtt_client: ^10.0.0, uuid: ^4.0.0
3import 'package:mqtt_client/mqtt_client.dart';
4import 'package:mqtt_client/mqtt_server_client.dart';
5import 'package:uuid/uuid.dart';
6
7// Store client globally so mqttPublish can reuse it
8MqttServerClient? _mqttClient;
9
10Future<bool> mqttConnect(
11 String brokerHost,
12 int brokerPort,
13 String username,
14 String password,
15 String deviceTopic,
16) async {
17 final clientId = const Uuid().v4();
18 _mqttClient = MqttServerClient(brokerHost, clientId);
19 _mqttClient!.port = brokerPort;
20 _mqttClient!.secure = brokerPort == 8883;
21 _mqttClient!.keepAlivePeriod = 30;
22 _mqttClient!.onDisconnected = () {
23 // Update App State: deviceOnline = false
24 };
25
26 try {
27 await _mqttClient!.connect(username, password);
28 } catch (e) {
29 _mqttClient!.disconnect();
30 return false;
31 }
32
33 if (_mqttClient!.connectionStatus!.state !=
34 MqttConnectionState.connected) {
35 return false;
36 }
37
38 _mqttClient!.subscribe(deviceTopic, MqttQos.atLeastOnce);
39
40 _mqttClient!.updates!.listen((messages) {
41 final msg = messages[0];
42 final payload = MqttPublishPayload.bytesToStringAsString(
43 (msg.payload as MqttPublishMessage).payload.message,
44 );
45 // Parse payload JSON and update App State variables here
46 // e.g. FFAppState().update(() { FFAppState().deviceStatus = payload; });
47 });
48
49 return true;
50}
51
52// Custom Action: mqttPublish
53Future<void> mqttPublish(String topic, String payload) async {
54 if (_mqttClient == null ||
55 _mqttClient!.connectionStatus!.state !=
56 MqttConnectionState.connected) {
57 return;
58 }
59 final builder = MqttClientPayloadBuilder();
60 builder.addString(payload);
61 _mqttClient!.publishMessage(
62 topic,
63 MqttQos.atLeastOnce,
64 builder.payload!,
65 );
66}

Common mistakes

Why it's a problem: Sending IoT commands directly to the device IP from the FlutterFlow app

How to avoid: Use a message broker (MQTT via AWS IoT Core or HiveMQ) or a cloud relay (Firestore) that both the app and the device connect to outbound. The broker routes commands bidirectionally without requiring either side to have a public IP.

Why it's a problem: Opening a new MQTT connection on every page load or button tap

How to avoid: Connect once in the app's On App Load action or the dashboard page's On Page Load action. Store the client in a global Dart variable and reuse it in all publish actions. Reconnect only when the connection drops.

Why it's a problem: Hardcoding MQTT broker credentials in the Custom Action source code

How to avoid: Store broker username and password in Firestore (fetched at login for the authenticated user) or in FlutterFlow Secrets for development. Pass them as parameters to the mqttConnect action rather than hardcoding strings.

Best practices

  • Always use TLS (port 8883) for MQTT connections — plain TCP (1883) transmits device commands as cleartext over the network
  • Implement an exponential backoff reconnect strategy in the onDisconnected callback rather than immediately reconnecting to avoid hammering a temporarily unavailable broker
  • Use QoS level 1 (atLeastOnce) for device commands so commands survive brief disconnections — QoS 0 is fire-and-forget and will silently drop messages during reconnects
  • Debounce slider onChange events by at least 300ms before publishing to prevent flooding the broker with dozens of brightness messages per second while the user is dragging
  • Store last-known device state in Firestore so the dashboard shows the correct state immediately on app open, before the MQTT connection re-establishes
  • Add a connection timeout indicator in the UI — if the MQTT client has not connected within 10 seconds, show an error state with a retry button rather than a blank dashboard
  • For battery-powered devices, use MQTT retain flag on status topics so newly connected clients immediately receive the last known state without waiting for the next device heartbeat

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building a FlutterFlow app to control IoT devices. I want to use MQTT with the mqtt_client Flutter package. Write me two Custom Action functions: (1) mqttConnect that takes broker host, port, username, password, and a topic string, connects with TLS, subscribes to the topic, and stores the client in a global variable; (2) mqttPublish that takes a topic and JSON payload string and publishes it to the existing connection. Include proper error handling and disconnection callbacks.

FlutterFlow Prompt

Create a device dashboard page in my FlutterFlow app. The page should load device data from the App State deviceList variable (List of JSON with fields: id, name, online, brightness). Show each device as a card with a colored online/offline indicator, a Switch for power control, and a Slider for brightness (0-255). Call the mqttConnect custom action on page load.

Frequently asked questions

Can FlutterFlow connect directly to IoT devices over Bluetooth?

Yes, using a Custom Widget or Custom Action with the flutter_blue_plus package from pub.dev. Add the package in Custom Code → Pubspec Dependencies. The Custom Action calls FlutterBluePlus.startScan(), connects to a BLE device by service UUID, and reads or writes characteristics. Note that BLE requires camera/Bluetooth permissions configured in FlutterFlow's App Details settings, and testing requires a physical device — the emulator does not support Bluetooth hardware.

Which MQTT broker should I use for a FlutterFlow IoT project?

For development and small projects, HiveMQ Cloud's free tier (up to 100 connections, no credit card) is the easiest starting point. For production, AWS IoT Core offers certificate-based auth, fine-grained device policies, and integration with other AWS services. For self-hosted setups, Mosquitto on a Cloud Run or Compute Engine instance gives you full control. All three work with the mqtt_client Flutter package.

How do I show real-time device status updates in the FlutterFlow UI?

There are two approaches. With MQTT: the Custom Action listening to client.updates parses incoming JSON and calls FFAppState().update() to modify App State variables — widgets bound to those variables rebuild automatically. With Firebase: add a Backend Query to the devices collection with the real-time stream option enabled — FlutterFlow automatically refreshes the UI whenever a Firestore document changes, with no custom code needed.

Can I control IoT devices that only work on a local Wi-Fi network?

Devices on a local network are not directly reachable from a mobile app on cellular data. You have two options: (1) deploy a local MQTT broker or HTTP relay on the same network (a Raspberry Pi or home server), and have your cloud MQTT bridge route commands to it; (2) use a cloud platform like Home Assistant Cloud or SmartThings that acts as a relay between the internet and your local devices. Direct local control only works if the app and device are on the same Wi-Fi network simultaneously.

What if I need help building a complex IoT dashboard with multiple device types?

Multi-vendor IoT projects involving MQTT, BLE, and REST APIs simultaneously can become complex quickly. RapidDev's engineers have built IoT dashboards in FlutterFlow for smart home, industrial monitoring, and agricultural sensor applications. If you need a production-ready solution with offline support and device grouping, reach out for a scoping call.

How do I handle a device going offline mid-session?

Subscribe to a Last Will and Testament (LWT) message in MQTT — configure the device to set a retained message on its status topic before connecting, and have it publish an 'offline' message as the LWT. When the broker detects the device disconnect, it delivers the LWT message to all subscribers. In the FlutterFlow MQTT listener, parse the status message and update an App State boolean for that device, changing the UI indicator from green to red automatically.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.