Python OPC UA-Client mit CODESYS verbinden

Python OPC UA-Client mit CODESYS SPS verbinden

Im letzten Beitrag hatte ich das Einrichten des OPC UA-Servers (in CODESYS) und den freien Client UaExpert gezeigt. Richtig interessant wird es in diesem Artikel, da wir nun einen Python OPC UA-Client nutzen werden. Der UaExpert ist perfekt um schnell die Verbindung zum Server zu überprüfen oder um durch den Projektbaum zu navigieren. Mit einem Client Toolkit könnt Ihr nun ganz neue Konzepte entwerfen oder eure eigene GUI implementieren. Ich habe mich hier für die Scriptsprache Python entschieden, da sie eine sehr klare und übersichtliche Syntax bietet. Außerdem wird mit der Python Installation eine sehr umfangreiche Programmbibliothek, sowie zahlreiche nützliche Zusatzpakete, bereitgestellt. Ich persönlich, kann Python jedem empfehlen, da einige große kommerzielle Projekte, wie YouTube oder Google, ebenfalls teilweiße in Python implementiert sind.

FreeOpcUa pure Python OPC UA-Client

Für Python gibt es mit Python OPC-UA/freeopcua sowohl die Client Funktionalität, als auch einen OPC UA-Server. Das Toolkit umfasst fast alle Punkte die in der OPC UA-Spezifikation festgelegt sind. Außerdem haben die Entwickler die Funktionalität mit einer Vielzahl an OPC UA-Stacks geprüft um bestmögliche Kompatibilität zu gewährleisten. Was mich besonders beeindruckt, ist die Tatsache, dass ich mit ganz wenig Zeilen Code einen voll funktionsfähigen Server oder einen Client realisieren kann.

Informationen zu FreeOpcUa, sowie zahlreiche Beispiele findet Ihr auf GitHub.

Link: Pure Python OPC-UA Client and Server

Die Installation ist super einfach. Alles was Ihr braucht ist pip. Hierbei handelt es sich um ein Paketverwaltungsprogramm für Python-Pakete. Der Paketpool umfasst mittlerweile um die 100.000 Pakete, welche die Entwickler nach dem hochladen, anderen Benutzern, zur Verfügung stellen können. Wie Ihr pip unter Windows Installieren könnt, ist mit Google schnell zu finden. Solltet Ihr die Scriptsprache Python noch installieren müssen, so könnt Ihr den Installer hier herunterladen (Python 2.7 erforderlich). Dabei habt ihr den Vorteil, dass im Installations-Wizzard, pip gleich mit ausgewählt werden kann.

Python inklusive pip installieren
Python inklusive pip installieren

Bevor Ihr nun mit dem Paketverwaltungstool, opcua installieren könnt, müsst Ihr noch Microsoft Visual C++ Compiler for Python 2.7 installieren. Diesen könnt Ihr hier herunterladen. Der Compiler wird benötigt, da einige Abhängigkeiten von pip während der Installation kompiliert werden müssen. Danach führt Ihr die Befehle zum Installieren in der Kommandozeile aus:

 Kommandozeile pip install opcua

Beispiel

Beginnen wir nun mit der Implementierung des Clients. Ich werde das Programm zunächst in einzelnen Abschnitten vorstellen. Als erstes müssen wir in Python einige Module importieren und konfigurieren. Ich importiere hier aus dem opcua Modul den client und ua. Außerdem benutze ich das Logging Modul um Werte/Aktionen zu verschiedene Level (Debug, Info, Error,…) zu generieren.

from opcua import Client
from opcua import ua

import logging
logging.basicConfig(level=logging.DEBUG)

Als nächstes müsst Ihr im Hauptprogramm die Verbindung zum OPC UA-Server im Connection String definieren und die Verbindung aufbauen. Hier in diesem Beispiel wird eine Verbindung zur CODESYS Soft-SPS auf dem gleichen Host hergestellt. Mit der Funktion get_root_node() wird der Wurzelknoten ermittelt. Dieser dient euch dann als Ausgangspunkt, wenn Ihr durch den Projektbaum iteriert. Hier lässt sich bereits erkennen, dass mit sehr wenig Code, eine Verbindung zum OPC UA-Server hergestellt werden kann.

