, , , , , , , , , , , , , ,

Loruv Ortam İzleme Sistemi: n8n, Raspberry Pi, BLE Sensörler ve Telegram ile Akıllı Sıcaklık/Nem Alarm Otomasyonu

Loruv Ortam İzleme Sistemi: n8n, Raspberry Pi, BLE Sensörler ve Telegram ile Akıllı Sıcaklık/Nem Alarm Otomasyonu

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 == online mı?
  • Sıcaklık var mı?
  • Nem var mı?
  • Nem 0–100 arasında mı?
  • read_at geç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

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir



    Şimdi Ara +90 551 000 17 59