# libnodave und autoit



## Joline (19 Mai 2010)

Guten Morgen,

ich möchte zu bestimmten Ereignissen Daten aus einer SPS (DB) auslesen und in einer Textdatei ablegen. Dazu möchte ich als Schnittstelle libnodave benutzen und als Programmiersprache AutoIt (VB-ähnliche Sprache; Kunde kann ggf. Änderungen vornehmen, ohne eine komplette IDE haben/installieren zu müssen).

Hat hier schon jemand Erfahrung beim Einsatz von AutoIt mit libnodave? Ich möchte das Rad nicht unbedingt noch einmal erfinden.    Wäre prima, wenn mir jemand ein wenig Hilfestellung bei der korrekten Syntax zu Verbindungsaufbau und Datenauslesen geben könnte.

Danke und Gruß
Joline


----------



## Jochen Kühner (19 Mai 2010)

*Nee*

Ne hab Ich nicht, aber Beispiele für VB und VBA liegen LibNoDave bei! Falls du dann Konkrete Fragen zu irgendeiner Syntax hast helfe Ich auch gern weiter.

Kann dir aber auch noch meinen LibNodave Protokolle vorschlagen, da kannst du Daten aus einem DB z.B. in eine Sqllite Datenbank einlesen. (CSV oder Textfile könnte Ich dir implementieren).

Infos gibts hier:

http://www.sps-forum.de/showthread.php?t=35901


----------



## Joline (19 Mai 2010)

Hallo,

also irgendwie finde ich keinen Einstieg. Ich habe mal die notwendigen Funktionen in AutoIt-conforme Aufrufe umgewandelt:


```
Func _initialize()
  Local $res, $ph, $dc, $di

  ;ph = openSocket(102, "192.168.1.100")
  $ph = DllCall("libnodave.dll", "long", "opensocket", 102, "192.168.1.100")
  If $ph > 0 Then
    ;di = daveNewInterface(ph, ph, "IF1", 0, daveProtoISOTCP, daveSpeed187k)
    $di = DllCall("libnodave.dll", "long", "daveNewInterface", $ph, $ph, "IF1", 0, 122, 2)
    If $di > 0 Then
      ;res = daveInitAdapter(di)
      $res = DllCall("libnodave.dll", "long", "daveInitAdapter", $di)
      ;dc = daveNewConnection(di, MpiPpi, Rack, Slot)
      $dc = DllCall("libnodave.dll", "long", "daveNewConnection", $di, 2, 0, 2)
      If $dc > 0 Then
        ;res = daveConnectPLC(dc)
        $res = DllCall("libnodave.dll", "long", "daveConnectPLC", $dc)
      EndIf
    EndIf
  EndIf
EndFunc
```

Aber schon der erste Aufruf "opensocket" liefert "0" zurück.  

Hardware und Verbindung zur SPS sind OK. Habe ich mit einem anderen kleinen Testprogramm, was auch libnodave nutzt überprüft. Das funktioniert.

Hat vielleicht jemand eine Idee, was hier falsch ist?

Joline


----------



## Jochen Kühner (19 Mai 2010)

Hab hier noch was gefunden:

http://www.elitepvpers.de/forum/epvp-coders-tutorials/443887-autoit-dll-autoit-teil-1-a.html

da steht:



> Man sollte immer voher "DllOpen nutzen", wenn man eine DLL öffnet.



Und muss der Code nicht so aussehen:


```
$ph = DllCall("libnodave.dll", "long", "opensocket", "int", 102, "str", "192.168.1.100")
```


----------



## Jochen Kühner (20 Mai 2010)

Achso, das hab Ich auch noch gefunden:

http://bug-fix.info/dll/dll_tut.html


----------



## Joline (20 Mai 2010)

Hallo Jochen,

vielen Dank für die Hinweise. 

Dass ich beim Funktionsaufruf die Typen vergessen habe anzugeben, habe ich auch schon gefunden. Inzwischen funktioniert auch schon openSocket. 

daveNewinterface und daveNewConnection liefern einen Zeiger auf eine Struktur zurück. Da muss ich jetzt mal sehen, wie man das macht. Wenn man weiß, wie es geht, geht's schnell.    Läßt sich nur einfach Sch... debuggen, wenn man Visual Studio u.ä. gewöhnt ist.

Mir ist im Moment noch nicht so recht klar, was z.B. die Funktion daveNewinterface zurückliefert. Wenn ich mir das header file (nodave.h) anschaue, kommt da eine Struktur zurück (_daveInterface) und wenn ich mir das Excel-Beispiel anschaue, gibt es da einfach einen long Wert. 


Joline


----------



## Jochen Kühner (20 Mai 2010)

Joline schrieb:


> Hallo Jochen,
> 
> vielen Dank für die Hinweise.
> 
> ...



Dann nimm doch VS und gibt deienm Kunden SharpDevelop als USB Stick Version. Dann kann er auch was drann ändern...


----------



## Joline (20 Mai 2010)

Hallo Jochen,

inzwischen bin ich bei daveInitAdapter, bei welchem aber AutoIt abschmiert (und ich weiss noch nicht, warum). 



Jochen Kühner schrieb:


> Dann nimm doch VS und gibt deienm Kunden SharpDevelop als USB Stick Version. Dann kann er auch was drann ändern...



Mich hat zwar der sportliche Ehrgeiz gepackt, es zu Laufen zu bringen (bezahlt nur keiner  ), aber das ist doch mal ein Super-Tip. Eine echte Hochsprache und noch dazu portable. Spitze! Ich liebe portable Programme. Dass ich das noch nicht selbst gefunden habe... Vielen Dank.

Joline


----------



## Zottel (20 Mai 2010)

Joline schrieb:


> ...
> daveNewinterface und daveNewConnection liefern einen Zeiger auf eine Struktur zurück. Da muss ich jetzt mal sehen, wie man das macht.


Das, was zurückgegeben wird, in einer Variablen speichern und an nachfolgende Aufrufe wieder übergeben. Es kann deinem Programm egal sein, was es ist.


Joline schrieb:


> ...
> Mir ist im Moment noch nicht so recht klar, was z.B. die Funktion daveNewinterface zurückliefert.


Einen Zeiger, d.h. die Adresse eines Speicherbereichs, der eine Struktur daveInterface enthält


Joline schrieb:


> ...
> und wenn ich mir das Excel-Beispiel anschaue, gibt es da einfach einen long Wert.


Ja, denn ein long int reicht aus um eine Adresse zu speichern.


----------



## Joline (20 Mai 2010)

Also hier ist der aktuelle Code:


```
Func _initialize()
  Local $res
  $ph = DllCall("libnodave.dll", "long", "openSocket", "int", 102, "str", "192.168.1.100")
  ConsoleWrite("DllCall openSocket errorcode: " & @error & @CRLF)
  ConsoleWrite("port handle: " & $ph[0] & @CRLF)
  If $ph[0] > 0 Then
    $di = DllCall("libnodave.dll", "long", "daveNewInterface", "long", $ph[0], "long", $ph[0], "str", "IF1", "int", 0, "int", 122, "int", 2)
    ConsoleWrite("DllCall daveNewInterface errorcode: " & @error & @CRLF)
    ConsoleWrite("di: " & $di[0] & @CRLF)
    $res = DllCall("libnodave.dll", "int", "daveInitAdapter", "long", $di[0])
    ConsoleWrite("DllCall daveInitAdapter errorcode: " & @error & @CRLF)
    ConsoleWrite("result from initAdapter: " & $res & @CRLF)
    If $res = 0 Then
      $dc = DllCall("libnodave.dll", "long", "daveNewConnection", "long", $di[0], "int", 2, "int", 0, "int", 2)
      ConsoleWrite("DllCall daveNewConnection errorcode: " & @error & @CRLF)
      ConsoleWrite("dc: " & $dc[0] & @CRLF)
      $res = DllCall("libnodave.dll", "int", "daveConnectPLC", "long", $dc[0])
      ConsoleWrite("DllCall daveConnectPLC errorcode: " & @error & @CRLF)
      ConsoleWrite("result from connectPLC: " & $res & @CRLF)
      If $res = 0 Then
        ConsoleWrite("_initialize() OK." & @CRLF)
      EndIf
    EndIf
  EndIf
EndFunc    ;==>_initialize
```

daveNewInterface liefert einen Wert zurück (z.B. 41163736). Aber der Aufruf von daveInitAdapter reißt AutoIt in die Tiefe. Da passiert irgendeine Exception: 

```
Problemereignisname:	APPCRASH
  Anwendungsname:	autoit3.exe
  Anwendungsversion:	3.3.6.1
  Anwendungszeitstempel:	4bc81615
  Fehlermodulname:	libnodave.dll
  Fehlermodulversion:	0.0.0.0
  Fehlermodulzeitstempel:	4a59fafb
  Ausnahmecode:	c0000005
  Ausnahmeoffset:	00008f3a
  Betriebsystemversion:	6.1.7600.2.0.0.256.4
  Gebietsschema-ID:	1031
  Zusatzinformation 1:	0a9e
  Zusatzinformation 2:	0a9e372d3b4ad19135b953a78882e789
  Zusatzinformation 3:	0a9e
  Zusatzinformation 4:	0a9e372d3b4ad19135b953a78882e789
```

Leider ist eben nicht viel mit Debuggen. Das ist alles irgendwie die Methode der "Scharfen Hinguckens".   Irgendwie fände ich aber schon prima, wenn man so ein paar Werte aus einer S7 mittels einfachem Script abrufen könnte, ohne immer gleich mit riesigen Geschützen (IDE usw.) aufzufahren. 

Naja, aber ich muss hier irgendwie fertig werden und da ist SharpDevelop wohl eine prima Alternative. Wenn ich mal wieder ein wenig Zeit habe, schaue ich mir das mit dem Script noch mal an. Wäre doch gelacht, wenn das nicht geht.  

Joline


----------

