Delphi-PRAXiS
Seite 1 von 5  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi An com port gesendete daten lesen (https://www.delphipraxis.net/148540-com-port-gesendete-daten-lesen.html)

schweindi 3. Mär 2010 22:50


An com port gesendete daten lesen
 
Hallo alle,
wir verwenden eine SMS Notification software, die Broadcasts und Notifications per sms an alle Beützer versendet.
Das funktioniert so:
1) Ein ASP.NET Portal & SQL Datenbank ermöglichen die Eingabe von Benachrichtigungen und Nummern der Empfänger
2) Diese Daten werden von einer SMSServerRuntime in gsm befehle umgewandelt
3) Diese werden an COM1 geschickt, wobei COM1 ein USBModem ist, in dem sich die SIM Karte befindet, die dann letztendlich die SMS versendet.

Seitdem wir einen Modemwechsel durchgeführt haben, streikt die Software natürlich und nun ist es an mir, herauszufinden warum.
Gleich vorweg, ich arbeite mit dem Hersteller der SMSSoftware zusammen, doch er will/kann mir nicht die Sourcecodes geben, aber er arbeitet schon an einem Patch.
Ich dachte mir so als Herausforderung, versuche ich ein Delphi Programm zu schreiebn, dass mir bei der Suche nach dem Fehler bisschen hilft, doch leider bin ich in meinen Überlegungen nicht zu mehr gekommen als:
1) Man könnte einen Port emulieren und auslesen welche Befehle er zu gesendet bekommt.
2) Mann könnte die Befehle direkt von Port/ Software lesen.

Ich denke Möglichkeit 1) ist seeehr viel schwerer, deshalb denke ich an 2).
Ich weiß ja, welche Befehle das Modem eig. bekommen sollte:

at+cpin? +CPIN:READY
at+csca=xxx OK
at+cmgs="xx",xxx +CMGS:(Index)
at+cmsp=xx,xx,xx,xx OK
(Command : Response)

Das sind die GSM Befehle die ich erwarte. Da ich per Hyperterminal ja die SIM einwandfrei steuern kann und auch sms verschicken kann, denke ich der Fehler liegt genau bei der Schnittstelle Software/COM Anschluss.

Hat jemand eine Idee, wie ich die gesendeten Befehle auslesen kann?? Ich habe ja schon Bedenken, da der Anschluss nur von einem Programm gleichzeitig verwendet werden kann, aber vielleicht liege ich ja auch ganz falsch.

Bin gespannt, ob jemand eine gute Idee hat.
lg

s.h.a.r.k 3. Mär 2010 23:14

Re: An com port gesendete daten lesen
 
Warum schließt du nicht an Stelle des Modems einen anderen Rechner an den bisherigen an und liest so die ankommenden Werte? Ich kenne aber das Protokoll nicht und daher kann ich dir auch nicht sagen, ob du evtl. ankommende Nachrichten beantworten musst (ACK oder sowas). Aber ein Versuch ist es wert :) btw: das COM-Kabel muss natürlich gekreuzt sein!

schweindi 3. Mär 2010 23:56

Re: An com port gesendete daten lesen
 
also vielleicht ist das nicht so klar rausgekommen :)

Die SMS Software unterstützt als Modemlocation nur COM1-5 und ich habe das USB Modem am Anschluss COM1 eingerichtet... also softwaremäßig, damit das ganze läuft. Deshalb ist das alles bisschen komplizierter für mich :)

s.h.a.r.k 4. Mär 2010 00:01

Re: An com port gesendete daten lesen
 
Hä? Ich verstehe wohl immer noch nicht ganz :gruebel: Das hier ist doch der aktuelle Stand:
Code:
+-----------+     COM1
| Rechner B | <------------> GSM-Modem
+-----------+
Richtig soweit?

Was spricht gegen sowas?
Code:
+-----------+      COM1      +-----------+
| Rechner A | <------------> | Rechner B |
+-----------+                +-----------+
Oder folgendes

Code:
+-----------+     COM1
| Rechner B | <-----+------> GSM-Modem
+-----------+       |
                    |        +-----------+
                    +------> | Rechner B |
                             +-----------+

schweindi 4. Mär 2010 07:00

Re: An com port gesendete daten lesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
hmm... okay also vielleicht wirds klarer:

Modem -> USB Slot
In windows Settings: Modems -> Advanced Port Settings. Dort in dem drop down menu einfach den 'COM1' ausgewählt. (Siehe Anhang)

Deshalb hab ich eigentlich keinen "Hardware COM1" Anschluss, da es ja über usb geht- oder versteh ich da was falsch?

jfheins 4. Mär 2010 07:08

Re: An com port gesendete daten lesen
 
Naja, du hast einen virtuellen Comport, der wahrscheinlich direkt an den Mikrocontroller geht der an der SIM-Karte hockt. Das ist ein übliches Vorgehen, weil die meisten Mikrocontroller kein USB haben, aber RS232 - also wird ein Bauteil zwischengeschaltet und ein COM-Port über USB bereitgestellt. (es gibt dabei also keinen "COM-Port-Stecker" sondern nur ein paar Leiterbahnen auf der Platine, die diese serielle Verbindung herstellen)

Mein Ansatz wäre folgender (zugegebenermaßen langweiliger als den COM-Port abfangen): Lies die Doku durch die hoffentlich bei beiden Modems dabei war ;)
(oder guck, ob beide Hersteller sowas wie ein SDK haben, oder ein Beispiel um über ihr Modem eine SMS zu versenden)

schweindi 4. Mär 2010 09:13

Re: An com port gesendete daten lesen
 
ja, also ich weiß welche Befehle am Modem funktionieren und genau die Befehle von der SMSSoftware sind ja das Problem... deswegen "spannend" den Port auslesen :)

Leider hab ich von dem Anbieter noch keine Infos bekommen, welche Befehle gesendet werden und in welchem Format genau (Pud/Text mode).

Da das ganze schnell gelöst werden sollte, dachte ich so könnte das schnell gehen...

LargoD 4. Mär 2010 11:38

Re: An com port gesendete daten lesen
 
Du brauchst da nichts selbst zu schreiben, google einfach mal nach 'com port monitor' oder 'serial port monitor'. Es gibt da einige Programme, die Dir den Datenverkehr zeitlich korreliert in beide Richtungen anzeigen (auch für virtuelle Ports), und die Daten trotzdem zur Anwendung durchlassen. Teilweise Shareware, teilweise Freeware.
Gruß
Erich

schweindi 4. Mär 2010 13:47

Re: An com port gesendete daten lesen
 
ah super danke.. ich habe zwar gegoogelt, aber erst jetzt was gefunden!

Danke sehr...

//erledigt :) - Doch nicht!

Will da gleich weiterarbeiten:

Hab mir ein Com Monitor runtergeladen und sehe jetzt genau was das Programm sendet... ich möchte jetzt einmal selber eines schreiben, dass diese Befehle sendet, genau wie zb Hyperterminal.

Dazu hab ich schon mal von S.h.a.r.k das verwendet und bisschen umgeschrieben:

Delphi-Quellcode:
unit com_bridge;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Button3: TButton;
    Button4: TButton;
    Edit2: TEdit;
    Label2: TLabel;
    Button5: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
    procedure ConnectToCOMPort(Disconnect: Boolean);
    function ReadDataFromCom(lange:Integer):string;
    function WriteDataToCOMPort(Text: String): Boolean;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
//Anschluss
ComHandle : THandle;
comport:string;

implementation

{$R *.dfm}

