Join 136,075 C# Programmers for FREE! Get instant access to thousands of C# experts, tutorials, code snippets, and more! There are 1,585 people online right now. Registration is fast and FREE... Join Now!
I'm writing a very simple program which uses AT commands to send a SMS via a GSM modem on my com port. I've managed to successfully communicate with the modem through my program (thanks for the "serial Port Comms in c#" tutorial ) But one line is stumping me. When you issue the command to write a text in HyperTerminal you get a '>' prompt in which you type your message and then press 'ctrl-z' to return to the command prompt. How do I do this in my program? Any suggestions are much appreciated or anu pointers in the right direction will do nicely. Here is a bit of my code to help understanding.....maybe!!!
Thanks
csharp
private void button1_Click(object sender, EventArgs e) { //Firstly set the modem to text mode serialPort1.Write("at+cmgf=1\r\n"); //Now enter message writing mode to send an sms to the number below serialPort1.Write("at+cmgw=\"+447878xxxxxx\"\r\n"); //Now send the contents of the message serialPort1.Write("Test message from coded program"); At the end of this line I need ctrl-z //Now send the message stored at position 2 serialPort1.Write("at+cmss=2\r\n"); }
This post has been edited by PsychoCoder: 10 Apr, 2008 - 06:10 AM
Have a look at the SendKeys Class. This will allow you to simulate key presses, such as what you're looking for. Hope that helps
OK so sendkeys does seem to describe exactly what I want to do. I've managed to put the correct code as far as syntax is concerned into my program and it builds ok. Unfortunately it doesn't appear to do anything and my next command tags itself onto the end of the message as I've not escaped from the message writing yet. I suspect I need to somehow tell it that the sendkeys command is meant for the serial port, can I do this? I read I think that it is only for the "active application" so is this stopping me? I've also tried putting the sendkeys command on the end of the message line but it still appears to do nothing. Whilst I wait for any advice I'm going to look at the char command as I seem to have noted the ascii code for shift-z as 26 so maybe I can use that to send it. Thanks again folks.
[code] private void button1_Click(object sender, EventArgs e) { //Firstly set the modem to text mode serialPort1.Write("at+cmgf=1\r\n"); //Now enter message writing mode to send an sms to the number below serialPort1.Write("at+cmgw=\"+447878409893\"\r\n"); //Now send the contents of the message serialPort1.Write("Test message from coded program"); SendKeys.Send("^(z)"); //Now send the message stored at position 2 serialPort1.Write("at+cmss=4\r\n"); }
I'm doing the same project in C# I can use hyperterminal to send AT commands to the mobile to send sms. but when i tried doing it through C#, it didn't work. I tried your code and didn't work too.
Unfortunately, my PC has a single serial port, so i couldn't redirect the output to hyperterminal for debugging.
Is it possible to send me your source code or help me figure out what's wrong with mine ?
I used the default values for the serial port component (9600 BaudRate, 8 DataBits (tried 7 too), etc...)
QUOTE(Dandy1903 @ 13 Apr, 2008 - 03:05 PM)
OK so sendkeys does seem to describe exactly what I want to do. I've managed to put the correct code as far as syntax is concerned into my program and it builds ok. Unfortunately it doesn't appear to do anything and my next command tags itself onto the end of the message as I've not escaped from the message writing yet. I suspect I need to somehow tell it that the sendkeys command is meant for the serial port, can I do this? I read I think that it is only for the "active application" so is this stopping me? I've also tried putting the sendkeys command on the end of the message line but it still appears to do nothing. Whilst I wait for any advice I'm going to look at the char command as I seem to have noted the ascii code for shift-z as 26 so maybe I can use that to send it. Thanks again folks.
[code] private void button1_Click(object sender, EventArgs e) { //Firstly set the modem to text mode serialPort1.Write("at+cmgf=1\r\n"); //Now enter message writing mode to send an sms to the number below serialPort1.Write("at+cmgw=\"+447878409893\"\r\n"); //Now send the contents of the message serialPort1.Write("Test message from coded program"); SendKeys.Send("^(z)"); //Now send the message stored at position 2 serialPort1.Write("at+cmss=4\r\n"); }
Have a look at the SendKeys Class. This will allow you to simulate key presses, such as what you're looking for. Hope that helps
OK so sendkeys does seem to describe exactly what I want to do. I've managed to put the correct code as far as syntax is concerned into my program and it builds ok. Unfortunately it doesn't appear to do anything and my next command tags itself onto the end of the message as I've not escaped from the message writing yet. I suspect I need to somehow tell it that the sendkeys command is meant for the serial port, can I do this? I read I think that it is only for the "active application" so is this stopping me? I've also tried putting the sendkeys command on the end of the message line but it still appears to do nothing. Whilst I wait for any advice I'm going to look at the char command as I seem to have noted the ascii code for shift-z as 26 so maybe I can use that to send it. Thanks again folks.
csharp
private void button1_Click(object sender, EventArgs e) { //Firstly set the modem to text mode serialPort1.Write("at+cmgf=1\r\n"); //Now enter message writing mode to send an sms to the number below serialPort1.Write("at+cmgw=\"+447878409893\"\r\n"); //Now send the contents of the message serialPort1.Write("Test message from coded program"); SendKeys.Send("^(z)"); //Now send the message stored at position 2 serialPort1.Write("at+cmss=4\r\n"); }
The String objects store Unicode characters so we need to add a Unicode ^Z to the string being written. To do this add a Unicode escape sequence character, in this case \u001F, to the string. The serialport class defaults to ASCII encoding so hopefully will convert the string correctly.
csharp
//Now send the contents of the message serialPort1.Write("Test message from coded program\u001F");
You could instead create a string with just the ^Z in it and concatenate the strings:
csharp
string controlZ = "\u001F";
//Now send the contents of the message serialPort1.Write("Test message from coded program" + controlZ);
HTH,
Jeff
This post has been edited by n8wxs: 11 Aug, 2008 - 08:12 PM
Thanks for the help. I didn't know about the \u001F.
but my code still doesn't work
csharp
if(!serialPort1.IsOpen) { serialPort1.Open(); }
//set the modem to text mode serialPort1.Write("at+cmgf=1\r\n"); //Now enter message writing mode to send an sms to the number below serialPort1.Write("at+cmgs=\"**PhoneNumber**\"\r\n"); //Now send the contents of the message serialPort1.Write("Test message from coded program\u001F");
when i write that directly in heyperterminal, the sms is sent, but when i use the above C# code, it doesn't. also, i tried to read the return from serial port, but it doesn't return anything char[] RecievedBytes = new char[1]; serialPort1.Read(RecievedBytes, 0, 1);
here is a screenshot of my SerialPort1 properties:
and here is a screenshot of the hyperterminal settings that work:
I also tried using SerialPort1.WriteLine() instead of sending \r\n but it didn't make any difference.
QUOTE(n8wxs @ 11 Aug, 2008 - 07:25 PM)
The String objects store Unicode characters so we need to add a Unicode ^Z to the string being written. To do this add a Unicode escape sequence character, in this case \u001F, to the string. The serialport class defaults to ASCII encoding so hopefully will convert the string correctly.
csharp
//Now send the contents of the message serialPort1.Write("Test message from coded program\u001F");
You could instead create a string with just the ^Z in it and concatenate the strings:
csharp
string controlZ = "\u001F";
//Now send the contents of the message serialPort1.Write("Test message from coded program" + controlZ);
I'm writing a very simple program which uses AT commands to send a SMS via a GSM modem on my com port. I've managed to successfully communicate with the modem through my program (thanks for the "serial Port Comms in c#" tutorial ) But one line is stumping me. When you issue the command to write a text in HyperTerminal you get a '>' prompt in which you type your message and then press 'ctrl-z' to return to the command prompt. How do I do this in my program? Any suggestions are much appreciated or anu pointers in the right direction will do nicely. Here is a bit of my code to help understanding.....maybe!!!
Thanks
csharp
private void button1_Click(object sender, EventArgs e) { //Firstly set the modem to text mode serialPort1.Write("at+cmgf=1\r\n"); //Now enter message writing mode to send an sms to the number below serialPort1.Write("at+cmgw=\"+447878xxxxxx\"\r\n"); //Now send the contents of the message serialPort1.Write("Test message from coded program"); At the end of this line I need ctrl-z //Now send the message stored at position 2 serialPort1.Write("at+cmss=2\r\n"); }
I read your description above to say the modem is prompting (>) for the text to send. It requires the ^Z to terminate the text entry mode.
Your modified button1_click() method, with the embedded ^Z, is probably working correctly. But, the modem is not ready to receive your text input because you are not waiting for its ">" prompt before transmitting the text string. The modem is interpreting the characters in the text as commands/data since it is still in command mode and has not completed the switch to text entry mode. Any illegal command will abort the setup you have already provided.
Using hyperterm, you are self-synchronizing because you are waiting for the ">" prompt.
You need to add receive methods and synchronize sending your text message with the modem.
I read your description above to say the modem is prompting (>) for the text to send. It requires the ^Z to terminate the text entry mode.
Your modified button1_click() method, with the embedded ^Z, is probably working correctly. But, the modem is not ready to receive your text input because you are not waiting for its ">" prompt before transmitting the text string. The modem is interpreting the characters in the text as commands/data since it is still in command mode and has not completed the switch to text entry mode. Any illegal command will abort the setup you have already provided.
Using hyperterm, you are self-synchronizing because you are waiting for the ">" prompt.
You need to add receive methods and synchronize sending your text message with the modem.
Jeff
Actually, i have a thread listening to the serial port all the time but it never received anything (it should receive OK or ERROR if the commands are correct. AT modems don't reply if the command is not recognized)
csharp
void SerialPortListen() { char[] RecievedChars = new char[1]; serialPort1.Read(RecievedChars, 0, 1); textBox1.Text += RecievedChars.ToString(); SerialPortThread = new Thread(threadst); }
I also tried inserting the above code right after the first SerialPort1.Write() call, but it waited forever for the read.
Actually, i have a thread listening to the serial port all the time but it never received anything
You need to fix this first.
I´m Brazilian and I´m not good in english. I´m writing my program using C++ Builder 6 to use AT commands to send a SMS via a GSM modem too. I can read the modem but I have the same problem when I try to send a message. The modem returns the ">" but I couldn't write and send the message yet. This is my program:
csharp
"//--------------------------------------------------------------------------- #include <vcl.h> #include <vcl\registry.hpp> //Para TRegistry. #include<mmsystem.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" #define LEN_BUFFER 100 //Tamanho do Buffer. //--------------------------------------------------------------------------- //Variáveis e objetos Globais //--------------------------------------------------------------------------- TForm1 *Form1; TMultLinha *MultLinha; //Variáveis da API HANDLE hCom; DCB dcb; COMMTIMEOUTS CommTimeouts; //--------------------------- bool GLBEnviaDados = false; //Para habilitar/desabilitar o envio de dados pela serial. String StrComandos; //Armazena a string de comando lida da Serial. String teste2; char teste[LEN_BUFFER]; char BufferRecebe[LEN_BUFFER]; //Buffer temporário para trabalhar direto com ReadFile(). char AuxProtocoloRX[LEN_BUFFER]="0000000000"; bool GLB_Conectado = false; //Indica se a porta já está aberta. //------------------------- AnsiString StrMens; int tama; String ProtocoloRX, ControleMsg; String Data, Hora, Origem, Destino, Mensagem, numero; bool ChegouMsg=false, x=false,Modem=false; int count=0,FSelPos; int i=0; bool a=true;
//-------------------------------------------------------------------------- //Declaração das funções bool LeDados(char* EntradaDados, unsigned int TamBuffer,unsigned long& TotalLidos); bool EscreveDados(char* outputData,const unsigned int sizeBuffer,unsigned long& length); bool AbrirPorta(char *NomePorta); void MostraNomesCom(void); //Mostra os nomes das portas "COM" instaladas no sistema num ComboBox. bool ConfiguraControle(void); bool ConfiguraTimeOuts(void); void AvisoSonoro(String); AnsiString __fastcall DataHora(void); //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ComboBoxPorta->ItemIndex = 0; //Seleciona a porta COM1. 1=COM2; 2=COM3; dcb.BaudRate = CBR_9600; //bps (Velocidade). dcb.ByteSize = 8; //8 Bits de dados. dcb.Parity = NOPARITY; //Sem paridade. dcb.StopBits = ONESTOPBIT; //1 stop bit. } //---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender) { memset( BufferRecebe, 0, LEN_BUFFER); //Limpa o buffer. MostraNomesCom(); //Mostra os nomes das portas "COM" num FilterComboBox. MultLinha = new TMultLinha(true); //Aloca memória para o objeto. MultLinha->Priority = tpHigher; //Define a prioridade. Memo3->Lines->LoadFromFile("Mensagem recebida.txt"); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { MultLinha->Terminate(); MultLinha = NULL; delete MultLinha; if( GLB_Conectado ) CloseHandle(hCom); Memo3->Lines->Add(""); Memo3->Lines->Add("Ultimo acesso ao arquivo: " + TDateTime::CurrentDateTime().DateString() + " as " + TDateTime::CurrentDateTime().TimeString()); Memo3->Lines->SaveToFile("Mensagem recebida.txt"); } //--------------------------------------------------------------------------- __fastcall TMultLinha::TMultLinha(bool CreateSuspended) : TThread(CreateSuspended) { } //-------------------------------------------------------------------------- //Mostra os nomes das portas "COM" instaladas no sistema num ComboBox. //-------------------------------------------------------------------------- void MostraNomesCom(void) { TRegistry *Registro = new TRegistry; //Cria e aloca espaço na memória para o objeto. TStringList *Lista = new TStringList; //Cria e aloca espaço na memória para o objeto.
Registro->RootKey = HKEY_LOCAL_MACHINE; //Define chave raiz. Registro->OpenKey("HARDWARE\\DEVICEMAP\\SERIALCOMM", false); //Abre a chave. //Obtém uma string contendo todos os nomes de valores associados com a chave atual. Registro->GetValueNames(Lista); //Count é a quantidade de portas existentes. for(int indice=0; indice <= Lista->Count-1; indice++) //Pega nos nomes das portas. Form1->ComboBoxPorta->Items->Add(Registro->ReadString( Lista->Strings[indice] ));
//Adciona os nomes das porta no ComboBox1. if (Form1->ComboBoxPorta->Items->Count > 0) Form1->ComboBoxPorta->ItemIndex = 0; //Exibir o primeino nome da porta. Lista->Free(); Registro->CloseKey(); Registro->Free(); //Libera memória alocada anteriormente pelo objeto Registro. } //--------------------------------------------------------------------------- void __fastcall TForm1::SpeedAbrirPortaClick(TObject *Sender) { bool Sucesso; if(AbrirPorta(ComboBoxPorta->Text.c_str()) == true) { GLB_Conectado = true; Sucesso = ConfiguraControle(); Sucesso = ConfiguraTimeOuts();
if(ControleMsg == "+CMT:") { //MessageBeep(0); AvisoSonoro("OK"); //ShowMessage(StrApresentacao + StrOrigem + Origem + StrData + Data + StrHora + Hora + StrMensagem); //WinExec("calc.exe", SW_SHOW); } } //-------------------------------------------------------------------------- //FUNÇÃO PRINCIPAL //-------------------------------------------------------------------------- void __fastcall TMultLinha::Execute() { unsigned int cont=0; DWORD BytesEscritos; //Para armazenar a quantidade de dados escritos. DWORD BytesLidos; //Para armazenar a quantidade de dados lidos.
FreeOnTerminate = true; //O objeto é destruído automaticamente quando a Thead terminar.
while(!Terminated) //loop infinito. Vida do programa. { if(GLB_Conectado == true) //Se está conectado. { if(ReadFile( hCom, BufferRecebe, LEN_BUFFER, &BytesLidos, NULL) != 0 ) { cont = 0; if(BytesLidos > 0) //Se algum caracter foi lido. { BufferRecebe[BytesLidos] = '\0'; //Finaliza string. StrComandos += BufferRecebe; //Vai guardando o que recebeu na variável StrComandos. Form1->Memo1->Lines->Add(StrComandos);