if __name__ == "__main__":
    
    logging.info("Read/Write variable with OPC-UA")
    
    client = Client("opc.tcp://localhost:4840")
    #client = Client("opc.tcp://admin@192.168.2.1:4840") #connect using a user
    client.connect()

    # Get UA nodes in root
    root = client.get_root_node()

Die Verbindung zum OPC UA-Server steht. Jetzt müssen wir nur noch Variablen lesen und schreiben. Hierzu müsst Ihr euch zunächst einmal ein Objekt der Variable generieren. In der Python Implementierung habt Ihr hierzu zwei verschiedene Möglichkeiten:

  • getNode() wenn Ihr die nodeID eurer Variable kennt
  • getChild() wenn Ihr durch den Aufrufbaum iteriert

Beide Möglichkeiten findet Ihr im nachfolgenden Code Snippet, welches auch nochmals den gesamten Python Quelltext für den Client enthält. Darin findet Ihr ebenfalls ein Beispiel wie Ihr mit der setValue() Funktion Werte schreiben könnt.

# Install on windows:
# pip install opcua

import sys
sys.path.insert(0, "..")

from opcua import Client
from opcua import ua

import logging
logging.basicConfig()
#logging.basicConfig(level=logging.DEBUG)

if __name__ == "__main__":
    
    logging.info("Read/Write variable with OPC-UA")
    
    client = Client("opc.tcp://localhost:4840")
    #client = Client("opc.tcp://admin@192.168.2.1:4840") #connect using a user
    try:
        client.connect()

        # Get UA nodes in root
        root = client.get_root_node()

        # get a specific variable node knowing its node id
        #-----------------------------------------------------------------------------
        # read int16 variable
        var = client.get_node("ns=4;s=|var|CODESYS Control Win V3 x64.Application.GVL.uiCycleCounter")
        print("Value read from int16 variable: %s" % var.get_value())
        logging.info("Value read from int16 variable")

        # write int16 value
        newValue = var.get_value() + 1
        var.set_value(newValue, ua.VariantType.Int16)
        print("Value read from int16 variable (after write +1) : %s" % var.get_value())

        # read string variable
        var1 = client.get_node("ns=4;s=|var|CODESYS Control Win V3 x64.Application.GVL.sInfoMsg")
        print("Value read from string variable: %s" % var1.get_value())

        # write string value
        var1.set_value("Cool, I can write the value", ua.VariantType.String)
        print("Value read from string variable (after write): %s" % var1.get_value())
        
        # Now getting a variable node using its browse path
        #-----------------------------------------------------------------------------
        myvar = root.get_child(["0:Objects", "2:DeviceSet", "4:CODESYS Control Win V3 x64", "4:Resources", "4:Application", "3:GlobalVars", "4:GVL", "4:uiCycleCounter"])
        print("Value read from int16 variable using its browse path: %s" % myvar.get_value())

    finally:
        client.disconnect()

Damit Ihr nun Werte aus dem CODESYS OPC UA-Server lesen bzw. schreiben könnt, müssen wir ein CODESYS Projekt anlegen und eine GVL mit den folgenden Variablen hinzufügen (siehe vorheriger Artikel):

GVL - über OPC UA-Server bereitgestellte Variablen (Online)
GVL – Erstellen der Variablen

Zum Schluss müsst Ihr nun euere Python Programm ausführen. Ihr solltet dann den Variablenwert in eurer Konsole angezeigt, sowie den Wert der integer Variabel im CODESYS um eine Zahl erhöht bekommen.

 Kommandozeile python opcua_client_simple.py

Wenn alles passt und Ihr keine Fehlermeldung erhaltet, seht Ihr folgende Ausgabe in der Konsole:

