# Mit Libnodave Diagnosepuffer auslesen



## Bewareofthis (31 Oktober 2005)

Hallo zusammen,

ich möchte mit der Funktion daveReadSZL  Diagnosedaten einer CPU auslesen. Wie ist der empfangene Datensatz aufgebaut, bzw. wie liest man ihn richtig? 
Liefert einer der Teil-Datensätze einen String zurück?



> Step7-Hilfe:
> Ein Datensatz der Teilliste mit der SZL-ID W#16#xyA0 hat folgenden Aufbau:
> 
> Name	Länge in Worten  	Bedeutung
> ...



Thx vorab

Bewareofthis


----------



## Zottel (31 Oktober 2005)

Bewareofthis schrieb:
			
		

> Hallo zusammen,
> 
> ich möchte mit der Funktion daveReadSZL  Diagnosedaten einer CPU auslesen. Wie ist der empfangene Datensatz aufgebaut, bzw. wie liest man ihn richtig?
> Liefert einer der Teil-Datensätze einen String zurück?
> ...


daveReadSZL liefert die Rohdaten, so wie sie von der CPU kommen. Strings sind keine dabei. Vor den einzelnen Einträgen stehen noch einige Informationen zu der Liste: die SZL-ID und der Index werden wiederholt. Danach steht, wie lang ein einzelner Eintrag ist (in Byte) und wieviele Einträge es sind.
Sieh dir bitte die Funktion readSZL in den Testprogrammen (testMPI.c) an, um zu sehen, wie die Kopfinformationen ausgewertet werden können.
Der Diagnosepuffer besteht aus Einträgen von 20 byte (entsprechend 10 Worte wie in der Siemens-Doku).
Den Zeitstempel wirst du leicht erkennen, wenn du dir die Zeichen hexadezimal ausgeben läßt (testMPI --szlID=0xA0 tut das). Zeit/Datum sind BCD-codiert. Die letzten beiden Stellen sind Sekundenbruchteile (Vielfache von 100us).
Die restlichen Informationen (Bedeutung Ereignis-ID usw.) mußt du entweder in der Siemens-Doku finden (vielleicht kann jemand anders was dazu sagen. Man kann ja die Diagnose auch im SPS-Programm mit einer SFC auslesen. Da wird man das gleiche bekommen) oder du mußt die Ereignisse, die dich interessieren, absichtlich erzeugen lassen und schauen, wie sie codiert sind :-(


----------



## Bewareofthis (2 November 2005)

Das mit dem  Kopf-Datensatz  im Puffer hab ich übersehen . 
Den Zeitstempel kann ich jetz auch auslesen, Thx Zottel .
Allerdings hab ich noch keinen Schimmer was in den 5 Wörtern, die in der Siemens-Doku als Info dekl. sind, fürne Info steckt :?:
String(s) ist/sind es ja definitiv net, Codierung für kommendes bzw. gehendes Ereignis vielleicht, oder CPU Zustand (STOP->RUN)?

Gruß
Bewareofthis


----------



## Zottel (2 November 2005)

Bewareofthis schrieb:
			
		

> Allerdings hab ich noch keinen Schimmer was in den 5 Wörtern, die in der Siemens-Doku als Info dekl. sind, fürne Info steckt :?:
> String(s) ist/sind es ja definitiv net, Codierung für kommendes bzw. gehendes Ereignis vielleicht, oder CPU Zustand (STOP->RUN)?


Es wird etwas von dem sein, was Step7 dir in "Details zum Ereignis" unter der Liste anzeigt,
z.B. bei Parametrierfehler:
Baugruppenträger 0
Steckplatz 6
Fehlerart: projektierter Steckplatz nicht belegt.
usw.
Wenn es nicht dokumentiert ist, wirst du es durch brobieren rausfinden müssen:-(


----------



## Bewareofthis (8 November 2005)

@Zottel:
Was sind die Rückgabewerte der Funktion daveGetProgramBlock bzw. wie muss ich sie interpretieren?
zur Erklärung:
Ich habe die libnodave.net.dll um diese Methode erweitert:

```
[DllImport("libnodave.dll")]  
		protected static extern int daveGetProgramBlock(IntPtr dc,int blockType,int number, byte[] buffer,int length);
		public int GetProgramBlock(int blockType, int number ,byte[] buffer,int length)  
		{
			 return(daveGetProgramBlock(pointer,blockType,number,buffer,length)); //<-- hier tritt Exception auf !
		}
```
Ich bekomme allerdings eine NullReferenceException nach dem der Baustein von Livnodave geladen wurde und die Daten von der DLL zurückgegeben werden.

Thx vorab

Bewareofthis


----------



## Zottel (8 November 2005)

Bewareofthis schrieb:
			
		

> @Zottel:
> Was sind die Rückgabewerte der Funktion daveGetProgramBlock bzw. wie muss ich sie interpretieren?
> zur Erklärung:
> Ich habe die libnodave.net.dll um diese Methode erweitert:
> ...


Der Funktionswert ist ein Fehlercode (oder 0 für ok).
Der Puffer und die Länge werden von der Funktion beschrieben.
Beim Puffer ist das kein Problem: Wenn man ein array übergibt, wird immer ein Zeiger darauf übergeben, so daß die aufgerufene Funktion an der Adresse schreiben kann.
Statt "int length" könntest du "int * length" schreiben. Das ist dasselbe, wie die Funktion in C deklariert ist. Danach ist dein Programm (bzw. libnodave.dot.net) jedoch "unsafe" und müßte mit der entsprechenden Option kompiliert werden.
Ich bin kein Dot.NET-Experte. Es mag andere Wege geben, einen Funktionsparameter "by reference" (als Zeiger, als veränderbaren Wert) zu übergeben.
Eine Möglichkeit sollte sein, length auch als array zu deklarieren:

getProgramBlock(int blockType, int number ,byte[] buffer,int[] length);

int length=new int[1];
und dann damit aufrufen.


----------



## Bewareofthis (9 November 2005)

Thx Zottel jetz gehts !  

Das mit dem Call by Reference war mir klar, allerdings hab ich immer beide 
Parameter deklariert (ref byte[] buffer, ref int length), was widerum ein Schmarrn ist.
So gehts jetz:

```
[DllImport("libnodave.dll")]  
		protected static extern int daveGetProgramBlock(IntPtr dc,int blockType,int number,byte[] buffer,ref int length);
		public int GetProgramBlock(int blockType, int number , byte[] buffer, ref int length)
		{
			 return(daveGetProgramBlock(pointer,blockType,number, buffer,ref length));
		}
```

Gruß

Bewareofthis

BTW: Bekommt man nur den compilierten Code zurück ?


----------

