libnodave via S7Online macht Probleme nach Verbindungstrennung und erneuten Verbinden

bool

Level-1
Beiträge
94
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

inzwischen bin ich dabei mit dem S7Online Protokoll zu experimentieren und habe dieses prinzipiell mit dem PCMCIA CP5511 MPI/Profibus Adapter zum laufen bekommen. Den Verbindungsauf und Abbau habe ich gemäss diverser Programmbeispiele folgendermassen vorgenommen:


Verbindungsaufbau (wichtigsten Funktionen aus dem Code extrahiert):
fds.rfd = libnodave.openS7online(S7Online_accesspoint)
fds.wfd = fds.rfd
di = New libnodave.daveInterface(fds, "IF1", S7Online_localAddress, libnodave.daveProtoS7online, nodaveBaudrate)
di.setTimeout(1000)
res = di.initAdapter
dc = New libnodave.daveConnection(di, S7Online_remoteAddress, S7Online_rack, S7Online_slot)
res = dc.connectPLC

Verbindungsabbau (wichtigsten Funktionen aus dem Code extrahiert):

res = dc.disconnectPLC()
di.disconnectAdapter()
'res = libnodave.closePort(fds.rfd)
'WriteDebugInfo("Close S7Online Connection: closePort() ... (res=" & CStr(res) & " - " & libnodave.daveStrerror(res) & ")")
res = libnodave.closeS7online(fds.rfd)
WriteDebugInfo("Close S7Online Connection: closeS7online() ... (res=" & CStr(res) & " - " & libnodave.daveStrerror(res) & ")")

Für mich stellen sich nun folgende Fragen:

Muss ich beim Verbindungsabbau die Funktion
a) libnodave.closeS7online(fds.rfd) oder
b) libnodave.closePort(fds.rfd) ausführen
oder sogar beide?
Bei dem von mir als Vorlage verwendeten Programmbeispiel wurde Variante b) verwendet aber wofür gibt es dann a)?

Warum funktioniert das Lesen nur nach dem ersten Verbindungsaufbau und ab dem zweiten Verbindungsaufbau nicht mehr?

Dann bekomme ich vom dc.execReadRequest() nur noch eine "-128"
Leider funktioniert bei mir ausserdem die Funktion "libnodave.daveStrerror(res)" nicht richtig, ich bekomme leider den Fehlertext nicht im Klartext sondern nur kryptische Zeichen zurück.

Ich habe in einem anderen Thread gelesen, dass in "neueren versionen der LibNoDave an S7Online eine HWND Übergeben" werden muss.
Was steckt da dahinter? Was muss ich machen und wie würde dies Codetechnisch für VB 2008 Express aussehen?

Danke bereits jetzt im voraus für Eure Unterstützung.

Gruss,

bool
 
Zuviel Werbung?
-> Hier kostenlos registrieren
benutzt du auch S7Online aus der neusten LibNoDave der du die HWND des Fensters mitgeben musst?
Hallo Jochen,
was meinst Du mit der neuen LibNoDave und wie muss welcher Funktion das HWND des Fensters übergeben werden?
Ich verwende die LibNoDave 0.8.4.5 mit der libnodave.dll, libnodave.lib und libnodave.net.dll vom 12.07.2009.
Als Verweis eingebunden habe ich die libnodave.net.dll da VB2008Express ja auf .NET basiert. Bei der Funktion
fds.rfd = libnodave.openS7online(S7Online_accesspoint) kann ich leider kein HWND als zweiten Parameter übergeben.

Gibt es da neuere Bibliotheken und wenn ja wo kann ich diese herbekommen? Ich habe die dll aus LibNoDave 0.8.4.5 und eigenlich erst vor ein paar Wochen von http://sourceforge.net/projects/libnodave/
runtergeladen.

Für Informationen diesbezüglich wäre ich sehr dankbar.

Gruss,

bool
 