PowerShell: Python OPC UA-Client
PowerShell: Python OPC UA-Client

Das nachfolgende Bild zeigt die GlobaleVariablenliste aus CODESYS in der Online Ansicht. Hier könnt Ihr sehen, dass die beiden Variablen über den Python OPC UA-Client geschrieben werden konnten.

CODESYS GVL Editor - über OPC UA-Server bereitgestellte Variablen (Online)
GVL – über OPC UA-Server bereitgestellte Variablen (Online)

GitHub

Den gesamten Code für den Python OPC UA-Client findet Ihr übrigens auch bei mir auf GitHub.

https://github.com/Matthias-Gehring/OPCUA-Client-Simple

Benötigen wir den UaExpert noch?

In meinem Beispiel oben, habt Ihr bestimmt den Komplexen Pfad/Namen für die NodeID oder die verschiedenen Level des Aufrufbaumes gesehen. Hier muss ich leider anmerken, dass es alles andere als trivial ist, wie sich die NodeID zusammensetzt. Aber ich habe einen tollen Trick gefunden, der ordentlich Zeit spart. Was mich geärgert hat, ist die Tatsache, dass ich die NodeID nirgends kopieren konnte. Bei meinen Tests hatte Ich unzählige Skriptfehler, die nur dadurch entstanden sind, dass ich beim Abschreiben der NodeID (z.B. NS4|String||var|CODESYS Control Win V3 x64.Application.GVL.uiCycleCounter) Übertragungsfehler hatte. Um das zu vermeiden, könnt Ihr einfach im UaExpert die Log Messages speichern, im Text Editor (z.B. Notepad++) öffnen und den richtigen Abschnitt kopieren.

Fazit

Anfangs hatte ich auf tollen Möglichkeiten hingewiesen, welche durch den Python OPC UA-Client möglich sind. In diesem Beispiel hier haben wir nun die Grundlage für die nächsten Schritte geschaffen. Dieses Minimalbeispiel dient uns nun als Basis für tolle Projekte. In meinen folgenden Artikeln werden wir öfters mit Python und CODESYS in Berührung kommen. Egal ob Ihr nun CODESYS Einsteiger oder Experte seit – freut euch auf tolle Beispiele.

 

5 Kommentare

  1. so cool ich habe es geschafft! Mein wxpython application on Beaglebone kommuniziert mit das PLC runtime durch OPC-UA. besser dan vorher , dar habe ich data files gebraucht. jetzt kann ich PLC programs schreiben und der visu hat ein Windows/desktop feel. Und ich kann via ein boolean schalten zwischen webvisu und der wx api. Alles auf einer Beaglebone.
    Ich mus noch aus finden wie man die complexer struct variabelen lessen/schreiben kan aber das wird auch gut gehen.

    Danke.

    1. Hallo Roel,

      super Lösung! Ich würde gerne wissen, ob du ein wxPython GUI Builder/Designer nutzt, und wenn ja welchen? Hast du einen Touchscreen an deinem Beaglebone angeschlossen?
      Bzgl. OPC-UA und Strukturvariablen, kann ich dir hier (https://github.com/FreeOpcUa/python-opcua/blob/master/examples/client_read-custom_structures.py) zu einem Beispiel auf git weiterhelfen. Sieht sehr vielversprechend aus. Habe es aber noch nicht getestet.

      Grüße
      Matthias

      1. Hallo,

        Nein alles ist hand coded, no gui designer. Ja das ist ein 7″ display cape von 4D systems. Ja die read-custom_structures.py habe ich aug gefunden aber das gibt mir nog ein error. Will have to expiriment some more.

        Grüße
        Roel

  2. Im Data Access View des UaExpert kann übrigens auch direkt die Node Id eines beobachteten Wertes angeklickt und mit Strg+C kopiert werden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website benutzt Cookies und Google Analytics. Wenn du die Website weiter nutzt, gehen wir von deinem Einverständnis aus Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklärst du sich damit einverstanden.

Schließen