Lunex’in OPC UA Subscription bileşeni (opcua-subscription) bir OPC UA sunucusundaki çok sayıda node’u tek bağlantı ve tek abonelikle izler. Her değer değişikliği akışa ayrı bir mesaj olarak girer. Yüzlerce veya binlerce tag için tek route yeterlidir.
Camel’in kendi OPC UA Client bileşeni (milo-client) bir endpoint’te tek node izler; her tag için ayrı route gerekir. Yalnız birkaç node izliyor veya node’a yazıyorsanız milo-client kullanın. Çok sayıda tag’i yalnız okumak için bu bileşeni kullanın. Camel’in bileşeni çoklu node desteği kazandığında Lunex bu bileşeni kaldırır ve geçişi bu sayfada açıklar.
Hazırlayacağınız bilgiler
| Bilgi | Örnek |
|---|---|
| Runtime’dan erişilebilen sunucu adresi | opc.tcp://plc-gateway.example.test:4840 |
| Güvenlik politikası ve kimlik | None ile kullanıcı/parola veya sertifika (keystore) |
| İzlenecek node ID’leri | ns=1;s=[Line1]Filler/Temperature |
Adres proje runtime’ının ağından erişilebilir olmalıdır; kendi bilgisayarınızdan erişilebilmesi yetmez. Sunucu, bağlantı sırasında kendi adını içeren endpoint adresleri bildirir. Bu ad runtime’dan çözümlenemiyorsa Override Host (overrideHost) seçeneğini açın; bileşen bildirilen adres yerine sizin yazdığınız host’u kullanır.
Node listesini hazırlayın
Nodes alanı listeyi üç şekilde alabilir:
| Yazım | Ne zaman? |
|---|---|
ns=1;s=[Line1]OEE, ns=1;s=[Line1]Order | Birkaç node; liste doğrudan route’ta, virgülle ayrılmış. |
{{line1.nodes}} | Liste application.properties içinde virgülle ayrılmış. Ortama göre değişen liste için {{configmap:line1-tags/nodes}} ile bir ConfigMap anahtarını da kullanabilirsiniz. |
classpath:line-nodes.txt | Çok sayıda node; liste projede bir dosyada, her satırda bir node. |
Route içindeki liste YAML’da birden fazla satıra yayılabilir, ancak node’ları yine virgülle ayırın; satır sonu ayraç sayılmaz:
nodes: >-
ns=1;s=[Line1]Filler/Temperature,
ns=1;s=[Line1]Filler/State
Virgül içeren bir node ID’yi dosyaya yazın. Dosyada her satır tek bir node ID’dir.
Çok sayıda node için listeyi proje içinde bir metin dosyasında tutun, örneğin line-nodes.txt:
# Line1
ns=1;s=[Line1]OEE
ns=1;s=[Line1]Filler/Temperature
ns=1;s=[Line1]Filler/State
# Line2
ns=1;s=[Line2]Filler/Temperature
- Her satır bir node ID’dir. Boş satırlar ve
#ile başlayan satırlar yok sayılır; aynı node iki kez yazılırsa bir kez izlenir. ns=<index>;...veya namespace URI’linsu=<uri>;...biçimini kullanabilirsiniz. Namespace index’i sunucu yeniden yapılandırılınca değişebiliyorsansu=biçimi daha kalıcıdır.- Node ID’lerini OPC UA istemci aracınızın gezinme görünümünden veya sunucunun tag dışa aktarımından alın. Okunamayan bir satır route’u başlatmaz; hata mesajı satırı gösterir.
Listeyi sunucudan bir kez çıkarın
Çok sayıda node için listeyi Camel’in OPC UA Browser bileşeniyle (milo-browse) sunucudan çıkarabilirsiniz. Aşağıdaki route bir kez çalışır, [Line1] klasörünün altındaki node’ları gezer ve listeyi çalışmanın ekine yazar:
- route:
id: browse-line-nodes
from:
uri: timer:browse-line-nodes
parameters:
repeatCount: 1
steps:
- to:
uri: milo-browse:opc.tcp://plc-gateway.example.test:4840
parameters:
node: RAW(ns=1;s=[Line1])
recursive: true
depth: 5
nodeClasses: Variable,Object
allowedSecurityPolicies: None
username: '{{secret:opcua-line/username}}'
password: '{{secret:opcua-line/password}}'
- setBody:
groovy: "headers.CamelMiloNodeIds.join('\\n')"
- bean:
ref: lunexMonitor
method: "appendAttachment('line-nodes.txt','text/plain',${body})"
- Route’u Run ile çalıştırın.
- Message Monitor’da çalışmayı açıp Attachments bölümünden
line-nodes.txtiçeriğini alın. - İçeriği projede
line-nodes.txtdosyasına kaydedin ve klasör satırlarını silin. Klasörlerin değeri yoktur; listede kalırlarsa her biri bir kezBad_AttributeIdInvaliddurumuyla gelir. - Gezinme route’unu projeden kaldırın; liste her başlatmada yeniden çıkarılmamalıdır.
nodeClasses değerinde Object bulunmalıdır. Yalnız Variable yazılırsa gezinme alt klasörlere inmez ve yalnız ilk seviyedeki değişkenleri bulur.
Bileşen listeyi route başlarken okur. Listeyi (dosya, property veya ConfigMap) değiştirdikten sonra kaydedip Run’ı yeniden başlatın.
Route’u oluşturun
- Route’un girişi olarak OPC UA Subscription bileşenini seçin.
- Endpoint Uri alanına sunucu adresini yazın.
- Nodes alanına listeyi veya
classpath:line-nodes.txtyazın. - Güvenlik politikasını, kullanıcı adını ve parolayı girin. Parolayı bir Secret’tan referans verin (Secret oluşturun).
- Gerekirse yayın ve örnekleme aralıklarını ayarlayın.
| Seçenek | Anlamı |
|---|---|
requestedPublishingInterval | Sunucunun biriken değişiklikleri gönderme aralığı (ms). Varsayılan 1000. |
samplingInterval | Sunucunun her node’u örnekleme aralığı (ms). 0 sunucunun en hızlı aralığıdır. |
queueSize | İki yayın arasında node başına tutulan değişiklik sayısı. Varsayılan 1: yalnız son değer gelir. |
concurrentConsumers | Değişiklikleri işleyen thread sayısı. Varsayılan 1. Bir node’un değişiklikleri her zaman aynı thread’de, geliş sırasıyla işlenir; farklı node’lar paralel işlenir. |
allowedSecurityPolicies | Kabul edilen güvenlik politikaları, örneğin None veya Basic256Sha256. Boşsa sunucunun sunduğu en güvenli politika seçilir. |
username, password | Kullanıcı kimliği. Boşsa anonim bağlanır. |
keyStoreUrl, keyAlias, keyStorePassword, keyPassword | İmzalı/şifreli güvenlik politikası için istemci sertifikası. |
monitorFilterType, dataChangeFilter... | Deadband gibi değişiklik filtreleri; tüm node’lara uygulanır. |
Sunucu istenen aralıkları kendi sınırlarına göre değiştirebilir. Gerçekte kullanılan değerler Log’da görünür:
Subscribed 28 of 28 nodes at opc.tcp://...: publishing interval 500.0 ms, sampling interval 250.0 ms
Mesajın içeriği
Mesaj gövdesi node’un değeridir: sayı, metin, mantıksal değer, tarih (Instant) veya dizi için liste. Diğer bilgiler header’lardadır:
| Header | İçerik |
|---|---|
CamelMiloNodeId | Node ID, listede yazdığınız biçimde |
CamelMiloStatus | Durum adı, örneğin Good, Bad_NotConnected, Bad_NodeIdUnknown |
CamelMiloSourceTimestamp | Değerin kaynakta oluştuğu zaman |
CamelMiloServerTimestamp | Sunucunun değeri aldığı zaman |
milo-client gövdeye OPC UA DataValue nesnesini koyar; bu bileşen değeri doğrudan gövdeye, durumu ve zamanları header’lara koyar.
Durum Good değilse gövde boş olabilir. Akışınızda durumu kontrol edin ve değeri buna göre yayımlayın.
Bağlantı kesildiğinde
- Bağlantı koptuğunda her node için bir kez
Bad_NotConnecteddurumlu mesaj gelir. Böylece hedef sistem değerin güncel olmadığını bilir. - Bileşen bağlantıyı kendisi yeniden kurar ve aboneliği aktarır. Sunucu aboneliği kaybetmişse yeniden oluşturur. Run’ı yeniden başlatmanız gerekmez.
- Bağlantı yeniden kurulunca her node’un güncel değeri tekrar gönderilir.
- Sunucuda bulunmayan bir node için bir kez
Bad_NodeIdUnknowngelir; diğer node’lar izlenmeye devam eder. - Sunucuya hiç bağlanılamazsa bileşen 10 saniyede bir yeniden dener.
Örnek: tag’leri MQTT’ye yayımlayın
Aşağıdaki route her değişikliği node ID’sinden türetilen bir MQTT topic’ine JSON olarak yayımlar. ns=1;s=[Line1]Filler/Temperature node’u etzel/izmir/packaging/Line1/Filler/Temperature topic’ine gider:
- route:
id: line-tags-to-mqtt
from:
uri: opcua-subscription:opc.tcp://plc-gateway.example.test:4840
parameters:
nodes: classpath:line-nodes.txt
allowedSecurityPolicies: None
username: '{{secret:opcua-line/username}}'
password: '{{secret:opcua-line/password}}'
requestedPublishingInterval: 500
samplingInterval: 250
concurrentConsumers: 4
steps:
- script:
groovy: |-
def message = exchange.message
String node = message.getHeader('CamelMiloNodeId')
message.setHeader('CamelPahoMqtt5OverrideTopic',
'etzel/izmir/packaging/' + node.substring(node.indexOf('[') + 1).replace(']', '/'))
def value = message.body
message.body = groovy.json.JsonOutput.toJson([
value: value instanceof java.time.Instant ? value.toString() : value,
status: message.getHeader('CamelMiloStatus'),
sourceTime: message.getHeader('CamelMiloSourceTimestamp')?.toString()])
- to:
uri: paho-mqtt5:etzel/izmir/packaging/unrouted
parameters:
brokerUrl: tcp://mqtt.example.test:1883
clientId: lunex-line-tags
qos: 0
retained: true
Yayımlanan mesaj:
{"value":23.96,"status":"Good","sourceTime":"2026-10-12T16:24:13.889263Z"}
- Tek Groovy adımı her değişiklik için hem topic’i hem JSON gövdesini hazırlar. Yoğun tag trafiğinde ayrı ifade ve dönüşüm adımlarından belirgin biçimde daha az işlemci harcar.
concurrentConsumers: 4değişiklikleri dört thread’de yayımlar. Her topic değerlerini yine sırayla alır, çünkü bir node’un değişiklikleri hep aynı thread’de işlenir.- Topic ifadesi bu örnekteki node adı biçimine göredir (
ns=1;s=[Hat]Hücre/Tag). Kendi sunucunuzun node adlarına göre değiştirin. retained: true, yeni bağlanan bir abonenin her topic’in son değerini hemen almasını sağlar.qos: 0ile route broker’ın onayını beklemeden bir sonraki değişikliğe geçer. Kaybolan bir değerin yerini o tag’in sonraki değişikliği alır.qos: 1ve MQTT bileşeninin varsayılanı olanqos: 2her mesaj için broker onayını bekler; retained mesajlarla bu bekleme yoğun tag trafiğinde akışı belirgin biçimde yavaşlatır. Her mesajın ulaşması gereken iş olayları için QoS 1 kullanın.Bad_NotConnectedmesajları"value":nullile yayımlanır; aboneler son iyi değeri saklayıp durumu gösterebilir.- Groovy betiği tarih değerlerini ISO-8601 metnine çevirir.
Doğrulayın
- Run ile projeyi başlatın.
- Log’da
Subscribed N of N nodessatırını arayın. N’ler farklıysa eksik node’lar içinBad_...durumlu mesajlara bakın. - MQTT istemcinizle
etzel/izmir/packaging/#topic’ine abone olup değerlerin geldiğini doğrulayın.
Sınırlar
- Bileşen yalnız değer değişikliklerini izler. Node’a yazma, tek seferlik okuma veya gezinme (browse) için Camel’in
milo-clientvemilo-browsebileşenlerini kullanın. - Bir route bir sunucuya bağlanır. Birden fazla sunucu için her sunucuya bir route oluşturun.
- Değişiklik filtresi ve aralıklar listedeki tüm node’lara uygulanır. Farklı aralık gereken node’ları ayrı listeye ve ayrı route’a koyun.
- Tag yayımlayan projenin Log level değerini None yapın. Info her değişikliği Message Monitor’e ayrı bir çalışma olarak kaydeder ve yoğun tag trafiğinde akışı yavaşlatır. Ayar için Kayıt seviyesi sayfasına bakın.
- Tag yayımlayan projenin
application.propertiesdosyasınacamel.trace.standby=falseekleyin. Run podunda Camel, trace kapalıyken de her mesajı trace geçmişi için kaydeder; yoğun tag trafiğinde bu işlemcinin önemli bir kısmını harcar. Bu ayarla Run podu trace geçmişi tutmaz; trace gerektiğinde satırı kaldırıp projeyi yeniden çalıştırın. Build ile dağıtılan podlar bu kaydı zaten yapmaz. - Tek thread’li bir route saniyede birkaç bin değişiklik yayımlar. Daha yüksek hız için
concurrentConsumersdeğerini artırın, örneğin4. Route yine yetişemezse sunucu her node’un en son değerini gönderir ve ara değerler atlanır. - Farklı node’ların değişiklikleri paralel işlendiğinden aralarındaki sıra korunmaz. Değişiklikleri node’lar arası geliş sırasıyla işlemesi gereken bir akışta (örneğin birden fazla tag’den durum hesaplayan bir betik)
concurrentConsumersdeğerini1bırakın.