# LibnodaveConnection Library



## Jochen Kühner (6 Mai 2010)

Arbeite gerade an einer Bibliothek um die Libnodave Kommunikation und Konfiguration zu kappseln. Dazu hat die DLL einen Dialog um die Verbindungen zu Konfigurieren so das dies nicht in jeder Anwendung wieder von vorne gemacht werden muss.

Später kann ich so ganz leicht eine Configuration in mein Programm einbinden. 
Bsp:

```
LibNoDaveConnectionLibrary.Configuration.ShowConfiguration("JFK-TestConnection", true);
```
auch der Verbindungsaufbau und auslesen von Werten wird dann einfach:
Bsp:

```
private LibNoDaveConnection myConn = new LibNoDaveConnection("JFK-TestConnection");
myConn.Connect();
LibNoDaveValue myValue = LibNoDaveValue.GetLibNoDaveValueFromString("DB2.DBD4");
myValue = myConn.ReadValue(myValue);
label1.Text = myValue.Value.ToString();
```


Achtung: Dies ist erstmal eine Vorabversion, es geht noch lange nicht alles....

Diese dient nur dazu um mir Ideen und Vorschläge von euch anzuhören.

Features:

- Automatisches aufteilen von Variablen wenn ein ReadRequest zu viele Tags beinhalten würde oder die PDU Size überschritten werden würde! (Das aufteilen eines Tags kann blockiert werden!)
- Verbindungskonfiguration kann über aussenstehendes Programm geändert werden, wenn neue Typen hinzukommen muss am Programm selbst nichts geändert werden...
und viel mehr geplant!


----------



## Jochen Kühner (6 Mai 2010)

*Fragen.*

ich habe auch schon ein paar Fragen wo mir vielleicht jemand weiterhelfen kann.

1.) Wie kann Ich die in PG/PC Schnittstelle definierten Verbindungen auslesen?
(Hab in der Resitry gesucht, finde die dort aber nicht)
-> Erledigt

2.) Wie kann ich den Dialog PG/PC Schnittstelle von meiner Software aus öffnen?
-> Erledigt

3.) Wieso muss Ich neueren versionen der LibNoDave an S7Online eine HWND Übergeben und in früheren Versionen musste Ich das noch nicht!
-> Erledigt

4.) Hat jemand schon mal routing über LibNoDave Probiert, da gibt es ja einen Verbindungstyp dazu. Wie funzt das, was geht, was geht nicht?

5.) Wie funktioniert das, wenn Ich von mehrern Addressen auf einmal lesen will (in einer PDU). Denke mit prepareReadRequest, aber wie??
     Hab da jetzt auch in der Hilfe was dazu gefunden, aber ist es nicht möglich bei diesem Lesevorgang in einen eigenen Buffer zu lesen?
-> Hab Ich nun selbst gelöst bekommen!


----------



## pylades (6 Mai 2010)

Moinsens,

zu 2.)

rundll32.exe shell32.dll, Control_RunDLL S7EPATDX.CPL

Pylades


----------



## pylades (6 Mai 2010)

zu 1.)

HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\SINEC\LogNames

Pylades


----------



## Jochen Kühner (6 Mai 2010)

*Punkte...*

Punkte 1 und 2 habe Ich gleich mal implementiert.

Hab noch einen neuen 5ten Punkt.

Jemand sonst noch irgendwelche Ideen?


----------



## Jochen Kühner (6 Mai 2010)

*Multiple Reads...*

Multiple Reads sind nun mal voröäufig implementiert, die implementierung ist bestimmt noch nicht der Weisheits letzter Schuss, aber es geht!


----------



## Ralle (6 Mai 2010)

Jochen Kühner schrieb:


> 3.) Wieso muss Ich neueren versionen der LibNoDave an S7Online eine HWND Übergeben und in früheren Versionen musste Ich das noch nicht!



Weil ansonsten die Handles, die zum Öffnen intern wohl nötig sind offen blieben und nach und nach mehr wurden, bis nichts mehr ging. (So ist mir das in Erinnerung) Ich hab es bisher immer nur geschafft, auf die 1. geöffnete Verbindung per S7Online zuzugreifen. Jede weitere SPS-Verbindung wurde geöffnet, enthielt dann aber die selben Daten, wie die erste SPS, also ist da irgend etwas im Argen. Kannst das ja gerne mal prüfen, vielleicht mache ich da auch etwas falsch!


----------



## Jochen Kühner (6 Mai 2010)

*Mal sehn...*

Mal sehn, wenn Ich morgen @work dazu komme!


----------



## Jochen Kühner (6 Mai 2010)

*Noch ein Problem...*

6) Ich benutze einen Netlink lite, bekomme aber mit dem Netlink-Protokoll keine Verbindung, nur wenn ich ISO TCP nehme. Habe aber das Problem, das wenn Ich die Verbindung nicht sauber trenne, Ich den Netlink reseten muss, gibts da abhilfe?


----------



## Jochen Kühner (7 Mai 2010)

*Probleme....*

Habe noch Probleme mit PrepareReadrequest und addVarToReadRequest

Habe dieses Problem nur beim 2ten Aufruf der Funktionen. Es gehen ja mit einem Read Request bis zu 20 Variablen (nutze gearde max. 18). D.h. nach 18 Variablen führen Ich den Request aus, und starte dann mit einer neuen PDU! Die 18 liest er auch fehlerfrei, aber der 19ten kommt dann:

The desired Adress is beyond limit for this PLC
oder
The desired item is not available in the PLC

Hier noch ein Ausschnitt aus meinem Code:


```
//Count how Many Bytes from the PLC should be read and create a Byte Array for the Values
            int completeReadSize = 0;
            foreach (var libNoDaveValue in valueList)
            {
                completeReadSize += libNoDaveValue._internalGetReadSize();
            }
            byte[] completeData = new byte[completeReadSize];


            //Get the Maximum Answer Len for One PDU
            int maxReadSize = _dc.getMaxPDULen() - 18;


            int akReadSize = 0;
            int positionInCompleteData = 0;
            int akVar = 0;
            int anzVar = 0;
            int anzReadVar = 0;
           
            libnodave.PDU myPDU = _dc.prepareReadRequest();
            
            //Todo Split the Read Value, if it does not fit into one PDU
            foreach (var libNoDaveValue in valueList)
            {
                if (libNoDaveValue.LibNoDaveDataSource != LibNoDaveDataSource.Datablock && libNoDaveValue.LibNoDaveDataSource != LibNoDaveDataSource.InstanceDatablock)
                    libNoDaveValue.DatablockNumber = 0;

                int readSize = libNoDaveValue._internalGetReadSize();
                if (readSize + akReadSize > maxReadSize || anzReadVar == 18)
                {                    
                    var rs = new libnodave.resultSet();
                    int res = _dc.execReadRequest(myPDU, rs);
                    if (res != 0)
                        throw new Exception("Error: " + libnodave.daveStrerror(res));

                   

                    //Save the Read Data to a User Byte Array (Because we use this in the libnodavevalue class!)
                    int akres = 0;
                    for (; akVar < anzVar; akVar++)
                    {                       
                        res = _dc.useResult(rs, akres++);
                        if (res != 0)
                            throw new Exception("Error: " + libnodave.daveStrerror(res));

                        for (int n = 0; n < valueList[akVar]._internalGetReadSize(); n++)
                        {
                            completeData[positionInCompleteData++] = Convert.ToByte(_dc.getU8());
                        }
                    }
                    rs = null;
                    myPDU = null;
                    myPDU = _dc.prepareReadRequest();
                    readSize = 0;
                    anzReadVar = 0;
                }

                akReadSize = akReadSize + readSize;
                anzVar++;
                anzReadVar++;
                myPDU.addVarToReadRequest(Convert.ToInt32(libNoDaveValue.LibNoDaveDataSource), libNoDaveValue.DatablockNumber, libNoDaveValue.ByteAddress, readSize);
            }

            if(akReadSize>0)
            {
                var rs = new libnodave.resultSet();
                int res = _dc.execReadRequest(myPDU, rs);
                if (res != 0)
                    throw new Exception("Error: " + libnodave.daveStrerror(res));                

                //Save the Read Data to a User Byte Array (Because we use this in the libnodavevalue class!)
                int akres = 0;
                for (; akVar < anzVar; akVar++)
                {                    
                    res = _dc.useResult(rs, akres++);
                    if (res != 0)
                        throw new Exception("Error: " + libnodave.daveStrerror(res));

                    for (int n = 0; n < valueList[akVar]._internalGetReadSize(); n++)
                    {
                        completeData[positionInCompleteData++] = Convert.ToByte(_dc.getU8());
                    }
                }
                rs = null;
            }
```


----------



## bool (8 Mai 2010)

*wie S7Online Verbindung richtig schliessen ???*



Ralle schrieb:


> Weil ansonsten die Handles, die zum Öffnen intern wohl nötig sind offen blieben und nach und nach mehr wurden, bis nichts mehr ging. (So ist mir das in Erinnerung) Ich hab es bisher immer nur geschafft, auf die 1. geöffnete Verbindung per S7Online zuzugreifen. Jede weitere SPS-Verbindung wurde geöffnet, enthielt dann aber die selben Daten, wie die erste SPS, also ist da irgend etwas im Argen. Kannst das ja gerne mal prüfen, vielleicht mache ich da auch etwas falsch!


 
Hallo,
habe das selbe Problem.
Wie müsste das mit der Handleübergabe in VB 2008 Express aussehen?

Welcher Funktion muss welches Handle übergeben werden damit die erste Verbindung wirklich komplett und richtig geschlossen wird und die Kommunikation beim erneuten öffnen auch wieder richtig funktioniert?
Momentan gehts bei mir erst wieder wenn ich das komplette Programm beende und erneut starte.

Danke und Gruss,

bool


----------



## Jochen Kühner (12 Mai 2010)

*Neues...*

So, die Version kann nun auch mehr als 17 Variablen lesen, hatte mit meinem PrepareReadRequest da noch Probleme.

Nur wenn die Antwortlänge an die PDU Größe kommt kanns noch Probleme geben, da Ich nocht nicht weis wieviel Bytes Header Ich Pro Antwortvariable Rechnen muss (laut Zottel wahrscheinlich 4). Und auch wenn die Variablen größer als eine PDU sind...

Aber Ich arbeite drann...




Info, die Versionen der Lib hier im Forum sind nicht mehr aktuell, aber download ist nun unter: http://siemensplctoolboxlib.codeplex.com/


----------

