Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 10 von 10

Thema: Libnodave reconnect mit C#

  1. #1
    Registriert seit
    27.06.2013
    Beiträge
    5
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo,
    ich habe ein Problem mit dem reconnect zu S7 Steuerungen.
    Mein Programm läuft als Windows Service unter W2k8 und greift auf 10 unterschiedliche Steuerungen nacheinander zu.
    Das Ganze passiert per Connection Pooling, d.h. ich erzeuge mir eine Liste mit den Verbindungen, verbinde mich mit der S7 (teilweise über IBH) und bei Bedarf wird die Verbindung von einer Funktion verwendet.
    Leider passiert es sporadisch dass die Verbindung kurzzeitig verloren geht und danach nicht wieder neu aufgebaut werden kann.
    Dies äußert sich wenn das Ergebnis von Connection.readBytes(flags, area.Db, start, bytesToRead, buf) = 1025 ist.
    Was kann man da machen?
    Hier mal etwas Code.
    Der Connection Pool:

    Code:
    public S7Connection GetConnectionByServer(string server, int port, bool ibh)
            {
                foreach (var ls in this)
                    if (ls.Name.Equals(server))
                        return ls;
                var lib = new S7Connection();
                //libnodave.daveSetDebug(libnodave.daveDeb);
                
                var serialType = new libnodave.daveOSserialType
                    {
                        rfd = libnodave.openSocket(port, server)            
                        
                    };
                
                serialType.wfd = serialType.rfd;
                
                lib.IsIBH = ibh;
                if (ibh)
                {
                    lib.Interface = new libnodave.daveInterface(serialType, server, 0, libnodave.daveProtoMPI_IBH,
                                                                libnodave.daveSpeed187k);
                    lib.Interface.setTimeout(1000000);
                    lib.Connection = new libnodave.daveConnection(lib.Interface, 2, 0, 0);
                    
                }
                else
                {
                    lib.Interface = new libnodave.daveInterface(serialType, server, 0, libnodave.daveProtoISOTCP,
                                                                libnodave.daveSpeed500k);
                    lib.Interface.setTimeout(1000000);
                    lib.Connection = new libnodave.daveConnection(lib.Interface, 0, 0, 2);
                }
    //                                                        libnodave.daveSpeed1500k);
    //            lib.Interface.initAdapter();
                lib.ConnectResult = lib.Connection.connectPLC();
                lib.Connected = lib.ConnectResult == 0;
                lib.Name = server;
                lib.IP = server;
                lib.Port = port;
                Add(lib);
                return lib;
            }
    Auf- und Abbau der Verbindung:
    Code:
    public bool Connect()
            {
                
                ConnectResult = Connection.connectPLC();
                Interface.initAdapter();
                if (ConnectResult==0)
                    Connected = true;
                return true;
            }
    
    
            public void Disconnect()
            {
                Connection.disconnectPLC();
                Interface.disconnectAdapter();
           
                Connected = false;
            }
    Und der Lesevorgang:
    Code:
     public List<string> ReadAll()
            {
                try
                {
                    lock (_lockObject)
                    {
                        if (_connectionIsReading) // zum Absichern dass nicht doppelt gelsen wird
                            return null;
                        _connectionIsReading = true;
                    }
    
    
                    int i = 0;
                    if (!Connected)
                    {
                        i = Connection.connectPLC();
                        Connected = true;
                        if (i != 0)
                            LogIt(String.Format("Conection result on reconnect : {0}", i));                 
                        Interface.initAdapter();
                    }
                    var returnlist = new List<string>();
                    // Lesen und Zuordnen der Werte
                    foreach (var area in _dataAreaList)
                    {
                        var readarea = ReadArea(area);  // area ist eine Klasse welche Speicherbereiche liest und die meinen Eigenschaften zuordnet
                        if (readarea != null)
                            returnlist.AddRange(readarea);
                        else
                        { // Wenn das Ergebnis null ist ist etwas schief gelaufen und die Verbindung muss neu aufgebaut werden. Daher Abbruch des Lesens und Disconnect.
                            Disconnect();                      
                            break;
                        }
                        System.Threading.Thread.Sleep(100);
                    }                
                    if (!IsIBH)
                    {
                        i = Connection.disconnectPLC();
                        if (i != 0) // War bisher immer 0
                            LogIt(String.Format("*****ALERT !!! disconnectPLC result = {0}  !!!!******", i));
                    }
                    return returnlist;
                }
               catch
               {
                   return null;
               }
                finally
                {
                    _connectionIsReading = false;
                }
            }
    Der Hauptteil von ReadArea :
    Code:
     var remainBytes = area.Size;
    //                var start = 0;
                    var start = area.StartAddress;
                    do
                    {
                        // Wenn Size > 220 dann in 220er Blöcke teilen und jeweils zuordnen
                        var bytesToRead = remainBytes > 220 ? 220 : remainBytes;
                        remainBytes = remainBytes - bytesToRead;
                        var buf = new byte[bytesToRead];
                        int i = 0;
                        lock (_lockObject)
                        {
                            i = Connection.readBytes(flags, area.Db, start, bytesToRead, buf);
                        }
                        if (i != 0) // Alle paar Tage kommt hier als Ergebnis 1025 und danach geht nichts mehr
                        {
                            LogIt(String.Format("*****ALERT {6} !!! readBytes DB{1}.{2} Size:{3} Start:{4} Length:{5} result = {0} Skip Area !!!!******", i,
                                                area.Db, area.StartAddress, area.Size, start, bytesToRead,CPName ));
                            return null;
                        }
                        Array.Copy(buf, 0, area.Buffer, start-area.StartAddress, bytesToRead);
                        start += bytesToRead;
    
    
                    } while (remainBytes > 0);
    Ich wäre für jede Hilfe dankbar.

    Gruß
    Martin
    Zitieren Zitieren Libnodave reconnect mit C#  

  2. #2
    DaMartin ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    27.06.2013
    Beiträge
    5
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hat denn nicht mal jemand eine Idee in welche Richtung man sich orientieren kann?

    Danke
    MArtin

  3. #3
    Registriert seit
    19.06.2003
    Beiträge
    2.200
    Danke
    85
    Erhielt 259 Danke für 175 Beiträge

    Standard

    initAdapter() nach connectPLC() ist Unsinn.

    Welcher IBH-Link? weil: Neuere können mehr gleichzeitige MPI-Verbindungen offenhalten.
    Laufen die Verbindungen zu 10 SPS über denselben IBH-Link?

    Grundsätzliches Vorgehen: Wenn readbytes() mit Fehler endet kannst du es wiederholen oder die Verbindung schließen ( disConnectPLC(), disconnectAdapter() ). Je nach deinen Erfahrungen kannst du auf die Wiederholung verzivchten; es bringt meist nichts.

    Beim Neuverbinden wird eine neue logische Verbindung auf der MPI/Profibus-Seite aufgebaut. Das verbraucht Resourcen auf der S7-CPU (da kannst du es unter Baugruppenzustand/Kommunikation sehen) und im IBH-Link. Zwar sollte disconnectPLC die Verbindung beenden und damit die Resourcen wieder freimachen. Aber das Problem ist, wenn eh schon ein Kommunikationsproblem besteht, ist es halt fraglich, ob es im IBH-Link auch ausgeführt wird.
    Irgendwann sind alle Resourcen belegt. Dann hilft ein Reset des IBH-Links. Die CPU "merkt" dann ,daß sich ihr Partner aus dem Token Ring zurückgezogen hat und macht ihrerseits ihre Resourcen frei.
    Libnodave enthält eine Routine, um einen Reset über das Netzwerk auszulösen: daveResetIBH(daveInterface *)
    Es scheint, daß die es nicht in die libnodave.net.cs geschafft hat.

    Du kannst in libnodave.net.cs ergänzen:
    Code:
    [DllImport("libnodave.dll")]
    protected static extern int daveResetIBH(intPtr di);
    public int resetIBH() {
    return daveResetIBH(pointer);
    }
    Nach einem Reset siehst du am IBH-Link dieselebn Aktivitäten der LEDs wie nach Spannung ein.
    Er braucht dann ein paar Sekunden, bis er wieder Verbindungen aufbauen kann.

  4. Folgender Benutzer sagt Danke zu Zottel für den nützlichen Beitrag:

    DaMartin (03.07.2013)

  5. #4
    DaMartin ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    27.06.2013
    Beiträge
    5
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo Zottel,

    erstmal vielen Dank für deine Antwort. Ich werde das mal versuchen.
    Wenn ich es richtig interpretiere ist die sicherste Methode nach einem Verbindungsabbruch und einem fehlerhaften Leseergebnis den Adapter zu resetten.

    Das Ganze Verhalten ist übrigens nicht auf IBH beschränkt. Es passiert auch bei einer Verbindung zu einer S7 über einen CP343. Selbes Verhalten. Ergebis vom Read ist -1025. Ich versuche die Verbindung mit Connection.disconnectPLC(); und Interface.disconnectAdapter(); abzubauen und später wieder neu aufzubauen. Beim Aufbauen erhalte ich dann als Ergebnis -1.
    Es wird erst wieder eine Verbindung aufgebaut wenn mein Service beendet und wieder neu gestartet wird.
    Gibt es evtl auch eine Möglichkeit sich von einen CP343 zurückzuziehen?

    Irgendwie scheint mir dass eine einmalig verlorene Verbindung sich nicht dazu bewegen lässt wieder aufgebaut zu werden.

    Danke nochmal

    Grüße
    Martin

  6. #5
    Registriert seit
    17.06.2004
    Ort
    Offenau
    Beiträge
    3.746
    Danke
    209
    Erhielt 421 Danke für 338 Beiträge

    Standard

    Wenn das beenden deines Service zum erfolg führt, dann scheinst du ja deinen Socket nicht zu schließen, oder machst du das?

    Kannst dir auch mal meine Toolboxlib anschauen, die wrappt das ganze LibNoDave Zeugs für C# auf einer abstrahierteren Ebene (https://github.com/jogibear9988/DotN...ToolBoxLibrary)

  7. #6
    DaMartin ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    27.06.2013
    Beiträge
    5
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Wenn ich meinen Socket schließe bekomme ich ihn nicht mehr auf.
    Problematisch ist auch dass nicht die Verbindung zu allen SPS verloren geht, sondern immer nur eine. Soweit ich das verstanden habe kann ich aber mit libnodave.closePort(102); und libnodave.closeSocket(102); die Verbindungen zu allen SPSen kappen. Dann bekomme ich sie auch nicht wieder auf.
    Ich werde mir mal deinen Wrapper ansehen.
    Danke dir

  8. #7
    Registriert seit
    17.06.2004
    Ort
    Offenau
    Beiträge
    3.746
    Danke
    209
    Erhielt 421 Danke für 338 Beiträge

    Standard

    Zitat Zitat von DaMartin Beitrag anzeigen
    Wenn ich meinen Socket schließe bekomme ich ihn nicht mehr auf.
    Problematisch ist auch dass nicht die Verbindung zu allen SPS verloren geht, sondern immer nur eine. Soweit ich das verstanden habe kann ich aber mit libnodave.closePort(102); und libnodave.closeSocket(102); die Verbindungen zu allen SPSen kappen. Dann bekomme ich sie auch nicht wieder auf.
    Ich werde mir mal deinen Wrapper ansehen.
    Danke dir
    Du musst an libnodave.closeSocket auch dein Socket Handle und nicht den Port übergeben!
    ---------------------------------------------
    Jochen Kühner
    https://github.com/jogibear9988/DotN...ToolBoxLibrary - Bibliothek zur Kommunikation mit PLCs und zum öffnen von Step 5/7 Projekten

  9. #8
    DaMartin ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    27.06.2013
    Beiträge
    5
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo Jochen,

    Danke dir, das ist vermutlich mein Fehler.

    wo bekomme ich mein Socket Handle? Wenn ich closeSocket aufrufe fordert mich Visual Studio auf einen Port einzugeben. Das ist dann aber sicherlich der Quellport auf meinem Rechner, korrekt? Verwirrt etwas.


    Gruß
    Martin

  10. #9
    Registriert seit
    17.06.2004
    Ort
    Offenau
    Beiträge
    3.746
    Danke
    209
    Erhielt 421 Danke für 338 Beiträge

    Standard

    rfd = libnodave.openSocket(port, server)

    in rfd hast du dein handle!
    ---------------------------------------------
    Jochen Kühner
    https://github.com/jogibear9988/DotN...ToolBoxLibrary - Bibliothek zur Kommunikation mit PLCs und zum öffnen von Step 5/7 Projekten

  11. #10
    Registriert seit
    08.12.2004
    Beiträge
    94
    Danke
    2
    Erhielt 16 Danke für 14 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Kurzer Tip zu Connect, bzw. Reconnect:
    Bei meinen Libnodave Tools verwende ich vor dem eigentlichen Connect ein "Pre-Ping", um zu sehen ob die SPS überhaupt erreichbar ist.
    Wenn sie nicht per Ping erreichbar ist, dann connecte ich erst gar nicht. Dies erspart die relativ lange Wartezeit, wenn libnodave auf eine nicht vorhandene SPS zugreifen will.

    Leider kann ich aktuell nicht zum eigentlichen Problem beitragen.

    mfG. Klaus Loy

Ähnliche Themen

  1. libnodave Reconnect Problem
    Von fLaVa im Forum Hochsprachen - OPC
    Antworten: 4
    Letzter Beitrag: 31.05.2011, 08:48
  2. Antworten: 0
    Letzter Beitrag: 09.09.2010, 00:27
  3. Visualisierung mit Libnodave?
    Von Backdoor im Forum Simatic
    Antworten: 12
    Letzter Beitrag: 11.06.2010, 18:42
  4. Reconnect mit C# und Notification Handles
    Von Kauabunga im Forum CODESYS und IEC61131
    Antworten: 2
    Letzter Beitrag: 11.05.2010, 19:21
  5. Visualisieren mit Libnodave
    Von Hocheck im Forum Hochsprachen - OPC
    Antworten: 4
    Letzter Beitrag: 07.05.2010, 14:39

Stichworte

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •