the word microsoft spelled with white letters on a black background — Azure IoT Hub: Nesnelerin İnterneti ile Akıllı İş

Diyarbakır merkezli 280 üyeli bir tarım kooperatifi, sulama ve gübreleme verimini artırmak için 4.200 toprak/iklim/sulama sensörünü Azure IoT Hub ile yönetmeye karar verdi. 9 ay sonunda su tüketimi %22 azaldı, gübre maliyetleri %18 düştü, verim %14 arttı. Bu yazı projenin sahadaki teknik notlarını paylaşıyor.

Mimari Genel Bakış

  • 4.200 cihaz: 2.800 toprak nemi/sıcaklık (LoRaWAN gateway üzerinden), 800 hava istasyonu (NB-IoT), 600 sulama vana kontrolcüsü (LTE-M)
  • Azure IoT Hub Standard S2 (1.5M msg/gün): cihaz yönetimi, mesaj routing
  • IoT Edge gateway: Tarla başlarında 38 Edge cihaz (downstream sensörlerin lokal aggregation’ı)
  • Device Provisioning Service (DPS): Otomatik cihaz kayıt
  • Stream Analytics: Real-time anomali (anormal sıcaklık, vana kaçağı)
  • Cosmos DB: Telemetri (12 ay hot)
  • Azure Data Explorer: Time-series analytics, dashboard
  • Azure Functions: Sulama kararı (toprak nemi eşiğine göre vana açma komutu)

Device Provisioning Service (DPS)

4.200 cihazı manuel kaydetmek imkansız. DPS ile X.509 sertifika tabanlı zero-touch provisioning:

using var security = new SecurityProviderX509Certificate(deviceCert);
using var transport = new ProvisioningTransportHandlerAmqp();

var provClient = ProvisioningDeviceClient.Create(
    "global.azure-devices-provisioning.net",
    "0ne00ABCDEF",  // ID Scope
    security,
    transport);

var result = await provClient.RegisterAsync();
// result.AssignedHub: "iot-tarim-prod.azure-devices.net"
// result.DeviceId: cihaz seri numarası

using var iotClient = DeviceClient.Create(
    result.AssignedHub,
    new DeviceAuthenticationWithX509Certificate(result.DeviceId, deviceCert),
    TransportType.Mqtt);

Cihaz tarlaya yerleştirilip ilk kez bağlanınca DPS hangi IoT Hub’a yönlendireceğine karar veriyor (allocation policy: load balancing).

Message Routing

Tek IoT Hub’a düşen mesajlar tipine göre farklı destination’lara routing edildi:

# Telemetri (toprak nemi, sıcaklık) → Cosmos DB
az iot hub route create -g rg-iot --hub-name iot-tarim-prod 
  --route-name r-telemetry 
  --source devicemessages 
  --condition "messageType = 'telemetry'" 
  --endpoint-name eh-telemetry 
  --enabled true

# Alarm (vana kaçağı) → Service Bus → Functions
az iot hub route create -g rg-iot --hub-name iot-tarim-prod 
  --route-name r-alarms 
  --source devicemessages 
  --condition "messageType = 'alarm' AND severity > 'warning'" 
  --endpoint-name sb-alarms 
  --enabled true

# Diagnostics (cihaz durum) → Log Analytics
az iot hub route create -g rg-iot --hub-name iot-tarim-prod 
  --route-name r-diag 
  --source devicemessages 
  --condition "messageType = 'diagnostics'" 
  --endpoint-name la-diag 
  --enabled true

IoT Edge: Tarla Başında Lokal İşleme

38 Edge gateway her biri ~110 sensörü topluyor. Cloud bağlantısı koptuğunda son 24 saat lokal storage’da, bağlantı geri gelince batch upload. Lokal anomali detection da Edge’de:

version: '3'
modules:
  edgeAgent:
    image: mcr.microsoft.com/azureiotedge-agent:1.4
  
  edgeHub:
    image: mcr.microsoft.com/azureiotedge-hub:1.4
    environment:
      OptimizeForPerformance: false
      MqttSettings__Enabled: true
  
  sensorAggregator:
    image: tarim.azurecr.io/sensor-agg:1.2
    createOptions:
      HostConfig:
        Binds: ["/data:/data"]
  
  anomalyDetector:
    image: tarim.azurecr.io/anomaly:1.5
    routes:
      sensorIn: FROM /messages/modules/sensorAggregator/* INTO BrokeredEndpoint("/modules/anomalyDetector/inputs/sensors")

Sulama Otomasyonu (Cloud-to-Device)

Toprak nemi % 35’in altına düşünce Azure Functions vana cihazına direct method çağırıyor:

[Function("IrrigationDecider")]
public async Task Run(
    [CosmosDBTrigger("telemetry", "soil", LeaseContainerName = "leases")]
    IReadOnlyList<SoilReading> readings)
{
    foreach (var r in readings.Where(x => x.MoisturePct < 35))
    {
        var valveDevice = $"valve-{r.FieldId}";
        var method = new CloudToDeviceMethod("OpenValve")
            .SetPayloadJson($@"{{""durationMinutes"":{CalcDuration(r)}}}");
        
        var resp = await _serviceClient.InvokeDeviceMethodAsync(valveDevice, method);
        await _audit.LogAsync(r.FieldId, resp.Status);
    }
}

OTA Firmware Update

4.200 cihaza fiziksel erişim imkansız. Device Update for IoT Hub (ADU) ile OTA güncelleme:

# Yeni firmware import
az iot du update import 
  --account adu-tarim --instance prod 
  --update-source ./firmware-1.5.0.json

# Deployment grup oluştur (sadece soil sensörler)
az iot du deployment create 
  --account adu-tarim --instance prod 
  --deployment-id soil-fw-1.5.0 
  --group-id soil-sensors 
  --update-name soil-firmware --update-version 1.5.0

Strateji: %5 canary, 24 saat metrik takibi, sonra %100 rollout.

Maliyet

Servis Aylık (USD)
IoT Hub Standard S2 (1.5M msg/gün quota) 250
DPS ~~5
IoT Edge (free tier) 0
Stream Analytics (3 SU) 240
Cosmos DB (autoscale 1K-10K RU/s) ~~340
Azure Data Explorer (Dev SKU 2 vCPU) ~~280
Functions + Storage ~~25
NB-IoT/LTE-M data plan (operatör) ~~480
Toplam ~~$1.620

4.200 cihaz başına ~$0.39/ay. Tasarruf: yıllık ~~480.000 TL su+gübre maliyeti azalması.

Sahada Düşülen Üç Tuzak

  1. Cihaz başına ayrı bağlantı kurmak: 4.200 doğrudan bağlantı IoT Hub quota’sını yer. Edge gateway aggregation şart.
  2. Telemetriyi sadece Cosmos’ta tutmak: 12 ay sonra Cosmos pahalı. ADX veya cold storage’a archival politikası kurulmalı.
  3. OTA’yı tek seferde tüm filoya yapmak: Bozuk firmware tüm filoyu offline bırakır. Canary + faz şart.

CloudSpark olarak Azure IoT Hub mimarisi, IoT Edge deployment, DPS otomasyonu, OTA firmware ve endüstriyel IoT projeleri için danışmanlık veriyoruz.

🇹🇷 Türkçe🇬🇧 English🇩🇪 Deutsch🇫🇷 Français🇸🇦 العربية🇷🇺 Русский🇪🇸 Español