[Gelöst] SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 10:28

Hallo,

Folgendes Problem:
Ich muss für einen Kunde eine Schnittstelle programmieren, welche über den Socket Bus Adapter in Navision angesprochen werden muss. Das ausgeben der Daten von NAV an die Schnittstelle funktioniert.
Beim Einlesen habe ich ein "OutMsg.SendWaitForReply(20000);" eingebaut. Jedoch scheint mir NAV bei diesem Punkt nicht zu warten und gibt mir folgende Fehlermeldung aus:

-----------
Microsoft Dynamics NAV Classic
-----------
Diese Meldung ist für C/AL-Programmierer:

Der Aufruf zum Member SendWaitForReply ist fehlgeschlagen. SocketBusAdapter.SocketBusAdapter.1 gab die folgende Meldung zurück:
InMessage could not be created because information was not received.
-------------
OK
-------------

Hier der Code dazu (es handelt sich hauptsächlich um den Receive-Abschnitt ganz unten):
Code:
// Send
// Check if ComCom2 is clear
IF ISCLEAR(ComCom2) THEN
  IF NOT CREATE(ComCom2) THEN
    ERROR('Failed to create Communication Component');
// Check if Socket Bus Adapter is clear
IF ISCLEAR(SocketBusAdapter) THEN
  IF NOT CREATE(SocketBusAdapter) THEN
    ERROR('Failed to create SocketBusAdapter');

// Add the Winsock to the Comunication Component
ComCom2.AddBusAdapter(SocketBusAdapter, 0);
OutMsg:= ComCom2.CreateoutMessage('Sockets://localhost:6050');

// Create Output XML-File
// Initialisierung des Dokuments
CREATE(XMLDomDoc);

//Knoten erstellen und dem Dokument hinzufügen.
NewNode := XMLDomDoc.createNode(1,'WaWi','');
XMLDomDoc.appendChild(NewNode);

NewNodeBcmd := XMLDomDoc.createNode(1,'OCmd','');
NewNode.appendChild(NewNodeBcmd);

// Hinzufügen eines Attributs zu dem Knoten
NewAttribute := XMLDomDoc.createAttribute('RequesterNumber');
NewAttribute.value := '1';
NewNodeBcmd.attributes.setNamedItem(NewAttribute);

// Hinzufügen eines Attributs zu dem Knoten
NewAttribute := XMLDomDoc.createAttribute('OrderNumber');
NewAttribute.value := '4771';
NewNodeBcmd.attributes.setNamedItem(NewAttribute);

OutStr:= OutMsg.GetStream();
OutStr.WRITE(XMLDomDoc.xml);

OutMsg.Send(0);

//////////////////////////////////////////////////////////////////////////////////////

// Receive
ReceiveDoc := FALSE;
IF NOT CONFIRM('Ready to read', TRUE)THEN EXIT;                          //remove

// Prevent waiting for the reply
SocketBusAdapter.CloseSendWhenWaitForReply:= TRUE;
InMsg:= OutMsg.SendWaitForReply(20000);
IF (ISCLEAR(InMsg)) THEN
  ERROR('Fehler');

InStr:= InMsg.GetStream();

WHILE NOT (InStr.EOS) DO
BEGIN
  InStr.READ(txt);
  MESSAGE(txt);
END;

InMsg.CommitMessage();


Meine Frage:
Warum geht das so nicht? :-(
Zusätzlich habe ich einen Confirm-Dialog eingebaut um die Codeunit zu stoppen - hierbei werden die Daten eingelesen, ansonsten nicht (Wenn man den Confirm auskommentiert).


Ich hoffe, ihr könnt mir da weiter helfen. Habe da schon einige Tage mit rumprobieren und Googlen verbracht.

MfG
Kyrios
Zuletzt geändert von kyrios am 4. März 2013 13:58, insgesamt 2-mal geändert.

Re: SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 10:37

Wenn du noch eine NAV5.x Version hast, schau mal in den "Gemeinsame Dateien\NAV??\Communication Component"- Ordner von NAV, da ist eine Hilfe mit Beispielen für die Komponenten enthalten.

Gruß, Fiddi

Re: SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 11:29

fiddi hat geschrieben:Wenn du noch eine NAV5.x Version hast, schau mal in den "Gemeinsame Dateien\NAV??\Communication Component"- Ordner von NAV, da ist eine Hilfe mit Beispielen für die Komponenten enthalten.


Der Kunde hat NAV 2009 R2 im Einsatz (6.00.33277).

Wenn du damit die devguide.chm meinst, in der die Hilfe zu dem SBA und die Beispiele drinnen stehen, dann kenn ich die schon. Die Programmierung habe ich ja hauptsächlich anhand dieser Doku aufgebaut.
Bei mir funktioniert ja lediglich dies nicht: "OutMsg.SendWaitForReply(20000)". Ich weiß nicht, ob mir da sonst noch was fehlt, damit das funktionieren kann.
Eventuell der Save-Befehl vom DOMDocument ("DOM.save(OutMsg.GetStream());")? Wobei ich nicht denke, dass ich den brauche.

Gruß Kyrios

Re: SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 11:35

Die meinte ich.

schau dir doch mal die aktuellen ADCS- Module an, die benutzen auch den Socket-Bus.

Gruß, Fiddi

Re: SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 15:03

fiddi hat geschrieben:schau dir doch mal die aktuellen ADCS- Module an, die benutzen auch den Socket-Bus.


Danke für den Tipp, das ist aber so nicht das was ich brauche bzw. verwenden kann. Das müsste dann ja bei allen Mitarbeitern bei der Firma eingestellt werden - das sind über 100 Mitarbeiter.
Und es soll ja auch im RTC laufen (hab ich wohl vergessen zu erwähnen - sry).
Es sind also alles Rechner mit Windows 7 oder XP - also keine VT100 Stationen im Einsatz.

Die Maschine hängt so im Netz und wird über TCP/IP angesprochen. Also muss ich da ja mit dem Socket Bus Adapter arbeiten - oder habe ich da was falsch verstanden?

Grüße
Kyrios

Re: SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 15:46

Es sind also alles Rechner mit Windows 7 oder XP - also keine VT100 Stationen im Einsatz.


Das meinte ich auch nicht, sondern den Code der in CU 7700 enthalten ist. Der sorgt für die Kommunikation.

Gruß, Fiddi

Re: SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 18:58

ok, danke.
Werde mir das morgen gleich mal anschauen.

Grüße
Kyrios

Re: SocketBusAdapter Schnittstelle - Daten einlesen

23. Januar 2013 21:21

Spontane, villeicht doofe, Idee:
Deine CodeUnit ist schon eine SingleInstance-CodeUnit?

Gruss

Re: SocketBusAdapter Schnittstelle - Daten einlesen

24. Januar 2013 16:07

martinst hat geschrieben:Spontane, villeicht doofe, Idee:
Deine CodeUnit ist schon eine SingleInstance-CodeUnit?

Soo doof find ich die gar nicht - hätt ich zB nicht gewusst. Aber für mein aktuelles Bsp. brauch ich das eh nicht :) Jedoch für ein anderes, komplexeres, was nach dem dran kommt.

Ich hab den Fehler mehr oder weniger durch eine "blöde" Idee von mir rausbekommen. Diese Zeile
Code:
SocketBusAdapter.CloseSendWhenWaitForReply:= TRUE;

bedeutet ja, dass ich nur noch ein Send-Befehl schicken kann und dann auf eine Antwort warten muss. Anschließend habe ich diese Zeile drinnen
Code:
InMsg:= OutMsg.SendWaitForReply(20000);

