DotNetSiemensPLCToolBoxLibrary - "var changed handler"

Pico1184

Well-known member
Beiträge
327
Punkte Reaktionen
9
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo zusammen,

Ich bin für mein unter .net selbst entwickeltes Visualisierungssystem
"VisualControl" auf der Suche nach einem geeignetem S7 Kommunikationstreiber.

Hier bin ich auf das Projekt "DotNetSiemensPLCToolBoxLibrary" gestoßen.
Ich habe mich noch nicht großartig damit beschäftigt.
Daher hätte ich vorher erst mal ein zwei fragen ob es überhaupt etwas für mein Vorhaben ist.

Bisher verwende ich OPC zur Kommunikation.

Habe über die Softing OPC Toolbox einen OPC Client entwickelt und diesen in mein System eingebunden. Nachteile davon:

- kosten für die Softing Lizenz
- eventl. kosten für den OPC Server

Der Ablauf momentan ist folgender:

- anlegen von Variablen welche visualisiert werden sollen über eine Oberfläche in einer SQL Datenbank
- Windows Dienst als visu Server starten
- Dienst registriert alle Variablen aus der Datenbank im OPC Server
- Client (Webseite über html JavaScript (Ajax)) abonniert sich und die interessanten Variablen am Dienst
- Client erhählt vom Dienst aktuelle Daten (beim ersten Aufruf und bei Variablenänderungen)

Nun ist meine Frage ob dies auch mit der DotNetSiemensPLCToolBoxLibrary möglich ist?
Kann ich Variablen abonnieren d.h Änderungen der Variablen aus der Sps abonnieren

Wie stabil ist die DotNetSiemensPLCToolBoxLibrary?
Auf welcher Basis wird mit der S7 kommuniziert?
Für weitere Infos bin ich euch sehr dankbar!

Grüße Pico
 
Zuletzt bearbeitet:

Jochen Kühner

Well-known member
Beiträge
4.154
Punkte Reaktionen
474
Die ToolBox ist eine Bibliothek welche die Kommunikation zur SPS umsetzte. Sie nutzt zur Kommunikation die libnodave (eine abgewandelte Version). D.h. Kommunkation ist möglich per Seriell, NetLink, TCP/IP und S7Online. bei den letzten 3 ist auch Routing möglich. Du kannst im Endeffekt auch direkt libnodave benutzen, jedoch kappselt meine Bibliothek einige Funktionen. Z.B. definierst du einfach Objekte vom Typ PLCTag, Und übergibst dann eine Liste der Objekte an die Lesefunktion. Diese versucht dann die Werte optimiert (d.h. Speicherbereich bei denen es möglich ist werden zusammengefasst) aus der SPS zu lesen.
Es gibt keinen Variablenserver, dass musst du in deinem Backend selber programmieren. Ich hab da zwar auch schon mal was gemacht, dass ist aber noch nicht fertig, und Ich weiss auch noch nicht ob das auch Open Source wird!
 
OP
P

Pico1184

Well-known member
Beiträge
327
Punkte Reaktionen
9
Zuviel Werbung?
->Hier kostenlos registrieren
Es gibt keinen Variablenserver, dass musst du in deinem Backend selber programmieren.

Einen Variablenserver habe ich bereits schon.

Wie wird aber umgegangen wenn Variablen sich ändern? Gibt es da von der Toolbox ein Event welches bei jeder Änderung gefeuert wird???

Irgendwie muss ich ja benachrichtigt werden wenn sich ein Variablenwert ändert?!?!

Ich kann ja nicht dauerhaft werte aktualisieren da dies ja mein System enorm belastet?!?!

Grüße Pico
 

Jochen Kühner

Well-known member
Beiträge
4.154
Punkte Reaktionen
474
Einen Variablenserver habe ich bereits schon.

Wie wird aber umgegangen wenn Variablen sich ändern? Gibt es da von der Toolbox ein Event welches bei jeder Änderung gefeuert wird???

Irgendwie muss ich ja benachrichtigt werden wenn sich ein Variablenwert ändert?!?!

Ich kann ja nicht dauerhaft werte aktualisieren da dies ja mein System enorm belastet?!?!

Grüße Pico

Du musst die Variablen halt über einen Timer von der SPS-lesen (das macht der opc auch, der wird nicht von der sps benachrichtigt!). Die PLCTag Objekte haben dann ein Ereignis wenn ein wert sich geändert hat!

Also Ich habs bei mir so gemacht:

- Es wird am TagServer registiert, welche PLCTag Objekte vom aktuellen Bild gelesen werden sollen.
- Dann weis der Server noch welche er ständig lesen muss (z.b. störmeldungen, etc)
- Dann speicher ich zu den objekten die gewünschte aktualisierungszeit, und bilde mir aus der zeit "zuletzt gelesen"+aktulisierungszeit => neulesezeit denn zeitpunkt wann der wert neu gelesen werden soll.
- im timer prüfe ich nun welche tags zu lesen sind (aktuellezeit > neulesezeit) und lese diese!
 
