Node-RED ile HTTP'den MQTT'ye bir köprü, web isteği gönderebilen her sistemin, o sisteme bir MQTT kütüphanesi eklemeden MQTT cihazlarında komut tetiklemesini sağlar. Bu eğitimde Node-RED'de isteği doğrulayan, bir broker'a komut yayınlayan, isteğe bağlı olarak cihazın onaylamasını bekleyen ve uygun bir HTTP durum kodu döndüren bir REST uç noktası açacaksınız.
HTTP'den MQTT'ye Köprü Ne Zaman Mantıklıdır?
MQTT, cihazlar ile broker arasında doğru protokoldür, ancak bir fabrika ya da bina etrafındaki pek çok yazılım yalnızca HTTP bilir:
- Bir iş emri başladığında bir URL çağırabilen bir ERP ya da MES.
- Bir SaaS ürününden, bir ödeme sağlayıcısından ya da bir form aracından gelen webhook.
- Zaten
curlkullanan kabuk betikleri ve cron işleri. - Uzun ömürlü MQTT bağlantıları tutmasını istemediğiniz mobil uygulamalar ya da panolar.
- Yalnızca bir REST sözleşmesini kabul eden üçüncü taraf bir entegratör.
Bu sistemlerin her birine MQTT öğretmek yerine onlara küçük, iyi tanımlanmış bir HTTP API'si verirsiniz. Node-RED her isteği doğru topic'e yapılan bir yayına çevirir. Cihazlar saf MQTT istemcisi olarak kalır ve broker, mesajların aktığı tek yer olmaya devam eder.
Akışın Mimarisi
HTTP client --POST /api/devices/pump1/command--> Node-RED
Node-RED --publish connectmq/demo/h7r2pq/pump1/cmd--> MQTT broker --> device
device --publish connectmq/demo/h7r2pq/pump1/ack--> MQTT broker --> Node-RED
Node-RED --HTTP 200 or 202 or 504--> HTTP client
Üç uç nokta oluşturacağız:
| Metot ve yol | Amaç | Yanıt |
|---|---|---|
POST /api/devices/:id/command |
Bir komut yayınla ve hemen dön | 202 Accepted |
POST /api/devices/:id/command?wait=1 |
Yayınla ve cihaz onayını bekle | 200 OK veya 504 Gateway Timeout |
GET /api/devices/:id/state |
MQTT'den bilinen en son durumu döndür | 200 OK veya 404 Not Found |
Demo için connectmq/demo/h7r2pq ön ekiyle broker.connectmq.com adresindeki ücretsiz herkese açık MQTT broker'ını kullanıyoruz. Kendi rastgele ön ekinizi kullanın ve herkesin okuyup yayın yapabildiği herkese açık alan üzerinden asla gerçek kontrol komutları göndermeyin.
Adım 1: HTTP Uç Noktası ve Doğrulama
Metodu POST ve URL'si /api/devices/:id/command olan bir http in node'u ekleyin. İstemci Content-Type: application/json gönderdiğinde Node-RED JSON gövdelerini otomatik olarak ayrıştırır ve yol parametrelerini msg.req.params içine koyar.
Onu iki çıkışlı bir function node'una bağlayın: birincisi MQTT'ye gider, ikincisi hataları doğrudan bir http response node'una döndürür.
const PREFIX = "connectmq/demo/h7r2pq";
const ALLOWED_DEVICES = ["pump1", "pump2", "valve3"];
const ALLOWED_ACTIONS = ["start", "stop", "setpoint"];
const API_KEY = env.get("BRIDGE_API_KEY"); // akışta veya ortamda ayarlayın
function fail(code, message) {
msg.statusCode = code;
msg.payload = { error: message };
return [null, msg];
}
if (!API_KEY || msg.req.headers["x-api-key"] !== API_KEY) {
return fail(401, "invalid or missing API key");
}
const id = msg.req.params.id;
if (!ALLOWED_DEVICES.includes(id)) return fail(404, "unknown device " + id);
const body = msg.payload;
if (typeof body !== "object" || body === null) return fail(400, "JSON body required");
if (!ALLOWED_ACTIONS.includes(body.action)) return fail(400, "action must be one of " + ALLOWED_ACTIONS.join(", "));
if (body.action === "setpoint" && typeof body.value !== "number") {
return fail(400, "setpoint requires a numeric value");
}
const correlationId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
const command = {
action: body.action,
value: body.value,
correlationId,
issuedAt: new Date().toISOString(),
source: "http"
};
msg.deviceId = id;
msg.correlationId = correlationId;
msg.wait = msg.req.query.wait === "1";
msg.topic = `${PREFIX}/${id}/cmd`;
msg.payload = JSON.stringify(command);
msg.qos = 1;
msg.retain = false;
return [msg, null];
MQTT topic'ini asla kullanıcı girdisinden doğrudan, bir izin listesine karşı kontrol etmeden oluşturmayın. Aksi halde # ya da ../../other cihazı için yapılan bir istek, açmayı hiç düşünmediğiniz topic'lere yayın yapar.
Adım 2: Yayınla ve Yanıtla
Birinci çıkışı iki yere bağlayın:
msg.topicdeğerini kullanması için topic alanı boş bırakılmış, broker yapılandırma node'unuza bağlı bir mqtt out node'u.- HTTP çağırana nasıl yanıt verileceğine karar veren bir function node'u:
if (msg.wait) {
// Cihaz onaylayana veya zamanlayıcı dolana kadar isteği beklet
const pending = flow.get("pending") || {};
pending[msg.correlationId] = msg;
flow.set("pending", pending);
setTimeout(() => {
const p = flow.get("pending") || {};
const waiting = p[msg.correlationId];
if (waiting) {
delete p[msg.correlationId];
flow.set("pending", p);
waiting.statusCode = 504;
waiting.payload = { error: "device did not acknowledge in time", correlationId: msg.correlationId };
node.send(waiting);
}
}, 5000);
return null;
}
msg.statusCode = 202;
msg.payload = { status: "accepted", correlationId: msg.correlationId, topic: msg.topic };
return msg;
Bu function'ı ve 1. Adım'daki hata çıkışını aynı http response node'una bağlayın. Response node'u msg.statusCode değerini kullanır ve msg.payload değerini JSON olarak gönderir.
Asenkron 202 yanıtı doğru varsayılandır. MQTT cihazları uykuda, yeniden bağlanıyor ya da meşgul olabilir ve bir HTTP istemcisi buna takılıp kalmamalıdır. wait=1 varyantı, bir kişinin bir düğmeye tıklayıp pompanın gerçekten başlayıp başlamadığını bilmek istediği etkileşimli araçlar için faydalıdır.
Adım 3: Cihaz Onaylarını İşleyin
Cihaz, korelasyon kimliğini yineleyen bir onayı örneğin connectmq/demo/h7r2pq/pump1/ack topic'ine yayınlar:
{ "correlationId": "lrx2k9ab12cd", "result": "ok", "state": "running" }
connectmq/demo/h7r2pq/+/ack topic'ine bir mqtt in node'uyla (çıktı: ayrıştırılmış JSON) abone olun ve onu bekletilen istekle eşleştirin:
const ack = msg.payload;
const pending = flow.get("pending") || {};
const waiting = pending[ack.correlationId];
if (!waiting) return null; // zaten zaman aşımına uğradı veya bir 202 isteği
delete pending[ack.correlationId];
flow.set("pending", pending);
waiting.statusCode = ack.result === "ok" ? 200 : 409;
waiting.payload = { status: ack.result, state: ack.state, correlationId: ack.correlationId };
return waiting;
Onu aynı http response node'una bağlayın. Bekletilen mesaj hâlâ orijinal msg.res nesnesini taşıdığından yanıt doğru HTTP çağırana geri döner. Bekleyen istekler bellekte yaşar; bu sorun değildir, çünkü ait oldukları HTTP bağlantıları da Node-RED yeniden başladığında ortadan kalkar.
MQTT 5 kullanıyorsanız, kimliği JSON'a gömmek yerine giden komutta msg.responseTopic ve msg.correlationData ayarlayabilirsiniz. mqtt out node'u bunları MQTT 5 özellikleri olarak iletir ve bunları destekleyen cihazlar istenen topic'te yanıt verebilir. MQTT 5 özellikleri rehberi istek ve yanıtı daha ayrıntılı açıklıyor.
Adım 4: Cihaz Durumu için Bir Okuma Uç Noktası
Cihazlar durumlarını connectmq/demo/h7r2pq/<id>/state topic'ine retained message olarak yayınlamalıdır. connectmq/demo/h7r2pq/+/state topic'ine abone olun ve her birini flow context'inde saklayın:
const id = msg.topic.split("/")[3];
const states = flow.get("states") || {};
states[id] = { state: msg.payload, receivedAt: new Date().toISOString() };
flow.set("states", states);
return null;
Ardından GET /api/devices/:id/state için bir http in node'u ekleyin:
const states = flow.get("states") || {};
const s = states[msg.req.params.id];
if (!s) {
msg.statusCode = 404;
msg.payload = { error: "no state received for this device" };
} else {
msg.statusCode = 200;
msg.payload = s;
}
return msg;
Durum mesajları retained olduğu için Node-RED yeniden bağlanır bağlanmaz her cihazın en son değerini alır; böylece okuma uç noktası bir yeniden başlatmanın hemen ardından kullanılabilir.
curl ile Test Etmek
API anahtarını Node-RED için bir ortam değişkeni olarak ayarlayın (BRIDGE_API_KEY=change-me), deploy edin ve uç noktaları varsayılan 1880 portunda çağırın:
# Gönder ve unut
curl -i -X POST http://localhost:1880/api/devices/pump1/command \
-H "Content-Type: application/json" -H "X-API-Key: change-me" \
-d '{"action":"start"}'
# Onayı bekle (hiçbir cihaz yanıt vermezse 5 sn sonra 504 döner)
curl -i -X POST "http://localhost:1880/api/devices/pump1/command?wait=1" \
-H "Content-Type: application/json" -H "X-API-Key: change-me" \
-d '{"action":"setpoint","value":42.5}'
# Cihaz onayını simüle et (correlationId değerini cmd topic'inden kopyalayın)
mosquitto_sub -h broker.connectmq.com -p 1883 -i dev-h7r2pq -v -t "connectmq/demo/h7r2pq/pump1/cmd"
mosquitto_pub -h broker.connectmq.com -p 1883 -i ack-h7r2pq -t "connectmq/demo/h7r2pq/pump1/ack" \
-m '{"correlationId":"PASTE_ID","result":"ok","state":"running"}'
Node-RED HTTP MQTT Köprüsünü Güvenli Hale Getirmek
Pompaları hareket ettiren bir HTTP uç noktası bir saldırı yüzeyidir. Onu localhost dışına açmadan önce bu listeyi uygulayın:
- Her isteğin kimliğini doğrulayın. Yukarıdaki API anahtarı kontrolü asgari düzeydir. Tüm HTTP-in uç noktalarında temel kimlik doğrulama için
settings.jsiçindenode-red admin hash-pwile üretilmiş bir bcrypt hash'iylehttpNodeAuthayarlayın. - TLS'yi Node-RED'in önünde Nginx ya da Caddy gibi bir ters proxy ile sonlandırın. 1880 portunu doğrudan internete açmayın.
- Editörü
adminAuthile koruyun ya da editörü farklı, yalnızca dahili bir yol veya portta çalıştırın. - Girdileri cihaz ve eylem izin listelerine karşı doğrulayın ve değerlerin türünü kontrol edin.
- Proxy'de hız sınırlaması uygulayın ve broker'ın da sınır uyguladığını unutmayın. Herkese açık broker istemci başına saniyede 10 mesaja izin verir; üretim planlarının da kendi kotaları vardır.
- mqtt node'ları için 8883 portunda TLS üzerinden özel broker kimlik bilgileri kullanın.
Node-RED'i güvenli hale getirme makalemiz editör ve ayarlar tarafını derinlemesine ele alıyor.
Üretim Broker'ına Geçiş
Demo broker yapılandırmasını özel bir ConnectMQ broker ile değiştirin: port 8883, TLS etkin ve portalda üretilen YOUR_USERNAME, YOUR_PASSWORD ve YOUR_CLIENT_ID değerleri. ConnectMQ kendi webhook'larını ya da HTTP yayın API'sini sunmaz; bu desenin var olma nedeni de tam olarak budur: Node-RED HTTP'ye bakan katmandır, broker ise MQTT'ye odaklı kalır. Broker'ı barındırılan bir MQTT broker olarak çalıştırmak, ilgilenmeniz gereken tek sunucunun Node-RED örneği olması demektir.
Node-RED Köprünüzü ConnectMQ Üzerinde Çalıştırın
app.connectmq.com adresinde kredi kartı gerektirmeden Serverless planında ücretsiz bir broker oluşturun ve Node-RED köprünüzü TLS üzerinden ona yönlendirin. Uç noktalarınızı curl ile test ederken komutları ve onayları portalın canlı topic gezgininde izleyebilirsiniz. MQTT node'larının temelleri için Node-RED MQTT eğitimine, ters yön olan insanlara uyarı göndermek için ise Node-RED Telegram botu rehberine bakın.
Sık Sorulan Sorular
Node-RED webhook alıp bunları MQTT'ye yayınlayabilir mi?
Evet. Bir http in node'u webhook'u kabul eder, bir function node'u onu doğrulayıp bir topic oluşturur ve bir mqtt out node'u yayınlar. Webhook göndereninin yeniden denememesi için hızlıca bir 2xx yanıtı döndürün.
HTTP uç noktası cihazın yanıt vermesini beklemeli mi?
Varsayılan olarak 202 Accepted döndürün ve istemcilerin durumu ayrıca kontrol etmesine izin verin. Bir onayı beklemek etkileşimli kullanım için faydalıdır, ancak her zaman kısa bir zaman aşımı uygulayın.
HTTP'den gelen komutlar için hangi QoS'u kullanmalıyım?
Komutlar için QoS 1 iyi bir varsayılandır; yinelenen bir teslimatın zarar vermemesi için toggle yerine start ve stop gibi idempotent eylemlerle birleştirin.
ConnectMQ bir REST yayın API'si sunuyor mu?
Hayır. ConnectMQ, MQTT, TLS ve WebSocket uç noktalarına sahip bir MQTT broker'dır. HTTP isteklerini MQTT yayınlarına çevirmek için Node-RED'i ya da kendinize ait küçük bir servisi kullanın.



