1. Pengenalan MQTT
MQTT (Message Queuing Telemetry Transport) adalah protokol komunikasi ringan yang dirancang khusus untuk perangkat IoT dan jaringan dengan bandwidth terbatas. Protokol ini pertama kali dikembangkan oleh Andy Stanford-Clark (IBM) dan Arlen Nipper pada tahun 1999 untuk memantau jalur pipa minyak melalui jaringan satelit.
MQTT menggunakan model publish/subscribe (pub/sub) di mana pengirim pesan (publisher) dan penerima pesan (subscriber) tidak perlu saling mengenal secara langsung. Komunikasi dimediasi oleh sebuah broker yang bertugas meneruskan pesan dari publisher ke subscriber yang relevan.
Mengapa MQTT Penting untuk IoT?
| Keunggulan | Penjelasan |
|---|---|
| Ringan | Header hanya 2 byte, cocok untuk perangkat dengan resource terbatas |
| Low Bandwidth | Sangat efisien di jaringan dengan bandwidth rendah seperti LoRa, NB-IoT |
| Bi-directional | Mendukung komunikasi dua arah antara device dan server |
| Scalable | Bisa menangani jutaan koneksi perangkat secara simultan |
| Reliable | Memiliki 3 level QoS untuk menjamin pengiriman pesan |
| Decoupled | Publisher dan subscriber tidak perlu online bersamaan |
| Standar Terbuka | Diatur oleh OASIS dan didukung luas di industri IoT |
MQTT vs Protokol Lain
| Aspek | MQTT | HTTP | WebSocket | CoAP |
|---|---|---|---|---|
| Model | Pub/Sub | Request/Response | Full Duplex | Request/Response |
| Header Size | ๐ข 2 byte | ๐ด Besar | ๐ก Sedang | ๐ข 4 byte |
| Persistent Connection | โ Ya | โ Tidak | โ Ya | โ Opsional |
| QoS | โ 3 Level | โ Tidak ada | โ Tidak ada | โ Konfirmasi |
| Bidirectional | โ Ya | โ Satu arah | โ Ya | โ Satu arah |
| Cocok untuk | IoT, Messaging | Web API | Real-time Web | Constrained Devices |
2. Arsitektur dan Komponen MQTT
Sistem MQTT terdiri dari tiga komponen utama yang saling berinteraksi. Memahami arsitektur ini sangat penting sebelum mulai mengimplementasikan MQTT di proyek IoT Anda.
Tiga Komponen Utama
| Komponen | Fungsi | Contoh |
|---|---|---|
| Publisher | Mengirim pesan ke broker pada topik tertentu | ESP32, sensor, Raspberry Pi |
| Broker | Menerima pesan dan mendistribusikannya ke subscriber | Mosquitto, HiveMQ, EMQX |
| Subscriber | Menerima pesan dari broker berdasarkan topik yang di-subscribe | Mobile app, dashboard, server |
Packet Structure MQTT
Setiap pesan MQTT terdiri dari fixed header (minimal 2 byte), variable header (tergantung tipe pesan), dan payload (data aktual).
MQTT Packet Types
| Tipe | Direction | Fungsi |
|---|---|---|
| CONNECT | Client โ Broker | Permintaan koneksi baru |
| CONNACK | Broker โ Client | Konfirmasi koneksi |
| PUBLISH | Dua arah | Mengirim pesan |
| PUBACK | Dua arah | Konfirmasi QoS 1 |
| PUBREC/PUBREL/PUBCOMP | Dua arah | Handshake QoS 2 |
| SUBSCRIBE | Client โ Broker | Langganan topik |
| SUBACK | Broker โ Client | Konfirmasi subscribe |
| UNSUBSCRIBE | Client โ Broker | Berhenti langganan |
| PINGREQ/PINGRESP | Dua arah | Heartbeat / keep-alive |
| DISCONNECT | Client โ Broker | Putus koneksi secara graceful |
3. MQTT Broker
Broker adalah jantung dari sistem MQTT. Broker bertanggung jawab menerima semua pesan dari publisher, memfilter pesan berdasarkan topik, dan mendistribusikannya ke subscriber yang sesuai. Pemilihan broker yang tepat sangat mempengaruhi performa sistem IoT Anda.
Perbandingan MQTT Broker Populer
| Broker | Tipe | Gratis? | Fitur Utama | Cocok Untuk |
|---|---|---|---|---|
| Mosquitto | Open Source | โ | Ringan, mudah setup, populer | Prototyping, home IoT |
| EMQX | Open Source + Cloud | โ (Community) | Skalabilitas tinggi, clustering | Enterprise, industri |
| HiveMQ | Commercial | โ (CE) | Enterprise grade, MQTT 5.0 | Enterprise |
| VerneMQ | Open Source | โ | Distributed, Erlang-based | High availability |
| AWS IoT Core | Cloud Managed | ๐ณ Pay-as-you-go | Fully managed, integrasi AWS | Cloud-native IoT |
| HiveMQ Cloud | Cloud Managed | โ (Free tier) | Serverless, MQTT 5.0 | Quick start |
Instalasi Mosquitto Broker
Mosquitto adalah broker MQTT open source yang paling populer dan cocok untuk memulai belajar.
flowchart TD
subgraph qos0["QoS 0: At Most Once"]
A0["Publisher"] -->|"Fire & Forget"| B0["Broker"]
B0 -->|"No Ack"| C0["Subscriber"]
end
subgraph qos1["QoS 1: At Least Once"]
A1["Publisher"] -->|"Publish"| B1["Broker"]
B1 -->|"Deliver"| C1["Subscriber"]
C1 -->|"PUBACK โ
"| B1
end
subgraph qos2["QoS 2: Exactly Once"]
A2["Publisher"] -->|"PUBREL"| B2["Broker"]
B2 -->|"PUBREC"| C2["Subscriber"]
C2 -->|"PUBCOMP โ
"| B2
end
style qos0 fill:#0f2a1f,stroke:#3ecf8e
style qos1 fill:#0f1d3a,stroke:#60a5fa
style qos2 fill:#2a1f0a,stroke:#f59e0b
Perbandingan Detail QoS
| Aspek | QoS 0 | QoS 1 | QoS 2 |
|---|---|---|---|
| Delivery | At most once | At least once | Exactly once |
| Pesan Hilang? | โ ๏ธ Mungkin | โ Tidak | โ Tidak |
| Pesan Duplikat? | โ Tidak | โ ๏ธ Mungkin | โ Tidak |
| Round Trip | 1 | 2 | 4 |
| Bandwidth | ๐ข Paling hemat | ๐ก Sedang | ๐ด Paling boros |
| Latency | ๐ข Terendah | ๐ก Sedang | ๐ด Tertinggi |
| Cocok untuk | Sensor periodik | Notifikasi, alarm | Transaksi keuangan |
Pemilihan QoS yang Tepat
# QoS 0 โ Data sensor periodik (hilang sesekali tidak masalah)
# Contoh: pembacaan suhu setiap 5 detik
mosquitto_pub -t "sensor/suhu" -m "25.5" -q 0
# QoS 1 โ Notifikasi alarm (harus sampai, duplikat tidak masalah)
# Contoh: notifikasi kebakaran
mosquitto_pub -t "alarm/kebakaran" -m "LANTAI3_API" -q 1
# QoS 2 โ Data kritis (harus tepat sekali)
# Contoh: pembayaran atau perintah aktuator kritis
mosquitto_pub -t "cmd/pembayaran" -m '{"amount":100000}' -q 2
# Penting: QoS di sisi publisher dan subscriber BISA BERBEDA
# Broker mengirim dengan QoS MINIMUM dari keduanya
#
# Publisher QoS 2 + Subscriber QoS 1 โ Broker mengirim QoS 1
# Publisher QoS 1 + Subscriber QoS 2 โ Broker mengirim QoS 1
# Publisher QoS 1 + Subscriber QoS 1 โ Broker mengirim QoS 1
QoS di Python dengan paho-mqtt
import paho.mqtt.client as mqtt
import json
import time
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Terhubung ke broker MQTT")
# Subscribe dengan QoS berbeda
client.subscribe("sensor/suhu", qos=0) # QoS 0
client.subscribe("alarm/#", qos=1) # QoS 1
client.subscribe("cmd/kritis", qos=2) # QoS 2
else:
print(f"Gagal koneksi, kode: {rc}")
def on_message(client, userdata, msg):
print(f"[QoS {msg.qos}] {msg.topic}: {msg.payload.decode()}")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.hivemq.com", 1883, 60)
# Publish dengan QoS yang sesuai
client.publish("sensor/suhu", "25.5", qos=0) # Data sensor
client.publish("alarm/kebakaran", "API!", qos=1) # Alarm
client.publish("cmd/kritis", json.dumps({
"action": "emergency_stop",
"device": "conveyor_01"
}), qos=2) # Perintah kritis
client.loop_forever()
6. Retain Message dan Last Will
Dua fitur penting MQTT yang sering dilupakan pemula adalah Retain Message dan Last Will and Testament (LWT). Keduanya sangat berguna untuk membangun sistem IoT yang robust.
Retain Message
Retain message adalah pesan yang disimpan oleh broker dan dikirimkan ke subscriber baru yang pertama kali subscribe ke topik tersebut. Tanpa retain, subscriber baru harus menunggu publish berikutnya untuk mendapatkan data.
# Publish dengan retain flag (-r)
mosquitto_pub -t "sensor/suhu" -m "25.5" -r
mosquitto_pub -t "sensor/lembab" -m "65" -r
mosquitto_pub -t "device/status" -m "online" -r
# Subscriber yang baru bergabung langsung menerima data terakhir
mosquitto_sub -t "sensor/#" -v
# Output:
# sensor/suhu 25.5 โ diterima langsung (retain)
# sensor/lembab 65 โ diterima langsung (retain)
# device/status online โ diterima langsung (retain)
# Hapus retained message dengan payload kosong
mosquitto_pub -t "sensor/suhu" -m "" -r
# Topik "sensor/suhu" sekarang tidak punya retained message
# โ ๏ธ Setiap topik hanya punya SATU retained message
# Publish baru dengan retain akan MENGGANTIKAN retained sebelumnya
Cara Kerja Retain Message
Last Will and Testament (LWT)
LWT adalah pesan "wasiat" yang dikirim broker secara otomatis ketika client terputus secara tidak terduga (abnormal disconnect). Ini sangat berguna untuk memantau status perangkat IoT.
import paho.mqtt.client as mqtt
client = mqtt.Client(client_id="sensor_gedung1_lantai1")
# Set Last Will sebelum connect
client.will_set(
topic="device/sensor_gedung1_lantai1/status",
payload="offline",
qos=1,
retain=True # Simpan sebagai retained message
)
def on_connect(client, userdata, flags, rc):
print("Terhubung!")
# Publish status online setelah connect
client.publish(
"device/sensor_gedung1_lantai1/status",
"online",
qos=1,
retain=True
)
def on_disconnect(client, userdata, rc):
if rc != 0:
print("Koneksi terputus secara tidak terduga!")
# Broker akan otomatis publish LWT "offline"
client.on_connect = on_connect
client.on_disconnect = on_disconnect
# Last Will + Retain = Sistem monitoring yang robust!
# Ketika device mati:
# 1. Broker mendeteksi koneksi terputus
# 2. Broker publish LWT "offline" ke topic status
# 3. Semua subscriber langsung tahu device offline
# 4. Subscriber baru yang subscribe juga langsung tahu
client.connect("broker.hivemq.com", 1883, keepalive=60)
client.loop_forever()
Skema LWT + Retain yang Ideal
| Kondisi | Aksi | Pesan |
|---|---|---|
| Device connect | Publish manual | "online" dengan retain |
| Device heartbeat | Publish periodik | "alive" setiap 30 detik |
| Device disconnect (graceful) | Publish manual | "offline" dengan retain |
| Device disconnect (crash) | LWT (otomatis) | "offline" dengan retain |
7. Koneksi dan Session
Memahami mekanisme koneksi dan session di MQTT penting untuk membangun sistem IoT yang reliable, terutama di lingkungan dengan koneksi jaringan yang tidak stabil.
CONNECT Packet Parameters
import paho.mqtt.client as mqtt
# Parameter koneksi MQTT
client = mqtt.Client(
client_id="sensor_001", # ID unik per device
clean_session=True, # True = session baru setiap connect
protocol=mqtt.MQTTv311 # Versi protokol
)
# Clean Session = True (default)
# - Broker tidak menyimpan subscription dan QoS messages
# - Cocok untuk device yang tidak peduli pesan yang terlewat
# - Lebih hemat resource broker
# Clean Session = False
# - Broker menyimpan subscription dan pending messages
# - Saat reconnect, device langsung menerima pesan yang terlewat
# - Cocok untuk device yang HARUS menerima semua pesan
# - Membutuhkan client_id yang sama
client = mqtt.Client(
client_id="sensor_001",
clean_session=False # Persistent session
)
# Keep Alive
# Interval (detik) di mana client mengirim PINGREQ ke broker
# Jika broker tidak menerima PINGREQ dalam 1.5x keepalive,
# broker menganggap client offline dan mengirim LWT
client.connect(
host="broker.example.com",
port=1883,
keepalive=60 # Ping setiap 60 detik
)
# Username & Password
client.username_pw_set("sensor_user", "secure_password123")
# Reconnect otomatis
client.reconnect_delay_set(
min_delay=1, # Delay minimum 1 detik
max_delay=120 # Delay maksimum 120 detik
)
# Connect dengan TLS/SSL
client.tls_set(
ca_certs="ca.crt",
certfile="client.crt",
keyfile="client.key"
)
client.connect("broker.example.com", 8883, 60) # Port 8883 = MQTTS
Clean Session vs Persistent Session
8. Keamanan MQTT
Keamanan adalah aspek kritis dalam implementasi MQTT di lingkungan produksi. Tanpa keamanan yang tepat, data sensor dan perintah kontrol bisa disadap, dimanipulasi, atau diserang oleh pihak yang tidak berwenang.
Lapisan Keamanan MQTT
| Lapisan | Mekanisme | Fungsi |
|---|---|---|
| Transport | TLS/SSL | Enkripsi data dalam transit, mencegah eavesdropping |
| Authentication | Username/Password, Client Certificate | Verifikasi identitas client |
| Authorization | ACL (Access Control List) | Kontrol siapa bisa publish/subscribe ke topik mana |
| Application | Payload Encryption | Enkripsi data di level aplikasi (end-to-end) |
TLS/SSL Configuration
# Generate self-signed certificates (untuk testing)
# 1. Generate CA key dan certificate
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 365 -key ca.key -out ca.crt \
-subj "/CN=MQTT CA"
# 2. Generate server key dan CSR
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
-subj "/CN=mqtt.example.com"
# 3. Sign server certificate dengan CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 365
# 4. Generate client key dan certificate
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr \
-subj "/CN=sensor_001"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out client.crt -days 365
# Mosquitto TLS config
# /etc/mosquitto/conf.d/tls.conf
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true
use_identity_as_username true
Access Control List (ACL)
# /etc/mosquitto/acl.conf
# Admin bisa akses semua topic
user admin
topic readwrite #
# Sensor hanya bisa publish ke topic sendiri
user sensor_001
topic write device/sensor_001/#
# Dashboard bisa subscribe ke semua data sensor
user dashboard
topic read device/+/data
topic read device/+/status
# Lampu controller bisa publish dan subscribe topic lampu
user lampu_ctrl
topic readwrite lampu/#
# Anonymous access (disable untuk produksi)
# topic read $SYS/#
Security Best Practices
- Selalu gunakan TLS/SSL untuk koneksi di jaringan publik
- Jangan gunakan default credentials โ ganti password default broker
- Gunakan Client ID yang unik untuk setiap perangkat
- Implementasi ACL untuk membatasi akses per topik
- Rotasi password/certificate secara berkala
- Monitor log broker untuk aktivitas mencurigakan
- Rate limiting untuk mencegah DDoS melalui broker
- Hindari payload sensitif tanpa enkripsi tambahan
9. Contoh Praktik dengan ESP32
Mari kita implementasikan semua konsep MQTT yang sudah dipelajari dalam proyek nyata menggunakan ESP32. Kita akan membuat sistem monitoring suhu dan kelembaban dengan fitur retain, LWT, dan multiple QoS.
Sketch Arduino untuk ESP32
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
// WiFi credentials
const char* ssid = "WiFi-Rumah";
const char* password = "password123";
// MQTT Broker
const char* mqtt_server = "192.168.1.100";
const int mqtt_port = 1883;
const char* mqtt_user = "sensor_001";
const char* mqtt_pass = "secure_pass";
// Topics
const char* topic_suhu = "gedung1/lantai1/ruang1/suhu";
const char* topic_lembab = "gedung1/lantai1/ruang1/lembab";
const char* topic_status = "gedung1/lantai1/ruang1/status";
const char* topic_cmd_lampu = "gedung1/lantai1/ruang1/cmd/lampu";
const char* topic_cmd_ac = "gedung1/lantai1/ruang1/cmd/ac";
// DHT Sensor
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// LED dan Relay
#define LED_LAMPU 2
#define RELAY_AC 5
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastPublish = 0;
const long publishInterval = 5000; // Publish setiap 5 detik
void setup_wifi() {
delay(10);
Serial.println("Menghubungkan ke WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi terhubung!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.printf("Pesan diterima [%s]: %s\n", topic, message.c_str());
// Handle perintah lampu
if (String(topic) == topic_cmd_lampu) {
if (message == "ON") {
digitalWrite(LED_LAMPU, HIGH);
client.publish("gedung1/lantai1/ruang1/lampu/status",
"ON", true); // retain
Serial.println("Lampu: ON");
} else if (message == "OFF") {
digitalWrite(LED_LAMPU, LOW);
client.publish("gedung1/lantai1/ruang1/lampu/status",
"OFF", true); // retain
Serial.println("Lampu: OFF");
}
}
// Handle perintah AC
if (String(topic) == topic_cmd_ac) {
int targetTemp = message.toInt();
float currentTemp = dht.readTemperature();
if (!isnan(currentTemp)) {
if (currentTemp > targetTemp) {
digitalWrite(RELAY_AC, HIGH); // AC ON
client.publish("gedung1/lantai1/ruang1/ac/status",
"ON", true);
} else {
digitalWrite(RELAY_AC, LOW); // AC OFF
client.publish("gedung1/lantai1/ruang1/ac/status",
"OFF", true);
}
}
}
}
void reconnect() {
while (!client.connected()) {
Serial.print("Menghubungkan ke MQTT Broker...");
// Client ID unik + Last Will + Clean Session
if (client.connect(
"sensor_gedung1_lantai1_ruang1", // client_id
mqtt_user, // username
mqtt_pass, // password
topic_status, // will topic
1, // will QoS
true, // will retain
"offline" // will message
)) {
Serial.println(" TERHUBUNG!");
// Publish status online (retained)
client.publish(topic_status, "online", true);
// Subscribe ke perintah kontrol (QoS 1)
client.subscribe(topic_cmd_lampu, 1);
client.subscribe(topic_cmd_ac, 1);
Serial.println("Subscribe ke topik kontrol...");
} else {
Serial.printf(" GAGAL (rc=%d). Coba lagi 5 detik...\n",
client.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_LAMPU, OUTPUT);
pinMode(RELAY_AC, OUTPUT);
dht.begin();
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
if (now - lastPublish > publishInterval) {
lastPublish = now;
float suhu = dht.readTemperature();
float lembab = dht.readHumidity();
if (!isnan(suhu) && !isnan(lembab)) {
// Publish data sensor (QoS 0, retained)
char suhuStr[8], lembabStr[8];
dtostrf(suhu, 1, 2, suhuStr);
dtostrf(lembab, 1, 2, lembabStr);
client.publish(topic_suhu, suhuStr, true); // retained
client.publish(topic_lembab, lembabStr, true); // retained
Serial.printf("Published: Suhu=%sยฐC, Lembab=%s%%\n",
suhuStr, lembabStr);
// Alert jika suhu tinggi (QoS 1)
if (suhu > 35.0) {
client.publish("alarm/suhu_tinggi",
"{\"device\":\"gedung1_lantai1_ruang1\","
"\"temp\":35.5,\"threshold\":35}",
1); // QoS 1
}
}
}
}
Gunakan library PubSubClient untuk Arduino/ESP32. Ukuran payload maksimal default adalah 256 byte. Jika membutuhkan payload lebih besar, gunakan client.setBufferSize(1024) sebelum connect().
10. Best Practices MQTT
Berikut adalah best practices yang harus diikuti saat mengimplementasikan MQTT di proyek IoT Anda untuk memastikan sistem yang reliable, aman, dan scalable.
Topic Design
| Praktik | Contoh Baik | Contoh Buruk |
|---|---|---|
| Hierarki logis | gedung/lantai/ruang/sensor | sensor_data_room1_temp |
| Hindari leading slash | device/sensor01 | /device/sensor01 |
| Gunakan lowercase | sensor/suhu | Sensor/Suhu |
| Tidak ada spasi | data/suhu | data / suhu |
| Konsisten | Semua sensor sama format | Format beda-beda |
Payload Design
// โ
Payload yang BAIK โ menggunakan JSON standar
{
"device_id": "sensor_001",
"timestamp": 1719484800,
"data": {
"temperature": 25.5,
"humidity": 65.2,
"pressure": 1013.25
},
"battery": 87,
"rssi": -45,
"version": "1.0"
}
// โ Payload yang BURUK โ tidak terstruktur
// "25.5,65.2,1013.25"
// "suhu=25.5 lembab=65.2"
// "sensor 1: temp 25.5 humidity 65"
// Pertimbangkan CBOR (binary) untuk device dengan
// resource sangat terbatas โ lebih kecil dari JSON
// Standarisasi payload di seluruh sistem Anda!
// Buat schema dan dokumentasikan formatnya
Error Handling dan Reconnection
import paho.mqtt.client as mqtt
import json
import time
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("MQTT")
class RobustMQTTClient:
def __init__(self, broker, port, client_id):
self.client = mqtt.Client(client_id=client_id, clean_session=False)
self.broker = broker
self.port = port
self.connected = False
# Setup callbacks
self.client.on_connect = self._on_connect
self.client.on_disconnect = self._on_disconnect
self.client.on_message = self._on_message
# LWT
self.client.will_set(
f"device/{client_id}/status",
json.dumps({"status": "offline", "ts": int(time.time())}),
qos=1, retain=True
)
# Reconnect settings
self.client.reconnect_delay_set(min_delay=1, max_delay=60)
def _on_connect(self, client, userdata, flags, rc):
if rc == 0:
self.connected = True
logger.info("Terhubung ke broker MQTT")
# Publish online
self.client.publish(
f"device/{self.client._client_id.decode()}/status",
json.dumps({"status": "online", "ts": int(time.time())}),
qos=1, retain=True
)
else:
logger.error(f"Gagal koneksi: rc={rc}")
def _on_disconnect(self, client, userdata, rc):
self.connected = False
if rc != 0:
logger.warning(f"Terputus tak terduga (rc={rc}), reconnecting...")
def _on_message(self, client, userdata, msg):
try:
payload = json.loads(msg.payload.decode())
logger.info(f"[{msg.topic}] {payload}")
except json.JSONDecodeError:
logger.warning(f"Invalid JSON: {msg.payload}")
def connect(self):
self.client.connect(self.broker, self.port, keepalive=60)
self.client.loop_start()
def publish(self, topic, data, qos=0):
if self.connected:
payload = json.dumps(data)
result = self.client.publish(topic, payload, qos=qos)
return result.rc == mqtt.MQTT_ERR_SUCCESS
return False
# Penggunaan
client = RobustMQTTClient("broker.example.com", 1883, "sensor_001")
client.connect()
client.publish("sensor/suhu", {"value": 25.5, "unit": "celsius"}, qos=1)
11. Troubleshooting
Berikut masalah umum yang sering dihadapi saat bekerja dengan MQTT beserta solusinya.
Masalah Umum dan Solusi
| Masalah | Penyebab | Solusi |
|---|---|---|
| Connection refused | Broker offline / port salah | Cek broker: telnet broker 1883 |
| Auth failed | Username/password salah | Cek credential, cek ACL |
| Client ID conflict | Dua device pakai ID sama | Gunakan ID unik per device |
| Pesan tidak diterima | Topic salah / tidak subscribe | Cek exact match topic (case-sensitive) |
| Retain tidak bekerja | Tidak pakai flag retain | Pastikan publish dengan retain=True |
| Koneksi putus-putus | Keepalive terlalu pendek | Tambah keepalive, cek jaringan |
| QoS downgrade | Broker tidak support QoS | Cek broker capability, gunakan QoS lebih rendah |
# Test koneksi ke broker
telnet broker.example.com 1883
# Test dengan verbose output (-d = debug)
mosquitto_sub -h broker.example.com -t "test/#" -d -v
# Monitor semua pesan di broker (dengan auth)
mosquitto_sub -h localhost -t "#" -u admin -P password -v
# Test retain message
mosquitto_pub -t "test/retain" -m "hello" -r
mosquitto_sub -t "test/retain" # Langsung menerima "hello"
mosquitto_pub -t "test/retain" -m "" -r # Hapus retain
# Cek broker log
sudo tail -f /var/log/mosquitto/mosquitto.log
# Test TLS connection
mosquitto_sub -h broker.example.com -p 8883 \
--cafile ca.crt --cert client.crt --key client.key \
-t "test/#" -d
12. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang MQTT: