AWS IoT Core ile Endüstriyel Veri Toplama: ZMA Cihazlarından Buluta
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
- Raspberry Pi / Jetson Nano: Linux tabanlı, Python/Node.js ile özel script
- Endüstriyel IoT Gateway'ler: Moxa, Advantech, Siemens gibi hazır çözümler
- HMI Panelimiz: Embedded Linux üzerinde hem HMI hem gateway görevini yapabilir
- 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şen | Fiyat | Aylı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.