Blog Archive

Arduino Indonesia. Gambar tema oleh Storman. Diberdayakan oleh Blogger.

Supported by Electronics 3 in 1

1. Jasa pencetakan PCB single layer dengan harga paling murah.

(Metode Pembuatan dengan Transfer Toner)
>PCB design sendiri (siap cetak) : Rp.150,-/Cm2
>PCB design dari kami : Rp.250,-/Cm2

(Metode Sablon Full Masking dan Silk Screen minimal pemesanan 100 Pcs)
>PCB design sendiri (siap cetak) : Rp.200,-/Cm2
>PCB design dari kami : Rp.250,-/Cm2

2. Jasa perancangan, perakitan, dan pembuatan trainer pembelajaran elektronika untuk SMK dan Mahasiswa.

3. Jasa perancangan, perakitan, dan pembuatan berbagai macam kontroller, sensor, aktuator, dan tranduser.
>Design Rangkaian / Sistem Elektronika
>Design Rangkaian / Sistem Instrumentasi
>Design Rangkaian / Sistem Kendali
>Kerjasama Riset (data atau peralatan)
>Kerjasama Produksi Produk-Produk KIT Elektronika
>Produksi Instrumentasi Elektronika

4. Jasa Pembuatan Proyek, Tugas Akhir, Tugas Laboratorium, PKM, Karya Ilmiah, SKRIPSI, dll

Like My Facebook

Popular Posts

Selasa, 13 Januari 2026

Panduan Lengkap MicroPython ESP32/ESP8266 - MQTT untuk Pemula

Pada artikel ini, Arduino Indonesia akan mebahas tentang cara menggunakan MQTT untuk bertukar data antara dua papan ESP32/ESP8266 menggunakan firmware MicroPython. Sebagai contoh, kami akan bertukar pesan teks sederhana antara dua papan ESP. Tujuannya adalah menggunakan konsep yang dipelajari di sini untuk bertukar pembacaan sensor atau perintah.

MQTT Broker

Untuk menggunakan MQTT, Anda memerlukan broker. Kami akan menggunakan broker Mosquitto yang terinstal di Raspberry Pi. 

Komponen yang Diperlukan

Untuk tutorial ini, Anda memerlukan dua papan ESP32 atau dua ESP8266:

- 2x papan ESP32 DEVKIT DOIT

- (Alternatif) 2x ESP8266-12E NodeMCU Kit

Anda juga memerlukan Raspberry Pi dan aksesori berikut:

- Papan Raspberry Pi

- Kartu MicroSD – 32GB Class10

- Catu Daya Raspberry Pi (5V 2.5A)

 

Baca juga: Panduan Lengkap Install Firmware MicroPython ESP32 & ESP8266 Menggunakan esptool.py

Gambaran Proyek

Berikut adalah gambaran umum dari proyek yang akan kami bangun:

- ESP#1 memublikasikan pesan pada topik hello. Ia memublikasikan pesan "Hello" diikuti dengan penghitung (Hello 1, Hello 2, Hello 3, …). Pesan baru dipublikasikan setiap 5 detik.

- ESP#1 berlangganan (*subscribe*) ke topik notification untuk menerima pemberitahuan dari papan ESP#2.

- ESP#2 berlangganan ke topik hello. Karena ESP#1 memublikasikan ke topik ini, ESP#2 menerima pesan dari ESP#1.

- Saat ESP#2 menerima pesan, ia mengirimkan pesan 'received'. Pesan ini dipublikasikan pada topik notification. ESP#1 berlangganan ke topik tersebut, sehingga ia menerima pesan tersebut.

Mempersiapkan ESP#1

Mari kita mulai dengan menyiapkan ESP#1:

- Berlangganan ke topik notification

- Memublikasikan ke topik hello

Mengimpor Library umqttsimple

Untuk menggunakan MQTT dengan ESP32/ESP8266 dan MicroPython, Anda perlu menginstal library umqttsimple.

1. Buat file baru dengan menekan tombol New File.

2. Salin kode library umqttsimple ke dalamnya. Anda dapat mengakses kode library umqttsimple di tautan berikut:

 

