9

I am developing an application for GSM Modems (D-Link DWM-156) in C#.Net using AT commands. I have a problem sending Unicode messages (Such as messages written in Persian or Arabic). Here it is the core of my program:

SerialPort GSMPort = new SerialPort();

GSMPort.PortName = "COM6";
GSMPort.BaudRate = 9600;
GSMPort.Parity = Parity.None;
GSMPort.DataBits = 8;
GSMPort.StopBits = StopBits.One;
GSMPort.Handshake = HandShake.RequestToSend;
GSMPort.DtrEnable = true;
GSMPort.RtsEnable = true;

GSMPort.Open();

GSMPort.Write("AT\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGF=1\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGS=\"" + destinationNumber + "\"\r\n");
Thread.Sleep(1000);
GSMPort.Write(shortMessage+ "\x1A");

It works fine for English and ASCII letters. I have read this article and can send Unicode messages in Hyperterminal using AT commands:

AT [Enter]
OK
AT+CSCS="UCS2" or AT+CSCS="HEX" [Enter] ---> We have to convert our message to hex 
OK
AT+CMGF=1 [Enter]
OK
AT+CMGS="destinationNumber" [Enter]
> 0633064406270645002006450631062D06280627 ---> The hex format of our message (سلام مرحبا)
+CMGS: 139
OK

Since this commands worked correctly, I have added GSMPort.Write("AT+CSCS=\"UCS2\"\r"); to my application, and tried to send 0645 0631 062D 0628 0627 (مرحبا) or 0633 0644 0627 0645 (سلام).

GSMPort.Write("AT\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CSCS=\"UCS2\"\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGF=1\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGS=\"" + destinationNumber + "\"\r\n");
Thread.Sleep(1000);
GSMPort.Write("0633064406270645" + "\x1A");

But unlike AT commands in Hyperterminal, destination does not receive correct letters. What is the difference between these AT commands in C# code and Hyperterminal code? I will appreciate if you help me to resolve this problem.


Additional information: As you know I have no problem for sending Unicode messages (such as Persian letters) by hyperterminal and using AT commands. In below code I try to send سلام, and "0633064406270645" is the hexadecimal form of it. But I receive □□□□ in my phone.

GSMPort.Encoding = UnicodeEncoding.GetEncoding(1256);
GSMPort.Write("AT\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CSCS=\"UCS2\"\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGF=1\r");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGS=\"" + destinationNumber + "\"\r\n");
Thread.Sleep(1000);
GSMPort.Write("0633064406270645" + "\x1A");

In the hyperterminal environment, On the other hand, everything goes fine and I receive سلام.

AT [Enter]
OK
AT+CSCS="UCS2"
OK
AT+CMGF=1 [Enter]
OK
AT+CMGS="destinationNumber" [Enter]
> 0633064406270645 [Ctrl+Z]
+CMGS: 139
OK

I have noticed that in the hyperterminal properties if I check the "send line ends with line feeds" (it is in properties->Settings-> ASCII Setups, please check the picture below), I will have the same problem as I had in C# code. I think "send line ends with line feeds" is enabled in GSMPort.Write by default? If yes, how can I disable it?

enter image description here

Yasser Mohseni
  • 453
  • 2
  • 7
  • 17
  • 1
    on your AT+CMGS command you a writeline as wel as a \r\n. In the AT script I only see a \r. – rene Mar 09 '13 at 15:03
  • Yes that is right, WriteLine produces extra lines ([Enter]) in message. – Yasser Mohseni Mar 09 '13 at 15:29
  • check whether your modem supports unicode!! – saeed Mar 09 '13 at 15:31
  • 1
    Yes it does support Unicode. I already mentioned in my question that I can send Unicode messages using AT commands in Hyperterminal environment. In addition, the result of **AT+CSCS=?** is **+CSCS: ("IRA", "GSM", "HEX", "PCCP437", "8859-1", "UCS2", "UCS2_0X81")**. It means that this modem supports Hex ("HEX") and Unicode ("UCS2"). Please read [this article](http://www.smssolutions.net/tutorials/gsm/sendsmsat/). – Yasser Mohseni Mar 09 '13 at 15:40
  • 2
    Add this line before you start sending to see in your debug window what your modem is telling you : `GSMPort.DataReceived += (s, e) => { Debug.WriteLine( GSMPort.ReadLine()); }; ` – rene Mar 09 '13 at 15:43
  • @rene I will try it and let you know about its results. – Yasser Mohseni Mar 09 '13 at 16:11
  • Dear All, I have added some additional information to my question, I will appreciate it if you check them as well. – Yasser Mohseni Mar 16 '13 at 14:42
  • Please see also http://stackoverflow.com/a/25155746/638977 (Convert to UCS2) – Behzad Ebrahimi Aug 06 '14 at 14:16

3 Answers3

10

I have finally found out how to resolve this problem. As I said in in the "Additional Information" section of my question, sending line ends with line feeds caused this mismatching between SerialPort in C# and AT commands in hyperterminal for sending Unicode messages. I have just replaced \r with \n line feeds. The modified code is as follow:

GSMPort.Write("AT\n");
Thread.Sleep(1000);
GSMPort.Write("AT+CSCS=\"UCS2\"\n");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGF=1\n");
Thread.Sleep(1000);
GSMPort.Write("AT+CMGS=\"" + destinationNumber + "\"\n");
Thread.Sleep(1000);
GSMPort.Write("0633064406270645" + "\x1A"); 

Leave SerialPort.Encoding and SerialPort.NewLine properties unchanged. It is not necessary to change their default values, just set AT+CSCS="UCS2" to send messages in Unicode format.

ahmad molaie
  • 1,512
  • 2
  • 21
  • 41
Yasser Mohseni
  • 453
  • 2
  • 7
  • 17
  • It helped me so I marked it as useful but I have still a question : Do you convert all messages to HEX including ASCII or UNICODE? I appreciate if u could let me know what did you do finally. – Masoud Sep 08 '13 at 07:58
  • @Masoud I tyied to send arabic sms using the code above but I got "esponse received is incomplete" Can you help me – Abdulsalam Elsharif Jan 13 '18 at 15:38
4

First of all check your modem support unicode then change your code to this
we have to specify the correct DCS (Data Coding Scheme) for Unicode messages, which is 0x08.

We can set this value by changing the fourth parameter of the AT+CSMP command to '8':

AT+CSMP=1,167,0,8

    GSMPort.Write("AT\r");
    Thread.Sleep(1000);
    GSMPort.Write("AT+CSCS=\"UCS2\"\r");
    Thread.Sleep(1000);
    GSMPort.Write("AT+CMGF=1\r");
    Thread.Sleep(1000);
    GSMPort.Write("AT+CSMP=1,167,0,8\r"); //AT+CSMP=1,167,0,8
    Thread.Sleep(1000);
    GSMPort.WriteLine("AT+CMGS=\"" + destinationNumber + "\"\r\n");
    Thread.Sleep(1000);
    GSMPort.WriteLine("0633064406270645" + "\x1A");
saeed
  • 2,477
  • 2
  • 23
  • 40
  • I can send Unicode messages using AT commands in Hyperterminal environment, So yes I am sure that modem supports Unicode. Thanks for your solution, I have tried `GSMPort.Write("AT+CSMP=1,167,0,8\r");` but it does not change anything. Using `AT+CSMP?` this structure in hyperterminal is `+AT+CSMP=1,71,0,0` but it doesn't work neither. I also tried `AT+CSMP=1,71,0,8`. – Yasser Mohseni Mar 09 '13 at 16:09
  • does it works fine when you send sms by hyperterminal commands if so what is your command queue – saeed Mar 09 '13 at 16:14
  • Please check my question. I describe what sequence of AT commands I used in hyperterminal. If you need further information about my modem and its status please let me know. – Yasser Mohseni Mar 09 '13 at 16:21
  • Thanks, in my case, the `AT+CSMP=1,167,0,8` & `AT+CSCS="UCS2"` part was most important, then getting the encoding right, i.e. sending the message as what I would describe as AT HEX UCS2/UTF-16, i.e. encoding the string to UTF-16BE, then taking each byte and formatting it as ASCII HEX characters, i.e. which is U+1F408 becomes "D83D DC08" that is sent to the modem. – drott Oct 19 '20 at 08:47
2

The default encoding for SerialPort is Encoding.ASCII. Either set SerialPort.Encoding to an encoding to supports the character set you're using (like Encoding.UTF32) or use SerialPort.Write(char[], int, int) and convert your Unicode string to bytes in whatever way'd prefer.

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
  • Thanks for your answer. I have changed the encoding of GSMPort.Encoding to Encoding.UTF8, Encoding.Unicode, and Encoding.UTF32. But none of these changes was successful. The problem still exists: GSMPort.Write("AT+CSCS=\"UCS2\"\r"); GSMPort.Encoding = Encoding.Unicode; – Yasser Mohseni Mar 09 '13 at 15:23
  • Be sure to set `Encoding` *before* you call `Write` – Peter Ritchie Mar 09 '13 at 15:35
  • Yes I had called `GSMPort.Encoding` in advance before all `Write`s, but it still does not work. – Yasser Mohseni Mar 09 '13 at 15:46