Endüstriyel IoT

EtherNet/IP MQTT Dönüşümü: Python ile CIP Cihazlarını ve Logix Tag'lerini Okuma

ControlLogix ve CompactLogix tag'lerini ve genel EtherNet/IP cihaz özniteliklerini bir edge gateway üzerinde açık kaynak CIP kütüphaneleriyle okuyun, ardından temiz MQTT mesajları olarak yayınlayın.

Bir Logix PLC rafından CIP tag'lerini okuyup EtherNet/IP verilerini MQTT mesajları olarak bulut broker'a gönderen edge gateway
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

EtherNet/IP MQTT dönüşümü, kontrol programına dokunmadan Rockwell Logix kontrolörlerinden, sürücülerden ve diğer CIP cihazlarından veriyi alıp panolara, historian sistemlerine ve bulut uygulamalarına taşımanın bir yoludur. Bu eğitimde implicit ve explicit messaging arasındaki farkı öğrenecek, ardından açık kaynak pycomm3 kütüphanesini bir gateway üzerinde kullanarak Logix tag'lerini ve genel CIP özniteliklerini okuyup temiz, kendini açıklayan payload'larla MQTT üzerinden yayınlayacaksınız.

Beş Dakikada EtherNet/IP ve CIP

EtherNet/IP, standart Ethernet ve TCP/UDP üzerinden taşınan Common Industrial Protocol (CIP) protokolüdür. CIP her cihazı sınıf, örnek (instance) ve özniteliklere sahip bir nesneler kümesi olarak modeller. Örneğin bir sürücüde üretici, ürün kodu ve seri numarasını tanımlayan bir Identity nesnesi (sınıf 0x01) ile hız, akım ve durum için uygulama nesneleri bulunur.

CIP trafiği iki türde gelir:

Mesajlaşma türü Taşıma Model Tipik kullanım Gateway için uygun mu?
Implicit (I/O) UDP, port 2222 Scanner ile adapter arasında döngüsel, zamanlanmış bağlantılar I/O ve sürücülerin gerçek zamanlı kontrolü Nadiren; scanner veya yapılandırılmış bir adapter olmayı gerektirir
Explicit TCP, port 44818 İstek/yanıt Tag, öznitelik ve tanılama okuma Evet, olağan yaklaşım budur

İzleme amaçlı bir gateway explicit messaging kullanmalıdır. Kontrolörün I/O bağlantılarını bozmaz, PLC projesinde değişiklik gerektirmez ve duruş olmadan eklenip kaldırılabilir. Bedeli ise bunun bir sorgulama (polling) protokolü olmasıdır; yani ne sıklıkta okuyacağınızı siz seçersiniz.

İki Tür Hedef

  1. Logix kontrolörleri (ControlLogix, CompactLogix, kısmen Micro800). Bunlar sembolik tag erişimini destekler: Line1_Speed veya Conveyor[3].Status değerini adıyla okursunuz. Bu, açık ara en pratik veri kaynağıdır.
  2. Genel CIP cihazları (sürücüler, I/O adapter'ları, scanner'lar, üçüncü taraf cihazlar). Bunlar, cihaz dokümantasyonundan veya EDS dosyasından alınan sınıf, örnek ve öznitelik numarasıyla okuduğunuz nesne özniteliklerini sunar.

pycomm3 her ikisini de yönetir: tag tabanlı kontrolörler için LogixDriver, genel explicit mesajlar için CIPDriver. Logix tag'leri için bir diğer popüler açık kaynak seçenek pylogix'tir. Siemens, Beckhoff ve diğer platformların kendi erişim yolları vardır; kontrolör yapılandırması gibi Rockwell'e özgü konular için Allen-Bradley MQTT rehberimize bakın.

Ön Koşullar

  • Kontrolöre TCP 44818 üzerinden erişebilen bir gateway'de Python 3.10 veya üzeri.
  • pycomm3 ve paho-mqtt 2.x.
  • Kontrolörün IP adresi ve şasi tabanlı kontrolörler için slot numarası (örneğin slot 0 için 10.0.0.20/0).
  • Kontrol mühendisiyle mutabık kalınmış, salt okunur bir tag listesi.
python -m venv .venv && source .venv/bin/activate
pip install pycomm3 "paho-mqtt>=2.0"

Adım 1: Kontrolörü Keşfedin

Köprüyü yazmadan önce bağlantıyı doğrulayın ve mevcut tag'leri listeleyin. Bu betik kontrolör bilgilerini ve kontrolör kapsamlı ilk tag'leri yazdırır.

# explore_logix.py - bağlantıyı doğrula ve tag'leri listele
from pycomm3 import LogixDriver

with LogixDriver("10.0.0.20/0") as plc:          # kontrolörün IP/slot bilgisi
    print(plc.info)                               # üretici, ürün, revizyon, ad
    tags = plc.get_tag_list()                     # kontrolör kapsamlı tag'ler
    for t in tags[:30]:
        print(t["tag_name"], t["data_type_name"])

get_tag_list(), kullanıcı tanımlı tipler dahil tag tanımlarını yükler; bu nedenle büyük projelerde biraz zaman alabilir. Program kapsamlı tag'ler Program:MainProgram.TagName sözdizimiyle okunur.

Adım 2: Genel Bir CIP Özniteliği Okuyun

Sembolik tag'i olmayan bir sürücü veya herhangi bir CIP cihazı için explicit mesajlar kullanın. Örnek, her EtherNet/IP cihazının uyguladığı Identity nesnesinden ürün adını okur.

# identity.py - herhangi bir CIP cihazından Identity nesnesinin 7. özniteliğini (Product Name) oku
from pycomm3 import CIPDriver, Services, ClassCode, SHORT_STRING

with CIPDriver("10.0.0.31") as dev:
    resp = dev.generic_message(
        service=Services.get_attribute_single,
        class_code=ClassCode.identity_object,   # 0x01
        instance=1,
        attribute=7,                             # Product Name
        data_type=SHORT_STRING,
        connected=False,
        name="product_name",
    )
    print(resp.value if not resp.error else resp.error)

Çıkış frekansı veya motor akımı gibi uygulama verilerini okumak için sınıf, örnek, öznitelik ve veri tipini cihaz kılavuzundaki değerlerle değiştirin.

Adım 3: EtherNet/IP MQTT Köprüsü

Köprü, her döngüde tag listesini tek bir çoklu tag isteğiyle okur, değişen (veya ölü bandı aşan) değerleri yayınlar ve okuma hatalarını eski değerleri sessizce tutmak yerine kötü kalite olarak raporlar.

# eip_mqtt_bridge.py - Logix tag'lerini EtherNet/IP üzerinden sorgula, MQTT'ye yayınla
import json, logging, time, uuid
import paho.mqtt.client as mqtt
from pycomm3 import LogixDriver, CommError

logging.basicConfig(level=logging.INFO)
log = logging.getLogger("eip")

PLC_PATH = "10.0.0.20/0"
POLL_SECONDS = 1.0
TOPIC_ROOT = "connectmq/demo/9e6d/plant1/packaging/line2"   # kendi rastgele kimliğiniz
MQTT_HOST, MQTT_PORT = "broker.connectmq.com", 1883         # üretim: TLS ile 8883
MQTT_USER, MQTT_PASS = None, None                           # üretim: "YOUR_USERNAME", "YOUR_PASSWORD"
CLIENT_ID = f"eip-bridge-{uuid.uuid4().hex[:8]}"            # üretim: "YOUR_CLIENT_ID"

# PLC tag'i -> (topic yaprağı, birim, ölü bant)
TAGS = {
    "Line2_Speed":          ("speed", "ppm", 1.0),
    "Line2_Running":        ("running", "", 0),
    "Line2_GoodCount":      ("good_count", "count", 0),
    "Line2_RejectCount":    ("reject_count", "count", 0),
    "Filler.MotorCurrent":  ("filler_current", "A", 0.2),
}


def mqtt_client():
    c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
    if MQTT_USER:
        c.username_pw_set(MQTT_USER, MQTT_PASS)
        c.tls_set()
    c.will_set(f"{TOPIC_ROOT}/bridge", "offline", qos=1, retain=True)
    c.on_connect = lambda cl, u, f, rc, p: cl.publish(f"{TOPIC_ROOT}/bridge", "online", qos=1, retain=True)
    c.connect(MQTT_HOST, MQTT_PORT, keepalive=30)
    c.loop_start()
    return c


def changed(old, new, deadband):
    if old is None:
        return True
    if isinstance(new, (int, float)) and not isinstance(new, bool) and deadband:
        return abs(new - old) >= deadband
    return new != old


def main():
    mq = mqtt_client()
    last = {}
    while True:
        try:
            with LogixDriver(PLC_PATH) as plc:
                log.info("connected to %s", plc.info.get("product_name"))
                while True:
                    results = plc.read(*TAGS.keys())
                    if not isinstance(results, list):
                        results = [results]
                    now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
                    for r in results:
                        leaf, unit, deadband = TAGS[r.tag]
                        topic = f"{TOPIC_ROOT}/{leaf}"
                        if r.error:
                            if last.get(r.tag, {}).get("quality") != "bad":
                                mq.publish(topic, json.dumps({"value": None, "quality": "bad",
                                                              "error": r.error, "ts": now}), qos=1, retain=True)
                                last[r.tag] = {"value": None, "quality": "bad"}
                            continue
                        prev = last.get(r.tag, {})
                        if prev.get("quality") == "bad" or changed(prev.get("value"), r.value, deadband):
                            payload = {"value": r.value, "unit": unit, "type": r.type,
                                       "quality": "good", "ts": now}
                            mq.publish(topic, json.dumps(payload), qos=1, retain=True)
                            last[r.tag] = {"value": r.value, "quality": "good"}
                    time.sleep(POLL_SECONDS)
        except CommError as exc:
            log.error("EtherNet/IP connection lost: %s - retrying in 5 s", exc)
            time.sleep(5)


if __name__ == "__main__":
    main()

Birden fazla tag adıyla çağrılan plc.read(), bunları bağlantı boyutunun izin verdiği en az sayıda isteğe paketler; bu da kontrolör için tag başına bir istek göndermekten çok daha hafiftir. Her sonuç tag, value, type ve error alanlarına sahip bir Tag nesnesidir; böylece köprü veri tipini de değerle birlikte yayınlayabilir.

Adım 4: Çalıştırın ve Doğrulayın

python eip_mqtt_bridge.py
mosquitto_sub -h broker.connectmq.com -p 1883 -i eip-viewer-9e6d -t "connectmq/demo/9e6d/#" -v
connectmq/demo/9e6d/plant1/packaging/line2/speed {"value": 118.0, "unit": "ppm", "type": "REAL", "quality": "good", "ts": "2026-10-16T12:00:01Z"}
connectmq/demo/9e6d/plant1/packaging/line2/running {"value": true, "unit": "", "type": "BOOL", "quality": "good", "ts": "2026-10-16T12:00:01Z"}

Topic ağacı ISA-95 tarzı bir düzeni (saha, alan, hat, nokta) izler; böylece veri EtherNet/IP, Modbus veya OPC UA'dan gelse de aynı tüketiciler çalışır. Kuralları ISA-95 MQTT topic'leri rehberimiz açıklıyor.

Tag ve Sorgulama Hızı Seçimi

Bir Logix projesindeki her tag kendi topic'ini hak etmez. Tüketicilerin soracağı sorulardan başlayın: hat çalışıyor mu, ne hızda, kaç sağlam ve kaç ıskarta ürün var, hangi alarmlar aktif ve ana sürücüler ne kadar enerji çekiyor. Bu genellikle hat başına binlerce değil, birkaç düzine değer anlamına gelir. Değerleri ne kadar hızlı değiştiklerine göre gruplayın. Durumlar ve sayaçlar her saniye okunup değiştiğinde yayınlanabilir; tank seviyeleri veya sıcaklıklar gibi yavaş analog değerler ise bir ölü bantla beş ya da on saniyede bir okunabilir. Bir değer yalnızca vardiya toplamı olarak işe yarıyorsa, onu PLC'nin biriktirmesine izin verip daha yavaş bir döngüde yayınlamayı düşünün.

Üretim İçin İyi Uygulamalar

  1. Tasarım gereği salt okunur. İzleme köprüsüne yazma desteği eklemeyin. Bir gün komut göndermeniz gerekirse, açık onay mantığına sahip ayrı bir servis kurun.
  2. Bir arayüz tag kümesi kullanın. Kontrol mühendisinden ihtiyaç duyduğunuz değerleri özel bir UDT veya diziye kopyalamasını isteyin. Böylece onlarca dağınık tag yerine tek bir yapı okursunuz ve program değişiklikleri köprüyü bozmaz.
  3. Bağlantı limitlerine dikkat edin. Kontrolörler, HMI'lar, SCADA ve mühendislik araçlarıyla paylaşılan sınırlı sayıda CIP bağlantısını destekler. Köprü başına uzun ömürlü tek bir bağlantı idealdir; her döngüde yeniden bağlanmaktan kaçının.
  4. İhtiyacınız olan hızda sorgulayın. Üretim sayıları ve durumlar için bir saniye fazlasıyla yeterlidir. Daha hızlı sorgulama, içgörü katmadan yük ekler.
  5. Ağ segmentasyonu. Gateway'i OT ağına veya bir DMZ'ye yerleştirin; yalnızca kontrolörlerdeki 44818 portuna ve broker'a giden 8883 portuna erişimi olsun. Bu düzeni MQTT DMZ yazımız ele alıyor.
  6. Gerçek veriler için özel broker. Herkese açık test broker'ı herkes tarafından okunabilir. Gerçek bir hattı bağlamadan önce TLS ve broker başına kimlik bilgileri sunan tam yönetilen bir MQTT servisine geçin.

Sorun Giderme

Belirti Olası neden Çözüm
Bağlanırken CommError Yanlış IP, 44818'i engelleyen güvenlik duvarı, yanlış slot Kontrolöre ping atın, ip/slot yolunu kontrol edin
Tag okumaları Tag doesn't exist döndürüyor Program kapsamlı tag veya yazım hatası Program:Name.Tag kullanın, get_tag_list() ile kontrol edin
Çalışıyor, saatler sonra hata veriyor Bağlantı kontrolör veya switch tarafından kesilmiş Yeniden deneme döngüsü tekrar bağlanır; kontrolörün bağlantı kullanımını kontrol edin
Genel mesaj CIP durum hatası döndürüyor Yanlış sınıf, örnek, öznitelik veya veri tipi Cihaz kılavuzunu veya EDS dosyasını kontrol edin
Değerler yavaş güncelleniyor Büyük tag listesi çok sayıda isteğe bölünmüş Bir arayüz UDT'si kullanın, tag sayısını azaltın

ConnectMQ'nun Rolü

ConnectMQ bu hattın bulut tarafıdır: 8883 portunda TLS ve tarayıcı panoları için WebSocket sunan yönetilen bir MQTT broker. ISA-95 topic yapılarını algılar; böylece cihazlar görünümü hatları ve makineleri otomatik olarak gruplar, eşik tabanlı alarm kuralları da sınırlarının dışına çıkan bir ıskarta sayısını veya motor akımını işaretleyebilir. Yönetilen broker'larda yeniyseniz bir bulut MQTT broker çözümünün kendi sunucunuzda barındırmayla nasıl karşılaştırıldığına bakın; mimarinin tamamı için endüstriyel IoT MQTT rehberini okuyun.

ConnectMQ ile Başlayın

İlk EtherNet/IP hattınızı bugün bağlayın. app.connectmq.com adresinden kaydolun, kredi kartı gerektirmeyen ücretsiz Serverless planını seçin, bir broker oluşturun ve üretilen kullanıcı adı, parola ve client ID bilgilerini köprüye yapıştırın. Logix tag'leriniz saniyeler içinde ConnectMQ topic gezgininde görünecektir.

Sık Sorulan Sorular

EtherNet/IP üzerinden tag okumak PLC programını etkiler mi?

Explicit messaging, kontrolörün I/O bağlantılarını değil iletişim kaynaklarını kullanır ve programı değiştirmez. HMI'ları ve SCADA'yı etkilememek için sorgulamayı makul düzeyde, bağlantı sayısını da düşük tutun.

Bir MQTT gateway için implicit I/O messaging kullanabilir miyim?

Gateway, PLC'nin I/O ağacında bir adapter olarak yapılandırılırsa mümkündür, ancak bu bir proje değişikliği gerektirir. İzleme için explicit tag okumaları daha basittir ve sisteme müdahale etmez.

pycomm3, Micro800 ve eski PLC-5 veya SLC kontrolörlerle çalışır mı?

pycomm3, Logix kontrolörlerini hedefler ve Micro800 için kısmi destek sunar; eski PLC-5 ve SLC aileleri farklı adresleme kullanır. Kendi kontrolörünüz için kütüphane dokümantasyonunu kontrol edin.

EtherNet/IP explicit messaging hangi portu kullanır?

TCP 44818 portunu. Implicit I/O trafiği ise UDP 2222 portunu kullanır.

İlgili yazılar

CODESYS MQTT Client: PLC Değişkenlerini Bir Broker'a Yayınlama

CODESYS IIoT MQTT Client kütüphanesini PLC değişkenlerini JSON olarak yayınlayacak şekilde yapılandırın, broker.connectmq.com üzerinde doğrulayın, ardından kimlik bilgileri ve TLS içeren özel bir broker'a geçin.

6 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.