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.
- Diskusi umum dan tanya jawab praktik: https://t.me/edukasielektronika
- Kendala spesifik dan kasus tertentu: http://bit.ly/Chatarduino











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