Zuletzt bearbeitet:
Verbindungsaufbau (wichtigsten Funktionen aus dem Code extrahiert):
fds.rfd = libnodave.openS7online(S7Online_accesspoint)
fds.wfd = fds.rfd
di = New libnodave.daveInterface(fds, "IF1", S7Online_localAddress, libnodave.daveProtoS7online, nodaveBaudrate)
di.setTimeout(1000)
res = di.initAdapter
dc = New libnodave.daveConnection(di, S7Online_remoteAddress, S7Online_rack, S7Online_slot)
res = dc.connectPLC

Verbindungsabbau (wichtigsten Funktionen aus dem Code extrahiert):

res = dc.disconnectPLC()
di.disconnectAdapter()
'res = libnodave.closePort(fds.rfd)
'WriteDebugInfo("Close S7Online Connection: closePort() ... (res=" & CStr(res) & " - " & libnodave.daveStrerror(res) & ")")
res = libnodave.closeS7online(fds.rfd)
WriteDebugInfo("Close S7Online Connection: closeS7online() ... (res=" & CStr(res) & " - " & libnodave.daveStrerror(res) & ")")

Für mich stellen sich nun folgende Fragen:

Muss ich beim Verbindungsabbau die Funktion
a) libnodave.closeS7online(fds.rfd) oder
b) libnodave.closePort(fds.rfd) ausführen
oder sogar beide?
Bei dem von mir als Vorlage verwendeten Programmbeispiel wurde Variante b) verwendet aber wofür gibt es dann a)?

Warum funktioniert das Lesen nur nach dem ersten Verbindungsaufbau und ab dem zweiten Verbindungsaufbau nicht mehr?

Dann bekomme ich vom dc.execReadRequest() nur noch eine "-128"
Leider funktioniert bei mir ausserdem die Funktion "libnodave.daveStrerror(res)" nicht richtig, ich bekomme leider den Fehlertext nicht im Klartext sondern nur kryptische Zeichen zurück.

Hilft hier überhaupt die neue Funktion welcher das hWnd des aktiven Fensters mit übergegeben wird oder müsste dies auch mit der älteren Variante funktionieren welche so wie es scheint noch bei der aktuellen libnodave.net.dll (für .NET Applikationen) implementiert ist?
Oder gibt es eine aktueller dll welche ich hier verwenden sollte?
Welche der folgenden Funktionen müssen beim Verbindungsabbau in welcher Reihenfolge ausgeführt werden, so dass die Verbindung sauber und komplett geschlossen wird und nach dem nächsten Verbindungsaufbau wieder erfolgreich gelesen werden kann?

a) libnodave.closeS7online(fds.rfd) oder
b) libnodave.closePort(fds.rfd) ? oder beide?

Danke bereits im voraus.

Gruss,

bool
 
Hm.

also bei mir geht der aufruf ohne die hwnd gar nicht mehr, kann es sein, das du viel noch eine alte version der dll im system32 ordner hast!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
also bei mir geht der aufruf ohne die hwnd gar nicht mehr, kann es sein, das du viel noch eine alte version der dll im system32 ordner hast!

Hab grad den kompletten Windowsordner durchsuchen lassen, doch da habe ich überhaupt keine libnodave DLL, ich habe sie nur im Projektordner, im Debug und Releaseordner.

Die libnodave.net.dll habe ich wie in meinem anderen Thread gepostet über Verweise eingebunden.

Gruss,

bool
 
Hab grad den kompletten Windowsordner durchsuchen lassen, doch da habe ich überhaupt keine libnodave DLL, ich habe sie nur im Projektordner, im Debug und Releaseordner.

Die libnodave.net.dll habe ich wie in meinem anderen Thread gepostet über Verweise eingebunden.

Gruss,

bool

Also bei mir wurde von CSharp auf jeden fall gemeckert das er in der Libnodave .dll die funktion ohne 2 parameter nicht gefunden hat. Ich habe aber die libnodave.net.dll auch nicht benutzt sondern das csharp sourcefile!
 
Also bei mir wurde von CSharp auf jeden fall gemeckert das er in der Libnodave .dll die funktion ohne 2 parameter nicht gefunden hat. Ich habe aber die libnodave.net.dll auch nicht benutzt sondern das csharp sourcefile!

Heisst dies, dass das gesamte libnodave in csharp also sourcefile vorliegt und alle Funktionen direkt eingesehen und bei Bedarf (wie hier nun in meinem Fall) angepasst werden können?
So langsam glaube ich, dass in Bezug auf libnodave es wahrscheinlich am besten wäre sich von VB zu lösen und auf CSharp umzusatteln.


Gruss,

bool
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Heisst dies, dass das gesamte libnodave in csharp also sourcefile vorliegt und alle Funktionen direkt eingesehen und bei Bedarf (wie hier nun in meinem Fall) angepasst werden können?
So langsam glaube ich, dass in Bezug auf libnodave es wahrscheinlich am besten wäre sich von VB zu lösen und auf CSharp umzusatteln.


Gruss,

bool

Nein, das heisst es nicht, d.h. Ich habe die LibNoDave.net.cs in meinem Projekt und nicht als Dll eingebunden, nicht die libnodave.dll!
 
Nein, das heisst es nicht, d.h. Ich habe die LibNoDave.net.cs in meinem Projekt und nicht als Dll eingebunden, nicht die libnodave.dll!

Wie in meinem anderen Thread gepostet, habe ich (mit Hilfe Deiner Tips) inzwischen die libnodave.net.dll aus der Datei libnodave.net.cs erzeugen können.

Zwar bekomme ich nun ebenfalls die openS7online(S7ONLINE, HWND) Deklaration inkusive hWnd aber ein Variablenzugriff nach dem ersten Verbindungsabbau und erneuten Verbindungsaufbau funktioniert leider immer noch nicht. Ich bekomme von der Funktion dc.execReadRequest() nur noch eine "-128", dieses mal jedoch mit dem Klartext "Unexpected function code in answer". Wie gesagt, nach dem ersten Verbindungsaufbau funktioniert das Pollen der Daten mit dc.execReadRequest() einwandfrei, nach dem Verbindungsabbau (Programmcodeauszug siehe in meinem ersten post von diesem Thread) und erneuten Verbindungsaufbau dann leider nicht mehr.

Kann es vielleich auch sein, dass ich das HWND Handle falsch erzeuge?
Was mich wundert ist nämlich, dass in der angezeigten Deklaration das hWnd als Integer angegeben wird und nicht als IntPtr weshalb ich den Aufruf folgendermassen gestaltet habe:

Dim hWnd As IntPtr = GetForegroundWindow()
Dim ihWnd AsInteger = CInt(hWnd)
For i = 0 To 3
fds.rfd = libnodave.openS7online(S7Online_Accesspoint, ihWnd)
fds.wfd = fds.rfd
If fds.rfd > 0 Then
ExitFor
EndIf
Next


Auf diese Weise bekomme ich den Handlewert als Integer in die ihWnd Variable geschrieben und sollte so eigentlich funktionieren.
Doch wie gesagt ergab dies leider keine Besserung nach dem zweiten Connect.

Ich hoffe Ihr habt weiterhin Ideen, ich werde sie gerne ausprobieren.

Gruss,

bool
 
Zwar bekomme ich nun ebenfalls die openS7online(S7ONLINE, HWND) Deklaration inkusive hWnd aber ein Variablenzugriff nach dem ersten Verbindungsabbau und erneuten Verbindungsaufbau funktioniert leider immer noch nicht. Ich bekomme von der Funktion dc.execReadRequest() nur noch eine "-128", dieses mal jedoch mit dem Klartext "Unexpected function code in answer". Wie gesagt, nach dem ersten Verbindungsaufbau funktioniert das Pollen der Daten mit dc.execReadRequest() einwandfrei, nach dem Verbindungsabbau (Programmcodeauszug siehe in meinem ersten post von diesem Thread) und erneuten Verbindungsaufbau dann leider nicht mehr.

Hallo, jetzt muss ich mich schon selbst zitieren ;), aber ich habe eine neue interessante Erkenntniss welche vielleicht helfen könnte dem Problem auf die Spur zu kommen.

Für die S7ONLINE verwende ich einen SIEMENS PCMCIA Adapter des Typs CP5511.

Als dll verwende ich übrigens inzwischen die als dll compilierte libnodave.net.cs von Jochen Kühner welche die Funktion openS7online via Windowhandle parametriert.

Und jetzt kommts:
Wenn der CP5511 in "PG/PC Schnittestelle einstellen" fest auf "MPI" eingestellt ist funktioniert das Auslesen auch nach dem x-ten Verbindungsaufbau, wenn der Adapter jedoch "Auto" eingestellt (z.B. um über Profibus zu kommunizieren) ist, geht bereits wie oben im Thread beschrieben das Auslesen ab der zweiten Verbindung schief. Ab der zweiten Verbindung bekomme ich dann auch beinahe unverzögert das Ergebnis 0 (ok) von di.initAdapter und dc.connectPLC.
Wenn jedoch die Verbindung richtig beendet worden wäre müsste der erneute Verbindungsaufbau ja auch wieder um einiges länger dauern, was es ja auch tut wenn ich den CP551 Adapter unter "PG/PC Schnittstelle einstellen" fest auf "MPI" stelle.

fds.rfd = libnodave.openS7online(S7Online_Accesspoint, CInt(hWnd))
fds.wfd = fds.rfd
...
di =
New libnodave.daveInterface(fds, "IF1", S7Online_LocalAddress, libnodave.daveProtoS7online, nodaveBaudrate)
di.setTimeout(1000)
res = di.initAdapter
dc = New libnodave.daveConnection(di, S7Online_remoteAddress, S7Online_rack, S7Online_slot)
res = dc.connectPLC

Vielleicht kann hiermit die Problemursache eingeschränkt werden und es hat jemand eine Idee.

Ich würde mich sehr freuen.

Ein anderes Phenomen welches ich grade eben beobachtet habe ist, dass die Funktion "res = dc.connectPLC" auch die Rückmeldung 0 (ok) bringt, obwohl die parametrierte remote Profibus- oder MPI-Adresse aus
dc = New libnodave.daveConnection(di, S7Online_remoteAddress, S7Online_rack, S7Online_slot) im MPI- bzw Profibusnetz gar nicht existiert. Das Ergebnis ist dann auch hier, dass die Lesefunktion
dc.execReadRequest() ebenfalls eine "-128" (Unexpected function code in answer) ausspuckt.

Hat hier vielleicht jemand eine Idee wie man das Verhindern kann oder ist es noch ein Bug in der Funktion dc.connectPLC?

Gruss,

bool
 
Und jetzt kommts:
Wenn der CP5511 in "PG/PC Schnittestelle einstellen" fest auf "MPI" eingestellt ist funktioniert das Auslesen auch nach dem x-ten Verbindungsaufbau, wenn der Adapter jedoch "Auto" eingestellt (z.B. um über Profibus zu kommunizieren) ist, geht bereits wie oben im Thread beschrieben das Auslesen ab der zweiten Verbindung schief. Ab der zweiten Verbindung bekomme ich dann auch beinahe unverzögert das Ergebnis 0 (ok) von di.initAdapter und dc.connectPLC.
Wenn jedoch die Verbindung richtig beendet worden wäre müsste der erneute Verbindungsaufbau ja auch wieder um einiges länger dauern, was es ja auch tut wenn ich den CP551 Adapter unter "PG/PC Schnittstelle einstellen" fest auf "MPI" stelle.

