Libnodave 0.8.5

Zottel

Level-3
Beiträge
2.299
Reaktionspunkte
278
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe soeben eine neue Version von Libnodave veröffentlicht. Die wesentlichen Neuerungen sind:
- Routing möglich.
- Auswahl der Kommunikation (PG-, OP-, S7-Basis-Kommunikation) möglich.
- Große PDUs können nun über mehrere ISO- oder IBH-Pakete verteilt und wieder zusammengesetzt werden.
- Hoffentlich ein paar Bugs weniger.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es sind noch ein paar kleine Bugfixes welche in meiner Version schon behoben sind welche noch rein gehören:

Funktion doUpload, letzte zeile von *len+=netLen; in *len=netLen; ändern

Kannst schaun, in meiner Version gibts auch noch ein "davePutProgramBlock" vielleicht willst du das ja auch noch einbauen...

Muss Ich mal schaun wie Ich den stand jetzt wieder mit meinem gleichziehe, da das routing ja anderst gelöst wurde als bei mir (mir gefällt deine Lösung aber besser)...

falls ich noch fixes finde welche Ich eingebaut hatte, werde Ich sie hier posten...
 
Ich hab noch gesehen, Ich hatte die Funktion davTestresultdataMulti umgebaut, die gibts aber jetzt nicht mehr

Code:
int DECL2 _daveTestResultDataMulti(PDU * p) {	
	int res; /*=daveResCannotEvaluatePDU;*/
	if ((p->data[0]==255)&&(p->dlen>4))
	{
		res=daveResOK;
		p->udata=p->data+4;
		p->udlen=p->data[2]*0x100+p->data[3];
		if (p->data[1]==4) {
			p->udlen>>=3;	/* len is in bits, adjust */
		} else if (p->data[1]==9) {
			/* len is already in bytes, ok */
		} else if (p->data[1]==3) {
			/* len is in bits, but there is a byte per result bit, ok */
		} else {
			if (daveDebug & daveDebugPDU)
				LOG2("fixme: what to do with data type %d?\n",p->data[1]);
			res = daveResUnknownDataUnitSize;
			//res = 0;
		}	    
	}
	else if (p->data[0]==10 || p->data[0]==5)
	{
		//This Section returns ok, even if nothing was read,
		//because with the multiple read we get the error in (daveUseResult)
		res = daveResOK;		
	}
	else {
		res=p->data[0];
	}
	return res;    
}

die hatte glaub sonst wenn ein item nicht gefunden wurde ein fehler ausgegeben. Ich hatte es so umgebaut das trotzdem Ok zurück kam, und bei daveUseResult dann der Fehler kam. (es kann ja sein, man liest mehrere Items, und ein paar davon funktionieren und ein paar nicht!) Geht das bei der neuen Version dann auch so?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es sind noch ein paar kleine Bugfixes welche in meiner Version schon behoben sind welche noch rein gehören:

Funktion doUpload, letzte zeile von *len+=netLen; in *len=netLen; ändern
Wenn ich mich noch richtig erinnere ist die Funktion wie folgt:
Beim Laden eines Blocks, der länger als eine PDU ist, wird die Funktion doUpload mehrfach aufgrufen.
Ihr wird als Parameter len ein Zeiger auf einen int übergeban, der vor dem 1. Aufruf 0 sein sollte.
Bei jedem Aufruf addiert nun doUpload die empfangene Teillänge.
Kannst schaun, in meiner Version gibts auch noch ein "davePutProgramBlock" vielleicht willst du das ja auch noch einbauen...
Die Funktionalität gibt es seit jeher in den Testprogrammen testISO_TCPload.c etc. Sie unterscheidet sich jedoch irgenwie zwischen rotokollarten, so daß sie sich nicht auf einfache Weise in eine Bibliotheksfunktion für alle Protokollarten gießen ließe (wenn ich mich richtig erinnere).


falls ich noch fixes finde welche Ich eingebaut hatte, werde Ich sie hier posten...
Ich würde mich freuen, wenn du als Dot.NET-Experte dir mal die libnodave.net.cs anschauen würdest. Es gab da mal eine Diskussion von Anwendern, die Abstürze beklagten und angebliche memory leaks gefunden und gefixt hatten. Konnte ich aber nicht nachvollziehen. Deren Änderungen sollten aus den Dateien change.cs oder ch.cs im Ordner Dot.NET ersichtlich sein.
 
Wenn ich mich noch richtig erinnere ist die Funktion wie folgt:
Beim Laden eines Blocks, der länger als eine PDU ist, wird die Funktion doUpload mehrfach aufgrufen.
Ihr wird als Parameter len ein Zeiger auf einen int übergeban, der vor dem 1. Aufruf 0 sein sollte.
Bei jedem Aufruf addiert nun doUpload die empfangene Teillänge.

Ja, aber das zusammenzählen machst du ausserhalb von doUpload nochmal: totlen+=len; Deshalb darf doupload nur die aktuelle länge zurückgeben!


Die Funktionalität gibt es seit jeher in den Testprogrammen testISO_TCPload.c etc. Sie unterscheidet sich jedoch irgenwie zwischen rotokollarten, so daß sie sich nicht auf einfache Weise in eine Bibliotheksfunktion für alle Protokollarten gießen ließe (wenn ich mich richtig erinnere).
Zwischen was für Protkollen gibts den da unterschiede?

Ich hab auf jeden Fall eine bei mir eingebaut die bei mir funzt (musste glaub auch noch ein paar kleinigkeiten fixen welche in TestIsoTcpLoad falsch waren).

Code.
Code:
int DECL2 davePutProgramBlock(daveConnection * dc, int blockType, int blknumber, char* buffer, int * length) {
#define maxPBlockLen 0xDe	// real maximum 222 bytes

	int res=0;
	int cnt=0;
	int size=0;
	int blockNumber,rawLen,netLen,blockCont;
	int number=0;

	uc pup[]= {			// Load request
		0x1A,0,1,0,0,0,0,0,9,
		0x5F,0x30,0x42,0x30,0x30,0x30,0x30,0x34,0x50, // block type code and number
		//     _    0    B   0     0    0    0    4    P
		//		SDB		
		0x0D,
		0x31,0x30,0x30,0x30,0x32,0x30,0x38,0x30,0x30,0x30,0x31,0x31,0x30,0	// file length and netto length
		//     1   0     0    0    2    0    8    0    0    0    1    1    0
	};

	PDU p,p2;

	uc pablock[]= {	// parameters for parts of a block
		0x1B,0
	};
	
	uc progBlock[maxPBlockLen + 4]= {
		0,maxPBlockLen,0,0xFB,	// This seems to be a fix prefix for program blocks
	};

	pup[11] = blockType;
	paInsert[13] = blockType;
	/*pup[12] = number / (10*10*10*10);
	pup[13] = (number - (pup[12] * 10*10*10*10 )) / (10*10*10);
	pup[14] = (number - (pup[13] * 10*10*10)) / (10*10);
	pup[15] = (number - (pup[14] * 10*10)) / (10);
	pup[16] = (number - (pup[15] * 10));
	
	pup[12] = pup[12] + 0x30;
	pup[13] = pup[13] + 0x30;
	pup[14] = pup[14] + 0x30;
	pup[15] = pup[15] + 0x30;
	pup[16] = pup[16] + 0x30;*/
	
	memcpy(progBlock+4,buffer,maxPBlockLen);

	progBlock[9] = (blockType + 0x0A - 'A'); //Convert 'A' to 0x0A
	if (blockType == '8') progBlock[9] = 0x08;
	
	progBlock[10] = blknumber / 0x100;
	progBlock[11] = blknumber - (progBlock[10] * 0x100);
		
		
	rawLen=daveGetU16from(progBlock+14);
	netLen=daveGetU16from(progBlock+38);

	sprintf((char*)pup+19,"1%06d%06d",rawLen,netLen);

	sprintf((char*)pup+12,"%05d",blknumber);
	sprintf((char*)paInsert+14,"%05d",blknumber);
	
	pup[17]='P';
	paInsert[19]='P';
	
	p.header=dc->msgOut+dc->PDUstartO;
	_daveInitPDUheader(&p, 1);
	_daveAddParam(&p, pup, sizeof(pup)-1);

	res=_daveExchange(dc, &p);
	if (res==daveResOK) {
		res=_daveSetupReceivedPDU(dc, &p2);
		if (daveGetDebug() & daveDebugPDU) {
			_daveDumpPDU(&p2);
		}
		res=daveGetPDUerror(&p2);

		if (res==0) {
			blockCont=1;
			res=daveGetResponse(dc);
			res=_daveSetupReceivedPDU(dc, &p2);

			cnt = 0;

			do {
				res=0;
				res=_daveSetupReceivedPDU(dc, &p2);

				number=((PDUHeader*)p2.header)->number;
				if (p2.param[0]==0x1B) {
					//READFILE
					memcpy(progBlock+4,buffer+(cnt*maxPBlockLen),maxPBlockLen);
					
					if (cnt == 0)
					{
						progBlock[9] = (blockType + 0x0A - 'A'); //Convert 'A' to 0x0A
						if (blockType == '8') progBlock[9] = 0x08;
	
						progBlock[10] = blknumber / 0x100;
						progBlock[11] = blknumber - (progBlock[10] * 0x100);						
					}

					p.header=dc->msgOut+dc->PDUstartO;
					_daveInitPDUheader(&p, 3);
					size = maxPBlockLen;

					if (*length > ((cnt+1) * maxPBlockLen))  
						pablock[1]=1;
					else
					{
						size = *length - (cnt * maxPBlockLen);
						pablock[1]=0;	//last block
						blockCont=0;
					}
					   
					progBlock[1]=size;
					_daveAddParam(&p, pablock, sizeof(pablock));
					_daveAddData(&p, progBlock, size + 4 /* size of block) */);
					((PDUHeader*)p.header)->number=number;
					if (daveGetDebug() & daveDebugPDU) {
						_daveDumpPDU(&p);
					}
					_daveExchange(dc,&p);
				}
				cnt++;
			} while (blockCont);  

			res=_daveSetupReceivedPDU(dc, &p2);
			if (daveGetDebug() & daveDebugPDU) {
				_daveDumpPDU(&p2);
			}
			number=((PDUHeader*)p2.header)->number;
			if (p2.param[0]==0x1C) {
				p.header=dc->msgOut+dc->PDUstartO;

				_daveInitPDUheader(&p, 3);
				_daveAddParam(&p, p2.param,1);
				((PDUHeader*)p.header)->number=number;
				_daveExchange(dc,&p);

				p.header=dc->msgOut+dc->PDUstartO;
				_daveInitPDUheader(&p, 1);
				_daveAddParam(&p, paInsert, sizeof(paInsert));
				res=_daveExchange(dc, &p);
				res=_daveSetupReceivedPDU(dc, &p2);
				res=daveGetPDUerror(&p2);
			}
		} else {
			printf("CPU doesn't accept load request:%04X\n",res);
		}	
		return res;
	}
	return res;
}

