Adafruit MiniMQTT (adafruit_minimqtt), CircuitPython'un MQTT istemcisidir. ESP32-S2, ESP32-S3 ve Raspberry Pi Pico W gibi Wi-Fi'lı kartlarda çalışır, kartın yerleşik TLS yığınını kullanır ve paho-mqtt kullandıysanız size tanıdık gelecek bir callback stili izler. Bu eğitimde kütüphaneyi kuruyor, güvenli şekilde bağlanıyor, 10 saniyede bir ölçüm publish ediyor, komutlara tepki veriyor ve Wi-Fi kopmalarını atlatıyoruz.
Örnekler, Adafruit bundle'ındaki güncel bir MiniMQTT sürümüyle CircuitPython 9.x'i hedefler. CircuitPython her kaydettiğinizde code.py'yi yeniden yüklediği için hızlı deneme yapabilirsiniz; sahaya çıkan bir cihazın neden gerçek bir hata yönetimi döngüsüne ihtiyaç duyduğunu da göreceksiniz.
Gerekenler
| Parça | Notlar |
|---|---|
| Wi-Fi'lı CircuitPython kartı | ESP32-S2/S3 Feather veya QT Py, Pico W ya da bir AirLift kartı |
| CircuitPython 9.x | circuitpython.org'dan tam olarak kartınıza uygun sürümü yükleyin |
adafruit_minimqtt kütüphanesi | Bağımlılıklarıyla birlikte, circup ile kurulur |
| Bir MQTT broker | Örnekler broker.connectmq.com (8883 TLS) kullanır |
Kütüphaneyi, doğru .mpy dosyalarını ve bağımlılıkları CIRCUITPY sürücüsüne kopyalayan circup ile kurun:
pip install circup
circup install adafruit_minimqtt
circup list # kurulu sürümleri gösterir, eskileri işaretleradafruit_minimqtt klasörünü bundle'dan lib/ içine elle de kopyalayabilirsiniz; circup, bundle'ı CircuitPython sürümünüze göre seçtiği için daha az hataya yol açar.
1. settings.toml'da gizli bilgiler
CircuitPython, settings.toml dosyasını sürücünün kök dizininden okur. İki CIRCUITPY_WIFI_* anahtarı ayrıca kartın açılışta Wi-Fi'ye otomatik bağlanmasını sağlar.
CIRCUITPY_WIFI_SSID = "your-ssid"
CIRCUITPY_WIFI_PASSWORD = "your-wifi-password"
MQTT_BROKER = "broker.connectmq.com"
MQTT_PORT = 8883
MQTT_USER = "username"
MQTT_PASS = "password"Değerleri os.getenv() ile okuyun. Kimlik bilgilerini burada tutmak, code.py'yi hiçbir şey sızdırmadan paylaşmanıza veya commit etmenize olanak tanır.
2. Eksiksiz bir publisher ve subscriber
import os, time
import microcontroller, ssl, socketpool, wifi
import adafruit_minimqtt.adafruit_minimqtt as MQTT
if not wifi.radio.connected:
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"),
os.getenv("CIRCUITPY_WIFI_PASSWORD"))
print("Wi-Fi:", wifi.radio.ipv4_address)
DEVICE = "cpy-" + microcontroller.cpu.uid.hex()
BASE = f"testmqtt/cpy/{DEVICE}"
def on_connect(client, userdata, flags, rc):
print("bağlandı, rc =", rc)
client.subscribe(f"{BASE}/cmd", qos=1)
def on_disconnect(client, userdata, rc):
print("bağlantı koptu, rc =", rc)
def on_message(client, topic, message):
print(f"{topic}: {message}")
if message == "ping":
client.publish(f"{BASE}/pong", str(time.monotonic()))
pool = socketpool.SocketPool(wifi.radio)
mqtt = MQTT.MQTT(
broker=os.getenv("MQTT_BROKER"),
port=os.getenv("MQTT_PORT"),
username=os.getenv("MQTT_USER"),
password=os.getenv("MQTT_PASS"),
client_id=DEVICE,
is_ssl=True,
keep_alive=60,
socket_pool=pool,
ssl_context=ssl.create_default_context(),
)
mqtt.on_connect = on_connect
mqtt.on_disconnect = on_disconnect
mqtt.on_message = on_message
mqtt.will_set(f"{BASE}/status", "offline", retain=True, qos=1)
mqtt.connect()
mqtt.publish(f"{BASE}/status", "online", retain=True, qos=1)
last = 0
while True:
mqtt.loop(timeout=1) # gelen paketleri okur, zamanı gelince PINGREQ gönderir
if time.monotonic() - last >= 10:
temp = microcontroller.cpu.temperature
mqtt.publish(f"{BASE}/temperature", f"{temp:.1f}")
last = time.monotonic()Önemli satırların yaptığı iş:
socket_poolvessl_context, MiniMQTT'yi kartın ağ yığınına bağlar.ssl.create_default_context(), CircuitPython firmware'ine gömülü kök sertifikaları kullanır; böylece sertifikası genel bir CA'dan gelen bir broker ek dosya olmadan doğrulanır.loop(timeout=1)sık sık çalışmalıdır. Gelen mesajları işler,on_message'ı çağırır ve keep-alive ping'lerini zamanında gönderir. Timeout, istemcininsocket_timeoutdeğerinden (varsayılan 1 saniye) küçük olamaz; aksi halde MiniMQTT hata fırlatır.on_connectiçinde abone olmak, ilki ve her yeniden bağlanma dahil her başarılı bağlantının aboneliği geri getirmesini sağlar. Bu önemlidir, çünkübroker.connectmq.comgibi paylaşımlı test uç noktaları bağlantılar arasında session saklamaz.microcontroller.cpu.uidkalıcı ve benzersiz bir client ID verir. Geçici testler için rastgele ID tercih ederseniz client ID oluşturucu geçerli ID'ler üretir.microcontroller.cpu.temperaturedemo için pratik bir değerdir; bazı kartlardaNonedöndürür. Gerçek ölçümler için yerine gerçek bir sensör sürücüsü (BME280, SHT4x…) koyun.
Topic bazlı yönlendirme
Bir kart birden fazla topic'e abone olduğunda topic bazlı callback'ler kodu düzenli tutar:
def on_led(client, topic, message):
led.value = message == "on"
mqtt.add_topic_callback(f"{BASE}/led", on_led)
mqtt.subscribe(f"{BASE}/led")Bu topic'teki mesajlar on_led'e gider; geri kalan her şey genel on_message'a ulaşmaya devam eder.
3. Tarayıcıdan test edin
code.py'yi kaydedin ve seri konsolu açın (Mu, Thonny veya screen /dev/tty.usbmodem* 115200). IP adresini, ardından bağlandı, rc = 0 satırını görmelisiniz.
Şimdi online MQTT istemcisini açın, aynı broker'a bağlanın ve testmqtt/cpy/# topic'ine abone olun. Retained online durumunu ve her 10 saniyede bir sıcaklık değerini göreceksiniz. testmqtt/cpy/<device>/cmd topic'ine ping publish edin; bir saniye içinde pong geri gelir.
CircuitPython kartınızı tarayıcıda izleyin
Last Will'i test etmek için kartın gücünü kesin: yaklaşık bir buçuk keep-alive süresi sonra broker, durum topic'ine offline publish eder.
4. Bağlantı kopmalarını atlatmak
Geliştirme sırasında bir istisna code.py'yi durdurur ve siz düzeltirsiniz. Bir dolabın içindeki cihazda ise yakalanmamış bir istisna, biri gücü kesip yeniden verene kadar cihazın sessiz kalması demektir. Döngüyü sarmalayın:
def ensure_wifi():
if not wifi.radio.connected:
print("Wi-Fi yeniden bağlanıyor")
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"),
os.getenv("CIRCUITPY_WIFI_PASSWORD"))
delay = 1
last = 0
while True:
try:
mqtt.loop(timeout=1)
if time.monotonic() - last >= 10:
mqtt.publish(f"{BASE}/temperature", f"{microcontroller.cpu.temperature:.1f}")
last = time.monotonic()
delay = 1
except (OSError, RuntimeError, ConnectionError, MQTT.MMQTTException) as e:
print("hata:", e, "- yeniden deneme", delay, "sn sonra")
time.sleep(delay)
delay = min(delay * 2, 60)
try:
ensure_wifi()
mqtt.reconnect() # on_connect yeniden çalışır ve tekrar abone olur
mqtt.publish(f"{BASE}/status", "online", retain=True, qos=1)
except Exception as e2:
print("yeniden bağlanma başarısız:", e2)
if delay >= 60:
microcontroller.reset() # tekrarlanan hatalardan sonra son çareKalıp her platformda aynıdır: önce ağ katmanını, sonra MQTT'yi düzeltin; bir filonun yeniden başlayan bir broker'ı ezmemesi için üstel backoff uygulayın ve son güvenlik ağı olarak donanım reset'ini elde tutun. MQTT yeniden bağlanma en iyi uygulamaları mantığını daha ayrıntılı açıklıyor.
5. TLS ve sertifika notları
- Genel CA sertifikaları doğrudan çalışır. CircuitPython bir kök sertifika paketiyle gelir ve
ssl.create_default_context()bunu kullanır. - Kendinden imzalı veya özel CA mı? Açıkça yükleyin:
ctx = ssl.create_default_context(); ctx.load_verify_locations(cadata=CA_PEM); buradaCA_PEM, kök sertifikanızın PEM metnidir. - Bellek sınırlıdır. TLS büyükçe bir buffer ister. PSRAM'i olmayan kartlarda
code.pyiçinde MQTT'ye erken bağlanın ve el sıkışmadan önce büyük bellek ayırmalarından kaçının. - 1883'te şifresiz TCP,
is_ssl=Falseveport=1883ile çalışır ama şifreyi düz metin gönderir. Yalnızca masa üstü test ağında kullanın.
El sıkışma başarısız olursa önce bilgisayarınızdan bir TLS bağlantı testi yaparak broker tarafını eleyin.
Karşılaşacağınız hatalar
| Mesaj | Sebep |
|---|---|
ConnectionError: No network with that ssid | Yanlış SSID veya yalnızca 5 GHz yayın yapan ağ |
ConnectionError: Authentication failure | Yanlış Wi-Fi şifresi |
MMQTTException: Connection Refused - Incorrect username/password | Broker kimlik bilgilerini reddetti (CONNACK 4) |
MMQTTException: Connection Refused - Unauthorized | Bağlanma izni yok (CONNACK 5) |
OSError: [Errno 116] ETIMEDOUT | Port engelli, host yanlış veya broker'a ulaşılamıyor |
MemoryError | TLS veya büyük bir payload için yetersiz heap |
CONNACK kodları standart MQTT 3.1.1 dönüş kodlarıdır; reason code aracı hepsini listeler. Daha ileri giden bir sensör projesi için (birden fazla sensör, JSON payload'lar, bir dashboard) MQTT hava istasyonu yazısına bakın. Platformlar arasında seçim yapıyorsanız MicroPython umqtt eğitimi aynı görevleri daha alt seviye bir istemciyle gösteriyor.
MiniMQTT, CircuitPython kartlarına birkaç düzine satırda TLS destekli eksiksiz bir MQTT istemcisi kazandırır. Gizli bilgileri settings.toml'a koyun, on_connect içinde abone olun, loop()'u sürekli çağırın ve hepsini bir yeniden bağlanma döngüsüne sarın: bir hobi kartı, aylarca çalışır halde bırakabileceğiniz bir cihaza dönüşür.
Sıkça sorulan sorular
Adafruit MiniMQTT hangi kartlarda çalışır?
Ağ yığını olan her CircuitPython kartında: ESP32-S2, ESP32-S3 ve Raspberry Pi Pico W gibi yerleşik Wi-Fi'lı kartlarda ve esp32spi kütüphanesi üzerinden bir ESP32 AirLift yardımcı işlemcisi kullanan kartlarda. MQTT kodu aynıdır; yalnızca socket pool kurulumu farklıdır.
MiniMQTT MQTT 5 veya QoS 2 destekliyor mu?
Hayır. MiniMQTT, MQTT 3.1.1 konuşur ve QoS 0 ile QoS 1'i destekler. MQTT 5 destekleyen broker'lar 3.1.1 istemcilerini de kabul eder, yani onlarla çalışır; ancak karttan MQTT 5 özelliklerini kullanamazsınız.
MiniMQTT mesajlarım neden bytes yerine str olarak geliyor?
MiniMQTT varsayılan olarak payload'ları UTF-8 olarak çözer ve on_message'a bir str iletir. CBOR veya görüntü gibi ikili payload'lar için istemciyi use_binary_mode=True ile oluşturun; böylece bytes alırsınız.