procedure TForm1.ConnectToCOMPort(Disconnect: Boolean);
var
DCB : TDCB;
TimeOut : TCommTimeouts;
i : Integer;
begin
  { Wenn die Verbindung wieder getrennt werden soll }
  if (Disconnect) then
  begin
  FileClose(ComHandle);
  ComHandle := 0;
  exit;
  end else
{ Die Verbindung zum COM-Port wird hergestellt - wenn dies nicht
funktioniert
wird es bis zu zehn Mal probiert }
  begin
  COMPort:=Edit1.Text; //Com-Ports beginnen bei Com1, Com2, Com3...
  i := 0;
  while (ComHandle <= 0) and (i < 10) do
  begin
  ComHandle := CreateFile(pchar(COMPort), GENERIC_READ or
  GENERIC_WRITE,0, nil, OPEN_EXISTING, 0, 0);
  inc(i);
  end;
{ Einstellungen zum COM-Port zuweisen, wenn die Verbindung aktiv
ist }
if (ComHandle > 0) then
begin
DCB.DCBlength := SizeOf(DCB);
DCB.ByteSize := 8;
DCB.Parity := NoParity;
DCB.StopBits := ONESTOPBIT;
DCB.BaudRate := 9600;
{
DCB.Flags := 5123; // Wenn 2 Pins belegt sind
DCB.EofChar := #0;
DCB.ErrorChar := #0;
DCB.EvtChar := #0;
DCB.XoffChar := #0;
DCB.XoffLim := 0;
DCB.XonChar := #0;
DCB.XonLim := 0;
}
SetCommState(ComHandle, DCB);
GetCommTimeOuts(ComHandle, TimeOut);
TimeOut.ReadIntervalTimeOut := 100;
TimeOut.ReadTotalTimeoutMultiplier := 0;
TimeOut.ReadTotalTimeoutConstant := 250;
TimeOut.WriteTotalTimeoutMultiplier := 0;
TimeOut.WriteTotalTimeoutConstant := 200;
SetCommTimeouts(ComHandle, TimeOut);
end;
end;
end;

function TForm1.WriteDataToCOMPort(Text: String): Boolean;
var
i,k : integer;
str:string;
begin
{ Senden der Daten an den COM-Port - mit Ausgabe ob der Befehl
erfolgreich war }
i:=FileWrite(ComHandle, Text[1], Length(Text));
ShowMessage(str);
if (i <> Length(Text)) then
Result := False
else
Result := True;
end;

function TForm1.ReadDataFromCom(lange:Integer):string;
var n:string;
begin
FileRead(ComHandle,n,lange);
ShowMessage(n);
Result:=n;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Application.Terminate;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
ConnectToComPort(false);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
ConnectToComPort(True);
ShowMessage('Disconnected from '+Edit1.Text);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
WriteDataToComPort(Edit2.Text);
ShowMessage('Write Data Successfull');
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
ReadDataFromCom(length(Edit2.Text))
end;

end.
so nun das schicken hab ich per virtual serial port schon überprüft, das funktioniert.
Wenn ich aber in hyperterminal mir das anschaue, sehe ich dass irgendwie ein 'Zeilenumbruch' noch gesendet wird, was ist das für ein Befehl?

im monitor siehts so aus:

Log # / Zeit / Programm / Befehl / Port / Status / Details
...
16 15:36:28 SMSServer IRP_MJ_READ USBER000 TIMEOUT Length 16: AT+CMGF=0...OK..
17 15:36:28 SMSServer IRP_MJ_WRITE USBER000 SUCCESS Length 11: AT+CMGF=0...
18 15:36:28 SMSServer IRP_MJ_FLUSH_BUFFERS USBER000 SUCCESS
...

also dieser "Success" Befehl, den sollte ich auch iwie schicken können, aber das wichtigste ist nun, wie "lese" ich die Antworten vom Modem??

Mein ReadDataFromCom() geht leider nicht, da kommt ein leerer String, wenn ich 2-10 Zeichen Lesen lasse.
Wie sollte das genau gehen?

schweindi 5. Mär 2010 10:20

Re: An com port gesendete daten lesen
 
muss ich überhaupt extra die Antworten des Modems abwarten und ausgeben, oder geht das iwie automatisch, also als eine Art "echo"?

Wenn man es extra abfragen muss, wäre eine while schleife dafür geeignet?

Delphi-Quellcode:
var input: string;
    NumberOfBytesRead : dword;
    Buffer           : array[0..255] of char;

begin
ReadFile(hCommFile, Buffer, sizeof(Buffer), NumberOfBytesRead, nil);

//Buffer -> input?

while input <> '' do#
  begin
//irgendetwas
  end;
ich hab irgendwo gelesen, dass einer diese Wartezeit, bis das Modem antwortet, zwar geschafft hat zu verarbeiten aber dauerhaft CPU auf 100%, was bei mir nicht sein darf, da noch andere Programme laufen müssen.

Oder gibt es ein Event im Sinne von "Nachricht erhalten"?

Und noch eine kleine Erklärung von ReadFile() wäre ganz super.

ReadFile( (COMPort Handle) , (die Variable die den gelesene String bekommt) , ?? , ?? , (wieso nil?) );

muss ein Array of char oder string verwendet werden als input variable?


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:09 Uhr.
Seite 1 von 5  1 23     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz