






Github Repo: https://github.com/emrecagri/Loruv-n8n-IoT-Automation-Monitoring-Alerts
Türkçe
Proje Özeti
Bu projede, daha önce geliştirdiğim Loruv LYWSD03MMC BLE Climate Bridge API üzerinden alınan sıcaklık ve nem verilerini kullanarak, evde ve çatıda bulunan elektronik cihazların çalışma ortamını otomatik olarak takip eden bir n8n izleme ve alarm sistemi geliştirdim.
Sistem yalnızca sıcaklığın belirli bir değeri geçip geçmediğine bakan basit bir otomasyon değil. Tasarım sırasında aşağıdaki problemlerin tamamını ele aldım:
- Ev ve çatıdaki sensörlerin ayrı ayrı izlenmesi
- Yaz ve kış aylarında farklı kontrol zamanları
- Kritik saatlerde daha sık ölçüm
- Normal saatlerde gereksiz BLE trafiğini azaltma
- Anlık sıcaklık ve nem kontrolü
- Son bir saatlik minimum/maksimum değerlerin analizi
- Çiğ noktası hesabı
- Yoğuşma riskinin değerlendirilmesi
- Elektronik cihazların çalışma sıcaklıklarının ortak güvenli aralığının hesaplanması
- Warning ve Critical seviyeleri
- Hysteresis ile sınır çevresindeki alarm spam’inin engellenmesi
- BLE sensörünün okunamaması durumunda retry
- REST API’ye hiç ulaşılamaması durumunda ayrı hata yönetimi
- RSSI ile Bluetooth bağlantı kalitesinin izlenmesi
- Sensör pil voltajının takibi
- Sensör tekrar çalışmaya başladığında recovery bildirimi
- Ortam tekrar normale döndüğünde recovery bildirimi
- Telegram üzerinden HTML formatlı alarm mesajları
- Günlük sistem sağlık raporu
- Tek sensör bozulduğunda diğer sensörün izlenmeye devam etmesi
- Aynı alarmın sürekli gönderilmesini önleyen state management
Ortaya çıkan yapı, klasik bir “sıcaklık 40 °C’yi geçtiyse mesaj gönder” workflow’undan çok daha kapsamlı bir environment monitoring state machine haline geldi.
Projenin Amacı
Evde sürekli çalışan elektronik cihazlar bulunuyor:
- Raspberry Pi
- SSD
- Modem/router
- LCD TV
- Robot süpürge ve şarj ünitesi
- Akım korumalı priz
Çatı tarafında ise:
- DVR
- 12 V güç adaptörleri
- CCTV ekipmanları
- Ses/mikrofon ekipmanları
özellikle yaz aylarında yüksek sıcaklığa maruz kalabiliyor.
Bu nedenle temel hedefim şuydu:
Elektronik cihazların bulunduğu ortam güvenli çalışma aralığından çıkarsa, sistem bunu otomatik olarak fark etsin ve Telegram üzerinden bana haber versin.
Ancak bunun güvenilir çalışabilmesi için sadece anlık sıcaklığa bakmak yeterli değildi.
Genel Sistem Mimarisi
Sistem dört ana katmandan oluşuyor:
LYWSD03MMC BLE Sensörleri
│
▼
Raspberry Pi + BlueZ
│
▼
Loruv BLE Climate Bridge API
│
│ REST / JSON
▼
n8n Environment Monitoring Workflow
│
├── Zamanlama
├── Retry
├── Veri doğrulama
├── Sıcaklık / Nem analizi
├── Son 1 saat analizi
├── Dew Point
├── Hysteresis
├── Sensor Health
└── Alarm State Machine
│
▼
Telegram
BLE iletişimini doğrudan n8n’e bırakmak yerine arada geliştirdiğim REST API’yi kullanmak mimariyi önemli ölçüde sadeleştirdi.
n8n yalnızca HTTP/JSON ile ilgilenirken Bluetooth, GATT ve BlueZ işlemleri Climate Bridge API tarafından yönetiliyor.
Workflow Yapısı
Son workflow aşağıdaki mantıkla çalışıyor:
Schedule Trigger
↓
Merkezi Ayarlar + Kontrol Planı
↓
Kontrol Zamanı mı?
↓ TRUE
Loruv Sensörlerini Oku
│
├── HTTP Error
│ ↓
│ Retry Bekleme
│
↓ SUCCESS
Sensör Verisini Hazırla
↓
Tüm Sensörler Geçerli mi?
┌──┴───────────────┐
TRUE FALSE
│ ↓
│ 70 saniye bekle
│ ↓
│ Loruv Sensörlerini Tekrar Oku
│ ↓
│ Retry Sensör Verisini Hazırla
│ ↓
│ Retry Sonrası Sensörler Geçerli mi?
│ ┌──┴───┐
│ TRUE FALSE
│ │ │
└─────────────────┴───────┘
↓
Nihai Sensör Durumu + Veri Alarmı
┌──┴─────────────┐
│ │
▼ ▼
Veri Alarmları Ortam Alarm Motoru
│ │
▼ ▼
Telegram Telegram
1. Schedule Trigger
Workflow her saat çalışıyor:
5 * * * *
Bu ifade:
00:05
01:05
02:05
03:05
...
23:05
anlamına geliyor.
Workflow timezone:
Europe/Istanbul
olarak ayarlandı.
Her saat workflow’un uyanmasının nedeni, gerçek kontrol kararını cron yerine merkezi bir Code node’unda vermek.
Bu yaklaşım sayesinde yaz/kış saatleri veya kontrol sıklığı değiştirilmek istendiğinde cron expression değiştirmek gerekmiyor.
2. Mevsimsel Akıllı Kontrol Planı
Sistem üç farklı çalışma dönemi kullanıyor.
Yaz
Haziran, Temmuz, Ağustos ve Eylül:
summerMonths: [6, 7, 8, 9]
Sıcaklığın en kritik olabileceği saatler:
summerPriorityHours: [
12, 13, 14, 15,
16, 17, 18, 19
]
Bu saatlerde:
Her saat kontrol
yapılıyor.
Diğer zamanlarda:
3 saatte bir kontrol
yapılıyor.
Kış
winterMonths: [
11, 12, 1, 2, 3
]
Soğuk saatler:
winterPriorityHours: [
3, 4, 5, 6, 7, 8, 9
]
Bu saatlerde de sistem saatte bir çalışıyor.
Geçiş Ayları
Nisan, Mayıs ve Ekim:
transitionMonths: [
4, 5, 10
]
Bu dönemlerde normal 3 saatlik kontrol kullanılıyor.
3. Merkezi CONFIG Yapısı
Workflow’un mümkün olduğunca kolay yönetilebilir olması için tüm önemli değerleri tek bir Code node içinde topladım.
Örneğin:
const CONFIG = {
system: {
name: "Loruv Ortam İzleme Sistemi",
timezone: "Europe/Istanbul",
},
api: {
baseUrl: "http://RASPBERRY_PI_IP:8765",
endpoint: "/api/v1/lywsd03mmc-devices",
timeoutMs: 120000,
maxDataAgeMinutes: 15,
},
schedule: {
summerMonths: [6, 7, 8, 9],
summerPriorityHours: [12,13,14,15,16,17,18,19],
winterMonths: [11,12,1,2,3],
winterPriorityHours: [3,4,5,6,7,8,9],
transitionMonths: [4,5,10],
normalIntervalHours: 3,
dailyReportHour: 9,
},
retry: {
httpMaxAttempts: 2,
httpWaitSeconds: 5,
sensorRetryWaitSeconds: 70,
sensorRetryAttempts: 1,
},
alerts: {
warningRepeatMinutes: 180,
criticalRepeatMinutes: 60,
dataFailureRepeatMinutes: 180,
sendDataRecovery: true,
sendEnvironmentRecovery: true,
sendDailyHealthReport: true,
},
hysteresis: {
temperatureC: 2,
humidityPercent: 5,
},
condensation: {
enabled: true,
warningSpreadC: 4,
criticalSpreadC: 2,
},
};
Bu yapı sayesinde workflow’un diğer node’larında sabit değerleri tekrar tekrar yazmak gerekmiyor.
4. Ev ve Çatı Sensörleri
Her sensör API tarafından oluşturulan kalıcı device_id ile takip ediliyor.
Blog yazısında gerçek kimlikler yerine örnek kullanıyorum:
sensors: {
home: {
zoneKey: "home",
name: "Ev",
deviceId: "lywsd03mmc-example-home",
},
attic: {
zoneKey: "attic",
name: "Çatı",
deviceId: "lywsd03mmc-example-attic",
},
}
MAC adresleri alarm workflow’unun temel kimlik mekanizması olarak kullanılmıyor.
5. Elektronik Cihaz Profilleri
Model bazında üretici çalışma limitleri elimde olmadığı için başlangıçta muhafazakâr genel çalışma ortamı varsayımları kullandım.
Ev
Örneğin:
{
name: "Raspberry Pi",
tempMin: 0,
tempMax: 50,
humidityMin: 10,
humidityMax: 80,
},
{
name: "SSD",
tempMin: 0,
tempMax: 50,
humidityMin: 10,
humidityMax: 80,
},
{
name: "Modem",
tempMin: 0,
tempMax: 40,
humidityMin: 10,
humidityMax: 80,
},
{
name: "LCD TV",
tempMin: 0,
tempMax: 40,
humidityMin: 20,
humidityMax: 80,
},
{
name: "Robot Süpürge",
tempMin: 5,
tempMax: 40,
humidityMin: 10,
humidityMax: 80,
}
Ortak Güvenli Aralığın Otomatik Hesaplanması
Workflow her cihazın limitini ayrı ayrı kontrol etmek yerine bütün cihazların birlikte güvenli kalacağı ortak aralığıhesaplıyor.
Örneğin:
Raspberry Pi 0–50 °C
SSD 0–50 °C
Modem 0–40 °C
LCD TV 0–40 °C
Robot Süpürge 5–40 °C
ortak sonuç:
5–40 °C
oluyor.
Kod:
const tempMin =
Math.max(...tempMins);
const tempMax =
Math.min(...tempMaxs);
Aynı yöntem nem için de uygulanıyor.
Bu tasarımın en güzel taraflarından biri şu:
Daha sonra gerçek cihaz datasheet’i bulunursa yalnızca cihaz profilindeki değer değiştirilir.
Alarm algoritmasına dokunmaya gerek kalmaz.
Warning Seviyeleri
Critical seviyeye ulaşmadan önce haber almak için warning margin kullandım.
Örneğin:
warningMargins: {
temperatureUpperC: 5,
temperatureLowerC: 3,
humidityUpperPercent: 5,
humidityLowerPercent: 5,
}
Çatı için kritik üst sıcaklık:
40 °C
ise warning:
35 °C
seviyesinde başlıyor.
Bu, özellikle güç adaptörleri için önemli.
Ortam 40 °C olduğunda adaptörün kendi içerisindeki güç elektroniği doğal olarak daha yüksek sıcaklığa ulaşabilir.
6. Loruv Climate Bridge API Çağrısı
n8n iki sensör için ayrı API isteği göndermiyor.
Tek endpoint kullanılıyor:
GET /api/v1/lywsd03mmc-devices
Böylece Climate Bridge:
BLE scan
↓
Tüm LYWSD03MMC cihazlarını bul
↓
Sensörleri sırayla oku
↓
Tek snapshot üret
↓
JSON döndür
işlemini bir kez gerçekleştiriyor.
Bu hem BLE yükünü hem de gereksiz bağlantıları azaltıyor.
HTTP Retry
HTTP Request node:
Retry On Fail: ON
Max Tries: 2
Wait Between Tries: 5000 ms
olarak ayarlandı.
Ayrıca:
On Error:
Continue (using error output)
kullanıldı.
Bu sayede API’ye ulaşılamadığında workflow tamamen çöküp durmuyor.
Hata ayrı bir branch üzerinden alarm sistemine aktarılıyor.
7. Sensör Seviyesi Retry
HTTP isteğinin başarılı olması sensörlerin başarıyla okunduğu anlamına gelmiyor.
Örneğin API:
{
"success": false,
"device_count": 2
}
dönebilir.
Bir sensör:
status: error
iken diğeri:
status: online
olabilir.
Bu nedenle ayrıca sensör-seviyesi retry tasarladım.
İlk okuma başarısızsa:
70 saniye bekle
↓
API'yi tekrar çağır
70 saniye seçilmesinin nedeni Climate Bridge API’nin 60 saniyelik RAM cache kullanması.
5 saniye sonra yeniden çağrı yapılırsa aynı başarısız snapshot tekrar gelebilir.
70 saniye sonunda yeni BLE scan ve GATT okuması tetikleniyor.
8. Sensör Verilerinin Ayrılması
API cevabındaki:
"devices": []
array’i içerisinden cihazlar device_id ile bulunuyor.
Örneğin:
const device =
devices.find(
item =>
item.device_id ===
sensorConfig.deviceId
);
Her sensör bağımsız olarak hazırlanıyor.
Bu çok önemli çünkü:
Ev ❌
Çatı ✅
durumunda sistem:
Ev için veri alarmı üret
+
Çatı ortam analizine devam et
şeklinde davranıyor.
9. Veri Doğrulama
Her sensör için kontrol edilen alanlar:
- Cihaz bulundu mu?
status == onlinemı?- Sıcaklık var mı?
- Nem var mı?
- Nem 0–100 arasında mı?
read_atgeçerli mi?- Veri çok eski mi?
Örneğin:
if (
dataAgeMinutes >
CONFIG.api.maxDataAgeMinutes
) {
errors.push(
"Sensör verisi eski."
);
}
Bu sayede stale bir değer güvenilir sensör verisi olarak kullanılmıyor.
10. Son Bir Saatlik Verilerin Kullanılması
LYWSD03MMC’nin doğrudan okunabilen son saat kaydı da analiz ediliyor.
Kullanılan alanlar:
temperature_max_c
temperature_min_c
humidity_max_percent
humidity_min_percent
Örneğin n8n sensörü saat 15:05’te kontrol ettiğinde:
Şu an:
38.0 °C
ama:
Son 1 saat maximum:
41.2 °C
ise sistem sadece mevcut 38 °C değerine bakıp geçmiyor.
41.2 °C’lik kritik olay da tespit ediliyor.
11. Dew Point — Çiğ Noktası
Sadece bağıl nem değerini değerlendirmek yerine dew point hesabı da sisteme dahil edildi.
Magnus yaklaşımı kullanılıyor:
const a = 17.62;
const b = 243.12;
const gamma =
Math.log(humidity / 100) +
(a * temperature) /
(b + temperature);
const dewPoint =
(b * gamma) /
(a - gamma);
Daha sonra:
Ortam sıcaklığı - Dew Point
farkı hesaplanıyor.
Yoğuşma Riski
Örneğin:
Ortam sıcaklığı: 22 °C
Dew Point: 20 °C
Fark: 2 °C
ise yüksek yoğuşma riski kabul ediliyor.
Konfigürasyon:
condensation: {
warningSpreadC: 4,
criticalSpreadC: 2,
}
Buradaki önemli ayrım:
Bu hesap elektronik cihazın yüzey sıcaklığını ölçmediği için “kesin yoğuşma var” anlamına gelmez.
Yalnızca ortam koşullarının yoğuşmaya yaklaşmasını gösteren bir risk metriğidir.
12. Hysteresis
Alarm sistemlerinde en önemli konulardan biri eşik etrafındaki dalgalanmadır.
Örneğin kritik sınır:
40 °C
olduğunda sıcaklık:
40.1
39.9
40.1
39.8
şeklinde değişirse basit bir sistem:
🚨 Critical
✅ Normal
🚨 Critical
✅ Normal
mesajları gönderebilir.
Bunu engellemek için hysteresis kullandım.
hysteresis: {
temperatureC: 2,
humidityPercent: 5,
}
40 °C’de kritik olan bir ortam hemen 39.9 °C’de normal kabul edilmiyor.
Yaklaşık:
38 °C
seviyesine dönmesi bekleniyor.
13. State Machine
Her bölge için aşağıdaki durumlar tutuluyor:
normal
warning
critical
unavailable
Geçişler:
NORMAL
↓
WARNING
↓
CRITICAL
ve recovery:
CRITICAL
↓
WARNING
↓
NORMAL
şeklinde değerlendiriliyor.
n8n workflow static data kullanılarak önceki durum hatırlanıyor.
Örneğin:
const storage =
$getWorkflowStaticData("global");
Bu sayede her workflow çalışması birbirinden tamamen bağımsız değil.
14. Alarm Spam Koruması
Bir ortam 4 saat boyunca kritik kalırsa her kontrol sırasında aynı mesaj gönderilmiyor.
Konfigürasyon:
alerts: {
warningRepeatMinutes: 180,
criticalRepeatMinutes: 60,
dataFailureRepeatMinutes: 180,
}
Yani:
Warning:
3 saatte bir tekrar
Critical:
1 saatte bir tekrar
Sensör/API problemi:
3 saatte bir tekrar
15. Sensör Veri Hatası
Sensör bulunamıyorsa Telegram mesajı hazırlanıyor.
Örnek:
🔴 EV SENSÖR VERİ HATASI
Loruv Ortam İzleme Sistemi Ev sensöründen
geçerli veri alamadı.
Tespit edilen sorunlar:
• Ev sensörü API cevabında bulunamadı.
Ardışık başarısız kontrol: 1
Sensör bulundu: Hayır
Sensör durumu: Bilinmiyor
Diğer çalışan sensörler izlenmeye devam edecektir.
16. API Tamamen Kapalıysa
Sadece BLE cihazlarının değil API’nin kendisinin de çökebileceğini dikkate aldım.
Örneğin:
- Raspberry Pi kapalı
- Climate Bridge container durmuş
- Port 8765 erişilemiyor
- Docker network problemi var
HTTP Request’in Error branch’i:
API Erişim Hatasını Hazırla
Code node’una bağlanıyor.
Bu node iki sensörü de:
status = api_unreachable
durumuna getiriyor.
Sonrasında mevcut veri alarm sistemi aynı mekanizmayla Telegram uyarısını üretiyor.
Bu sayede ayrı bir ikinci alarm altyapısı yazmak gerekmedi.
17. RSSI İzleme
BLE bağlantısının kalitesi için RSSI da takip ediliyor.
Konfigürasyon:
sensorHealth: {
weakSignalDbm: -90,
criticalSignalDbm: -100,
}
RSSI zayıflarsa ortam alarmından ayrı bir:
📡 SENSOR SIGNAL WARNING
oluşturulabiliyor.
Sinyal tekrar düzeldiğinde recovery mesajı üretilebiliyor.
18. Pil Takibi
LYWSD03MMC stock firmware tarafından raporlanan pil yüzdesi her zaman güvenilir olmadığı için gerçek voltajı da API üzerinden kullanıyorum.
Örneğin:
{
"voltage_v": 2.94,
"reported_percent": 100
}
Şimdilik voltaj alarm eşiklerini bilinçli olarak aktif etmedim.
Gerçek cihazların pil davranışı gözlemlendikten sonra merkezi CONFIG içinden kolayca aktif edilebilir.
19. Ortam Alarm Motoru
Gerçek ortam alarm motoru şu verilerin tamamını birlikte değerlendiriyor:
Anlık sıcaklık
+
Anlık nem
+
Son 1 saat max sıcaklık
+
Son 1 saat min sıcaklık
+
Son 1 saat max nem
+
Son 1 saat min nem
+
Dew Point
+
Dew Point spread
+
Bölge cihaz limitleri
+
Warning limitleri
+
Hysteresis
+
RSSI
+
Önceki alarm state
Bu nedenle karar basit bir IF temperature > 40 kontrolünden daha güçlü.
20. Telegram Bildirim Yapısı
Bildirimler Code node içerisinde bir array olarak oluşturuluyor:
notifications.push({
type:
"environment_critical",
severity:
"critical",
zoneKey:
zoneKey,
zoneName:
zone.zoneName,
message:
telegramMessage,
});
Daha sonra:
Ortam Bildirimlerini Ayır
node’u her notification’ı ayrı n8n item’ına dönüştürüyor.
Bu sayede aynı çalışmada:
Ev Warning
+
Çatı Critical
+
RSSI Warning
oluşursa Telegram node’u üç ayrı mesaj gönderebiliyor.
Örnek Kritik Alarm
Telegram mesajı örneği:
🚨 ÇATI ORTAM KRİTİK ALARMI
• Sıcaklık üst kritik sınırı aştı:
41.2 °C ≥ 40 °C
🌡 Şu an: 41.2 °C
💧 Nem: %31
📊 Son 1 Saat
🔥 Max sıcaklık: 42.0 °C
❄️ Min sıcaklık: 37.8 °C
💧 Max nem: %35
💧 Min nem: %28
🌫 Çiğ noktası: 19.1 °C
↔️ Çiğ noktası farkı: 22.1 °C
💨 Yoğuşma riski: normal
📶 BLE RSSI: -59 dBm
🔋 Sensör pili: 2.94 V
📋 Kritik ortam aralığı
🌡 0–40 °C
💧 %10–80
⚙️ Üst sıcaklık limitini belirleyen ekipman:
12V Güç Adaptörleri
🚨 DURUM: KRİTİK
21. Günlük Sağlık Raporu
Alarm gelmemesi sistemin çalışmadığı anlamına gelebileceği için ayrıca günlük sağlık raporu ekledim.
Her gün:
09:05
civarında Telegram üzerinden:
📋 LORUV GÜNLÜK ORTAM SAĞLIK RAPORU
gönderiliyor.
Örneğin:
✅ Ev
🌡 23.8 °C
💧 %44
🔥 1 sa. max: 24.1 °C
❄️ 1 sa. min: 23.5 °C
🌫 Dew point: 11.2 °C
📶 -72 dBm
🔋 2.91 V
📊 Durum: normal
✅ Çatı
🌡 28.3 °C
💧 %29
🔥 1 sa. max: 28.8 °C
❄️ 1 sa. min: 28.4 °C
🌫 Dew point: 8.6 °C
📶 -60 dBm
🔋 2.94 V
📊 Durum: normal
Böylece hiç alarm gelmese bile otomasyonun ve sensörlerin çalıştığı günlük olarak doğrulanabiliyor.
Sistemin Hata Toleransı
Workflow’un en önemli özelliklerinden biri tek bir arızanın bütün sistemi durdurmaması.
Örneğin:
Ev Sensor ❌
Çatı Sensor ✅
ise:
Ev
→ veri alarmı
Çatı
→ sıcaklık/nem analizi devam
eder.
Çatı 41 °C olursa aynı çalışmada:
🔴 EV SENSÖR VERİ HATASI
ve:
🚨 ÇATI ORTAM KRİTİK ALARMI
birlikte alınabilir.
Kullanılan Teknolojiler
IoT / Bluetooth
- Xiaomi LYWSD03MMC
- Bluetooth Low Energy
- BlueZ
- GATT
- Bleak
Backend
- Python
- FastAPI
- Uvicorn
- REST API
- JSON
Infrastructure
- Raspberry Pi
- Docker
- Docker Compose
- Portainer
Automation
- n8n
- Schedule Trigger
- HTTP Request
- IF
- Wait
- Code Nodes
- Workflow Static Data
Notification
- Telegram Bot API
- HTML formatted messages
Sonuç
Bu proje ile daha önce geliştirdiğim BLE Climate Bridge API’nin üzerine tam kapsamlı bir otomasyon ve alarm katmanı ekledim.
Ortaya çıkan sistem artık yalnızca:
Sensörü oku
→ sıcaklık yüksekse mesaj gönder
mantığında değil.
Bunun yerine:
Mevsimi belirle
↓
Doğru kontrol zamanını seç
↓
API'yi kontrol et
↓
Gerekirse HTTP retry
↓
Sensörleri oku
↓
Gerekirse BLE seviyesinde retry
↓
Ev ve Çatı'yı bağımsız doğrula
↓
Anlık değerleri analiz et
↓
Son 1 saati kontrol et
↓
Dew point hesapla
↓
Elektronik cihaz limitlerini değerlendir
↓
Hysteresis uygula
↓
Önceki alarm state'ini kontrol et
↓
Spam kontrolü yap
↓
Telegram bildirimi gönder
↓
Recovery durumunu takip et
şeklinde çalışan gerçek bir IoT environment monitoring pipeline haline geldi.
Bu mimari ileride farklı BLE sensörleri, yeni odalar, sunucu odaları veya farklı alarm kanalları eklemek için de genişletilebilir.
English
Loruv Environment Monitoring System: Smart Temperature and Humidity Monitoring with n8n, Raspberry Pi, BLE Sensors and Telegram
Project Overview
In this project, I built a complete environment monitoring and alert automation system on top of my previously developed Loruv LYWSD03MMC BLE Climate Bridge API.
The purpose of the system is to monitor the operating environment of electronic equipment located in two different zones — Home and Attic — and generate intelligent Telegram alerts when temperature, humidity, connectivity or sensor conditions become unsafe.
This is not a simple:
temperature > 40
→ send Telegram message
workflow.
The final architecture includes:
- Seasonal scheduling
- Different summer and winter monitoring periods
- Hourly monitoring during critical periods
- Three-hour monitoring outside priority periods
- Current temperature monitoring
- Current humidity monitoring
- Last-hour minimum and maximum analysis
- Dew point calculation
- Condensation risk estimation
- Equipment-specific operating limits
- Automatically calculated common safe ranges
- Warning and Critical states
- Hysteresis
- HTTP retry
- Sensor-level BLE retry
- API availability monitoring
- Independent Home and Attic monitoring
- RSSI health monitoring
- Battery voltage monitoring
- Alert deduplication
- Persistent state management
- Recovery notifications
- Daily health reports
- Telegram HTML messages
Architecture
LYWSD03MMC BLE Sensors
│
▼
Raspberry Pi / BlueZ
│
▼
Loruv BLE Climate Bridge API
│
▼
n8n Monitoring Workflow
│
├── Scheduling
├── Retry
├── Validation
├── Temperature
├── Humidity
├── Last-hour history
├── Dew Point
├── Hysteresis
├── Sensor Health
└── State Machine
│
▼
Telegram
The separation between BLE communication and automation was intentional.
Bluetooth and GATT communication are handled by the Climate Bridge API, while n8n communicates only through HTTP and JSON.
Seasonal Monitoring
The workflow is triggered every hour at minute five:
5 * * * *
Timezone:
Europe/Istanbul
The real monitoring decision is made by a centralized Code node.
Summer
summerMonths: [6, 7, 8, 9]
Priority hours:
summerPriorityHours: [
12, 13, 14, 15,
16, 17, 18, 19
]
During these hours the environment is checked every hour.
Outside the priority period:
Every 3 hours
Winter
winterMonths: [
11, 12, 1, 2, 3
]
Cold priority hours:
winterPriorityHours: [
3, 4, 5, 6, 7, 8, 9
]
Again, monitoring becomes hourly during the coldest expected period.
Central Configuration
All important settings are stored in one central configuration object.
const CONFIG = {
system: {
name: "Loruv Environment Monitoring System",
timezone: "Europe/Istanbul",
},
api: {
baseUrl: "http://RASPBERRY_PI_IP:8765",
endpoint: "/api/v1/lywsd03mmc-devices",
timeoutMs: 120000,
maxDataAgeMinutes: 15,
},
schedule: {
summerMonths: [6,7,8,9],
summerPriorityHours: [12,13,14,15,16,17,18,19],
winterMonths: [11,12,1,2,3],
winterPriorityHours: [3,4,5,6,7,8,9],
normalIntervalHours: 3,
dailyReportHour: 9,
},
retry: {
httpMaxAttempts: 2,
httpWaitSeconds: 5,
sensorRetryWaitSeconds: 70,
sensorRetryAttempts: 1,
},
alerts: {
warningRepeatMinutes: 180,
criticalRepeatMinutes: 60,
dataFailureRepeatMinutes: 180,
sendDataRecovery: true,
sendEnvironmentRecovery: true,
sendDailyHealthReport: true,
},
};
This makes future maintenance much easier.
Equipment Profiles
The Home zone includes:
- Raspberry Pi
- SSD
- Modem/router
- LCD TV
- Robot vacuum
- Surge-protected power strip
The Attic includes:
- DVR
- 12 V power adapters
- CCTV equipment
- Audio equipment
Because exact manufacturer specifications were not available for every device, conservative initial environmental limits were used.
These values can later be replaced with exact manufacturer specifications without modifying the alarm algorithm.
Automatic Safe Range Calculation
Each device can have its own environmental limits.
For example:
Raspberry Pi 0–50 °C
SSD 0–50 °C
Router 0–40 °C
LCD TV 0–40 °C
Robot Vacuum 5–40 °C
The common safe range becomes:
5–40 °C
The algorithm calculates this using:
const minTemperature =
Math.max(...deviceMinimums);
const maxTemperature =
Math.min(...deviceMaximums);
The most restrictive device automatically defines the zone limit.
Warning Margins
Warnings are generated before a critical threshold is reached.
Example configuration:
warningMargins: {
temperatureUpperC: 5,
temperatureLowerC: 3,
humidityUpperPercent: 5,
humidityLowerPercent: 5,
}
If the critical maximum temperature is:
40 °C
the warning begins around:
35 °C
This provides early warning before electronics reach the configured environmental limit.
Single API Snapshot
n8n does not request each sensor separately.
Instead:
GET /api/v1/lywsd03mmc-devices
is used.
The Climate Bridge then performs:
BLE scan
↓
Discover compatible sensors
↓
Read each sensor sequentially
↓
Create one snapshot
↓
Return JSON
This minimizes unnecessary Bluetooth activity.
HTTP Retry
The HTTP Request nodes use:
Retry On Fail: Enabled
Max Tries: 2
Wait Between Tries: 5000 ms
and:
On Error:
Continue using error output
Therefore, an HTTP failure does not terminate the entire automation.
Sensor-Level Retry
A successful HTTP request does not necessarily mean all BLE sensors were read successfully.
A sensor may still return:
status: error
For this reason, an additional sensor-level retry is performed.
Initial sensor request
↓
Invalid sensor?
↓
Wait 70 seconds
↓
Request a new BLE snapshot
The 70-second delay is intentional because the Climate Bridge API uses a 60-second RAM cache.
Waiting longer than the cache TTL ensures that the retry can trigger a new BLE scan instead of receiving the previous failed snapshot.
Independent Zone Monitoring
One of the most important design decisions was to never discard valid sensor data just because another sensor failed.
For example:
Home ❌
Attic ✅
results in:
Home
→ data failure alert
Attic
→ environment monitoring continues
This prevents a single BLE problem from blinding the entire monitoring system.
Data Validation
Each zone validates:
- Device presence
- Online status
- Temperature
- Humidity
- Valid humidity range
- Read timestamp
- Data age
- Last-hour information
- RSSI
- Battery information
Stale data is rejected instead of being treated as current sensor information.
Last-Hour Analysis
The system also evaluates the directly readable last-hour history record.
This includes:
temperature_max_c
temperature_min_c
humidity_max_percent
humidity_min_percent
For example:
Current temperature:
38 °C
Last-hour maximum:
41.2 °C
The system can still generate a critical event based on the recorded 41.2 °C peak.
Dew Point
Dew point is calculated using the Magnus approximation.
const a = 17.62;
const b = 243.12;
const gamma =
Math.log(relativeHumidity / 100) +
(a * temperature) /
(b + temperature);
const dewPoint =
(b * gamma) /
(a - gamma);
The workflow then calculates:
Temperature - Dew Point
to estimate condensation risk.
Condensation Risk
Configuration:
condensation: {
warningSpreadC: 4,
criticalSpreadC: 2,
}
For example:
Ambient temperature: 22 °C
Dew point: 20 °C
Spread: 2 °C
is treated as a high condensation-risk environment.
This does not prove that condensation exists on an electronic device because surface temperature is not directly measured.
It is instead used as an environmental warning indicator.
Hysteresis
Hysteresis prevents notification spam around alarm thresholds.
Without hysteresis:
40.1 °C → Critical
39.9 °C → Normal
40.1 °C → Critical
39.8 °C → Normal
could generate repeated notifications.
Configuration:
hysteresis: {
temperatureC: 2,
humidityPercent: 5,
}
A critical state therefore requires the environment to move clearly back into the safe range before recovery is declared.
Persistent State Machine
Each zone maintains a persistent state:
normal
warning
critical
unavailable
The workflow uses:
$getWorkflowStaticData("global")
to remember previous conditions.
This enables meaningful state transitions instead of stateless comparisons.
Notification Throttling
Repeated alarms are controlled with:
warningRepeatMinutes: 180
criticalRepeatMinutes: 60
dataFailureRepeatMinutes: 180
This prevents Telegram from being flooded with duplicate alerts.
API Failure Handling
The workflow also handles complete API failure.
Examples:
- Raspberry Pi offline
- Climate Bridge container stopped
- Port unavailable
- Docker network failure
After both HTTP attempts fail, the API error is converted into the same normalized zone structure used by sensor errors.
Both zones are marked unavailable and the existing data-monitoring alarm engine handles the notification.
This keeps the architecture consistent.
RSSI Monitoring
BLE signal strength is monitored independently.
sensorHealth: {
weakSignalDbm: -90,
criticalSignalDbm: -100,
}
Weak BLE connectivity can therefore generate a separate sensor health warning without being confused with environmental danger.
Battery Monitoring
The stock LYWSD03MMC firmware may report an unreliable battery percentage, so battery voltage is retained separately.
Example:
{
"voltage_v": 2.94,
"reported_percent": 100
}
Automatic voltage alarms can later be enabled from the central configuration after enough real-world battery behavior has been observed.
Telegram Notifications
Notifications are built as structured objects:
notifications.push({
type: "environment_critical",
severity: "critical",
zoneKey: zoneKey,
zoneName: zone.zoneName,
message: telegramMessage,
});
A separate Code node converts each notification into an individual n8n item.
This allows one workflow execution to send multiple Telegram messages when necessary.
Example Critical Alert
🚨 ATTIC ENVIRONMENT CRITICAL ALERT
Temperature exceeded the critical maximum:
41.2 °C ≥ 40 °C
Current:
🌡 41.2 °C
💧 31 %
Last Hour:
🔥 Maximum: 42.0 °C
❄️ Minimum: 37.8 °C
💧 Humidity max: 35 %
💧 Humidity min: 28 %
Dew Point: 19.1 °C
Dew Point Spread: 22.1 °C
BLE RSSI: -59 dBm
Sensor Battery: 2.94 V
Configured Safe Environment:
0–40 °C
10–80 % RH
Limiting equipment:
12V Power Adapters
STATUS: CRITICAL
Daily Health Report
Every morning at approximately:
09:05
a daily system report can be sent.
The report includes:
- Current temperature
- Current humidity
- Last-hour maximum
- Last-hour minimum
- Dew point
- RSSI
- Battery voltage
- Zone status
This provides positive confirmation that the monitoring system is still alive even when no alarms have occurred.
Technologies Used
IoT / BLE
- LYWSD03MMC
- Bluetooth Low Energy
- BlueZ
- GATT
- Bleak
Backend
- Python
- FastAPI
- Uvicorn
- REST
- JSON
Infrastructure
- Raspberry Pi
- Docker
- Docker Compose
- Portainer
Automation
- n8n
- Schedule Trigger
- HTTP Request
- Wait
- IF
- JavaScript Code Nodes
- Workflow Static Data
Notifications
- Telegram Bot
- HTML formatted messages
Final Result
The final system is no longer a basic sensor notification workflow.
It operates as a complete environment monitoring pipeline:
Determine season
↓
Determine monitoring schedule
↓
Query Climate Bridge
↓
Retry network failures
↓
Validate BLE sensors
↓
Retry failed sensor reads
↓
Process Home and Attic independently
↓
Analyze current values
↓
Analyze last-hour extremes
↓
Calculate dew point
↓
Evaluate equipment limits
↓
Apply hysteresis
↓
Check persistent alarm state
↓
Throttle duplicate notifications
↓
Send Telegram alerts
↓
Track recovery states
↓
Generate daily health reports
The architecture is intentionally modular, making it possible to add more sensors, additional rooms, server cabinets, different notification channels or new IoT devices in the future.
This project turned the Loruv BLE Climate Bridge API into a complete IoT environmental monitoring and alerting platform.









Bir yanıt yazın