Ich würde mich freuen, wenn du als Dot.NET-Experte dir mal die libnodave.net.cs anschauen würdest. Es gab da mal eine Diskussion von Anwendern, die Abstürze beklagten und angebliche memory leaks gefunden und gefixt hatten. Konnte ich aber nicht nachvollziehen. Deren Änderungen sollten aus den Dateien change.cs oder ch.cs im Ordner Dot.NET ersichtlich sein.

Ich wüsste jetzt nicht das es da Probleme mit memleaks gab/gibt... Aber die sieht bei mir ja ganz anderst aus, da Ich da 32/64 Bit verzweigungen und auch mappings für monotouch eingebaut habe...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja, aber das zusammenzählen machst du ausserhalb von doUpload nochmal: totlen+=len; Deshalb darf doupload nur die aktuelle länge zurückgeben!
Wo? Ich habe jetzt mal in testMPI.C und testISO_TCP.c geschaut und dort steht:

if (0==initUpload(dc, blockType, dbe.number, &uploadID)) {
do {
doUpload(dc,&more,&bb,&len,uploadID);
} while (more);
 
nodave.c

Code:
int DECL2 daveGetProgramBlock(daveConnection * dc, int blockType, int number, char* buffer, int * length) {
    int res, uploadID, len, more, totlen;
    uc *bb=(uc*)buffer;	//cs: is this right?
    len=0;
    totlen=0;
    if (dc->iface->protocol==daveProtoAS511) {	    
	return daveGetS5ProgramBlock(dc, blockType, number, buffer, length);
    }
    
    res=initUpload(dc, blockType, number, &uploadID); 
    if (res!=0) return res;
    do {
	res=doUpload(dc,&more,&bb,&len,uploadID);
	totlen+=len;
	if (res!=0) return res;
    } while (more);
    res=endUpload(dc,uploadID);
    *length=totlen;
    return res;
}
 
Danke. getProgramBlock hatte ich jetzt nicht mehr auf dem Schirm...
Nun dazu, wie es zu lösen ist, damit bestehende Anwendungen möglichst wenig beeinträchtigt werden:
Wenn ich doUpload verändere, stünden alle Benutzer auf dem Schlauch, die sich an die Beispiele in testMPI oder testISO_TCP etc gehalten haben.
getProgramBlock hingegegen kann noch nie funktioniert haben, wie es soll.
Insofern scheint es mir richtig, getProgramBlock anzupassen...
 
Was bedeutet das? Heist das Ich kann nun mehr Variablen Anfragen, so das mehr als 240 Bytes zurückgegeben werden?
Eventuell ja. Hängt von der CPU ab.
Wie groß ist die Grenze?
Die Grenze ist die von der CPU zurückgegebene Größe der PDU. Ich habe es mit einer VIPA-CPU getestet, die 960 Byte große PDUs verwenden kann. Dann können auch 960-18 Bytes mit einer Anfrage gelesen werden. Die Antworten auf solch eine Anfrage werden aber auf mehrere Profibus- (oder MPI-) Pakete verteilt, da die Profibus-PDU auf 240 Byte beschränkt ist. Bei Verwendung von IBH-Link müssen sie immer PC-seitig zusammengesetzt werden. Bei ISO over TCP dann, wenn die ausgehandelte Größe der TPDU kleiner ist als die PDU.
 
Bei ISO over TCP dann, wenn die ausgehandelte Größe der TPDU kleiner ist als die PDU.
Kommt das denn mal vor?
In meinen Aufzeichnungen zu diversen S7 wird immer eine TPDU Größe von 1024 ausgehandelt.
Was man evtl. mal versuchen könnte ist, ob man zwei PDUs, bzw. die Anzahl die man bei Verbindungsaufbau mitgeteilt bekommt, in eine TPDU packen kann wenn die TPDU entsprechend größer ist. Das könnte bei kleinen PDU-Größen wirklich einen Schub in der Kommunikationsleistung bringen, wobei bei TCP ja die meiste Zeit in der SPS vertrödelt wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kommt das denn mal vor?
Das weiß ich jetzt nicht mehr. Es kann sein, daß ich zum Testen bei der VIPA die Verbindung mit TPDU-Größe 256 oder 512 initiiert habe. Darüber hinaus meine ich mich dunkel zu erinnern, daß es auch ein Profibus-Ethernet-Gateway gab, wo bei ISO over TCP jede Profibus-PDU in ein eigenes ISO-Paket gepackt wurde.
 
Hast Du nich Lust, libnodave von sourceforge zu Github zu transferieren, so dass im forked repository model daran mitgearbeitet werden kann? Dann könnte Jochen seine Änderungen mit pull requests einfügen und der Administrationsaufwand sinkt. Es gäbe dann auch einen vernünftigen Issue-Tracker usw.
Es wäre dann zentral. Ich habe schon so viele zerpflückte gepatchte libnodave-versionen heumfliegen gesehen, die auf github der irgendwelchen Privathomepages rumlagen, die aber keinen wirklichen Maintainer hatten. Wäre toll, wenn Dein geniales Projekt noch lange besteht.
Gruß

Jochen
 
libnodave und DotNetSiemensPLCToolBoxLibrary

Hallo,

Hast Du nich Lust, libnodave von sourceforge zu Github zu transferieren, so dass im forked repository model daran mitgearbeitet werden kann? Dann könnte Jochen seine Änderungen mit pull requests einfügen und der Administrationsaufwand sinkt. Es gäbe dann auch einen vernünftigen Issue-Tracker usw.
Es wäre dann zentral. Ich habe schon so viele zerpflückte gepatchte libnodave-versionen heumfliegen gesehen, die auf github der irgendwelchen Privathomepages rumlagen, die aber keinen wirklichen Maintainer hatten. Wäre toll, wenn Dein geniales Projekt noch lange besteht.

es hat schon jemand libnodave nach Github gebracht: https://github.com/netdata/libnodave
So wie es aussieht, ist es aber "nur" die Kopie aus einem älteren Tar-Archiv.

Schön wäre es, wenn sich dort die aktuelle Version befinden würde. (Evtl. mit kompletter Historie mittels git cvsimport oder git svn clone ...)
Dann könnte man die Änderungen aus https://github.com/jogibear9988/Dot...ry/tree/master/externalDlls/libnodave_patches einfliessen lassen (falls nötig in einem eigenen Branch).
Und dann könnte libnodave als gitsubmodule in DotNetSiemensPLCToolBoxLibrary/tree/master/externalDlls eingebunden werden.

Im Moment ist es für mich nicht zu verstehen, welche Version von libnodave mit den Patches aus libnodave_patches überschrieben werden soll.
Wenn libnodave als gitsubmodule geladen würde, dann würde git automatisch die richtige "Version" nehmen.

Gruß
Jürgen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab auch ein git repo von libnoadve angelegt: https://github.com/jogibear9988/libnodave

Da ich das Routing aber anderst gelöst habe, kann man die Versionen im Moment nicht mergen. Ich ziehe bei mir aber immer die fixes aus libnodave nach! Deshalb habe Ich auch dieses Repo erstellt um die Unterschiede in den Versionen zu sehen...
 
Zurück
Oben