Häufige Fragen


PowerShell

Kann das SDK auch in der PowerShell verwendet werden?

Ja, ein Beispiel hierzu samt Bootstrapper existiert auf GitHub: OPC UA .NET Samples - PowerShell Client

NuGet Preview

Nach der Verwendung einer alten NuGet Preview (als Download für die eine NuGet-Source) kann nicht auf eine neue Version aktualisiert werden. Woran liegt das?

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.

  • Wird das SDK über NuGet referenziert (mit packages.config-Datei):
    • Schließen Sie Visual Studio
    • Navigieren Sie im Explorer zum Projektverzeichnis
    • Löschen Sie das Verzeichnis „packages“ neben ihrer Solution
    • Öffnen Sie das Projekt und erstellen Sie es erneut
  • Wird das SDK über NuGet referenziert (ohne packages.config-Datei):
    • Schließen Sie Visual Studio
    • Navigieren Sie zum lokalen NuGet-Cache: C:\Users\Benutzername\.nuget\packages
    • Löschen Sie das Verzeichnis „Opc.UaFx.Client“ bzw. „Opc.UaFx.Advanced“
    • Öffnen Sie das Projekt und erstellen Sie es erneut

Anschließend kann wie gewohnt über den NuGet-Client auf die aktuelle Version aktualisiert bzw. diese installiert werden.

.NET Exceptions

Beim Start meiner Anwendung erhalte ich beim Aufruf einer API des SDKs eine ''TypeInitializationException''. Woran kann das liegen?

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:

  • Schließen Sie Visual Studio
  • Navigieren Sie im Explorer zum Projektverzeichnis
  • Löschen Sie alle „bin“ und „obj“ Verzeichnisse
  • Öffnen Sie das Projekt und erstellen Sie es erneut

Sollte der Fehler bei der Ausführung weiterhin bestehen, dann sollten folgende Schritte das Problem lösen:

  • Wird das SDK aus den ZIP Archiv referenziert:
    • wurden alle Dateien die Teil des Zielframework-Ordners im Projekt referenziert
    • wurden die Dateien aus dem korrekten Zielframework-Ordner referenziert
  • Wird das SDK über NuGet referenziert (mit packages.config-Datei):
    • Schließen Sie Visual Studio
    • Navigieren Sie im Explorer zum Projektverzeichnis
    • Löschen Sie das Verzeichnis „packages“ neben ihrer Solution
    • Öffnen Sie das Projekt und erstellen Sie es erneut
  • Wird das SDK über NuGet referenziert (ohne packages.config-Datei):
    • Schließen Sie Visual Studio
    • Navigieren Sie zum lokalen NuGet-Cache: C:\Users\Benutzername\.nuget\packages
    • Löschen Sie das Verzeichnis „Opc.UaFx.Client“ bzw. „Opc.UaFx.Advanced“
    • Öffnen Sie das Projekt und erstellen Sie es erneut

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.

Nach ca. 30 Minuten erhalte ich eine ''LicenseException'' beim Aufruf einer Client API, wieso?

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!

Im laufenden Betrieb meines OPC UA Servers bekommen die Client Anwendungen nach ca. 30 Minuten eine Antwort mit dem Code ''BadLicenseExpired'', wieso?

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!

Client + Server

Ist es möglich in nur einer Anwendung den Client und den Server gleichzeitig zu betreiben?

Ja, das funktioniert ohne Probleme. Viele unserer Tests beruhen deshalb auch auf Codeausschnitten wie der folgende:

using (var server = new OpcServer()) {
    server.Start();
 
    using (var client = new OpcClient(server.Address)) {
        client.Connect();
        ...
    }
}

OPC UA + S7-Steuerungen

Warum erhalte ich nicht innerhalb der eingestellten Intervalle eine Benachrichtigung?

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:

  • Das PublishingInterval kann über die CurrentPublishingInterval-Eigenschaft geprüft werden.
  • Das 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.

OpcObjectNode vs. OpcFolderNode

Was ist der Unterschied zwischen ''OpcObjectNode'' und ''OpcFolderNode'', wann sollte welcher Node verwendet werden?

Die folgenden Typen werden hier besprochen: OpcObjectNode und OpcFolderNode.

Die Unterschied ist semantischer Natur. Während OpcFolderNode eine Unterklasse von OpcObjectNode ist, wird ihr Einsatz wie folgt differenziert:
  • OpcObjectNode gruppiert Nodes, welche auch in einer physikalischen Beziehung zueinander stehen
  • OpcFolderNode gruppiert Nodes, welche eher in einer logischen Beziehung zueinander stehen
In der Dokumentation zum OpcObjectNode steht:
Definiert eine logische Einheit zur Darstellung komplexerer Informationen als OpcVariableNode. Objekte werden verwendet, um Systeme, Systemkomponenten, reale Objekte und Softwareobjekte darzustellen.
Aus einer abstrakteren Sicht werden Objekte verwendet, um Variablen und andere Objekte im Adressraum zu gruppieren. Daher sollten Objekte verwendet werden, wenn einige gemeinsame Strukturen/Gruppen von Objekten und/oder Variablen beschrieben werden sollen. Einfache Objekte mit nur einem Wert (z.B. ein einfacher Wärmesensor) können ebenfalls als Variablen modelliert werden. Es sollten jedoch Erweiterungsmechanismen berücksichtigt werden (z.B. ein komplexer Wärmesensor-Subtyp könnte mehrere Werte haben) und ob dieses Objekt als Objekt in der GUI des Clients oder nur als Wert verfügbar gemacht werden soll. Wenn ein Modellierer Zweifel hat, welche Lösung das Objekt mit einer Variablen verwenden soll, sollte die Lösung mit dem Objekt bevorzugen.

In der Dokumentation zum OpcFolderNode steht:

Definiert einen Knoten, um den Adressraum in einer Hierarchie von Knoten zu organisieren. Sie stellen den Wurzelknoten eines Teilbaums dar und haben keine andere Semantik.

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:

  • OpcObjectNode gruppiert Nodes, welche auch in einer physikalischen Beziehung zueinander stehen
  • OpcFolderNode gruppiert Nodes, welche eher in einer logischen Beziehung zueinander stehen

OpcNodeId

Ist es möglich das Separator-Zeichen in NodeIds zu ändern?

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 = '.'
};

OpcMethodNode

Ist es möglich über einen OpcMethodNode mehrere Werte zurückzugeben?

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));

OpcVariableNode

Gibt es eine Möglichkeit das Schreiben von Werten einer nicht-typisierten OpcVariableNode auf einen bestimmten Datentypen zu beschränken?

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;
}

Ist es möglich den Wert, der für einen nicht-typisierten OpcVariableNode geschrieben werden soll, in einen bestimmten Datentypen zu konvertieren?

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;
}