Scheibenkleister,
nachdem ich die Hardwarekonfig neu übertragen habe um die Schnittstelle auf Profibus umzustellen und diese ebenfalls unter der Einstellung "Auto" des CP5511 zu testen (funktioniert ebenfalls nur nach dem ersten Verbidnungsaufbau) und wieder auf MPI zurück bin. funktionierte das Lesen nach dem zweiten Verbindungsaufbau auch bei fest konfiguriertem "MPI" nicht mehr. Was zuvor grade noch reproduzierbar war, ist jetzt wieder hahnebüchen... alles wieder auf Anfang.
Scheibenkleister!

Habe folgendes Dokument gefunden:
https://support.automation.siemens.c...nodeid=1653428
dort ist unter Besonderheiten für Windows beschriebn wofür das Handele überhaupt verwendet wird, vieleicht ist das Problem das in der WinProc des Programmes nicht auf die Messages reagiert wird??
Ok, danke schon mal für die Anregung..., aber als reiner libnodave user kann ich darauf wahrscheinlich keinen Einfluss nehmen, oder doch?
Ich denke da ist Zottel gefragt, das ist doch so meine ich der Urvater von libnodave wenn ich mich nicht irre.
Ich hoffe er kann mir mit diesem Problem weiterhelfen.

Gruss,

bool
 
Zuletzt bearbeitet von einem Moderator:
Ich kann nun noch folgende Erkenntnis beisteuern:

Bei dem ersten Verbindungsaufbau (nach Applikationsstart) ist vor dem ersten Aufruf (FOR Schleife 0-3 da die S7ONLINE Verbindung hin und wieder mehrere Anläufe braucht) von
fds.rfd = libnodave.openS7online(S7Online_accesspoint)
das fds.rdf noch = 0, nach dem Funktionsaufruf ist dieses dann =1.

Beim Verbindungsabbau ist nach dem Funktionsaufruf von
res = libnodave.closeS7online(fds.rfd)
das fds.rfd immer noch 1 (res=0) und ich glaube hier liegt der Hund begraben.

Bei dem zweiten Verbindungsaufbau ist vor dem ersten Aufruf von
fds.rfd = libnodave.openS7online(S7Online_accesspoint)
das fds.rdf noch immer = 1, es wird jedoch keine neue Verbindung aufgebaut. Es scheint als wäre die alte Verbindung hängen geblieben.
Eine stumpfe Zuweisung von "0" an fds.rfd beim Verbindungsabbau bringt hier keine Besserung, auch kein Schleifen der libnodave.closeS7online() Funktion bis fds.rdf = 0 ist, denn diese wird nicht 0, aber res dagegen wird ab dem zweiten Aufruf der closeS7online() Funktion -1.

Ich hoffe es kann jemand mit dieser neuen Erkenntnis etwas anfangen und mir bei meinem Problem weiterhelfen.

Gruss,

bool
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kann nun noch folgende Erkenntnis beisteuern:

Bei dem ersten Verbindungsaufbau (nach Applikationsstart) ist vor dem ersten Aufruf (FOR Schleife 0-3 da die S7ONLINE Verbindung hin und wieder mehrere Anläufe braucht) von
fds.rfd = libnodave.openS7online(S7Online_accesspoint)
das fds.rdf noch = 0, nach dem Funktionsaufruf ist dieses dann =1.

Beim Verbindungsabbau ist nach dem Funktionsaufruf von
res = libnodave.closeS7online(fds.rfd)
das fds.rfd immer noch 1 (res=0) und ich glaube hier liegt der Hund begraben.

Bei dem zweiten Verbindungsaufbau ist vor dem ersten Aufruf von
fds.rfd = libnodave.openS7online(S7Online_accesspoint)
das fds.rdf noch immer = 1, es wird jedoch keine neue Verbindung aufgebaut. Es scheint als wäre die alte Verbindung hängen geblieben.
Eine stumpfe Zuweisung von "0" an fds.rfd beim Verbindungsabbau bringt hier keine Besserung, auch kein Schleifen der libnodave.closeS7online() Funktion bis fds.rdf = 0 ist, denn diese wird nicht 0, aber res dagegen wird ab dem zweiten Aufruf der closeS7online() Funktion -1.