try:

    import usocket as socket

except:

    import socket

import ustruct as struct

from ubinascii import hexlify


class MQTTException(Exception):

    pass


class MQTTClient:


    def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,

                 ssl=False, ssl_params={}):

        if port == 0:

            port = 8883 if ssl else 1883

        self.client_id = client_id

        self.sock = None

        self.server = server

        self.port = port

        self.ssl = ssl

        self.ssl_params = ssl_params

        self.pid = 0

        self.cb = None

        self.user = user

        self.pswd = password

        self.keepalive = keepalive

        self.lw_topic = None

        self.lw_msg = None

        self.lw_qos = 0

        self.lw_retain = False


    def _send_str(self, s):

        self.sock.write(struct.pack("!H", len(s)))

        self.sock.write(s)


    def _recv_len(self):

        n = 0

        sh = 0

        while 1:

            b = self.sock.read(1)[0]

            n |= (b & 0x7f) << sh

            if not b & 0x80:

                return n

            sh += 7


    def set_callback(self, f):

        self.cb = f


    def set_last_will(self, topic, msg, retain=False, qos=0):

        assert 0 <= qos <= 2

        assert topic

        self.lw_topic = topic

        self.lw_msg = msg

        self.lw_qos = qos

        self.lw_retain = retain


    def connect(self, clean_session=True):

        self.sock = socket.socket()

        addr = socket.getaddrinfo(self.server, self.port)[0][-1]

        self.sock.connect(addr)

        if self.ssl:

            import ussl

            self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)

        premsg = bytearray(b"\x10\0\0\0\0\0")

        msg = bytearray(b"\x04MQTT\x04\x02\0\0")


        sz = 10 + 2 + len(self.client_id)

        msg[6] = clean_session << 1

        if self.user is not None:

            sz += 2 + len(self.user) + 2 + len(self.pswd)

            msg[6] |= 0xC0

        if self.keepalive:

            assert self.keepalive < 65536

            msg[7] |= self.keepalive >> 8

            msg[8] |= self.keepalive & 0x00FF

        if self.lw_topic:

            sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)

            msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3

            msg[6] |= self.lw_retain << 5


        i = 1

        while sz > 0x7f:

            premsg[i] = (sz & 0x7f) | 0x80

            sz >>= 7

            i += 1

        premsg[i] = sz


        self.sock.write(premsg, i + 2)

        self.sock.write(msg)

        #print(hex(len(msg)), hexlify(msg, ":"))

        self._send_str(self.client_id)

        if self.lw_topic:

            self._send_str(self.lw_topic)

            self._send_str(self.lw_msg)

        if self.user is not None:

            self._send_str(self.user)

            self._send_str(self.pswd)

        resp = self.sock.read(4)

        assert resp[0] == 0x20 and resp[1] == 0x02

        if resp[3] != 0:

            raise MQTTException(resp[3])

        return resp[2] & 1


    def disconnect(self):

        self.sock.write(b"\xe0\0")

        self.sock.close()


    def ping(self):

        self.sock.write(b"\xc0\0")


    def publish(self, topic, msg, retain=False, qos=0):

        pkt = bytearray(b"\x30\0\0\0")

        pkt[0] |= qos << 1 | retain

        sz = 2 + len(topic) + len(msg)

        if qos > 0:

            sz += 2

        assert sz < 2097152

        i = 1

        while sz > 0x7f:

            pkt[i] = (sz & 0x7f) | 0x80

            sz >>= 7

            i += 1

        pkt[i] = sz

        #print(hex(len(pkt)), hexlify(pkt, ":"))

        self.sock.write(pkt, i + 1)

        self._send_str(topic)

        if qos > 0:

            self.pid += 1

            pid = self.pid

            struct.pack_into("!H", pkt, 0, pid)

            self.sock.write(pkt, 2)

        self.sock.write(msg)

        if qos == 1:

            while 1:

                op = self.wait_msg()

                if op == 0x40:

                    sz = self.sock.read(1)

                    assert sz == b"\x02"

                    rcv_pid = self.sock.read(2)

                    rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]

                    if pid == rcv_pid:

                        return

        elif qos == 2:

            assert 0


    def subscribe(self, topic, qos=0):

        assert self.cb is not None, "Subscribe callback is not set"

        pkt = bytearray(b"\x82\0\0\0")

        self.pid += 1

        struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)

        #print(hex(len(pkt)), hexlify(pkt, ":"))

        self.sock.write(pkt)

        self._send_str(topic)

        self.sock.write(qos.to_bytes(1, "little"))

        while 1:

            op = self.wait_msg()

            if op == 0x90:

                resp = self.sock.read(4)

                #print(resp)

                assert resp[1] == pkt[2] and resp[2] == pkt[3]

                if resp[3] == 0x80:

                    raise MQTTException(resp[3])

                return


    # Wait for a single incoming MQTT message and process it.

    # Subscribed messages are delivered to a callback previously

    # set by .set_callback() method. Other (internal) MQTT

    # messages processed internally.

    def wait_msg(self):

        res = self.sock.read(1)

        self.sock.setblocking(True)

        if res is None:

            return None

        if res == b"":

            raise OSError(-1)

        if res == b"\xd0":  # PINGRESP

            sz = self.sock.read(1)[0]

            assert sz == 0

            return None

        op = res[0]

        if op & 0xf0 != 0x30:

            return op

        sz = self._recv_len()

        topic_len = self.sock.read(2)

        topic_len = (topic_len[0] << 8) | topic_len[1]

        topic = self.sock.read(topic_len)

        sz -= topic_len + 2

        if op & 6:

            pid = self.sock.read(2)

            pid = pid[0] << 8 | pid[1]

            sz -= 2

        msg = self.sock.read(sz)

        self.cb(topic, msg)

        if op & 6 == 2:

            pkt = bytearray(b"\x40\x02\0\0")

            struct.pack_into("!H", pkt, 2, pid)

            self.sock.write(pkt)

        elif op & 6 == 4:

            assert 0


    # Checks whether a pending message from server is available.

    # If not, returns immediately with None. Otherwise, does

    # the same processing as wait_msg.

    def check_msg(self):

        self.sock.setblocking(False)

        return self.wait_msg()

 

3. Simpan file dengan menekan tombol Save.

4. Beri nama file baru tersebut "umqttsimple.py" lalu tekan OK.

5. Klik tombol Download and Run.

6. File akan tersimpan di folder perangkat dengan nama "umqttsimple.py", seperti yang ditunjukkan pada gambar di bawah.


Sekarang, Anda dapat menggunakan fungsionalitas library dalam kode dengan mengimpor library tersebut.

boot.py

Buka file boot.py dan salin kode berikut ke ESP#1.

 

import time

from umqttsimple import MQTTClient

import ubinascii

import machine

import micropython

import network

import esp

esp.osdebug(None)

import gc

gc.collect()


ssid = 'REPLACE_WITH_YOUR_SSID'

password = 'REPLACE_WITH_YOUR_PASSWORD'

mqtt_server = 'REPLACE_WITH_YOUR_MQTT_BROKER_IP'

mqtt_user = 'REPLACE_WITH_YOUR_MQTT_USERNAME'

mqtt_pass = 'REPLACE_WITH_YOUR_MQTT_PASSWORD'


#EXAMPLE IP ADDRESS

#mqtt_server = '192.168.1.144'

client_id = ubinascii.hexlify(machine.unique_id())

topic_sub = b'notification'

topic_pub = b'hello'


last_message = 0

message_interval = 5

counter = 0


station = network.WLAN(network.STA_IF)


station.active(True)

station.connect(ssid, password)


while station.isconnected() == False:

  pass


print('Connection successful')

print(station.ifconfig()

)

 

Penjelasan Kode

Anda perlu mengimpor semua library berikut:

 

import time

from umqttsimple import MQTTClient

import ubinascii

import machine

import micropython

import network

import esp

Atur `debug` ke `None` dan aktifkan *garbage collector*.

esp.osdebug(None)

import gc

gc.collect()

 

Pada variabel berikut, Anda perlu memasukkan kredensial jaringan Anda, alamat IP broker, serta nama pengguna dan kata sandi broker.

 

ssid = 'REPLACE_WITH_YOUR_SSID'

password = 'REPLACE_WITH_YOUR_PASSWORD'

mqtt_server = 'REPLACE_WITH_YOUR_MQTT_BROKER_IP'

mqtt_user = 'REPLACE_WITH_YOUR_MQTT_USERNAME'

mqtt_pass = 'REPLACE_WITH_YOUR_MQTT_PASSWORD'

 

Misalnya, alamat IP broker kami adalah: 192.168.1.144.

Catatan: Baca tutorial ini untuk melihat cara mendapatkan alamat IP broker Anda.

Untuk membuat klien MQTT, kita perlu mendapatkan ID unik ESP. Itulah yang kami lakukan pada baris berikut (disimpan dalam variabel client_id).

 

client_id = ubinascii.hexlify(machine.unique_id())

 

Selanjutnya, tentukan topik yang di-subscribe oleh ESP#1, dan topik tempat ia akan memublikasikan pesan:

 

topic_sub = b'notification'

topic_pub = b'hello'

 

Kemudian, buat variabel berikut:

 

last_message = 0

message_interval = 5

counter = 0

 

Variabel last_message akan menyimpan waktu terakhir pesan dikirim. message_interval adalah jeda waktu antara setiap pesan yang dikirim. Di sini, kami mengaturnya menjadi 5 detik (artinya pesan baru akan dikirim setiap 5 detik). Variabel counter hanyalah sebuah penghitung yang akan ditambahkan ke dalam pesan.

 

Setelah itu, kami membuat prosedur untuk terhubung ke jaringan.

 

station = network.WLAN(network.STA_IF)


station.active(True)

station.connect(ssid, password)


while station.isconnected() == False:

  pass


print('Connection successful')

print(station.ifconfig())

 

main.py

Di file main.py inilah kami akan menulis kode untuk memublikasikan dan menerima pesan. Salin kode berikut ke file main.py Anda.

 

def sub_cb(topic, msg):

  print((topic, msg))

  if topic == b'notification' and msg == b'received':

    print('ESP received hello message')


def connect_and_subscribe():

  global client_id, mqtt_server, topic_sub

  client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_pass)

  client.set_callback(sub_cb)

  client.connect()

  client.subscribe(topic_sub)

  print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub))

  return client


def restart_and_reconnect():

  print('Failed to connect to MQTT broker. Reconnecting...')

  time.sleep(10)

  machine.reset()


try:

  client = connect_and_subscribe()

except OSError as e:

  restart_and_reconnect()


while True:

  try:

    client.check_msg()

    if (time.time() - last_message) > message_interval:

      msg = b'Hello #%d' % counter

      client.publish(topic_pub, msg)

      last_message = time.time()

      counter += 1

  except OSError as e:

    restart_and_reconnect(

)

 

Penjelasan Kode

Hal pertama yang harus dilakukan adalah membuat fungsi callback yang akan dijalankan setiap kali pesan dipublikasikan pada topik yang di-subscribe oleh ESP.

Fungsi Callback

Fungsi callback harus menerima topik dan pesan sebagai parameter.

 

def sub_cb(topic, msg):

  print((topic, msg))

  if topic == b'notification' and msg == b'received':

    print('ESP received hello message')

 

Dalam fungsi callback kami, kami mulai dengan mencetak topik dan pesan. Kemudian, kami memeriksa apakah pesan dipublikasikan pada topik notification, dan apakah isi pesannya adalah 'received'. Jika pernyataan `if` ini benar, itu berarti ESP#2 menerima pesan 'hello' yang dikirim oleh ESP#1.

 

Intinya, fungsi callback ini menangani apa yang terjadi ketika pesan tertentu diterima pada topik tertentu. 

Hubungkan dan Subscribe

Selanjutnya, kami memiliki fungsi connect_and_subscribe(). Fungsi ini bertanggung jawab untuk terhubung ke broker sekaligus subscribe ke sebuah topik.

 

def connect_and_subscribe():

 

Mulailah dengan mendeklarasikan variabel client_id, mqtt_server, dan topic_sub sebagai variabel global. Dengan cara ini, kita dapat mengakses variabel-variabel ini di seluruh kode.

 

global client_id, mqtt_server, topic_sub

 

Kemudian, buat objek MQTTClient bernama client. Kita perlu memberikan parameter client_id, alamat IP broker MQTT (mqtt_server), serta nama pengguna dan kata sandi broker. Variabel-variabel ini telah diatur di file boot.py.

 

client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_pass)

 

Setelah itu, atur fungsi callback ke klien (sub_cb).

 

client.set_callback(sub_cb)

 

Selanjutnya, hubungkan klien ke broker menggunakan metode connect() pada objek MQTTClient.

 

client.connect()

 

Setelah terhubung, kita subscribe ke topik topic_sub. Nilai topic_sub diatur di file boot.py (yaitunotification).

 

client.subscribe(topic_sub)

 

Terakhir, cetak pesan dan kembalikan klien:

 

print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub))

return client

 

Restart dan Sambung Ulang

Kami membuat fungsi bernama restart_and_reconnect(). Fungsi ini akan dipanggil jika ESP32 atau ESP8266 gagal terhubung ke broker.

 

Fungsi ini mencetak pesan untuk memberi tahu bahwa koneksi tidak berhasil. Kami menunggu 10 detik. Kemudian, kami me-reset ESP menggunakan metode `reset()`.

 

def restart_and_reconnect():

  print('Failed to connect to MQTT broker. Reconnecting...')

  time.sleep(10)

  machine.reset()

 

Menerima dan Memublikasikan Pesan

Hingga saat ini, kami telah membuat fungsi untuk menangani tugas-tugas terkait komunikasi MQTT. Mulai sekarang, kode akan memanggil fungsi-fungsi tersebut untuk membuat sesuatu terjadi.

 

Hal pertama yang perlu kami lakukan adalah terhubung ke broker MQTT dan subscribe ke sebuah topik. Jadi, kami membuat klien dengan memanggil fungsi connect_and_subscribe().

 

try:

  client = connect_and_subscribe()

 

Jika kami tidak dapat terhubung ke broker MQTT, kami akan me-restart ESP dengan memanggil fungsi restart_and_reconnect().

 

except OSError as e:

  restart_and_reconnect()

 

Di dalam perulangan while adalah tempat kami akan menerima dan memublikasikan pesan. Kami menggunakan pernyataan try dan except untuk mencegah ESP crash jika terjadi kesalahan.

 

Di dalam blok try, kami mulai dengan menerapkan metode check_msg() pada klien.

 

try:

  client.check_msg()

 

Metode check_msg() memeriksa apakah ada pesan tertunda dari server yang tersedia. Ia menunggu satu pesan MQTT masuk dan memprosesnya. Pesan yang di-subscribe akan dikirimkan ke fungsi callback yang telah kami definisikan sebelumnya (fungsi sub_cb()). Jika tidak ada pesan tertunda, ia akan mengembalikan None.

 

Kemudian, kami menambahkan pernyataan if untuk memeriksa apakah 5 deti (message_interval) telah berlalu sejak pesan terakhir dikirim.

 

if (time.time() - last_message) > message_interval:

 

Jika sudah waktunya mengirim pesan baru, kami membuat variabel `msg` dengan teks "Hello" diikuti oleh penghitung.

 

msg = b'Hello #%d' % counter

 

Untuk memublikasikan pesan pada topik tertentu, Anda hanya perlu menerapkan metode publish() pada klien dan memberikan topik serta pesan sebagai argumen. Variabel topic_pub telah diatur ke hello di file boot.py.

 

client.publish(topic_pub, msg)

 

Setelah mengirim pesan, kami memperbarui waktu terakhir pesan diterima dengan mengatur variabel last_message ke waktu saat ini.

 

last_message = time.time()

 

Terakhir, kami menambah variabel counter di setiap perulangan.

 

counter += 1

 

Jika terjadi sesuatu yang tidak terduga, kami memanggil fungsi restart_and_reconnect().

 

except OSError as e:

  restart_and_reconnect()

 

Selesai untuk ESP#1. Ingat bahwa Anda perlu mengunggah semua file berikut agar proyek berfungsi (unggah file secara berurutan):

1. umqttsimple.py;

2. boot.py;

3. main.py.

Setelah mengunggah semua file, Anda akan mendapatkan pesan sukses tentang: membuat koneksi jaringan, terhubung ke broker, dan subscribe ke topik.

ESP #2

Sekarang mari kita siapkan ESP#2:

- Berlangganan ke topik hello

- Memublikasikan ke topik notification

Seperti ESP#1, Anda juga perlu mengunggah file umqttsimple.py, boot.py, dan main.py.

Mengimpor umqttsimple

Untuk menggunakan MQTT dengan ESP32/ESP8266 dan MicroPython, Anda perlu menginstal library umqttsimple. Ikuti langkah-langkah yang dijelaskan sebelumnya untuk menginstal library umqttsimple di ESP#2.

Anda dapat mengakses kode library umqttsimple di tautan berikut:

 

try:

    import usocket as socket

except:

    import socket

import ustruct as struct

from ubinascii import hexlify


class MQTTException(Exception):

    pass


class MQTTClient:


    def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,

                 ssl=False, ssl_params={}):

        if port == 0:

            port = 8883 if ssl else 1883

        self.client_id = client_id

        self.sock = None

        self.server = server

        self.port = port

        self.ssl = ssl

        self.ssl_params = ssl_params

        self.pid = 0

        self.cb = None

        self.user = user

        self.pswd = password

        self.keepalive = keepalive

        self.lw_topic = None

        self.lw_msg = None

        self.lw_qos = 0

        self.lw_retain = False


    def _send_str(self, s):

        self.sock.write(struct.pack("!H", len(s)))

        self.sock.write(s)


    def _recv_len(self):

        n = 0

        sh = 0

        while 1:

            b = self.sock.read(1)[0]

            n |= (b & 0x7f) << sh

            if not b & 0x80:

                return n

            sh += 7


    def set_callback(self, f):

        self.cb = f


    def set_last_will(self, topic, msg, retain=False, qos=0):

        assert 0 <= qos <= 2

        assert topic

        self.lw_topic = topic

        self.lw_msg = msg

        self.lw_qos = qos

        self.lw_retain = retain


    def connect(self, clean_session=True):

        self.sock = socket.socket()

        addr = socket.getaddrinfo(self.server, self.port)[0][-1]

        self.sock.connect(addr)

        if self.ssl:

            import ussl

            self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)

        premsg = bytearray(b"\x10\0\0\0\0\0")

        msg = bytearray(b"\x04MQTT\x04\x02\0\0")


        sz = 10 + 2 + len(self.client_id)

        msg[6] = clean_session << 1

        if self.user is not None:

            sz += 2 + len(self.user) + 2 + len(self.pswd)

            msg[6] |= 0xC0

        if self.keepalive:

            assert self.keepalive < 65536

            msg[7] |= self.keepalive >> 8

            msg[8] |= self.keepalive & 0x00FF

        if self.lw_topic:

            sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)

            msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3

            msg[6] |= self.lw_retain << 5


        i = 1

        while sz > 0x7f:

            premsg[i] = (sz & 0x7f) | 0x80

            sz >>= 7

            i += 1

        premsg[i] = sz


        self.sock.write(premsg, i + 2)

        self.sock.write(msg)

        #print(hex(len(msg)), hexlify(msg, ":"))

        self._send_str(self.client_id)

        if self.lw_topic:

            self._send_str(self.lw_topic)

            self._send_str(self.lw_msg)

        if self.user is not None:

            self._send_str(self.user)

            self._send_str(self.pswd)

        resp = self.sock.read(4)

        assert resp[0] == 0x20 and resp[1] == 0x02

        if resp[3] != 0:

            raise MQTTException(resp[3])

        return resp[2] & 1


    def disconnect(self):

        self.sock.write(b"\xe0\0")

        self.sock.close()


    def ping(self):

        self.sock.write(b"\xc0\0")


    def publish(self, topic, msg, retain=False, qos=0):

        pkt = bytearray(b"\x30\0\0\0")

        pkt[0] |= qos << 1 | retain

        sz = 2 + len(topic) + len(msg)

        if qos > 0:

            sz += 2

        assert sz < 2097152

        i = 1

        while sz > 0x7f:

            pkt[i] = (sz & 0x7f) | 0x80

            sz >>= 7

            i += 1

        pkt[i] = sz

        #print(hex(len(pkt)), hexlify(pkt, ":"))

        self.sock.write(pkt, i + 1)

        self._send_str(topic)

        if qos > 0:

            self.pid += 1

            pid = self.pid

            struct.pack_into("!H", pkt, 0, pid)

            self.sock.write(pkt, 2)

        self.sock.write(msg)

        if qos == 1:

            while 1:

                op = self.wait_msg()

                if op == 0x40:

                    sz = self.sock.read(1)

                    assert sz == b"\x02"

                    rcv_pid = self.sock.read(2)

                    rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]

                    if pid == rcv_pid:

                        return

        elif qos == 2:

            assert 0


    def subscribe(self, topic, qos=0):

        assert self.cb is not None, "Subscribe callback is not set"

        pkt = bytearray(b"\x82\0\0\0")

        self.pid += 1

        struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)

        #print(hex(len(pkt)), hexlify(pkt, ":"))

        self.sock.write(pkt)

        self._send_str(topic)

        self.sock.write(qos.to_bytes(1, "little"))

        while 1:

            op = self.wait_msg()

            if op == 0x90:

                resp = self.sock.read(4)

                #print(resp)

                assert resp[1] == pkt[2] and resp[2] == pkt[3]

                if resp[3] == 0x80:

                    raise MQTTException(resp[3])

                return


    # Wait for a single incoming MQTT message and process it.

    # Subscribed messages are delivered to a callback previously

    # set by .set_callback() method. Other (internal) MQTT

    # messages processed internally.

    def wait_msg(self):

        res = self.sock.read(1)

        self.sock.setblocking(True)

        if res is None:

            return None

        if res == b"":

            raise OSError(-1)

        if res == b"\xd0":  # PINGRESP

            sz = self.sock.read(1)[0]

            assert sz == 0

            return None

        op = res[0]

        if op & 0xf0 != 0x30:

            return op

        sz = self._recv_len()

        topic_len = self.sock.read(2)

        topic_len = (topic_len[0] << 8) | topic_len[1]

        topic = self.sock.read(topic_len)

        sz -= topic_len + 2

        if op & 6:

            pid = self.sock.read(2)

            pid = pid[0] << 8 | pid[1]

            sz -= 2

        msg = self.sock.read(sz)

        self.cb(topic, msg)

        if op & 6 == 2:

            pkt = bytearray(b"\x40\x02\0\0")

            struct.pack_into("!H", pkt, 2, pid)

            self.sock.write(pkt)

        elif op & 6 == 4:

            assert 0


    # Checks whether a pending message from server is available.

    # If not, returns immediately with None. Otherwise, does

    # the same processing as wait_msg.

    def check_msg(self):

        self.sock.setblocking(False)

        return self.wait_msg()

boot.py

Salin kode berikut ke file boot.py ESP#2.

 

import time

from umqttsimple import MQTTClient

import ubinascii

import machine

import micropython

import network

import esp

esp.osdebug(None)

import gc

gc.collect()

ssid = 'REPLACE_WITH_YOUR_SSID'

password = 'REPLACE_WITH_YOUR_PASSWORD'

mqtt_server = 'REPLACE_WITH_YOUR_MQTT_BROKER_IP'

mqtt_user = 'REPLACE_WITH_YOUR_MQTT_USERNAME'

mqtt_pass = 'REPLACE_WITH_YOUR_MQTT_PASSWORD'

#EXAMPLE IP ADDRESS

#mqtt_server = '192.168.1.144'

client_id = ubinascii.hexlify(machine.unique_id())

topic_sub = b'hello'

topic_pub = b'notification'

station = network.WLAN(network.STA_IF)

station.active(True)

station.connect(ssid, password)

while station.isconnected() == False:

  pass

print('Connection successful')

print(station.ifconfig())


Kode ini sangat mirip dengan file boot.py sebelumnya. Anda perlu mengganti variabel berikut dengan kredensial jaringan Anda, alamat IP broker, serta nama pengguna dan kata sandi broker.

 

ssid = 'REPLACE_WITH_YOUR_SSID'

password = 'REPLACE_WITH_YOUR_PASSWORD'

mqtt_server = 'REPLACE_WITH_YOUR_MQTT_BROKER_IP'

mqtt_user = 'REPLACE_WITH_YOUR_MQTT_USERNAME'

mqtt_pass = 'REPLACE_WITH_YOUR_MQTT_PASSWORD'

 

Satu-satunya perbedaan di sini adalah kami subscribe ke topik hello dan publish ke topik notification.

 

topic_sub = b'hello'

topic_pub = b'notification'

 

main.py

Salin kode berikut ke file main.py ESP#2.

 

def sub_cb(topic, msg):

  print((topic, msg))


def connect_and_subscribe():

  global client_id, mqtt_server, topic_sub

  client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_pass)

  client.set_callback(sub_cb)

  client.connect()

  client.subscribe(topic_sub)

  print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub))

  return client


def restart_and_reconnect():

  print('Failed to connect to MQTT broker. Reconnecting...')

  time.sleep(10)

  machine.reset()


try:

  client = connect_and_subscribe()

except OSError as e:

  restart_and_reconnect()


while True:

  try:

    new_message = client.check_msg()

    if new_message != 'None':

      client.publish(topic_pub, b'received')

    time.sleep(1)

  except OSError as e:

    restart_and_reconnect()

 

Kode ini sangat mirip dengan main.py dari ESP#1. Kami membuat fungsi sub_cb(), connect_and_subscribe(), dan restart_and_reconnect(). Kali ini, fungsi sub_cb() hanya mencetak informasi tentang topik dan pesan yang diterima.

 

def sub_cb(topic, msg):

  print((topic, msg))

 

Di dalam perulangan while, kami memeriksa apakah ada pesan baru dan menyimpannya dalam variabel new_message.

 

new_message = client.check_msg()

 

Jika kami menerima pesan baru, kami memublikasikan pesan yang bertuliskan 'received' pada topik topic_sub (dalam hal ini kami mengaturnya ke notification di file boot.py).

 

if new_message != 'None':

  client.publish(topic_pub, b'received')

 

Selesai untuk ESP#2. Ingat bahwa Anda perlu mengunggah semua file berikut agar proyek berfungsi (unggah file secara berurutan):

1. umqttsimple.py;

2. boot.py;

3. main.py.

ESP32/ESP8266 akan membuat koneksi jaringan dan terhubung ke broker dengan sukses.

Demonstrasi

Setelah mengunggah semua skrip yang diperlukan ke kedua papan ESP dan memastikan kedua papan serta Raspberry Pi dengan broker Mosquitto berjalan, Anda siap untuk menguji setup ini.

 

ESP#2 akan menerima pesan "Hello" dari ESP#1, seperti yang ditunjukkan pada gambar di bawah.

Di sisi lain, papan ESP#1 akan menerima pesan "received". Pesan "received" ini dipublikasikan oleh ESP#2 pada topik notification. Karena ESP#1 berlangganan ke topik tersebut, ia akan menerima pesan tersebut.



Baca juga: 
Tutorial MicroPython ESP32/ESP8266 - Membaca Input Analog (ADC)

Dalam praktik, hasil dan kendala yang ditemui bisa berbeda tergantung perangkat, konfigurasi, versi library, dan sistem yang digunakan.

0 on: "Panduan Lengkap MicroPython ESP32/ESP8266 - MQTT untuk Pemula "