โ˜€๏ธSiang
IoT

๐Ÿ“จ MQTT Protocol: Panduan Lengkap

Panduan lengkap protokol MQTT untuk IoT โ€” broker, Quality of Service, topic hierarchy, retain message, last will and testament, serta keamanan MQTT dengan contoh kode praktis

Artikel: Mqtt Lengkap Artikel: Mqtt Lengkap


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
RinganHeader hanya 2 byte, cocok untuk perangkat dengan resource terbatas
Low BandwidthSangat efisien di jaringan dengan bandwidth rendah seperti LoRa, NB-IoT
Bi-directionalMendukung komunikasi dua arah antara device dan server
ScalableBisa menangani jutaan koneksi perangkat secara simultan
ReliableMemiliki 3 level QoS untuk menjamin pengiriman pesan
DecoupledPublisher dan subscriber tidak perlu online bersamaan
Standar TerbukaDiatur oleh OASIS dan didukung luas di industri IoT

MQTT vs Protokol Lain

Aspek MQTT HTTP WebSocket CoAP
ModelPub/SubRequest/ResponseFull DuplexRequest/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 untukIoT, MessagingWeb APIReal-time WebConstrained Devices
Diagram: Model Publish/Subscribe MQTT
Model Publish/Subscribe MQTT

Sensor Suhu publish โ–บ 'ruang/suhu'

Mobile App โ—„

Dashboard Web โ—„



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
PublisherMengirim pesan ke broker pada topik tertentuESP32, sensor, Raspberry Pi
BrokerMenerima pesan dan mendistribusikannya ke subscriberMosquitto, HiveMQ, EMQX
SubscriberMenerima pesan dari broker berdasarkan topik yang di-subscribeMobile 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).

Diagram: MQTT Packet Structure

FIXED HEADER (2+ bytes) Byte 1 Byte 2-5 Packet ...

VARIABLE HEADER (0+ bytes) Tergantung tipe pack...

PAYLOAD (0+ bytes) Data aktual: sensor reading,...

Byte 1 Byte 2-5 Packet Type Remaining Length (4...

MQTT Packet Types

Tipe Direction Fungsi
CONNECTClient โ†’ BrokerPermintaan koneksi baru
CONNACKBroker โ†’ ClientKonfirmasi koneksi
PUBLISHDua arahMengirim pesan
PUBACKDua arahKonfirmasi QoS 1
PUBREC/PUBREL/PUBCOMPDua arahHandshake QoS 2
SUBSCRIBEClient โ†’ BrokerLangganan topik
SUBACKBroker โ†’ ClientKonfirmasi subscribe
UNSUBSCRIBEClient โ†’ BrokerBerhenti langganan
PINGREQ/PINGRESPDua arahHeartbeat / keep-alive
DISCONNECTClient โ†’ BrokerPutus 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
MosquittoOpen Sourceโœ…Ringan, mudah setup, populerPrototyping, home IoT
EMQXOpen Source + Cloudโœ… (Community)Skalabilitas tinggi, clusteringEnterprise, industri
HiveMQCommercialโœ… (CE)Enterprise grade, MQTT 5.0Enterprise
VerneMQOpen Sourceโœ…Distributed, Erlang-basedHigh availability
AWS IoT CoreCloud Managed๐Ÿ’ณ Pay-as-you-goFully managed, integrasi AWSCloud-native IoT
HiveMQ CloudCloud Managedโœ… (Free tier)Serverless, MQTT 5.0Quick 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
DeliveryAt most onceAt least onceExactly once
Pesan Hilang?โš ๏ธ MungkinโŒ TidakโŒ Tidak
Pesan Duplikat?โŒ Tidakโš ๏ธ MungkinโŒ Tidak
Round Trip124
Bandwidth๐ŸŸข Paling hemat๐ŸŸก Sedang๐Ÿ”ด Paling boros
Latency๐ŸŸข Terendah๐ŸŸก Sedang๐Ÿ”ด Tertinggi
Cocok untukSensor periodikNotifikasi, alarmTransaksi keuangan

Pemilihan QoS yang Tepat

Contoh โ€” QoS Usage
# 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

Python โ€” QoS Example
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.

Bash โ€” Retain Message
# 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

Diagram: RETAIN MESSAGE FLOW

Publish suhu=25.5 (retain)

Simpan retained message

Subscribe sensor/suhu

Kirim retained: suhu=25.5

Sudah subscribe

Publish baru: suhu=26.0

Kirim retained baru: suhu=26.0

๐ŸŒก๏ธ Sensor

๐Ÿ“ก Broker

๐Ÿ“ฑ App Baru

๐Ÿ“ฑ App Lama

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.

Python โ€” Last Will and Testament
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 connectPublish manual"online" dengan retain
Device heartbeatPublish 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

Python โ€” Connection 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

Diagram: Session Behavior

Ya

Tidak

๐Ÿ”Œ Client Koneksi ke Broker

Clean Session?

๐Ÿงน Clean Session = True

๐Ÿ’พ Persistent Session = False

โŒ Hapus semua langganan & undelivered messages

โœ… Simpan langganan & QoS 1-2 messages

๐Ÿ“ก Mulai Session Baru



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
TransportTLS/SSLEnkripsi data dalam transit, mencegah eavesdropping
AuthenticationUsername/Password, Client CertificateVerifikasi identitas client
AuthorizationACL (Access Control List)Kontrol siapa bisa publish/subscribe ke topik mana
ApplicationPayload EncryptionEnkripsi data di level aplikasi (end-to-end)

TLS/SSL Configuration

Config โ€” TLS Mosquitto
# 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)

Config โ€” ACL Mosquitto
# /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

โš ๏ธ Checklist Keamanan MQTT
  1. Selalu gunakan TLS/SSL untuk koneksi di jaringan publik
  2. Jangan gunakan default credentials โ€” ganti password default broker
  3. Gunakan Client ID yang unik untuk setiap perangkat
  4. Implementasi ACL untuk membatasi akses per topik
  5. Rotasi password/certificate secara berkala
  6. Monitor log broker untuk aktivitas mencurigakan
  7. Rate limiting untuk mencegah DDoS melalui broker
  8. 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

Arduino โ€” ESP32 MQTT Client
#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
            }
        }
    }
}
๐Ÿ’ก Tips

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 logisgedung/lantai/ruang/sensorsensor_data_room1_temp
Hindari leading slashdevice/sensor01/device/sensor01
Gunakan lowercasesensor/suhuSensor/Suhu
Tidak ada spasidata/suhudata / suhu
KonsistenSemua sensor sama formatFormat beda-beda

Payload Design

JSON โ€” Payload Standar
// โœ… 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

Python โ€” Robust MQTT Client
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 refusedBroker offline / port salahCek broker: telnet broker 1883
Auth failedUsername/password salahCek credential, cek ACL
Client ID conflictDua device pakai ID samaGunakan ID unik per device
Pesan tidak diterimaTopic salah / tidak subscribeCek exact match topic (case-sensitive)
Retain tidak bekerjaTidak pakai flag retainPastikan publish dengan retain=True
Koneksi putus-putusKeepalive terlalu pendekTambah keepalive, cek jaringan
QoS downgradeBroker tidak support QoSCek broker capability, gunakan QoS lebih rendah
Bash โ€” Debugging MQTT
# 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:

Pertanyaan 1: Berapa ukuran minimal header MQTT packet?

a) 1 byte
b) 2 byte
c) 4 byte
d) 8 byte

Pertanyaan 2: QoS level berapa yang menjamin pesan diterima tepat sekali (exactly once)?

a) QoS 0
b) QoS 1
c) QoS 2
d) Semua QoS menjamin exactly once

Pertanyaan 3: Apa fungsi dari Last Will and Testament (LWT) di MQTT?

a) Mengirim data sensor secara periodik
b) Mengenkripsi pesan MQTT
c) Mengirim pesan otomatis saat client terputus tak terduga
d) Menyimpan semua pesan yang pernah dikirim

Pertanyaan 4: Apa wildcard yang digunakan untuk menangkap semua level topik di bawahnya?

a) *
b) +
c) #
d) ?

Pertanyaan 5: Apa yang terjadi jika subscriber baru subscribe ke topik yang punya retained message?

a) Tidak menerima apa-apa
b) Menerima retained message langsung dari broker
c) Menerima semua pesan yang pernah dikirim ke topik tersebut
d) Error karena topik sudah digunakan
๐Ÿ” Zoom
100%
๐ŸŽจ Tema