OPC UA in MFC-Anwendungen: Integration von open62541 für industrielle SCADA unter Windows
Industrielle Automatisierungssysteme verlassen zunehmend monolithische, proprietäre SCADA-Lösungen zugunsten flexibler, sicherer und plattformübergreifender OPC-UA-basierter Plattformen. In diesem Kontext stellt die Entwicklung eines leichten SCADA-Systems auf Basis der Microsoft Foundation Classes (MFC) mit open62541-Integration eine technisch sinnvolle Wahl für mittelständische Unternehmen dar – insbesondere wenn Kompatibilität mit bestehenden Windows-Infrastrukturen sowie strenge Latenzanforderungen bei der Kommunikation mit Siemens S7-1200/S7-1500-Steuerungen erforderlich sind.
Architektonischer Wandel: Von proprietärer SCADA zu OPC-UA-gesteuerter Integration
Traditionelle SCADA-Plattformen (WinCC, InTouch, EcoStruxure) basieren auf geschlossenen Protokollen und Herstellerabhängigkeit. Ihre Bereitstellung erfordert Lizenzierung, umfangreiche Konfiguration und führt häufig zu überladenen Softwareinstallationen – Setup-Pakete können bis zu 20 GB groß sein, obwohl nur 15–20 % der Funktionalität tatsächlich genutzt werden. Für kleine und mittlere Unternehmen ist dies wirtschaftlich nicht vertretbar.
OPC UA adressiert drei systemische Herausforderungen:
- Interoperabilität: Ein einheitlicher Adressraum (NodeId), typisierte Variablen und ein einziges Abonnement-Mechanismus ermöglichen die Datenaggregation von Geräten verschiedener Hersteller ohne Zwischengateways.
- Sicherheit out-of-the-box: Unterstützung für X.509-Zertifikate, Sicherheitsrichtlinien (None, Basic128Rsa15, Basic256Sha256) sowie Verschlüsselung und Authentifizierung auf Protokollebene.
- Flexibilität bei der Bereitstellung: Clients können native Windows-Anwendungen (MFC/Win32), Webdienste oder Microservices sein, die auf Linux laufen – ohne Änderungen an der Serverlogik.
In der industriellen Praxis bedeutet dies, teure SCADA-Systeme durch maßgeschneiderte Lösungen zu ersetzen, die direkt über OPC UA mit Steuerungen verbunden sind, sich in SQL Server zur Speicherung von Rezepten und historischen Daten integrieren und Fernüberwachung über Diagramme und Anlagenstatusanzeigen ermöglichen.
Integration von open62541 in MFC: Technische Merkmale und Einschränkungen
open62541 ist eine C99-konforme, abhängigkeitsfreie Open-Source-Bibliothek, die für Embedded- und Desktopsysteme konzipiert wurde. Ihre Verwendung in einem MFC-Projekt setzt mehrere Bedingungen voraus:
- Das Projekt muss im
/MD-Modus kompiliert werden (dynamische Verknüpfung mit CRT), da open62541 auf der Standard-C-Bibliothek basiert. - Bei Verwendung sicherer Richtlinien ist eine explizite Initialisierung des TLS/SSL-Stapels erforderlich – unter Windows erfolgt dies über
Wincrypt.hundCryptInitialize(). - Alle Objekte wie
UA_Client,UA_CreateSubscriptionRequestundUA_MonitoredItemCreateRequestmüssen manuell verwaltet werden: Speicherzuweisung, Aufruf vonUA_Client_disconnect()und Freigabe mitUA_Client_delete().
Eine kritische Einschränkung ist das Fehlen eines integrierten Thread-Pools. In einer MFC-Anwendung mit GUI-Thread müssen alle Aufrufe von UA_Client_* in einem separaten Worker-Thread (AfxBeginThread) oder über PostMessage/WM_USER ausgeführt werden, um eine Blockierung der Benutzeroberfläche zu vermeiden. Ein direkter Aufruf von UA_Client_connect() in CMainFrame::OnInitialUpdate() würde das Fenster einfrieren lassen.
Implementierung von Verbindung und Abonnement in C++/MFC
Die Funktion CMainFrame::ConnectCPUOnline() zeigt einen minimal tragfähigen Szenario für die Verbindung mit einem OPC-UA-Server. Sie initialisiert den Client, konfiguriert die Einstellungen und stellt die Verbindung her. Wichtige Punkte sind:
- Die Verwendung von
UA_String_fromChars()zur Konvertierung vonCT2A-Strings inUA_String– eine zwingende Voraussetzung der open62541-API. - Die Einstellung von
cc->securityMode = UA_MESSAGESECURITYMODE_NONEist nur in isolierten Netzwerken akzeptabel; in realen Projekten mussUA_MESSAGESECURITYMODE_SIGNANDENCRYPTgewählt und Zertifikate überUA_ClientConfig_setDefaultEncryption()geladen werden. - Logging auf der Ebene
UA_LOGLEVEL_ERRORbietet das optimale Gleichgewicht zwischen Diagnose und Performance in der Produktion.
Nach der Verbindung wird ein Abonnement erstellt und Monitoring-Items konfiguriert. Nachfolgend ein Ausschnitt, wie ein Abonnement erstellt und das erste Tag hinzugefügt wird:
// Erstellung eines Abonnements
UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
request.requestedPublishingInterval = 500.0; // ms
request.requestedMaxKeepAliveCount = 10;
request.requestedLifetimeCount = 30;
UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(
StrCPUADR[iAdr].g_clientOnline, request, NULL, NULL, NULL);
if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
return false;
}
StrCPUADR[iAdr].g_subscriptionId = response.subscriptionId;
// Konfiguration des Monitors für das Tag
UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest_default();
monRequest.itemToMonitor.nodeId = UA_NODEID_NUMERIC(0, StrDBINI[i].iIDUA);
monRequest.itemToMonitor.attributeId = UA_ATTRIBUTEID_VALUE;
monRequest.monitoringMode = UA_MONITORINGMODE_REPORTING;
UA_MonitoredItemCreateResult monResponse = UA_Client_MonitoredItems_createSingle(
StrCPUADR[iAdr].g_clientOnline,
StrCPUADR[iAdr].g_subscriptionId,
&monRequest);
Beachten Sie, dass iIDUA die NodeId des Controllers ist, die aus der Datenbank stammt (z. B. ns=2;s=Channel1.Device1.Tag1). Sie muss exakt mit dem Adressraum des Servers übereinstimmen. Fehler in der NodeId führen zwar zu UA_STATUSCODE_BADNODEIDUNKNOWN, aber nicht zum Absturz – daher ist die Überprüfung von monResponse.statusCode unerlässlich.
Arbeit mit Daten: Vom Lesen bis zum Logging in SQL Server
Das System verwendet drei zentrale Strukturen zur Datenverwaltung:
StrDBCP– Konfiguration für Verbindungen zu Steuerungen: IP-Adresse, Online-/Offline-Status, Pointer aufUA_Client*, Abonnement-ID und einarrayValue-Puffer für den Empfang von Werten.StrDBINI– Metadaten zu Tags:iIDUA(NodeId),iTYPEID(Datentyp:UA_TYPES_INT32,UA_TYPES_DOUBLE,UA_TYPES_BOOLEAN) und einbSaveDb-Flag für das Logging.StrDBVAL– Historische Wertetabelle mit Zeitstempeln,CTime,iNOMEQ,iItemundiVal.
Die Logik zur Aktualisierung der Werte wird in der Callback-Funktion UA_Client_DataChangeNotification implementiert. Wenn ein neuer Wert empfangen wird:
- Überprüfung des
iTYPEIDund sicheres Casten des Typs mitUA_Variant_getScalarCopy(). - Schreiben in
arrayValue[i]unter Berücksichtigung vonsizearray. - Wenn
bSaveDb == true, Formulierung einer parametrisierten INSERT-Anweisung in SQL Server viaCDatabase::ExecuteSQL().
Wichtig: Alle Operationen an arrayValue müssen durch eine kritische Section (CCriticalSection) geschützt werden, da die Daten aus einem Hintergrundthread kommen, während der GUI-Thread sie gleichzeitig für die Diagrammrenderung anfordern kann.
Was wirklich zählt
- OPC UA in einer MFC-Anwendung erfordert die manuelle Verwaltung des Lebenszyklus von
UA_Client: Initialisierung → Verbindung → Abonnement → Lesen → Abmeldung → Trennung → Löschung. - Sicherheit ist kein Optional:
SECURITYPOLICY_NONEist nur in Testumgebungen akzeptabel; in industriellen Netzwerken sind X.509-Zertifikate undSIGNANDENCRYPTobligatorisch. - open62541 bietet keine asynchronen APIs für die Windows-GUI – alle Netzwerkoperationen müssen in einem separaten Thread durchgeführt und anschließend über
PostMessagesynchronisiert werden. - Die Strukturen
StrDBCP,StrDBINIundStrDBVALbilden eine Abstraktionsschicht über OPC UA, die es ermöglicht, zwischen verschiedenen Steuerungen zu wechseln, ohne die Datenverarbeitungslogik zu ändern. - Die Unterstützung von Siemens S7-1200/S7-1500 erfordert das Aktivieren des OPC-UA-Servers in der Controller-Firmware sowie die korrekte Konfiguration der User Access Control (UAC) in TIA Portal.
— Editorial Team
Noch keine Kommentare.