AWS IoT Core ile Endüstriyel Veri Toplama: ZMA Cihazlarından Buluta

Amazeng Teknik Ekip
12 dakika okuma
AWS IoT CoreMQTTZMAGDTModbus GatewayCloud IoTEndüstriyel IoT

Giriş

Endüstriyel verilerin buluta taşınması, Endüstri 4.0 ve kestirimci bakım süreçlerinin temel taşıdır. Ancak sahada sensörlerle toplanan veriler genellikle Modbus RTU veya Modbus TCP gibi geleneksel protokollerle iletişim kurar. Bu verileri AWS IoT Core gibi bulut platformlarına taşımak için bir IoT Gateway gereklidir.

Bu yazımızda, ZMA Data Acquisition ve GDT Dijital Transmitter cihazlarımızdan Modbus ile toplanan verilerin, IoT Gateway üzerinden AWS IoT Core'a nasıl aktarıldığını detaylıca inceliyoruz.

Mimari Genel Bakış

┌─────────────────────────────────────────────────────────────┐
│                    Fabrika / Saha                           │
│                                                             │
│  ┌─────────┐    Modbus RTU/TCP    ┌──────────────┐        │
│  │ ZMA-4   │◄────────────────────►│              │        │
│  │ Cihazı  │                      │  IoT Gateway │        │
│  └─────────┘                      │  (Linux Box) │        │
│                                   │              │        │
│  ┌─────────┐    Modbus RTU/TCP    │  - Modbus    │        │
│  │ GDT     │◄────────────────────►│    Client    │        │
│  │ Trans.  │                      │  - MQTT      │        │
│  └─────────┘                      │    Client    │        │
│                                   │  - TLS/SSL   │        │
│                                   └───────┬──────┘        │
└───────────────────────────────────────────┼───────────────┘
                                            │
                                            │ MQTT over TLS
                                            │ Port 8883
                                            ▼
                                   ┌────────────────┐
                                   │   AWS Cloud    │
                                   │                │
                                   │  ┌──────────┐  │
                                   │  │ IoT Core │  │
                                   │  └────┬─────┘  │
                                   │       │        │
                                   │  ┌────▼─────┐  │
                                   │  │Timestream│  │
                                   │  └──────────┘  │
                                   └────────────────┘

Önemli Not: IoT Gateway Gerekliliği

ZMA ve GDT cihazlarımız Modbus RTU (RS485) ve Modbus TCP (Ethernet) protokolleri ile haberleşir. AWS IoT Core ise MQTT protokolünü kullanır. Bu iki dünya arasında protokol dönüşümü yapacak bir IoT Gateway cihazına ihtiyaç vardır.

Gateway Seçenekleri

  1. Raspberry Pi / Jetson Nano: Linux tabanlı, Python/Node.js ile özel script
  2. Endüstriyel IoT Gateway'ler: Moxa, Advantech, Siemens gibi hazır çözümler
  3. HMI Panelimiz: Embedded Linux üzerinde hem HMI hem gateway görevini yapabilir
  4. PLC + OPC UA: PLC'nin OPC UA server'ı üzerinden buluta bağlantı

Bu yazımızda Raspberry Pi 4 + Python ile özel gateway çözümünü inceleyeceğiz, ancak aynı mantık tüm platformlarda geçerlidir.

AWS IoT Core Kurulumu

1. Thing (Cihaz) Oluşturma

AWS Console → IoT Core → Manage → Things → Create

{
  "thingName": "amazeng-factory-gateway-01",
  "thingTypeName": "ModbusGateway",
  "attributes": {
    "location": "Istanbul-Factory-A",
    "firmware": "1.0.0"
  }
}

2. Certificate Oluşturma ve İndirme

Her IoT cihazı AWS'ye X.509 sertifikası ile bağlanır:

# AWS CLI ile certificate oluştur
aws iot create-keys-and-certificate \
  --set-as-active \
  --certificate-pem-outfile gateway-cert.pem \
  --public-key-outfile gateway-public.key \
  --private-key-outfile gateway-private.key

Önemli: gateway-private.key dosyasını güvenli saklayin, bir daha indirilemez!

3. Policy (İzin) Tanımlama

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["iot:Connect"],
      "Resource": "arn:aws:iot:eu-west-1:123456789:client/${iot:Connection.Thing.ThingName}"
    },
    {
      "Effect": "Allow",
      "Action": ["iot:Publish"],
      "Resource": "arn:aws:iot:eu-west-1:123456789:topic/amazeng/factory/*"
    },
    {
      "Effect": "Allow",
      "Action": ["iot:Subscribe"],
      "Resource": "arn:aws:iot:eu-west-1:123456789:topicfilter/amazeng/factory/commands/*"
    }
  ]
}

4. Certificate'e Policy Attach Etme

aws iot attach-policy \
  --policy-name amazeng-gateway-policy \
  --target arn:aws:iot:eu-west-1:123456789:cert/xxxxx

IoT Gateway Yazılımı (Python)

Gerekli Kütüphaneler

pip install pymodbus awsiotsdk paho-mqtt

Modbus Client Konfigürasyonu

config.json

{
  "modbus_devices": [
    {
      "name": "ZMA-Tank1",
      "type": "tcp",
      "host": "192.168.1.101",
      "port": 502,
      "unit_id": 1,
      "registers": [
        { "address": 0, "count": 2, "type": "float", "name": "channel_1" },
        { "address": 2, "count": 2, "type": "float", "name": "channel_2" },
        { "address": 4, "count": 2, "type": "float", "name": "channel_3" },
        { "address": 6, "count": 2, "type": "float", "name": "channel_4" }
      ]
    },
    {
      "name": "GDT-Loadcell",
      "type": "tcp",
      "host": "192.168.1.102",
      "port": 502,
      "unit_id": 1,
      "registers": [
        { "address": 0, "count": 2, "type": "float", "name": "net_weight" },
        { "address": 2, "count": 2, "type": "float", "name": "gross_weight" }
      ]
    }
  ],
  "aws_iot": {
    "endpoint": "xxxxx-ats.iot.eu-west-1.amazonaws.com",
    "port": 8883,
    "cert_path": "/etc/iot-gateway/certs/",
    "thing_name": "amazeng-factory-gateway-01",
    "topic_prefix": "amazeng/factory"
  },
  "polling_interval": 1.0
}

Ana Gateway Uygulaması

gateway.py

#!/usr/bin/env python3

import json
import time
import struct
from pymodbus.client.sync import ModbusTcpClient, ModbusSerialClient
from awscrt import io, mqtt
from awsiot import mqtt_connection_builder