Ich hoffe es kann jemand mit dieser neuen Erkenntnis etwas anfangen und mir bei meinem Problem weiterhelfen.

Gruss,

bool

Denke nicht das das Problem ist. Wenn man sich den Source von "openS7online.c" anschaut, sieht man das der wert einfach ein Handle auf die Verbdinung ist, und diese dann auch mit Close geschlossen wird. Wieso sollte man dieses Handle auf 0 setzten müssen (wäre vielleicht schöner, sollte aber keine Probleme bereiten!)

Vieleicht sollte noch die Funktion SCP_get_errno in Libnodave eingebunden damit man die Fehlermeldung auslesen kann.
(Hups, hab grad gesehen wird ja verwendet, aber So wie Ich das sehe wird der Fehler nicht ausgewertet!)

Wenn Ich morgen mal Zeit habe, mache Ich mich mal an tests mit der S7Online Verbindung!
 
Probier mal

Hab in der DLL mal die Fehlercodes von S7 Online noch reinprogrammiert...

Schau mal ob damit was anderes passiert...
 

Anhänge

  • libnodave.zip
    36,4 KB · Aufrufe: 23
Hab in der DLL mal die Fehlercodes von S7 Online noch reinprogrammiert...

Schau mal ob damit was anderes passiert...

Hab grad mal die libnodave.dll ausgetauscht, das Programm stürzt dann jedoch schon bevor die Form1 überhaupt geladen wird mit folgendem Windows Fehler ab:

Fehler beim Erstellen des Formulars. Weitere Informationen finden Sie in Exception.InnerException. Fehler: Die DLL "libnodave.dll": Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E) kann nicht geladen werden..

Die ursprüngliche libnodave welche ich aus dem libnodave 0.8.4.5 zip-file verwendet habe hat 124kb, die neue aus Deinem post 81kb.
Die von mir aktuell verwendete libnodave.net.dll ist die compilierte libnodave.net.cs welche ich von Dir bekommen habe um das Unicode-Problem der libnodave.daveStrerror(res) Auswertung in den Griff zu bekommen.

Ich habe mal die aktuell von mir verwendeten dll`s und die lib dem post angehängt.

Gruss,

bool



 

Anhänge

  • libnodave.net.zip
    75,4 KB · Aufrufe: 20
Zuviel Werbung?
-> Hier kostenlos registrieren
Jo

Ja Ich weis das die viel kleiner ist.

Hab die auch mit VS2010 kompiliert, da das mit nmake bei mir nicht klappt.

Bringt es dir was wenn Ich dir den Source schicke das du in selber übersetzen kannst??

Also bei mir läufts mit meiner geänderten Dll
 
Ja Ich weis das die viel kleiner ist.

Hab die auch mit VS2010 kompiliert, da das mit nmake bei mir nicht klappt.

Bringt es dir was wenn Ich dir den Source schicke das du in selber übersetzen kannst??

Also bei mir läufts mit meiner geänderten Dll

mit nmake habe ich noch nichts gemacht, aber die letzte libnodave.net.cs welche Du mir gesedet hattest konnte ich mit dem c#-compiler (csc.exe) in die libnodave.net.dll verwandeln, ich nehme an das geht dann mit der Source für die libnodave.dll gleichermassen, oder liege ich da falsch?

Bezüglich meines "Handle wieder freigeben" Problemchens habe ich es mir erlaubt mal in die c# quelle des testS7online Konsolenprogramms zu spickeln und beim Verbindungsabbau fogenden Code gefunden:

dc.disconnectPLC();
}
di.disconnectAdapter();
libnodave.closeS7online(fds.rfd);
GC.Collect();
GC.WaitForPendingFinalizers();

Console.WriteLine("Here we are");

Hier wird am Ende mit dem GarbageCollector nicht verwendeter Speicher wieder freigegeben.
Gibt es auch so was für VB.NET?
Ist das vielleicht die Lösung für mein Problem?

Gruss,

bool
 
Zurück
Oben