ESP32'de MicroPython umqtt, derleme adımı olmadan ve hata ayıklama için etkileşimli bir komut istemiyle, birkaç satır Python ile MQTT kullanmanızı sağlar. Bu eğitimde bir ESP32'yi umqtt.simple ile broker.connectmq.com'a bağlıyor, umqtt.robust ile otomatik yeniden bağlanma ekliyor, gelen komutları bloklamadan işliyor ve bu istemcilere production'da güvenmeden önce bilmeniz gereken sınırları açıklıyoruz.
MQTT Cihazları İçin Neden MicroPython
Arduino core ile C++ daha hızlıdır ve daha fazla kütüphaneye sahiptir, ancak geliştirme döngüsünün hızında MicroPython öne çıkar. Bir dosyayı düzenler, karta kopyalar ve saniyeler içinde çalıştırırsınız. REPL, Wi-Fi, sensörler ve MQTT ile etkileşimli olarak denemeler yapmanıza izin verir; bu da bir şeyin neden çalışmadığını anlamaya çalışırken paha biçilmezdir.
micropython-lib içindeki umqtt paketi iki modül sunar:
umqtt.simple: minimal bir MQTT 3.1.1 istemcisi. Bağlanma, publish, subscribe, ping, last will. Hiçbir şey otomatik olarak gerçekleşmez.umqtt.robust:simpleüzerine kurulu ince bir alt sınıf;publish(),wait_msg()ve birkaç başka çağrıdaki soket hatalarını yakalar ve otomatik olarak yeniden bağlanır.
Her ikisi de herhangi bir ESP32'ye rahatça sığacak kadar küçüktür.
Kartın Hazırlanması
- Resmi indirme sayfasından ESP32'niz için güncel bir MicroPython firmware'ini
esptool.pyile yükleyin. - Bilgisayarınıza
mpremotekurun:pip install mpremote. umqttpaketinin zaten mevcut olup olmadığını kontrol edin. Bazı firmware derlemeleri onu içerir, bazıları içermez. REPL'deimport umqtt.simplebaşarısız olursa mip ile kurun:
mpremote connect auto mip install umqtt.simple
mpremote connect auto mip install umqtt.robust
mip, kartın internete bağlı olmasını gerektirir. Kart henüz Wi-Fi'a bağlı değilse kurulumu önce bağlantı kuran bir betikten çalıştırın veya modül dosyalarını mpremote cp ile elle kopyalayın. MicroPython paket yönetimi belgeleri tüm seçenekleri açıklar.
Wi-Fi'a Bağlanma
Her açılışta çalışması için bunu boot.py dosyasına koyun:
import network
import time
WIFI_SSID = "YOUR_WIFI"
WIFI_PASS = "YOUR_WIFI_PASSWORD"
def connect_wifi(timeout=15):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
wlan.connect(WIFI_SSID, WIFI_PASS)
start = time.time()
while not wlan.isconnected():
if time.time() - start > timeout:
raise RuntimeError("Wi-Fi connection timed out")
time.sleep(0.25)
print("Wi-Fi OK", wlan.ifconfig()[0])
return wlan
connect_wifi()
umqtt.simple ile Publish
İlk betik broker.connectmq.com'un herkese açık alanına bağlanır ve her beş saniyede bir ölçüm yayınlar. Client ID, çipin benzersiz kimliğinden oluşturulur; böylece asla boş olmaz ve başka bir kartla asla çakışmaz.
import time
import ubinascii
import machine
import esp32
from umqtt.simple import MQTTClient
BROKER = "broker.connectmq.com"
PREFIX = b"connectmq/demo/2b7e95"
CLIENT_ID = b"mpy-" + ubinascii.hexlify(machine.unique_id())
client = MQTTClient(CLIENT_ID, BROKER, port=1883, keepalive=30)
client.set_last_will(PREFIX + b"/status", b"offline", retain=True, qos=1)
client.connect()
client.publish(PREFIX + b"/status", b"online", retain=True, qos=1)
print("Connected as", CLIENT_ID)
while True:
temp_c = (esp32.raw_temperature() - 32) / 1.8 # dahili sensörden kaba bir ölçüm
payload = '{"temp":%.1f,"uptime":%d}' % (temp_c, time.ticks_ms() // 1000)
client.publish(PREFIX + b"/telemetry", payload.encode())
time.sleep(5)
raw_temperature() bulunmayan ESP32 varyantlarında bu satırı gerçek bir sensör okumasıyla değiştirin. Mesajları bilgisayarınızdan izleyin:
mosquitto_sub -h broker.connectmq.com -p 1883 -i pc-2b7e95 -t 'connectmq/demo/2b7e95/#' -v
Topic'lerin ve payload'ların byte türünde olduğuna dikkat edin. umqtt birçok yerde str kabul eder, ancak tutarlı biçimde byte kullanmak sürprizleri önler; özellikle her zaman byte alan callback'lerde.
Komutları Bloklamadan Almak
Mesaj almak için bir callback kaydedin ve subscribe olun. Ardından düzenli olarak ya bir mesaj gelene kadar bekleyen wait_msg() fonksiyonunu ya da bekleyen bir şey yoksa hemen dönen check_msg() fonksiyonunu çağırmanız gerekir. Başka işler de yapan bir döngüde check_msg() kullanın:
import time
import ubinascii
import machine
from umqtt.simple import MQTTClient
BROKER = "broker.connectmq.com"
PREFIX = b"connectmq/demo/2b7e95"
CLIENT_ID = b"mpy-" + ubinascii.hexlify(machine.unique_id())
led = machine.Pin(2, machine.Pin.OUT)
def on_message(topic, msg):
print("Received", topic, msg)
if topic == PREFIX + b"/led/set":
led.value(1 if msg == b"ON" else 0)
client.publish(PREFIX + b"/led/state", msg, retain=True)
client = MQTTClient(CLIENT_ID, BROKER, port=1883, keepalive=30)
client.set_callback(on_message)
client.connect()
client.subscribe(PREFIX + b"/led/set", qos=1)
last_ping = time.ticks_ms()
last_publish = time.ticks_ms()
while True:
client.check_msg() # bekleyen mesajı işle
now = time.ticks_ms()
if time.ticks_diff(now, last_publish) > 10000:
client.publish(PREFIX + b"/telemetry", b'{"alive":true}')
last_publish = now
last_ping = now
elif time.ticks_diff(now, last_ping) > 20000:
client.ping() # boştayken bağlantıyı canlı tut
last_ping = now
time.sleep_ms(50)
Test edin:
mosquitto_pub -h broker.connectmq.com -p 1883 -i pc-2b7e95-pub -t connectmq/demo/2b7e95/led/set -m ON
Gözden kaçması kolay iki nokta var. Birincisi, umqtt.simple keepalive ping'lerini kendiliğinden göndermez. Bir keepalive ayarlayıp bundan daha seyrek publish yapıyorsanız, yukarıdaki döngüde olduğu gibi ping() çağırmanız gerekir; aksi halde broker bağlantınızı keser. İkincisi, set_callback() mutlaka subscribe() öncesinde çağrılmalıdır.
umqtt.robust ile Otomatik Yeniden Bağlanma
umqtt.simple bağlantı koptuğunda OSError fırlatır ve siz bunu ele almazsanız betiğiniz durur. umqtt.robust ana çağrıları sarmalar ve denemeler arasında kısa bir gecikmeyle yeniden bağlanır. Tek değişiklik import satırıdır:
from umqtt.robust import MQTTClient
Bir püf noktası var. Robust istemci soketi yeniden bağlar, ancak sizin yerinize yeniden subscribe olmaz ve clean session ile broker aboneliklerinizi unutur. Güvenilir bir yöntem, bağlanma adımını bir fonksiyona sarmak ve onu hem açılışta hem de kendi yakaladığınız her hatadan sonra çağırmaktır:
def connect_and_subscribe():
client.connect(clean_session=True)
client.subscribe(PREFIX + b"/led/set", qos=1)
client.publish(PREFIX + b"/status", b"online", retain=True, qos=1)
connect_and_subscribe()
while True:
try:
client.check_msg()
# ... periyodik publish ...
except OSError as e:
print("MQTT error", e, "- reconnecting")
time.sleep(5)
try:
connect_and_subscribe()
except OSError:
pass
time.sleep_ms(50)
Tamamen gözetimsiz çalışan cihazlar için machine.WDT(timeout=30000) ekleyin ve döngü içinde besleyin; böylece tam bir kilitlenme kartı yeniden başlatır.
MicroPython umqtt ESP32 Projesini Yapılandırmak
Bir betik birkaç düzine satırı aştığında, onu herhangi bir Python projesinde yapacağınız gibi bölün. Kart üzerinde iyi çalışan bir düzen:
boot.pyyalnızca Wi-Fi bağlantısını kurar; böylece uygulamadaki bir hata sizi asla REPL'in dışında bırakmaz.config.pybroker host'unu, portu, topic önekini ve kimlik bilgilerini tutar. Sürüm kontrolünün dışında tutun ve her karta ayrı ayrı kopyalayın.main.pyconfigmodülünü import eder, istemciyi oluşturur ve ana döngüyü, istisnayı loglayıp kısa bir gecikmeden sonramachine.reset()çağıran birtry/exceptiçinde çalıştırır.
İki alışkanlık çok fazla hata ayıklama süresi kazandırır. Ana döngüyü, REPL'de Ctrl+C'ye basıldığında genel hata yakalayıcınıza takılmak yerine KeyboardInterrupt ile temiz biçimde duracak şekilde sarmalayın. Döngüde payload string'leri oluşturuyorsanız periyodik olarak gc.collect() çağırın; MicroPython'un heap'i küçüktür ve parçalanma dakikalar sonra değil, saatlerce çalıştıktan sonra MemoryError olarak ortaya çıkar.
JSON yayınlamanın en kolay yolu yerleşik json modülüdür: client.publish(topic, json.dumps({"temp": 22.4})). Komutları ayrıştırmak da callback içinde json.loads(msg) ile aynı şekilde çalışır; bozuk bir mesajın cihazı çökertmemesi için bunu bir try içine alın.
Bilmeniz Gereken umqtt Sınırlamaları
| Sınırlama | Etkisi | Çözüm |
|---|---|---|
| Yalnızca MQTT 3.1.1 | MQTT 5 özellikleri (properties), reason code'lar veya shared subscription özellikleri yok | MQTT 5'e ihtiyacınız varsa farklı bir istemci kullanın |
| Yalnızca QoS 0 ve 1 | QoS 2 desteklenmez | Çoğu telemetri ve komut için QoS 1 yeterlidir |
| Otomatik keepalive ping'i yok | Boştaki bağlantılar düşürülür | Periyodik olarak ping() çağırın |
| Bloklayan soket çağrıları | connect() ve wait_msg() betiği bloklar |
check_msg() kullanın; karmaşık cihazlar için asyncio tabanlı bir istemci düşünün |
| Yeniden bağlanmada otomatik subscribe yok | Yeniden bağlandıktan sonra komutlar gelmez | Kendi yeniden bağlanma fonksiyonunuzda yeniden subscribe olun |
| Çevrimdışı mesaj kuyruğu yok | Bağlantı yokken yayınlanan mesajlar kaybolur | Gerekirse ölçümleri kendiniz tamponlayın |
Aynı anda birden fazla iş yapması gereken cihazlar için keepalive ve yeniden bağlanmayı arka planda yöneten topluluk kaynaklı asyncio tabanlı MQTT istemcileri mevcuttur. Basit sensörler ve aktüatörler için umqtt en hafif seçenek olmaya devam eder.
8883 Portunda TLS Kullanımı
Özel bir broker için bağlantıyı şifreleyin. umqtt.simple'ın yeni sürümleri bir SSLContext alan ssl argümanını kabul eder; eski sürümler bunun yerine ssl_params sözlüğüyle birlikte ssl=True kullanır, bu yüzden kurduğunuz sürümü kontrol edin.
import ssl
from umqtt.simple import MQTTClient
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="isrg-root-x1.der") # Let's Encrypt kök CA'sı
client = MQTTClient(
b"YOUR_CLIENT_ID",
"broker.connectmq.com",
port=8883,
user=b"YOUR_USERNAME",
password=b"YOUR_PASSWORD",
keepalive=30,
ssl=ctx,
)
client.connect()
Önce ISRG Root X1 sertifikasını mpremote cp ile karta kopyalayın. TLS hatırı sayılır miktarda RAM gerektirir; PSRAM'li kartlar bunu daha rahat kaldırır. Broker'ınız için oluşturulan client ID, kullanıcı adı ve parolayı birebir kullanın, çünkü ConnectMQ client ID'yi verilen kimlik bilgilerine bağlar.
İlgili Rehberler
C++ ile çalışmayı tercih ediyorsanız ESP32 PlatformIO MQTT proje rehberi iyi yapılandırılmış bir Arduino kurulumunu gösterir, ESP32 MQTT Last Will rehberi ise ilk betikte kullanılan durum desenini açıklar. ESP32 IoT eğitimi cihazdan dashboard'a kadar tüm resmi ele alır; protokolde yeniyseniz bir MQTT broker'ın ne yaptığı yazısıyla başlayın.
MicroPython Cihazlarınızı ConnectMQ'ya Bağlayın
Buradaki tüm örnekler kayıt gerektirmeden herkese açık MQTT test broker'ı ile çalışır. Denemelerin ötesine geçtiğinizde ConnectMQ size 8883 portunda TLS ve kartınızın ne gönderdiğini kontrol edebileceğiniz tarayıcı içi bir MQTT istemcisi ile özel bir bulut MQTT broker sunar. Ücretsiz Serverless planında app.connectmq.com adresinden bir tane oluşturun, kredi kartı gerekmez.
Sık Sorulan Sorular
umqtt MQTT 5'i destekliyor mu?
Hayır. Hem umqtt.simple hem de umqtt.robust MQTT 3.1.1'i uygular. ConnectMQ gibi MQTT 5'i destekleyen broker'lar 3.1.1 bağlantılarını da kabul eder.
MicroPython MQTT istemcim neden bir dakika sonra bağlantıyı kesiyor?
Bir keepalive ayarladınız ancak bu süre içinde hiçbir şey göndermiyorsunuz. umqtt otomatik ping göndermez; bu yüzden düzenli olarak client.ping() çağırın veya keepalive süresinden daha sık publish yapın.
wait_msg() ile check_msg() arasındaki fark nedir?
wait_msg() bir mesaj gelene kadar bloklar. check_msg() bekleyen bir mesaj varsa onu işler ve hemen döner; bu da sensör okuyan döngüler için uygundur.
umqtt QoS 2 kullanabilir mi?
Hayır. QoS 0 ve 1'i destekler; bu da cihaz kullanım senaryolarının çoğunu karşılar.