class ModbusToMQTTGateway:
    def __init__(self, config_file):
        with open(config_file, 'r') as f:
            self.config = json.load(f)

        self.modbus_clients = {}
        self.mqtt_connection = None

        # Modbus clientları oluştur
        for device in self.config['modbus_devices']:
            if device['type'] == 'tcp':
                client = ModbusTcpClient(device['host'], port=device['port'])
            elif device['type'] == 'rtu':
                client = ModbusSerialClient(
                    method='rtu',
                    port=device['port'],
                    baudrate=device.get('baudrate', 9600),
                    timeout=device.get('timeout', 1)
                )

            client.connect()
            self.modbus_clients[device['name']] = {
                'client': client,
                'config': device
            }

        # AWS IoT MQTT connection
        self._setup_mqtt()

    def _setup_mqtt(self):
        """AWS IoT Core MQTT bağlantısı kur"""
        aws_config = self.config['aws_iot']
        cert_path = aws_config['cert_path']

        # TLS ile güvenli bağlantı
        self.mqtt_connection = mqtt_connection_builder.mtls_from_path(
            endpoint=aws_config['endpoint'],
            port=aws_config['port'],
            cert_filepath=f"{cert_path}gateway-cert.pem",
            pri_key_filepath=f"{cert_path}gateway-private.key",
            ca_filepath=f"{cert_path}AmazonRootCA1.pem",
            client_id=aws_config['thing_name'],
            clean_session=False,
            keep_alive_secs=30
        )

        # Bağlan
        connect_future = self.mqtt_connection.connect()
        connect_future.result()
        print(f"✓ AWS IoT Core'a bağlandı: {aws_config['endpoint']}")

    def read_modbus_device(self, device_name):
        """Bir Modbus cihazından tüm register'ları oku"""
        device = self.modbus_clients[device_name]
        client = device['client']
        config = device['config']

        data = {
            'device_name': device_name,
            'timestamp': int(time.time() * 1000),
            'values': {}
        }

        for register in config['registers']:
            try:
                # Holding register oku
                result = client.read_holding_registers(
                    address=register['address'],
                    count=register['count'],
                    unit=config['unit_id']
                )

                if not result.isError():
                    # Float dönüşümü (IEEE 754)
                    if register['type'] == 'float' and register['count'] == 2:
                        raw = (result.registers[0] << 16) | result.registers[1]
                        value = struct.unpack('f', struct.pack('I', raw))[0]
                    elif register['type'] == 'int':
                        value = result.registers[0]

                    data['values'][register['name']] = round(value, 3)
                else:
                    print(f"✗ Modbus okuma hatası: {device_name} @ {register['address']}")
                    data['values'][register['name']] = None

            except Exception as e:
                print(f"✗ Hata: {device_name} - {e}")
                data['values'][register['name']] = None

        return data

    def publish_to_aws(self, device_name, data):
        """Veriyi AWS IoT Core'a publish et"""
        topic = f"{self.config['aws_iot']['topic_prefix']}/{device_name}/data"
        payload = json.dumps(data)

        self.mqtt_connection.publish(
            topic=topic,
            payload=payload,
            qos=mqtt.QoS.AT_LEAST_ONCE
        )

        print(f"→ Published to {topic}: {payload}")

    def run(self):
        """Ana döngü: Modbus'tan oku, MQTT'ye gönder"""
        interval = self.config['polling_interval']

        print(f"Gateway başlatıldı. Polling interval: {interval}s")

        try:
            while True:
                for device_name in self.modbus_clients.keys():
                    # Modbus'tan oku
                    data = self.read_modbus_device(device_name)

                    # AWS'ye gönder
                    self.publish_to_aws(device_name, data)

                time.sleep(interval)

        except KeyboardInterrupt:
            print("\nGateway durduruluyor...")
            self.shutdown()

    def shutdown(self):
        """Bağlantıları kapat"""
        for device in self.modbus_clients.values():
            device['client'].close()

        disconnect_future = self.mqtt_connection.disconnect()
        disconnect_future.result()
        print("✓ Tüm bağlantılar kapatıldı")

if __name__ == "__main__":
    gateway = ModbusToMQTTGateway('/etc/iot-gateway/config.json')
    gateway.run()

Systemd Service Olarak Çalıştırma

/etc/systemd/system/iot-gateway.service

[Unit]
Description=Amazeng Modbus to AWS IoT Gateway
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/iot-gateway
ExecStart=/usr/bin/python3 /opt/iot-gateway/gateway.py
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl enable iot-gateway
sudo systemctl start iot-gateway
sudo systemctl status iot-gateway

AWS IoT Core'da Veri Akışı

Rule Engine ile Timestream'e Yazma

AWS IoT Core → Act → Rules → Create

SELECT
  device_name,
  timestamp,
  values.channel_1 as ch1,
  values.channel_2 as ch2,
  values.channel_3 as ch3,
  values.channel_4 as ch4
FROM 'amazeng/factory/+/data'
WHERE device_name = 'ZMA-Tank1'

Action: Amazon Timestream'e yaz

