![]() |
Daten von einem anderen Programm "auffangen" und v
sodala, wieder mal ich :)
mit großer Hilfe habe ich endlich mein Programm, dass mit einem Modem kommunizieren kann, fertiggestellt ( ![]() Jetzt bin ich mir garnicht sicher, ob die folgende Frage hier reinpasst, aber irgendwie hat sie doch mit Win API zu tun, denke ich. Wie ich schon in der oben genannten Frage geschrieben habe, ist die Software die wir verwenden alt und nicht kompatibel mit dem neuen Modem. Jetzt hab ich mir gedacht es müsste doch möglich sein, mit einem Programm die Daten/ Befehle die dieses SMS-Programm an den Com Anschluss sendet "abzufangen" und dann richtig verarbeitet weiterzuschicken. Leider fallen mir da auf Anhieb kaum gute Wege ein. Hat jemand vielleicht eine Idee, wie man das -eher leicht- machen könnte? (Ich hab mir mal angeschaut, wie leicht es wäre einen "virtuellen" com Anschluss zu erstellen und die Software auf diesen einzustellen um die empfangenen Daten dann ans richtige Modem weiterzusenden, doch das sah auf den ersten Blick extrem aufwendig aus, da man einen eigenen Driver bräuchte) Danke im Voraus |
Re: Daten von einem anderen Programm "auffangen" u
Hi,
Es gibt eine OpenSource software, die heisst ![]() Diese simuliert zwei serielle Schnittstellen, die miteinander verbunden sind. Wenn Programm A mit einer dieser Schnittstellen spricht, könnte Programm B die Gegenstelle auf der anderen Schnittstelle sein, und dein Modem hängt dann tatsächlich an der realen Schnittstelle C, und wird von Programm B versorgt. Gruss |
Re: Daten von einem anderen Programm "auffangen" u
das klingt ausgezeichnet, könnte genau das sein, was ich suche - danke ich schaus mir mal an :)
|
Re: Daten von einem anderen Programm "auffangen" u
jop, danke es war genau das was ich gesucht habe.
Ich hab zwar noch bisschen Probleme die Timeouts mit dem anderen Programm übereinzustimmen, deshalb werden manche Antworten schon gesendet, obwohl die Anfrage noch nicht ganz empfangen wurde, aber das mach ich noch. Mit sleep() und die Timeouts richtig einstellen, dann sollte es gehen. danke! |
Re: Daten von einem anderen Programm "auffangen" u
hmm.. jetzt geht mir das ganze doch schon ziemlich auf die Nerven, manchmal geht das Programm manchmal nicht und ich hab eig keine Ahnung, was ich verändert habe, damit es ging.
Folgendes Problem: Wenn ich mein Programm starte soll es zuerst "at+cfun=1" ans modem schicken, dann die Antwort des Modems abwarten und dann "at" schicken, wieder die Antwort abwarten. Klingt extrem einfach, doch irgendwie bin ich unfähig! mein Versuch:
Delphi-Quellcode:
So sleeptime hab ich 10ms,50ms,100ms und 1000ms probiert, es hilft natürlich nichts.
procedure TForm1.Button2Click(Sender: TObject);
var StartIni : TIniFile; begin ComPort1.Port:=Edit1.Text; //Ini File StartIni:=TIniFile.Create(ChangeFileExt(Application.ExeName,'.INI')); try StartIni.writeString('Com1','Name',Edit1.Text); finally StartIni.Free; end; ComPort1.Open; Memo_text.Lines.Add('-------'); Memo_text.Lines.Add('Connected to '+Edit1.text); Memo_text.Lines.Add('-------'); Writeln(Logf, 'Connected to '+Edit1.text); //logfile //set +cfun=1 ComPort1.WriteStr('AT+CFUN=1'); ComPort1.TransmitChar(#13); Writeln(Logf, 'SEND: AT+CFUN='); sleep(sleeptime); Application.ProcessMessages; //send status ComPort1.WriteStr('AT'); ComPort1.TransmitChar(#13); Writeln(Logf, 'SEND: AT'); sleep(sleeptime); Application.ProcessMessages; //brauch ich da noch eines? So siehts im Monitor aus:
Code:
daraus schließe ich, dass in der zeile IRP_MJ_READ at+cfun=1 vom modem zurückgesendet wurde und drangehängt "...OK.." wenn ich nach diesem Button dann manuell zb AT eingebe, passiert nichts, keine Antwort vom Modem kein Wait nichts.
REQUEST Port Result Other
IOCTL_SERIAL_GET_MODEMSTATUS USBER000 SUCCESS IRP_MJ_WRITE USBER000 SUCCESS Length 9: AT+CFUN=1 IOCTL_SERIAL_WAIT_ON_MASK USBER000 SUCCESS IOCTL_SERIAL_WAIT_ON_MASK USBER000 SUCCESS IOCTL_SERIAL_GET_COMMSTATUS USBER000 SUCCESS IRP_MJ_READ USBER000 SUCCESS Length 16: AT+CFUN=1...OK.. IOCTL_SERIAL_GET_COMMSTATUS USBER000 SUCCESS IRP_MJ_WRITE USBER000 SUCCESS Length 2: AT Interessant: wenn ich disconnect klicke (ComPort1.Close;) und dann wieder connecte steht vor der Ausgabe "Answer: OK" dh das Event OnPacket von TComPort1 hat sich eingeschaltet... also ich blicke da nicht mehr durch und kenne mich anscheinend zu wenig aus :S Was möchte ich? 1) Das Programm soll erst den nächsten Befehl senden, (in dem Fall "AT") wenn es vom Modem eine Antwort bekommen hat 2) Wenn es zum Timeout kommt, soll der Befehl erneut versendet werden. Danke für jede Hilfe! Gruß Schweindi |
Re: Daten von einem anderen Programm "auffangen" u
Hi,
ich würde dafür nicht TComport nehmen. Dies ist eine Ereignisgesteuerte Komponente. Wenn man warten will/muss, sollte man einen blockierenden Ansatz verwenden. ![]() Gruss |
Re: Daten von einem anderen Programm "auffangen" u
jop danke - jetzt hab ich das ganze mal mit Synaser umgeschrieben... folgendes:
Delphi-Quellcode:
das wird ausgeführt, wenn man den ConnectButton klickt.
procedure TForm1.Button2Click(Sender: TObject);
var StartIni : TIniFile; Answer : string; begin ComPort1.Connect(Edit1.Text); //Ini File StartIni:=TIniFile.Create(ChangeFileExt(Application.ExeName,'.INI')); try StartIni.writeString('Com1','Name',Edit1.Text); finally StartIni.Free; end; //Modem Configuration ComPort1.Config(com_rate, com_bits, Char(com_parity), com_stop, com_softflow, com_hardflow); Memo_text.Lines.Add('-------'); Memo_text.Lines.Add('Connected to '+Edit1.text); Memo_text.Lines.Add('-------'); Writeln(Logf, 'Connected to '+Edit1.text); //Modem status ComPort1.SendString('AT'+#13#10); Writeln(Logf, 'SEND: AT'); Answer := ComPort1.RecvString(readtotal); if (Answer = 'OK') then begin if Logout then Writeln(Logf, 'RECIEVED: '+Answer); if Memoout then Memo_text.Lines.Add('RECIEVED: '+Answer); end else begin Memo_text.Lines.Add('RECIEVED: no answer!'); Memo_text.Lines.Add('ERROR: '+IntToStr(ComPort1.LastError)); end; ComPort1.Flush; //set +cfun=1 ComPort1.SendString('AT+CFUN=1'+#13+#10); Writeln(Logf, 'SEND: AT+CFUN=1'); Answer := ComPort1.Recvstring(readtotal); if (Answer = 'OK') then begin if Logout then Writeln(Logf, 'RECIEVED: '+Answer); if Memoout then Memo_text.Lines.Add('RECIEVED: '+Answer); end else begin Memo_text.Lines.Add('RECIEVED: no answer!'); Memo_text.Lines.Add('ERROR: '+IntToStr(ComPort1.LastError)); end; end; Readtotal : Integer -> da hab ich zb 500 bzw 1000 eingegeben und es ging eigentlich. aber nach "AT+CFUN=1" bekomme ich keine Antwrot mehr... und wenn ich manuell die Befehle eingebe:
Delphi-Quellcode:
dann wird zwar der Befehl geschickt: (monitor) "COM Bridge.exe IRP_MJ_WRITE USBER000 SUCCESS AT+CFUN=1.."
procedure TForm1.Button4Click(Sender: TObject);
var Str: String; begin //write to port Str := Edit2.Text; ComPort1.SendString(str+#13+#10); // string type variable if logout then Writeln(Logf, '(ComPort1) SEND: '+str+' #13 #10'); if memoout then Memo_text.Lines.Add('SEND: '+str+' #13 #10'); ComPort1.RecvString(readtotal); if memoout then Memo_text.Lines.Add('Answer: '+str); Edit2.Clear; end; aber ich bekomme keine Antwort zurück......... und allgemein, wie kann ich, wie bei TComPort das Programm warten lassen, so dass es sofort, wenn es einen Input bekommt etwas macht... Klartext: Programm startet -> connect drücken (den code oben ausführen) -> Programm ist fertig, es bleibt offen -> Modem sendet irgendwas -> Programm "wacht auf" und macht was mit dem Befehl, den es bekommen hat. wie könnte das gehen? |
Re: Daten von einem anderen Programm "auffangen" u
Ich kenne jetzt TComPort nicht im Detail, aber ich denke es hat dafür ein Event
Sowas wie OnReadData oder so Schau mal im OI auf die Events - da sollte was dabei sein. Gruss P.S. Nochwas zu Synaser Wenn Du ReadString (timeout:integer) verwendest, dann ist der timeout in millisekunden. Du solltest wirklich mal ein Terminalprogramm (Hyperterm oder so) verwenden, und testen, ob deine Annahmen bzgl. des Timings stimmen. Gruss |
Re: Daten von einem anderen Programm "auffangen" u
naja ich verwende ja Synaser.
Stimmt der gepostete code so? ja ich weiß, dass es sich um ms handelt. Ich hab auch schon im hyperterm alle meine Befehle durchprobiert, um zu sehen, wie die Antworten des Modems sein werden. Aber wie bekomme ich die genauen timings?? Ich wollte nämlich genau die einstellungen von hyperterm nachahmen, da die ja sichtlich funktioniert haben. |
Re: Daten von einem anderen Programm "auffangen" u
Ansich sieht das gut aus, was du da machst.
Ich kenne die AT Befehle nicht, die Du da verwendest. Was sollte denn deiner Meinung nach dem AT+CFUN=1 passieren ? Es kommt ja nicht darauf an, die genaue Zeit zu warten, es geht um eine maximale Zeit. Also 5000 msec wären nicht zuviel, wenn die Daten früher einlaufen, werden sie auch früher geliefert und das Programm geht weiter. Noch ein Tipp zu Comport.Config () Die Stoppbits solltest Du mithilfe der Konstanten aus Synaser einstellen, denn: 0 = 1 stoppbit 1 = 1,5 stoppbits 2 = 2 stoppbits Synaser kennt SB1, SB1andHalf, SB2 das kann schonmal sehr wichtig werden. Gruss |
Re: Daten von einem anderen Programm "auffangen" u
ahso, ja :)
also wir verwenden ein Nokia CS-15 umts/gsm gateway und man muss die "telephone function of sim" erstmal einschalten, damit das ganze funktioniert. Auszug aus AT-Commands Revision A:
Code:
ja ich habe gerade in hyperterm geschaut:
Set phone functionality +CFUN
Command syntax: AT+CFUN=<functionality level> AT+CFUN=0 (ähnlich: AT+CPOF - power off) AT+CFUN=1 (start oder wenns schon gestartet ist modem reset) RI:10 - Readinterval? RM:0 - Read Multiplier? RC:0 - Read Konstante? WM:0 - Write Multiplier? WC:5000 - Write Konstante? also wenn meine Annahmen stimmen, hat hyperterm kein read timeout oder? naja ich denke die Befehle sollten, wie du gesagt hast, nie mehr als 5 Sekunden brauchen -> ich mach Read: 5000 ReadIntervall: 10 und Write: 5000 - das sollte dann passen... Danke für den Tipp, werde ich berücksichtigen. Ich probier das ganze umgeschrieben mal aus. |
Re: Daten von einem anderen Programm "auffangen" u
So sieht der traffic am Port gerade aus:#
Code:
Wie man sieht, nachdem ich cfun=1 eingegeben habe, kam ein Zeichen nur . (= #13) und dann egal welchen Befehl ich verschickt habe, kam jeweils die Antwort auf den vorigen Befehl zurück... Da verstehe ich leider garnicht!
Software: AT
Modem: OK.. S: AT+CFUN=1 M: . ERROR (Timeout) (so das wäre der "connect" teil) wenn ich jetzt manuell weitere Befehle sende: S: AT M: AT+CFUN=1..+CFUN=1..OK..OK S: AT+CNMI? M: . S: (irgendein Befehl) M: AT+CNMI?..+CNMI=2,2,0,1,0..OK..OK S: (irgendein Befehl) M: . usw usw Was kann das bewirken? P.S.: "at+cfun=1..+CFUN=1..OK..OK" mein Befehl wird als echo zurück gesendet, da ATE ein ist.. |
Re: Daten von einem anderen Programm "auffangen" u
Du solltest dich nicht darauf verlassen, dass Antworten ein bestimmtes Timing haben.
Stattdessen würde ich das abschliessende #13 als Endezeichen betrachten. Der Algorithmus sieht so aus: Es gibt einen Empfangspuffer (string). Bei jedem OnRead-Event werden die empfangen Daten zuerst an den Empfangspuffer angehängt. Dann schaut man nach, ob im Empfangspuffer eine ganze Zeile steht indem man nach dem Endezeichen sucht. (*) Die Antwort (inklusive Endezeichen) wird aus dem Empfangspuffer ausgeschnitten. Dann wird die Antwort (ohne Endezeichen) einer Procedure übergeben die dann entsprechend reagiert. Es könnte aber noch eine weitere Antwort im Empfangspuffer stehen; deshalb zurück zur mit (*) markierten Zeile. |
Re: Daten von einem anderen Programm "auffangen" u
hmm ja das ist dann das prinzip vom TComPort, ich will es jetzt aber mit den methoden von synaser machen!
ich hab da etwas gefunden: ComPort1.RecvBlock(timeout); Das liest ja genau soviel aus, wie viel am anfang der zeile angegeben wird. Mein Modem schickt zb: Lenght:4 OK.. dh 4 = anzahl der elemente und soviel müsste er auslesen, das Problem ist nur, wenn ich das ausprobiere, und ich schreibe im Hyperterm "4 OK" dann bekomme ich nachdem ich "O" geschrieben habe einen "Out of memory error"!? das ist jetzt schon eigenartig |
Re: Daten von einem anderen Programm "auffangen" u
Zitat:
Ein kurze Pause zwischen dem O und dem K und schon kommt .RecvBlock() mit einem unvollständigem Ergebnis zurück. Du musst dir klarmachen, dass du dich von einem Timeout ganz lösen musst. Ob jetzt alle zwei Sekunden eine einziges Zeichen hereinkommt oder ob alle Zeichen auf einen Rutsch eintreffen darf für dein Programm keine Rolle spielen. PS habe gerade gesehen, dass es bei Synaser die Methode RecvTerminated() gibt.
Delphi-Quellcode:
antwort := synaser.RecvTerminated(5000, #13);
|
Re: Daten von einem anderen Programm "auffangen" u
ich habe tiomeout auf 20000 gesetzt - 20 Sekunden sollten reichen für mich :)
ich habe schon das Problem gefunden: ich habe eingegeben: "4 OK" aber eig sollte es sein "0004 OK" da er ja 4 byte braucht. Jetzt muss ich nur noch herausfinden, wie ich 4 in byte darstellen kann, da, wenn ich 0004 eingeben kommt als Wert 8755723296 und nicht 4 heraus! |
Re: Daten von einem anderen Programm "auffangen" u
Zitat:
Du kannst RecvBlock() daher so nicht verwenden. Aber gehe mal einen Betrag zurück und lies noch mein PS. |
Re: Daten von einem anderen Programm "auffangen" u
ah sorry, hab das nicht mehr gesehen... okay, na dann verwende ich das mal.
also das Modem antwortet mit "OK"+CR+LF dh endstring ist immer #10? |
Re: Daten von einem anderen Programm "auffangen" u
okay, super funzt das alles jetzt.
Ich hab nur noch ein problem, das Modem sendet jeden Input als echo zurück. Wie kann ich diese Echos auslesen und somit aus dem Input löschen? Gelöst! Jetzt will ich aber, dass sobald er auf dem Port Daten bekommt, etwas macht. Bei TComPort war das OnRxChar. Wie geht das hier mit dem? bzw wie kann ich es machen, dass sobald er etwas im Input hat, eine procedure ausgeführt wird? |
Re: Daten von einem anderen Programm "auffangen" u
Alternative:
wäre es leichter das Windows Event: SERIAL_EV_RXCHAR zu verwenden und daraus ein (eigenes) Event zu machen. Ich habe zwar noch nie Events selber gemacht, aber ich denke mir, irgendwo muss im Endeffekt doch auf ein Windows Event verwiesen werden. Z.B. in der TComPort Unit wird jedem Event property zugeschrieben und irgendwann kommt "If Assigned(TEVENT) then ... .DOStatus" also das ist bezogen auf Serielle Anschlüsse. Aber ich sehe nirgendwo eine für mich verständliche Zuordnung, in der ein Windows Event irgendwie verwendet wird... also ist ein RxChar Event leicht selber machbar? |
Re: Daten von einem anderen Programm "auffangen" u
hat keiner eine Idee??
Mir fehlt nur noch eine Möglichkeit EV_RxChar einzubinden, dann müsste das ganze Programm funktionieren! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:01 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz