send English SMS with GSM Modems (D-Link DWM-156) - c#

I am developing an application for GSM Modems (D-Link DWM-156) in C#.Net using AT commands. I have a problem sending English SMS.
I try to send "hello", But I receive □□□□ in my phone or ...exept hello.
serialPort1.DataBits = 8;
serialPort1.Parity = Parity.None;
serialPort1.StopBits = StopBits.One;
serialPort1.BaudRate = 9600;
serialPort1.DtrEnable = true;
serialPort1.RtsEnable = true;
serialPort1.DiscardInBuffer();
serialPort1.DiscardOutBuffer();
serialPort1.WriteLine("AT\r");
Thread.Sleep(2000);
serialPort1.WriteLine("AT+CMGF=1\r");
Thread.Sleep(1000);
serialPort1.WriteLine("AT+CMGS=\"09390149196\"\r")
Thread.Sleep(2000);
serialPort1.WriteLine("hello" + "\x1A");
Thread.Sleep(1000);

Few fixes (maybe more but I don't see full-code).
Do not use WriteLine() but Write() because for \r (alone) is the command line and result code terminator character.
SerialPort.WriteLine() by default writes a usASCII encoded string but your GSM modem expect strings encoded as specified with an AT command. Set SerialPort.Encoding property to a specific encoding and send CSCS command. You can ask supported encodings with CSCS=? AT command. Even if default GSM should apply I'd avoid to rely implicitly on this.
You do not need to wait after each command but you have to wait for modem answer (checking for OK or ERROR strings).
From docs:
A command line is made up of three elements: the prefix, the body, and the termination character. The command line prefix consists of the characters "AT" or "at" [...] The termination character may be selected by a user option (parameter S3), the default being CR.
In pseudo-code:
void SendCommand(string command) {
serialPort.Write(command + "\r");
// Do not put here an arbitrary wait, check modem's response
// Reading from serial port (use timeout).
CheckResponse();
}
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
serialPort.BaudRate = 9600;
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
serialPort.Encoding = Encoding.GetEncoding("iso-8859-1");
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
SendCommand("AT"); // "Ping"
SendCommand("AT+CMGF=1"); // Message format
SendCommand("AT+CSCS=\"PCCP437\""); // Character set
SendCommand("AT+CMGS=\"123456\"") // Phone number
SendCommand("hello" + "\x1A"); // Message
To check response (absolutely avoid arbitrary waits!) you can start with something like this (raw untested adaption so you may need some debugging, see also this post):
AutoResetEvent _receive;
string ReadResponse(int timeout)
{
string response = string.Empty;
while (true)
{
if (_receive.WaitOne(timeout, false))
{
response += _port.ReadExisting();
}
else
{
if (response.Length > 0)
throw new InvalidOperationException("Incomplete response.");
else
throw new InvalidOperationException("No response.");
}
// Pretty raw implementation, I'm not even sure it covers
// all cases, a better parsing would be appreciated here.
// Also note I am assuming verbose V1 output with both \r and \n.
if (response.EndsWith("\r\nOK\r\n"))
break;
if (response.EndsWith("\r\n> "))
break;
if (response.EndsWith("\r\nERROR\r\n"))
break;
}
return response;
}
Adding _receive.Reset() just before you send your command and of course also adding OnPortDataReceived as handler for SerialPort.DataReceived event:
void OnPortDataReceived(object sender,
SerialDataReceivedEventArgs e)
{
if (e.EventType == SerialData.Chars)
_receive.Set();
}
If you have some trouble (but you can connect) you may replace \r with \n. Some modems incorrectly (assuming <CR> has not been mapped to anything else than 13 using S3 parameter) use this character as command line terminator by default (even if it should be present in output only for V1 verbose output). Either change your code or send appropriate S3.

Related

Serial Port Request-Response communication using c#

I want to do serial port communication with a machine which uses RS232-USB ports.
I am using serial port class. I am very new to the concept. In my first Machine interfacing I only had to do the serialport.readLine( to get the readings from the machine and there was no need to send ACK /NAK). but for the new machine interface the document says following things:
The following is an example of the RA500 communication:
Computer :<05h 31h 0dh>
RA500 :1st line of information
Computer :<06h 0dh>
RA500 :2nd line of information
Computer :<06h 0dh>
RA500 :”EOF”<0dh>
What i understood from this is i have to write to comport before reading from it. this is what i am doing in my code:
ACK = "06 0d"; NAK = "15 0d"; str = "05 31 0d";
while (count <= 5)
{
rx = ComPortDataReceived(str);
if (!string.IsNullOrEmpty(rx))
{
str = ACK;
returnReading += rx;
}
else if (string.IsNullOrEmpty(rx)) str = NAK;
count++;
}
private string ComPortDataReceived(string str)
{
string Rx = string.Empty;
string exceptionMessage = string.Empty;
try
{
byte[] bytes = str.Split(' ').Select(s => Convert.ToByte(s, 16)).ToArray();
comPort.Write(bytes, 0, bytes.Length);
Rx = comPort.ReadExisting();
PEHRsLibrary.writeTextFile(DateTime.Now + " RxString :" + Rx);
return Rx;
}
catch(Exception e){}
when i use this code i am receiving empty strings as responce. but if i use comPort.ReadExisting() only without using comPort.Write i am receving a string with all the readings but the probblem is it only gives one line of information and dosnt give 2nd or 3rd line readings.
when i try using comPort.ReadLine() after Write() I am getting Timeout exception.
i dont know what i am doing wrong in this case. I am writing ACk after receving 1st line but not receving 2nd line. Next thing i am gonna try is read() as byte and then convert it to string instead of using ReadExisting(). Any other way i can do this?

Serial.WriteLine("My message!"); Appending?

I am trying to send a message from a C# application to my arduino on the serial port.
However it hangs on the WriteLine. It never ends and when I read whats been stored in my buffer on the arduino it's like ive been sending it over and over 100 times.
Code on c# app
public void testSend()
{
if (mySerialPort.IsOpen)
{
//setup
//mySerialPort.Open();
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.WriteTimeout = 500;
try
{
mySerialPort.WriteLine("Sent from my c# app!");
}
catch(TimeoutException)
{
//Console.WriteLine("Timeout while sending data");
}
//mySerialPort.Close();
}
else
{
Console.WriteLine("Port already open!");
}
}
Code on arduino(for reference and clearance )
void setup()
{
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect. Needed for native USB
}
}
char* buf = malloc(1024);
int ReciveData()
{
if (Serial.available())
{
// read the incoming bytes:
String temp = Serial.readString();
if (temp.length() > 0)
{
temp.toCharArray(buf, temp.length() + 1);
}
}
}
void loop()
{
Serial.print("Sent from arduino!");
Serial.println(buf);
delay(1000);
ReciveData();
}
}
This is how it looks. Here is 4 messages, every send start with "Sent from arduino!". when i read it. You can see on line 1 and 2 everything is good but when I start the c# application and it goes Hawaii
Sent from arduino!Sent from serial terminal!
Sent from arduino!Sent from serial terminal!
Sent from arduino!Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from arduino!Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Not sure why. But when i tried to add \0 at end of the string it worked.
try
{
mySerialPort.WriteLine("Sent from my c# app! \0");
}
In c \0 is the string terminator character. Without it the read won't know the characher array has ended.
The mySerialPort.WriteLine method would send the string you specified + the mySerialPort.NewLine value, which in your case is the default value - System.Environment.NewLine (which is "\r\n").
Before the usage of WriteLine (and also ReadLine) - specify the protocol EOL character, in your case:
mySerialPort.NewLine = "\0"
And there will be no need to add manually the EOL character on each writing (and to miss the purpose of WriteLine over just Write)

Sending data through RS232 using C# [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have a device that can communicate trough RS232. and it comes with the communication protocol to access the data.
I'm writing a simple c# program to connect and get the status from the device and Im not quite sure whether Im on the right path.
Below is the sample they have given.
Command 50: status request
The status request command is used to request the register response package, without later actions that may alter the status of the system.
0 1 2 3 4 5 6 7 8 9 10 11 12 13
STX ADDR ADDR CMOD "5" "0" "0" "3" TKN1 TKN0 TYPE CHKL CHKH 0X0D
STX = Start byte of the frame (0x02)
ADDR = TE550 logical address [2 bytes]

CMOD = CMOD to refer [1 byte]
TKN1/0 = Frame identification bytes [2 bytes]

TYPE = Selection byte for customizable box (RiqA/B)* [1 byte]
CHKH/L = Checksum [2 bytes]
END = End byte of the frame (0x0D)
Example:
status request from PC to TE550 (address 01), CMOD 1, Token 01, Type 1
[0x02]0115003011EE[0x0D]
I can connect to the com port using the serial port.
I am referring to the answer by DesMy "RS232 serial port communication c# win7 .net framework 3.5 sp1"
So far Im not getting any signal once write to the COM port. However I'm not quite sure whether Im sending the correct data to the com port. Currently Im sending data as below
comPort.Write("20115003011EE3");
Any help / sample code etc would be much appreciated.
public void ConnectRS232 ()
{
try
{
SerialPort mySerialPort = new SerialPort("COM1");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.ReadTimeout = 2000;
mySerialPort.WriteTimeout = 500;
mySerialPort.DtrEnable = true;
mySerialPort.RtsEnable = true;
mySerialPort.Open();
mySerialPort.DataReceived += DataReceivedHandler;
mySerialPort.Write("20115003011EE3");
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
}
public void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
System.Threading.Thread.Sleep(500);
string indata = sp.ReadExisting();
this.BeginInvoke(new SetTextDeleg(DisplayToUI), new object[] { indata });
}
private void DisplayToUI(string displayData)
{
textBox1.Text += displayData.Trim();
}
When dealing with low level port I/O, characters are not bytes!
Do not send strings. Create a byte stream containing the correct characters and send that.
[In .NET characters are shorts, not bytes. Doesn't matter. Use bytes.]

C# SSHStream implementations give strange outputs

When creating a c# program that uses SSH implementations, I'm able to connect, receive data/execute commands and disconnect (using SSH.net (http://sshnet.codeplex.com) and SharpSSH (http://sourceforge.net/projects/sharpssh/)). In both implementations the output is rather strange. Instead of giving the same output as when I connect using for example PuTTY, these kind of messages apear:
For the command "ls":
ls
file1.jpg <-[0m<-[01;32mdirectory<[0m
<-[01;32mdirectory2m#ssh2.c1
<-[01;34~ $
How can I fix this? Is it an encoding issue or should I use a RegEX?
The code I'm using (SharpSSH)
SshShell ssh = new SshShell("host", "username", "password");
//This statement must be prior to connecting
ssh.RedirectToConsole();
Console.Write("Connecting...");
ssh.Connect();
Console.WriteLine("OK");
Console.Write("Enter a pattern to expect in response [e.g. '#', '$', C:\\\\.*>, etc...]: ");
string pattern = Console.ReadLine();
ssh.ExpectPattern = pattern;
ssh.RemoveTerminalEmulationCharacters = true;
Console.WriteLine();
Console.WriteLine(ssh.Expect(pattern));
while (ssh.ShellOpened)
{
Console.WriteLine();
Console.Write("Enter some data to write ['Enter' to cancel]: ");
string data = Console.ReadLine();
if (data == "") break;
ssh.WriteLine(data);
ssh.RemoveTerminalEmulationCharacters = true;
string output = ssh.Expect(pattern);
Console.WriteLine(output);
}
Console.Write("Disconnecting...");
ssh.Close();
Console.WriteLine("OK");

converting vb code to c#

im using mobitek gsm modem and the source code it used is in VB. now i want to convert the code into c#. the code that i have trouble with is intModemStatus = SMS.ModemInit(frmModem.txtPort.Text, ""). after that, the code will go through with select case as below:
intModemStatus = SMS.ModemInit(frmModem.txtPort.Text, "")
Select Case intModemStatus
Case 0
FrmModem.txtText.Text = "GSM Modem Not Connected!"
'[VB - Module1] frmModem.txtText = "GSM Modem Not Connected!"
Exit Sub
Case 1
FrmModem.txtText.Text = "CONNECTED!"
'[VB - Module1] frmModem.txtText = "GSM Modem Connected!"
Exit Sub
Case 2
FrmModem.txtText.Text = "PIN Required!"
'[VB - Module1] frmModem.txtText = "PIN Required!"
Exit Sub
Case 3
FrmModem.txtText.Text = "Incorrect PIN Entered! Warning after 3 tries of incorrect PIN entered, your SIM card will be blocked by TELCO!"
'[VB - Module1] frmModem.txtText = "Incorrect PIN entered! Warning: after 3 tries of incorrect PIN entered, your SIM card will be blocked by TELCO!"
Exit Sub
Case 4
FrmModem.txtText.Text = "Your SIM card is blocked by TELCO!"
'[VB - Module1] frmModem.txtText = "Your SIM card is blocked by TELCO!"
Exit Sub
Case 5
FrmModem.txtText.Text = "Your SIM card has problem!"
'[VB - Module1] frmModem.txtText = "Your SIM card has problem!"
Exit Sub
Case Else
FrmModem.txtText.Text = "GSM Modem Not Connected!"
'[VB - Module1] frmModem.txtText = "GSM Modem Not Connected!"
Exit Sub
End Select
i have converted everything into c# includes with the switch case like this:
int ModemStatus = sms.ModemInit(txtPort.Text, "");
switch (intModemStatus)
{
case 0:
txtText.Text = "GSM Modem Not Connected!";
//[VB - Module1] frmModem.txtText = "GSM Modem Not Connected!"
return;
break;
case 1:
txtText.Text = "CONNECTED!";
//[VB - Module1] frmModem.txtText = "GSM Modem Connected!"
return;
break;
case 2:
txtText.Text = "PIN Required!";
//[VB - Module1] frmModem.txtText = "PIN Required!"
return;
break;
case 3:
txtText.Text = "Incorrect PIN Entered! Warning after 3 tries of incorrect PIN entered, your SIM card will be blocked by TELCO!";
//[VB - Module1] frmModem.txtText = "Incorrect PIN entered! Warning: after 3 tries of incorrect PIN entered, your SIM card will be blocked by TELCO!"
return;
break;
case 4:
txtText.Text = "Your SIM card is blocked by TELCO!";
//[VB - Module1] frmModem.txtText = "Your SIM card is blocked by TELCO!"
return;
break;
case 5:
txtText.Text = "Your SIM card has problem!";
//[VB - Module1] frmModem.txtText = "Your SIM card has problem!"
return;
break;
default:
txtText.Text = "GSM Modem Not Connected!";
//[VB - Module1] frmModem.txtText = "GSM Modem Not Connected!"
return;
break;
}
however, i am having trouble with this code int ModemStatus = sms.ModemInit(txtPort.Text, "");. it said that
Argument 1cannot convert string to short.
the best overloaded method match for mobitekSMSAPI5.ModemInit(short, string) have some invalid argument.
then i tried to change int ModemStatus = sms.ModemInit(txtPort.Text, ""); but it says the same.
to use the mobitek gsm modem, i required to add reference of MobitekSMSAPI5 and i did. the switch code will determine if the modem have been connected or else.
i am really hoping for someone to step up solving this problem. im stuck in the middle and i did not know where to start. any kinds of helps are appreciated. thank you.
here is my error:
when im using this code it appears:
short port;
if (!short.TryParse(txtPort.Text, out port))
{
throw new Exception("Failed to parse port");
// or any other handling - depends on your needs
}
int ModemStatus = sms.ModemInit(port, "");
now it appears different error when im changing the code like below.
sms.ModemInit accepts short as a first parameter. As long as your were dealing with VB.Net, conversion of string into short was done implicitly. It was possible due to compiler's Option Strict option, which is disabled by default. When enabled this option allows only implicit widening conversions. When disabled (default state) this option allows both implicit narrowing and widening conversions.
In C# however narrowing implicit conversions are forbidden, and this is why your translated code fails. So you need to parse your string value explicitly and pass a parsed number to the method:
short port = short.Parse(txtPort.Text);
int ModemStatus = sms.ModemInit(port, "");
or, even better, use TryParse to avoid possible exceptions:
short port;
if (!short.TryParse(txtPort.Text, out port))
{
throw new Exception("Failed to parse port");
// or any other handling - depends on your needs
}
int ModemStatus = sms.ModemInit(port, "");
Your problem is just a couple of casting issues. The first one is related to the port number, the ModemInit method expects a short value but your passing a string, so you have already fixed that by using short.TryParse.
The other issue is your return type, the ModemInit method seems to return it's own custom enum value, if all your interested in is the integer value then all you need to do is cast it as an int.
int ModemStatus = (int)sms.ModemInit(port, "");
I would do this:
short shortValue = 0;
if (short.TryParse(txtPort.Text, out shortValue))
{
... continue using shortValue
}
else
{
...Tell user the value must be a number
}
This way you handle the condition of an user entering a non-number (without resorting to exceptions)
As the error clearly states, you can't pass a string as a short.
You need to call short.Parse().

Categories