OP
P

Pico1184

Well-known member
Beiträge
327
Punkte Reaktionen
9
Du musst die Variablen halt über einen Timer von der SPS-lesen (das macht der opc auch, der wird nicht von der sps benachrichtigt!). Die PLCTag Objekte haben dann ein Ereignis wenn ein wert sich geändert hat!
Ich erweitere im Moment meinen Server welcher bisher auf OPC basiert um die Funktionalität der SPSToolbox.
Werde die PLCTags in Gruppen einteilen und diesen Gruppen dann eine Aktualisierungszeit vergeben.
Ich muss nur immer alle registrierten Variablen updaten da ich noch logging Funktionen verwende d.h. nicht nur die von der aktuellen Seite.
Würde gerne noch einen SPS Scanner integrieren. Gibt es da in der Toolbox schon Funktionen dafür oder muss ich da mein ganzes Netzwerksegment durchsuchen und versuchen jede einzelne IP-Adresse über einen Connect
zu verbinden???
Und wie ist das mit den PLCTag Ereignissen wenn sich ein Wert ändert? Muss ich nicht ein PLCTag lesen und den gelesen Wert mit dem letzten gelesenen Wert vergleichen??
Es gibt ja die Methode ReadPLCTag ohne Rückgabewert.....wo bekomme ich dann die gelesenen Werte zurück??
Grüße Pico
 

Jochen Kühner

Well-known member
Beiträge
4.154
Punkte Reaktionen
474
Zuviel Werbung?
->Hier kostenlos registrieren
Jedes Plctag objekt hat ein ereignis, welches nur aufgerufen wird wenn sich der wer geändert hat. Du kannst immer die gleichen plctag objekte verwenden! Die haben sogar rudimentäre archiv unterstützung ( Ein array von alten werten).

Zum scannen gibts es keine funktionen, du kannst aber die listreachablepartners der libnodave verwenden... Die geht glaub aber auch nur für mpi/dp!
 
OP
P

Pico1184

Well-known member
Beiträge
327
Punkte Reaktionen
9
Also falls es jemanden interessiert, nachfolgend eine Methode in C#, welche ein
Netzwerksegment nach einer SPS abscannt, die Methode erwartet eine IP Adresse
als string Parameter und durchsucht dann dieses Segment von xxx.xxx.xxx.1 - 254 nach einer SPS.

Code:
public IEnumerable<Connectors> BrowseConnector(string ipAdress)
        {
            /*To do: String auf IP Adresse prüfen! */
            TraceManager.PublishHint("Start browsing native Connectors...");
            var ipSub = ipAdress.Split('.');
            var connectors = new List<Connectors>();
            var localIpSubstring = String.Join(".", ipSub, 0, 3);
            var lockObject = new object();

            Parallel.For(1, 255, i =>
            {              
                var nextIp = String.Concat(localIpSubstring, ".", Convert.ToString(i));

                if (!IpScanner.Ping(nextIp, 1, 500)) return;
                var tempConfig = new PLCConnectionConfiguration("tempConfig" + i);
                var tempConn = new PLCConnection(tempConfig);
                tempConfig.CpuIP = nextIp;
                TraceManager.PublishHint("Found Station: " + nextIp);
                try
                {
                    tempConn.Connect();
                    var szl = tempConn.PLCGetSZL(0x111, 1);
                    var connector = new Connectors { RemoteName = nextIp };
                    if (szl != null && szl.SZLDaten[0] is xy11Dataset)
                        connector.Description = ((xy11Dataset) szl.SZLDaten[0]).MlfB;
                    lock (lockObject)
                    {
                        connectors.Add(connector);
                    }

                    tempConn.Disconnect();                       
                }
                catch (Exception)
                {
                    TraceManager.PublishHint("Station: " + nextIp + " is not a valid PLC");
                }
            }

                );
            TraceManager.PublishWarning("Finalize browsing native Connectors...");
            return connectors;
        }

IP Scanner:

Code:
 public static bool Ping(string host, int attempts, int timeout)
        {
            var ping = new Ping();

            for (int i = 0; i < attempts; i++)
            {
                try
                {
                    PingReply pingReply = ping.Send(host, timeout);

                    // If there is a successful ping then return true.
                    if (pingReply != null &&
                        pingReply.Status == IPStatus.Success)
                        return true;
                }
                catch
                {
                    // Do nothing 
                }
            }

            return false;
        }

Kritik ist gerne willkommen ;)

Grüße Pico
 
Zuletzt bearbeitet:
Oben