Problem: Nach kurzer Unterbrechung oder bei schrittweiser Ausführung der Anwendung verliert der Client die Verbindung und es kommt zur Ausnahme „BadServerNotConnected“ mit der Meldung: „The operation could not complete because the client is not connected to the server.“
Diese Fragen können entsprechend Server-seitig entsprechend auch gestellt werden:
Gegen einen Verbindungsverlust auf physikalischer Ebene kann kein Client oder Server etwas ausrichten. Anders sieht es auf logischer Ebene aus. Betrachtet man das OSI-Modell gibt es verschiedene Layer die zur Prüfung der „Gesundheit“ einer Verbindung verwendet werden können. Unabhängig auf welchem Layer man ansetzt, ist das Verfahren immer das gleiche: Ein Client muss Anfragen stellen und ein Server muss Anfragen beantworten, um zu 100% sicher zu sein, dass die Verbindung noch „gesund“ (genug) für die weitere Kommunikation ist.
Woher weiß nun ein Client bzw. Server, ab wann eine Verbindung als „tot“ bewertet werden kann?
Unabhängig welcher Fall geprüft werden soll, müssen Client als auch Server an diese Fälle bestimmte Bedingungen knüpfen. Hierfür dienen Informationen über die Zeit:
Werden Anfragen und Antworten von den Teilnehmern mit dem aktuellen Zeitstempel (= Zeitpunkt an dem eine Nachricht abgesendet wird) versehen, kann der jeweils andere prüfen, ob noch eine Antwort bzw. weitere Anfrage erwartet werden kann. Ist der Zeitversatz zwischen der letzten Antwort / Anfrage zu groß, kann der jeweilige Teilnehmer von einem Verbindungsverlust ausgehen. Wie groß der dafür verwendete Zeitversatz sein darf legen Timeout-Einstellungen fest, die entweder Client- als auch Server-spezifisch oder auch zwischen Client und Server „ausgehandelt“ werden können.
ACHTUNG: Werden keine Timeout-Bedingungen für die Verbindung zwischen den Teilnehmern verwendet, wartet ein Client „ewig“ auf eine Antwort und ein Server reserviert „ewig“ einen Endpunkt für den Client. Während erster bis zur (unwahrscheinlichen) Antwort blockiert bleibt, gehen beim letzteren die Möglichen Endpunkte für weitere Clients aus und belegt somit wichtige Systemressourcen.
Unabhängig wie oder wer das Zeitfenster festlegt, muss garantiert werden, dass innerhalb des (insgesamt kleinsten) Zeitfensters von beiden Teilnehmern mindestens eine Nachricht ausgetauscht wurde. Die hierfür verwendete Logik wird als KeepAlive-Logik bezeichnet. Hierbei ist der aktive Teilnehmer verantwortlich dem passivem Teilnehmer zu signalisieren, dass die Verbindung zwischen den beiden weiterhin besteht. Hierzu definiert jedes Protokoll (das einen KeepAlive vorsieht), dass innerhalb eines bestimmten Intervalls (= Zeitfenster) entweder eine bestimmte „leichtgewichtige“ Anfrage oder überhaupt irgendeine Anfrage gestellt und mit einer zugehörigen Antwort beantwortet werden soll. Der passive Teilnehmer kann dann anhand dieser oder allgemein anhand der generell letzten Anfrage des anderen feststellen, ob der Teilnehmer „noch da“, somit „noch verbunden“ und somit die Verbindung zu diesem auch noch „gesund“ ist. Der aktive Teilnehmer kann wiederum durch die Antwort auf die Anfrage innerhalb des Zeitfensters sich ebenso sicher sein, dass die Verbindung „noch steht“.
Ja, ein Beispiel hierzu samt Bootstrapper existiert auf GitHub: OPC UA .NET Samples - PowerShell Client
NuGet speichert alle installierten NuGet-Pakete entweder neben der Visual Studio Solution im Ordner „packages“ (im Falle von nicht SDK-Style Projekten) oder im lokalen NuGet-Cache (im Falle von SDK-Style Projekten). Damit auf die offizielle Version aktualisiert werden kann, müssen die Preview-Pakete aus der eigenen NuGet-Source und den lokalen NuGet-Cache gelöscht werden. Wo sich der lokale NuGet-Cache befindet hängt von ihrem Projekt ab.
Anschließend kann wie gewohnt über den NuGet-Client auf die aktuelle Version aktualisiert bzw. diese installiert werden.
Dieser Fehler kann auftreten, wenn das Visual Studio nach einem Update auf eine neuere Version des SDKs nicht alle verwendeten Binär-Dateien im Projektverzeichnis aktualisiert hat. Führen Sie deshalb die folgenden Schritte durch:
Sollte der Fehler bei der Ausführung weiterhin bestehen, dann sollten folgende Schritte das Problem lösen:
Sollte keiner dieser Ansätze zur Lösung des Problems führen, senden Sie das Problem samt Details über die Exception beziehungsweise deren InnerException an support@traeger.de.
Das OPC UA .NET SDK kommt mit einer Testlizenz die je Anwendungsstart 30 Minuten uneingeschränkt zur Client- und Serverentwicklung verwendet werden kann. Sollte diese Einschränkung ihre Evaluationsmöglichkeiten einschränken, besteht die Möglichkeit eine alternative Testlizenz bei uns kostenlos zu beantragen.
Fragen Sie einfach unseren Support (via support@traeger.de) oder lassen Sie sich gleich direkt von uns beraten und offene Fragen durch unsere Entwickler klären!
Das OPC UA .NET SDK kommt mit einer Testlizenz die je Anwendungsstart 30 Minuten uneingeschränkt zur Client- und Serverentwicklung verwendet werden kann. Sollte diese Einschränkung ihre Evaluationsmöglichkeiten einschränken, besteht die Möglichkeit eine alternative Testlizenz bei uns kostenlos zu beantragen.
Fragen Sie einfach unseren Support (via support@traeger.de) oder lassen Sie sich gleich direkt von uns beraten und offene Fragen durch unsere Entwickler klären!
Die folgenden Typen werden hier besprochen: OpcSubscription, OpcMonitoredItem und OpcMonitoredItemStatus.
Ob ein Server die gewünschten Intervalle unterstützt beziehungsweise, ob diese Anwendung finden kann über diverse Eigenschaften geprüft werden:
PublishingInterval
kann über die CurrentPublishingInterval
-Eigenschaft geprüft werden.SamplingInterval
kann über die Status.SamplingInterval
-Eigenschaft geprüft werden.Das Hauptproblem ist häufig auch die Konfiguration des Servers. Je nach S7-Steuerung werden nur bestimmte Minimalwerte für die Einstellungen der Subscriptions/MonitoredItems unterstützt. Die folgenden Minimalwerte gelten laut Siemens:
Eigenschaft | CPU | ||
---|---|---|---|
1510, 1511, 1512, 1513 | 1515, 1516, 1505S | 1517, 1518, 1507S | |
Maximale Anzahl Subscriptions mit mehr als 1000 überwachten Elementen pro Subscription über alle Sessions | 10 | 10 | 10 |
Maximale Anzahl Subscriptions mit maximal 1000 überwachten Elementen pro Subscription über alle Sessions | 20 | 20 | 20 |
Maximale Anzahl Subscriptions pro Session | 20 | 20 | 20 |
Kleinstmögliches Abtastintervall | 100 ms | 100 ms | 10 ms |
Kleinstmögliches Sendeintervall | 500 ms | 200 ms | 10 ms |
Maximale Anzahl Sessions | 32 | 48 | 64 |
Empfohlene maximale Anzahl überwachter Elemente über alle Subscriptions | 1000 | 1000 (1505S), 2000 | 10000 |
Quelle: Welche Systemgrenzen enthält der OPC UA Server bei der S7-1500 mit der Firmware V2.8.x?
Welche Grenzwerte ein Server unterstützt kann über diverse Nodes im Pfad /Objects/Server/ServerCapabilities
und darunter im Node OperationLimits
geprüft werden. Eine Client-Anwendung hat auf diese Einstellungen keinen Einfluss.
Die folgenden Typen werden hier besprochen: OpcObjectNode und OpcFolderNode.
In der Dokumentation zum OpcFolderNode steht:
Aus dem Grund heraus, dass der OpcFolderNode eine Unterklasse des OpcObjectNode ist, gibt es keinen direkten strukturellen Unterschied zwischen den beiden Typen. Ein expliziter Unterschied ist der verwendete ReferenceType. Der OpcFolderNode verwendet den Referenztypen „Organizes“, während der OpcObjectNode den Referenztypen „HasComponent“ verwendet. Der Unterschied in den verwendeten Referenztypen spiegelt auch den Zweck der beiden bereits zuvor beschriebenen Knotentypen wieder. Vereinfacht kann somit definiert werden:
Die folgenden Typen werden hier besprochen: OpcNodeId und OpcNominalNodeIdFactory.
Ja, dazu muss die Standard-NodeIdFactory wie folgt geändert werden:
OpcNodeId.Factory = new OpcNominalNodeIdFactory() { Separator = '.' };
Die folgenden Typen werden hier besprochen: OpcMethodNode und OpcArgumentAttribute.
Ja, durch die Verwendung von return
-, ref
- und/oder out
-Werten. Zu beachten ist jedoch, dass ref
-Werte als Input- und als Output-Argument verwendet werden. Die Definition eines solchen OpcMethodNode könnte wie folgt aussehen:
private delegate void CalculateDelegate( int a, int b, ref int c, out int additionResult, out int differenceResult); private void Calculate( [OpcArgument("a", Description = "The left operand.")] int a, [OpcArgument("b", Description = "The right operand.")] int b, [OpcArgument("c", Description = "Factor")] ref int c, [OpcArgument("add", Description = "The result of addition.")] out int additionResult, [OpcArgument("diff", Description = "The result of difference.")] out int differenceResult) { additionResult = (a + b) * c; differenceResult = (a - b) * c; } this.methodNode = new OpcMethodNode( this.folderNode, nameof(Calculate), new CalculateDelegate(this.Calculate));
Die folgenden Typen werden hier besprochen: OpcVariableNode, OpcVariableValue und OpcWriteVariableValueContext.
Ja, indem über eine benutzerdefinierte Callback-Routine der zu schreibende Wert überprüft wird. Eine solche Callback-Routine könne dann wie folgt aussehen:
this.variableNode.WriteVariableValueCallback = this.WriteToNode; // Deny write of a specific type of value. private OpcVariableValue WriteToNode( OpcWriteVariableValueContext context, OpcVariableValue value) { if (!(value.Value is short)) value.Status.Update(OpcStatusCode.BadTypeMismatch); return value; }
Die folgenden Typen werden hier besprochen: OpcVariableNode, OpcVariableValue und OpcWriteVariableValueContext.
Ja, mit Hilfe einer benutzerdefinierten Callback-Routine kann der Wert vor dem Schreiben in den gewünschten Zieldatentypen konvertiert werden. Das Vorgehen könnte in etwa so aussehen:
// Inline change type of value to the expected type. private OpcVariableValue WriteToNode( OpcWriteVariableValueContext context, OpcVariableValue value) { if (!(value.Value is short)) { value = new OpcVariableValue( Convert.ChangeType(value.Value, typeof(short)), value.Timestamp ?? DateTime.UtcNow, value.Status); } return value; }
Das SDK ist für zahlreiche Verhaltensweisen anderer OPC UA Client- und Server-Anwendungen optimiert und versucht diese selbstständig zu erkennen und sich entsprechend so zu verhalten, sodass das Ergebnis dem vom Benutzer erwarteten entspricht. Die im Folgenden explizit aufgeführten Maßnahmen und Themen werden häufig angefragt.
Ja, ab Version 2.23.0.0 des OPC UA SDKs werden die von Microsoft empfohlenen Maßnahmen für OPC Classic (zur Kommunikation über DCOM bzw. OPC DA, OPC HDA und OPC AE) umgesetzt.
Hintergrund:
Das als CVE-2021-26414 bekannte Problem adressiert Microsoft mit einen Leitfaden für DCOM-Client- und DCOM-Server-Anwendungen.
Als Bestandteil des Leitfadens beschreibt Microsoft die nach und nach ergriffenen Maßnahmen, um das Problem dauerhaft zu lösen. Nach Umsetzung der letzten Phase am 14. Juni 2022, kann es zu Kommunikations-Problemen zwischen DCOM-Client und DCOM-Server-Anwendungen kommen. Wovon voraussichtlich ein Teil der über OPC Classic kommunizierenden Anwendungen betroffen sein wird.
Zur weiteren Unterstützung, auch nach Abschluss der Maßnahmen zur Lösung des 'CVE-2021-26414'-Problems setzt das OPC UA SDK zur Kommunikation über OPC Classic die von Microsoft empfohlenen Authentication Level um. Diese Logik wurde als Teil der Version 2.23.0.0 des SDKs veröffentlicht.