{
  "databaseName": "AmazengFactory",
  "tableName": "SensorData",
  "dimensions": [{ "name": "device", "value": "${device_name}" }],
  "timestamp": {
    "value": "${timestamp}",
    "unit": "MILLISECONDS"
  }
}

CloudWatch ile İzleme

Metric Filter ekleyin:

  • Topic: amazeng/factory/+/data
  • Metric: MessageCount, MessageSize
  • Alarm: 5 dakika boyunca veri gelmezse e-posta gönder

Gerçek Zamanlı Alarm Senaryosu

Lambda Function ile Threshold Kontrolü

alarm_handler.py

import json
import boto3

sns = boto3.client('sns')

def lambda_handler(event, context):
    # IoT Core'dan gelen veri
    device = event['device_name']
    weight = event['values'].get('net_weight', 0)

    # Eşik kontrolü
    if weight > 5000:  # 5 ton üzeri
        message = f"ALARM: {device} - Ağırlık limiti aşıldı: {weight} kg"

        sns.publish(
            TopicArn='arn:aws:sns:eu-west-1:123456789:factory-alarms',
            Subject='Tank Kapasite Alarmı',
            Message=message
        )

        return {'statusCode': 200, 'body': 'Alarm gönderildi'}

    return {'statusCode': 200, 'body': 'Normal'}

Güvenlik Best Practices

1. Certificate Rotation

Her 90 günde bir yeni certificate oluştur:

aws iot create-certificate-from-csr --set-as-active

2. IAM Policies - Least Privilege

Gateway sadece kendi topic'ine publish etsin:

{
  "Resource": "arn:aws:iot:*:*:topic/amazeng/factory/${iot:Connection.Thing.ThingName}/*"
}

3. VPN/Firewall

Gateway'in internet erişimi sadece AWS IoT endpoint'ine:

# UFW ile sadece 8883 portuna izin ver
sudo ufw allow out 8883/tcp
sudo ufw deny out 80,443/tcp

Maliyet Analizi

AWS IoT Core Fiyatlandırma (eu-west-1)

BileşenFiyatAylık Maliyet*
Connectivity$0.08 / milyon bağlantı-dakika$3.45 (2 cihaz, 7/24)
Messaging$1.00 / milyon mesaj$2.59 (1s polling, 2 cihaz)
Rule Engine$0.15 / milyon kural$0.38
Timestream Write$0.50 / milyon yazma$1.30
Timestream Storage$0.03 / GB-saat$21.60 (30GB)
TOPLAM~$29/ay

*2 cihaz, 1 saniye polling, 30 gün retention

Alternatif Gateway Çözümleri

1. HMI Panel ile Entegre Gateway

HMI Endüstriyel Ekran Çözümlerimiz, Embedded Linux tabanlı olduğu için hem operatör arayüzü hem gateway görevini yapabilir:

# HMI panel üzerinde çalışan aynı gateway.py scripti
# + Qt/QML ile lokal görsel arayüz

2. Moxa IoT Gateway

Moxa UC-8112, endüstriyel ortamlar için hazır çözüm:

  • 2x RS232/485 + 2x Ethernet
  • -40°C ile +75°C çalışma sıcaklığı
  • Azure/AWS ThingWorx SDK'ları built-in

3. Node-RED ile No-Code Gateway

Raspberry Pi üzerine Node-RED kurarak drag-drop ile gateway oluştur:

[Modbus] → [Function] → [MQTT out]

Sonuç ve Öneriler

ZMA ve GDT ürünlerimiz, Modbus RTU/TCP desteği sayesinde kolayca IoT Gateway üzerinden AWS IoT Core'a bağlanabilir. Bu sayede:

✅ Gerçek zamanlı veri izleme (Grafana/QuickSight)
✅ Uzun dönem veri saklama (Timestream)
✅ Kestirimci bakım (AI/ML modelleri)
✅ Uzaktan alarm ve bildirimler

Cloud & IoT Veri Toplama Çözümlerimiz hakkında daha fazla bilgi için iletişime geçin.

İlgili Çözümler