Node-RED context, bir flow'un mesajlar arasında değerleri hatırlamasını sağlayan yerleşik anahtar-değer deposudur; örneğin bir sensörün bildirdiği son sıcaklık veya bugünkü alarm sayacı. Bu yazı üç context kapsamını, context'in yeniden başlatmalardan nasıl sağ çıkacağını, aynı anda birden fazla deponun nasıl kullanılacağını ve her cihaz için son MQTT değerini tutmaya yönelik temiz bir deseni ele alıyor.
Flow'lar Neden Duruma İhtiyaç Duyar?
Node-RED'de mesajlar birbirinden bağımsızdır. Bir mqtt in node'u bir ölçüm yaydığında sonraki node yalnızca o mesajın içindekini bilir. Gerçek görevlerin çoğu bundan fazlasını gerektirir:
- Bir değişikliği veya eğilimi tespit etmek için bir değeri öncekiyle karşılaştırmak.
- Şu anda hiçbir MQTT mesajı gelmiyor olsa bile bir HTTP isteğine en son ölçümle yanıt vermek.
- Vardiya başına olayları saymak veya bir alarmın ne zaman başladığını hatırlamak.
- Farklı zamanlarda gelen iki topic'teki değerleri birleştirmek.
MQTT'nin kendisi retained mesajlar aracılığıyla bir tür bellek sunar: broker bir topic'teki son mesajı saklar ve yeni subscriber'lara iletir. Bu, istemciler arasında paylaşılan durum için harikadır ve kullanmalısınız. Context ise Node-RED'in içinde yaşayan durum için tamamlayıcı araçtır. Bir sorumluluğun hangi tarafa ait olduğundan emin değilseniz MQTT broker'ın ne yaptığı yazımız sınırı netleştirir.
Üç Node-RED Context Kapsamı
| Kapsam | Kimler görebilir | Tipik kullanım | Function içinde erişim |
|---|---|---|---|
| Node | Yalnızca onu ayarlayan node | Ölü bant filtreleri, tek bir function içindeki sayaçlar | context.get() / context.set() |
| Flow | Aynı sekmedeki (veya aynı subflow örneğindeki) tüm node'lar | Tek bir sekmede birden fazla node'un kullandığı son değerler | flow.get() / flow.set() |
| Global | Node-RED örneğindeki her node | Paylaşılan yapılandırma, arama tabloları | global.get() / global.set() |
İşinizi gören en dar kapsamı seçin. Global context'teki bir değer herhangi bir sekmedeki herhangi bir node tarafından değiştirilebilir; bu da hataların izini sürmeyi zorlaştırır. Node context özeldir, bu yüzden başka hiçbir şey onu bozamaz.
Context'i kullanmak için kod yazmanız gerekmez. Change node flow. ve global. özelliklerini ayarlayabilir, okuyabilir, taşıyabilir ve silebilir; Inject, Switch ve Template node'ları da bunları okuyabilir. Editör kenar çubuğundaki Context Data sekmesi her kapsamın güncel değerlerini gösterir ve hata ayıklama sırasında girdileri yenilemenize veya silmenize olanak tanır.
Subflow'larda ek bir incelik vardır: bir subflow içindeki flow context o örneğe aittir. Bir subflow, flow.get("$parent.lastTemp") gibi $parent. önekiyle üst flow'un context'ine erişebilir.
Bellek ve Kalıcı Context
Varsayılan olarak tüm context bellekte saklanır. Hızlıdır, ancak Node-RED yeniden başladığında, container yeniden oluşturulduğunda veya sunucu yeniden başlatıldığında kaybolur. Kolayca yeniden oluşturamayacağınız her şey için dosya tabanlı depolamayı açın.
settings.js dosyasını açın (standart kurulumda ~/.node-red/, Docker imajında /data/ içinde) ve contextStorage bölümünü bulun:
// settings.js
module.exports = {
// ...
contextStorage: {
default: { module: "memory" },
file: { module: "localfilesystem" }
},
// ...
};
Node-RED'i yeniden başlatın. Artık iki deponuz var: bellekte kalan default ve kullanıcı dizininizin context/ klasörü altına JSON dosyaları yazan file. Node'lar depoyu açıkça seçer:
flow.set("lastReading", msg.payload, "file"); // kalıcı
flow.set("scratch", 42); // bellek (varsayılan depo)
const last = flow.get("lastReading", "file");
Birden fazla deponuz olduğunda Change node ve diğer editörlerde flow. ve global. alanlarının yanında küçük bir depo seçici belirir.
Her şeyin kalıcı olmasını tercih ediyorsanız bunun yerine default: { module: "localfilesystem" } ayarlayın. Dosya deposunun nasıl çalıştığını aklınızda tutun: değerler bellekte önbelleğe alınır ve flushInterval seçeneğiyle kontrol edilen bir aralıkta, varsayılan olarak her 30 saniyede bir diske yazılır. Ani bir çökme son birkaç saniyelik değişiklikleri kaybettirebilir. Bu, son değerler ve sayaçlar için sorun değildir, ancak context bir veritabanı değildir. Geçmiş veriler için Node-RED InfluxDB rehberimizde gösterildiği gibi InfluxDB gibi bir zaman serisi deposuna yazın.
Ayrıca yalnızca JSON'a serileştirilebilen değerlerin güvenilir biçimde kalıcı olduğunu unutmayın. Fonksiyonlar, zamanlayıcılar ve sınıf örnekleri yeniden başlatmadan sonra bozulmadan geri gelmez; bu yüzden düz nesneler, sayılar ve string'ler saklayın.
Senkron ve Asenkron Erişim
Memory ve localfilesystem depolarında get ve set yukarıda gösterildiği gibi senkron çalışır. Redis tabanlı modüller gibi bazı üçüncü taraf depolar asenkrondur ve callback gerektirir:
flow.get("count", "redis", (err, count) => {
if (err) { node.error(err, msg); return; }
count = (count || 0) + 1;
flow.set("count", count, "redis", (err) => {
if (err) { node.error(err, msg); return; }
msg.payload = count;
node.send(msg);
node.done();
});
});
Kodu baştan callback'lerle yazmak az maliyetlidir ve depoyu daha sonra her function'ı yeniden yazmadan değiştirebileceğiniz anlamına gelir. Bir get ardından gelen set işleminin atomik olmadığını unutmayın. Asenkron bir depoda çok yüksek mesaj hızlarında iki mesaj aynı eski sayacı okuyabilir. Sayaçları yalnızca tek bir node'un yazdığı node context'te tutun veya güncellemeleri toplu yapın.
Diziler geçirerek aynı anda birden fazla anahtarı da okuyup yazabilirsiniz: flow.get(["a", "b"]) bir değerler dizisi döndürür.
Desen: Her Cihaz İçin Son MQTT Değerini Tutmak
Yaygın bir Node-RED context görevi canlı bir "bilinen son değer" tablosudur: cihaz başına bir girdi, her mesajda güncellenir ve flow'un her yerinden okunabilir. c8d1 yerine kendi rastgele dizenizi yazarak ConnectMQ herkese açık MQTT test broker'ına biraz test verisi publish edin:
mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-ctx-c8d1 \
-t "connectmq/demo/c8d1/boiler/tank1/telemetry" -m '{"level": 71.5, "temp": 63.2}'
mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-ctx-c8d1 \
-t "connectmq/demo/c8d1/boiler/pump2/telemetry" -m '{"rpm": 1450, "temp": 41.0}'
Node-RED'de çıkışı parsed JSON olarak ayarlanmış bir mqtt in node'u ile connectmq/demo/c8d1/+/+/telemetry topic'ine subscribe olun ve onu şu function'a bağlayın:
// Function "store latest"
const parts = msg.topic.split("/");
const deviceId = parts[3] + "/" + parts[4]; // örn. "boiler/tank1"
const latest = flow.get("latest", "file") || {};
latest[deviceId] = {
values: msg.payload,
ts: Date.now()
};
flow.set("latest", latest, "file");
node.status({ text: Object.keys(latest).length + " devices" });
return null;
Artık sekmedeki herhangi bir node tabloyu okuyabilir. GET /latest üzerinde bir http in node'u, ardından bu function ve bir http response node'u size küçük bir API sağlar:
// Function "serve latest"
const latest = flow.get("latest", "file") || {};
const staleMs = 5 * 60 * 1000;
const now = Date.now();
msg.payload = Object.entries(latest).map(([id, v]) => ({
device: id,
values: v.values,
ageSeconds: Math.round((now - v.ts) / 1000),
stale: now - v.ts > staleMs
}));
return msg;
Önemli ayrıntı stale bayrağıdır. Süresi hiç dolmayan bir son değer tablosu, dün ölmüş bir cihazın ölçümünü gönül rahatlığıyla gösterir. Değerle birlikte her zaman bir zaman damgası saklayın.
Node-RED Context En İyi Uygulamalar Kontrol Listesi
- En dar kapsamı kullanın: önce node, sonra flow, sonra global.
- Bir dosya deposunu etkinleştirin ve yeniden oluşturamayacağınız değerler için onu açıkça seçin.
- Bayat verileri tespit edebilmek için değerlerin yanında zaman damgası saklayın.
- Çok büyük nesnelerden kaçının; büyük context girdileri her diske yazmayı ve her kenar çubuğu yenilemesini yavaşlatır.
- Global anahtarlara amaca göre önek verin; örneğin yapılandırma için
cfg_, arama verileri içincache_. - Gizli bilgileri context'te saklamayın. Kimlik bilgilerinin yeri config node'ları ve ortam değişkenleridir.
- Diğer istemcilerin ihtiyaç duyduğu durum için retained MQTT mesajlarını, yalnızca Node-RED'in ihtiyaç duyduğu durum için context'i kullanın.
context/klasörünü flow'larınızla birlikte yedekleyin. Node-RED'i container'larda mı çalıştırıyorsunuz? Node-RED Docker rehberimiz/datadizinini kalıcı bir volume'de nasıl tutacağınızı gösterir.
Resmi context belgeleri depo API'sini ve yapılandırma seçeneklerini eksiksiz ele alır. Bu desenlerin kod tarafı için Node-RED function node rehberimize, flow'ları broker'lara bağlamanın genel resmi için Node-RED MQTT eğitimine bakın.
Node-RED Context'i ConnectMQ ile Birlikte Kullanın
Context Node-RED'in kendi belleğini tutar; broker ise diğer herkesinkini. ConnectMQ; retained mesajlar, MQTT 5 session expiry ve TLS sunan tam yönetilen bir MQTT hizmetidir; böylece cihazlar, panolar ve Node-RED tutarlı bilinen son değerleri görür. Portalı, bir flow oluşturmadan hızlı kontroller için canlı bir topic gezgini ve eşik alarm kuralları ekler. app.connectmq.com adresinde kredi kartı gerektirmeyen ücretsiz Serverless planla başlayın ve Node-RED'i oluşturulan kullanıcı adı, parola ve client ID ile bağlayın.
Sık Sorulan Sorular
Node-RED'de flow ve global context arasındaki fark nedir?
Flow context yalnızca aynı sekmedeki node'lar tarafından paylaşılır, global context ise Node-RED örneğindeki her node tarafından paylaşılır. Birden fazla sekme gerçekten aynı değere ihtiyaç duymuyorsa flow context kullanın.
Node-RED context'inin yeniden başlatmadan sağ çıkmasını nasıl sağlarım?
settings.js içinde contextStorage altına bir localfilesystem deposu ekleyin, Node-RED'i yeniden başlatın ve o depoya yazın; örneğin flow.set("key", value, "file").
Node-RED kalıcı context dosyalarını nerede saklar?
Node-RED kullanıcı dizini içindeki bir context klasöründe; genellikle ~/.node-red/context veya Docker'da /data/context; kapsama göre düzenlenmiş olarak.
Son değerler için context mi yoksa retained MQTT mesajları mı kullanmalıyım?
Diğer MQTT istemcilerinin son değere ihtiyacı varsa retained mesajları, yalnızca Node-RED'in ihtiyacı varsa (örneğin bir API sunmak veya ölçümleri karşılaştırmak için) context'i kullanın. Birçok flow ikisini birlikte kullanır.