die ja normalerweise ein Send-Befehl rausschickt und dann 20sec auf eine Rückmeldung wartet. Jedoch geht das so nicht. Es scheint mir so, als ob der 1. Befehl das senden sofort unterbindet, und ich deshalb das Senden in der zweiten Zeile nicht mehr durchführen kann/darf. :evil:

Weiß da jemand, warum das so ist :?: Ich komm da absolut nicht drauf.

Das heißt - wenn ich die Zeile mit "CloseSendWhenWaitForReply" auskommentiere, funktioniert auch alles, wie gewollt. Jedoch können dann mehrere Anfragen zur gleichen Zeit (mit ein paar Millisekunden dazwischen) gesendet werden. Das wäre dann ja schlecht. Das muss ich noch iwi unterbinden können.

@fiddi
Ich habe mir die Codeunit angeschaut, jedoch steht da nichts so drinnnen, wie in der Hilfe oder sonst wo. Aber danke für den Tipp, war auf jedenfall Wert, reinzuschauen :)

Re: SocketBusAdapter Schnittstelle - Daten einlesen

4. März 2013 13:57

ok, um das Thema zum abschluss zu bringen:
Microsoft hat darauf auch keine Antwort, warum das nicht geht.

Ich habe mitbekommen, dass beide Programme - also NAV und die Maschine - auf gleichem DLL kommunizieren müssen, sodass die Kommunikation erfolgreich durchläuft (in meinem Fall müsste auch die Maschine über die COMCOM Objekte kommunizieren, dass das richtig funktioniert).

Da dies jedoch bei mir nicht so ist, muss ich das über ein externes Programm lösen / ein externes Programm schreiben.

Vielen Dank jedoch für eure Hilfestellungen :)

MfG
Kyrios

Re: SocketBusAdapter Schnittstelle - Daten einlesen

22. Juli 2013 13:55

kyrios hat geschrieben:...
Das heißt - wenn ich die Zeile mit "CloseSendWhenWaitForReply" auskommentiere, funktioniert auch alles, wie gewollt. Jedoch können dann mehrere Anfragen zur gleichen Zeit (mit ein paar Millisekunden dazwischen) gesendet werden. Das wäre dann ja schlecht. Das muss ich noch iwi unterbinden können.
...

Da
Code:
OutMsg.Send(0);
und
Code:
InMsg:= OutMsg.SendWaitForReply(20000);
prinzipell das Gleiche machen, nimm einfach
Code:
OutMsg.Send(0);
raus.

Fall1) Es gibt Socket-Anwendungen, die auf eine Socket-Nachricht direkt antworten. Dann braucht es keine Events (WithEvents=No). Das Abfangen der Antwort funktioniert dann so wie in Deinem Code (bitte ohne OutMsg.Send). Die Gegenstelle ist dann der Socket-Server, Navision ist der Socket-Client.

Fall2) Andere Socket-Anwendungen antworten ggf. asyncron und bauen dafür eine eigene Verbindung auf. Dann brauchte es Events (WithEvents=Yes). Damit ist es möglich, dass die Antwort in keinem zeitlichen Zusammenhang mit der Anfrage steht. Grundsätzlich habe ich festgestellt, dass sich "WithEvent=Yes" wie ein eigener Socket-Server verhält. Dies wird eher selten verwendet. Hier ist Navision sowohl Socket-Client als auch Socket-Server gleichzeitig.

Zusätzliches:
Code:
SocketBusAdapter.CloseSendWhenWaitForReply:= TRUE;

ist dann zu verwenden, wenn die Verbindung mit dem Socket-Server nach der Kommunikation unmittelbar geschlossen werden soll. In vielen Fällen ist das gar nicht notwenig, da eine dauerhafte und sich wiederholende Kommunikation erwünscht ist. Deshalb experimentiere bei Bedarf bitte mit FALSE.

Code:
InMsg.CommitMessage();

Schließt die Verbindung zum Socket-Server nach dem Lesen. Muss (s.o.) ggf. auch nicht sein.

Grüße
BeRo