最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Why is my Persian SMS sending incorrect characters in PDU mode using UCS2 encoding? - Stack Overflow

programmeradmin1浏览0评论

I'm trying to send a Persian SMS to a recipient using a GSM modem and PDU mode with UCS2 encoding. The SMS message is in Persian text ("سلام"), and the recipient's number is 0777220XXX. However, the received message is showing incorrect characters like ㌆䐆✆ instead of the expected Persian text.

Here is the code I use for sending the SMS:

public void SendSms(string recipientNumber, string messageText)
{
    try
    {
        SerialPort port = new SerialPort();
        port.PortName = "COM9"; // Make sure this is correct
        port.BaudRate = 9600;
        port.Parity = Parity.None;
        port.DataBits = 8;
        port.StopBits = StopBits.One;
        port.Handshake = Handshake.None;
        port.ReadTimeout = 5000;
        port.WriteTimeout = 5000;

        port.Open();

        // Set to UCS2 character set
        port.WriteLine("AT+CSCS=\"UCS2\"\r");
        Thread.Sleep(1000);
        string response = port.ReadExisting();
        MessageBox.Show("Modem response UCS2: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        // Set SMS mode to PDU (0 = PDU mode)
        port.WriteLine("AT+CMGF=0\r");
        Thread.Sleep(1000);
        response = port.ReadExisting();
        MessageBox.Show("Modem response Text Mode: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        // Convert Persian message to PDU format
        string pduMessage = ConvertToPduFormat(recipientNumber, messageText);

        // Get PDU length (without SCA part)
        int pduLength = (pduMessage.Length / 2) - 1;

        // Send the PDU command
        port.WriteLine($"AT+CMGS={pduLength}\r");
        Thread.Sleep(1000);
        response = port.ReadExisting();
        MessageBox.Show("Modem response send pdu: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        // Send the actual PDU data
        port.Write(pduMessage + "\r");
        Thread.Sleep(1000);

        // Send Ctrl+Z (ASCII 26) to submit SMS
        port.Write(new byte[] { 26 }, 0, 1);
        Thread.Sleep(5000);

        // Read response
        response = port.ReadExisting();
        MessageBox.Show("Modem response send message: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        if (response.Contains("ERROR"))
        {
            MessageBox.Show("Send Failed!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            MessageBox.Show("Message Sent Successfully!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            SaveMessageToDatabase(recipientNumber, messageText);
        }

        port.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

public static string ConvertToPduFormat(string recipientNumber, string message)
{
    // Convert Persian text to UCS2 (UTF-16 Big Endian)
    byte[] ucs2Bytes = Encoding.BigEndianUnicode.GetBytes(message); // Use BigEndianUnicode for UCS2
    string hexMessage = BitConverter.ToString(ucs2Bytes).Replace("-", "");

    // Convert phone number to international format (remove leading 0)
    if (recipientNumber.StartsWith("0"))
    {
        recipientNumber = "+93" + recipientNumber.Substring(1); // Example for Afghanistan (+93)
    }

    // Convert phone number to semi-octet format
    string pduPhoneNumber = ConvertPhoneNumberToSemiOctets(recipientNumber);

    // PDU Header
    string pduHeader = "0001000B91" + pduPhoneNumber + "0008" + hexMessage;

    return pduHeader;
}

private static string ConvertPhoneNumberToSemiOctets(string phoneNumber)
{
    string semiOctets = "";
    if (phoneNumber.StartsWith("+"))
    {
        phoneNumber = phoneNumber.Substring(1);
    }

    for (int i = 0; i < phoneNumber.Length; i += 2)
    {
        if (i + 1 < phoneNumber.Length)
        {
            semiOctets += phoneNumber[i + 1].ToString() + phoneNumber[i].ToString();
        }
        else
        {
            semiOctets += "F" + phoneNumber[i].ToString(); // Add "F" padding if needed
        }
    }
    return semiOctets;
}

Problem: When I send the SMS message "سلام" to the number 077722XXX, the recipient receives it as ㌆䐆✆ instead of the correct Persian text.

I have set the character set to UCS2 using the command AT+CSCS="UCS2". I am converting the Persian message to UCS2 (UTF-16 Big Endian) format and then converting the phone number to semi-octet format. I am sending the message using the PDU mode with the AT+CMGF=0 command.

Question: Why is the SMS displaying incorrect characters when using UCS2 encoding, and how can I fix this issue to send Persian text correctly?

I'm trying to send a Persian SMS to a recipient using a GSM modem and PDU mode with UCS2 encoding. The SMS message is in Persian text ("سلام"), and the recipient's number is 0777220XXX. However, the received message is showing incorrect characters like ㌆䐆✆ instead of the expected Persian text.

Here is the code I use for sending the SMS:

public void SendSms(string recipientNumber, string messageText)
{
    try
    {
        SerialPort port = new SerialPort();
        port.PortName = "COM9"; // Make sure this is correct
        port.BaudRate = 9600;
        port.Parity = Parity.None;
        port.DataBits = 8;
        port.StopBits = StopBits.One;
        port.Handshake = Handshake.None;
        port.ReadTimeout = 5000;
        port.WriteTimeout = 5000;

        port.Open();

        // Set to UCS2 character set
        port.WriteLine("AT+CSCS=\"UCS2\"\r");
        Thread.Sleep(1000);
        string response = port.ReadExisting();
        MessageBox.Show("Modem response UCS2: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        // Set SMS mode to PDU (0 = PDU mode)
        port.WriteLine("AT+CMGF=0\r");
        Thread.Sleep(1000);
        response = port.ReadExisting();
        MessageBox.Show("Modem response Text Mode: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        // Convert Persian message to PDU format
        string pduMessage = ConvertToPduFormat(recipientNumber, messageText);

        // Get PDU length (without SCA part)
        int pduLength = (pduMessage.Length / 2) - 1;

        // Send the PDU command
        port.WriteLine($"AT+CMGS={pduLength}\r");
        Thread.Sleep(1000);
        response = port.ReadExisting();
        MessageBox.Show("Modem response send pdu: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        // Send the actual PDU data
        port.Write(pduMessage + "\r");
        Thread.Sleep(1000);

        // Send Ctrl+Z (ASCII 26) to submit SMS
        port.Write(new byte[] { 26 }, 0, 1);
        Thread.Sleep(5000);

        // Read response
        response = port.ReadExisting();
        MessageBox.Show("Modem response send message: " + response, "Response", MessageBoxButtons.OK, MessageBoxIcon.Information);

        if (response.Contains("ERROR"))
        {
            MessageBox.Show("Send Failed!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            MessageBox.Show("Message Sent Successfully!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
            SaveMessageToDatabase(recipientNumber, messageText);
        }

        port.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

public static string ConvertToPduFormat(string recipientNumber, string message)
{
    // Convert Persian text to UCS2 (UTF-16 Big Endian)
    byte[] ucs2Bytes = Encoding.BigEndianUnicode.GetBytes(message); // Use BigEndianUnicode for UCS2
    string hexMessage = BitConverter.ToString(ucs2Bytes).Replace("-", "");

    // Convert phone number to international format (remove leading 0)
    if (recipientNumber.StartsWith("0"))
    {
        recipientNumber = "+93" + recipientNumber.Substring(1); // Example for Afghanistan (+93)
    }

    // Convert phone number to semi-octet format
    string pduPhoneNumber = ConvertPhoneNumberToSemiOctets(recipientNumber);

    // PDU Header
    string pduHeader = "0001000B91" + pduPhoneNumber + "0008" + hexMessage;

    return pduHeader;
}

private static string ConvertPhoneNumberToSemiOctets(string phoneNumber)
{
    string semiOctets = "";
    if (phoneNumber.StartsWith("+"))
    {
        phoneNumber = phoneNumber.Substring(1);
    }

    for (int i = 0; i < phoneNumber.Length; i += 2)
    {
        if (i + 1 < phoneNumber.Length)
        {
            semiOctets += phoneNumber[i + 1].ToString() + phoneNumber[i].ToString();
        }
        else
        {
            semiOctets += "F" + phoneNumber[i].ToString(); // Add "F" padding if needed
        }
    }
    return semiOctets;
}

Problem: When I send the SMS message "سلام" to the number 077722XXX, the recipient receives it as ㌆䐆✆ instead of the correct Persian text.

I have set the character set to UCS2 using the command AT+CSCS="UCS2". I am converting the Persian message to UCS2 (UTF-16 Big Endian) format and then converting the phone number to semi-octet format. I am sending the message using the PDU mode with the AT+CMGF=0 command.

Question: Why is the SMS displaying incorrect characters when using UCS2 encoding, and how can I fix this issue to send Persian text correctly?

Share Improve this question edited Feb 8 at 9:54 Mohammad Samim Safi asked Feb 8 at 9:36 Mohammad Samim SafiMohammad Samim Safi 10810 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Solution for the sending persian text and also long persian text.

the code for setting to pdu and ucs2 mode

        // Set to UCS2 character set
            port.WriteLine("AT+CSCS=\"UCS2\"\r");
            Thread.Sleep(1000);
            string response = port.ReadExisting();

            // Set SMS mode to PDU
            port.WriteLine("AT+CMGF=0\r");
            Thread.Sleep(1000);
            response = port.ReadExisting();

Convert to PDU format (handling long messages)

List<string> pduMessages = ConvertToPduFormat(recipientNumber, messageText);

                foreach (string pduMessage in pduMessages)
                {
                    int pduLength = (pduMessage.Length / 2) - 1;

                    // Send the PDU command
                    port.WriteLine($"AT+CMGS={pduLength}\r");
                    Thread.Sleep(1000);
                    response = port.ReadExisting();

                    // Send the actual PDU data
                    port.Write(pduMessage + "\r");
                    Thread.Sleep(1000);

                    // Send Ctrl+Z (ASCII 26) to submit SMS
                    port.Write(new byte[] { 26 }, 0, 1);
                    Thread.Sleep(5000);

                    // Read response
                    response = port.ReadExisting();
                    if (response.Contains("ERROR"))
                    {
                        MessageBox.Show("Send Failed!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return false;
                    }
                }

with the below function we are converting the message into multiple part of pdu it accepts persian text and also long message in persian text

 // Convert Persian message into multiple PDUs with UDH
    public static List<string> ConvertToPduFormat(string recipientNumber, string message)
    {
        List<string> pduMessages = new List<string>();

        // Convert Persian text to UCS2
        byte[] ucs2Bytes = Encoding.BigEndianUnicode.GetBytes(message);
        string hexMessage = BitConverter.ToString(ucs2Bytes).Replace("-", "");

        // Split message into chunks of 268 characters (134 UCS2 chars = 153 bytes per SMS)
        int maxPartLength = 268;
        List<string> messageParts = new List<string>();
        for (int i = 0; i < hexMessage.Length; i += maxPartLength)
        {
            messageParts.Add(hexMessage.Substring(i, Math.Min(maxPartLength, hexMessage.Length - i)));
        }

        // Convert phone number to semi-octets
        if (recipientNumber.StartsWith("0"))
        {
            recipientNumber = "+93" + recipientNumber.Substring(1);
        }
        string pduPhoneNumber = ConvertPhoneNumberToSemiOctets(recipientNumber);
        int phoneNumberLength = recipientNumber.Length - 1;

        // SMSC, protocol, and validity settings
        string smsc = "00";
        string firstOctet = "51"; // SMS-SUBMIT with UDH
        string messageRef = "00";
        string addressLength = phoneNumberLength.ToString("X2");
        string protocolId = "00";
        string dcs = "08"; // UCS2
        string validityPeriod = "AA";

        // Concatenation reference (random number for message linking)
        Random rand = new Random();
        string concatRef = rand.Next(0x00, 0xFF).ToString("X2");

        for (int i = 0; i < messageParts.Count; i++)
        {
            string messageSegment = messageParts[i];
            int messageLength = messageSegment.Length / 2;

            // User Data Header (UDH) for multipart messages
            string udh = "050003" + concatRef + messageParts.Count.ToString("X2") + (i + 1).ToString("X2");

            // Final PDU format
            string pduMessage = smsc + firstOctet + messageRef + addressLength + "91" + pduPhoneNumber +
                                protocolId + dcs + validityPeriod + (udh.Length / 2 + messageLength).ToString("X2") + udh + messageSegment;

            pduMessages.Add(pduMessage);
        }

        return pduMessages;
    }

and now we converting phone number to the semi octet format for pdu removing the + from numbers

// Convert phone number to semi-octet format
    private static string ConvertPhoneNumberToSemiOctets(string phoneNumber)
    {
        string semiOctets = "";
        if (phoneNumber.StartsWith("+"))
        {
            phoneNumber = phoneNumber.Substring(1);
        }

        for (int i = 0; i < phoneNumber.Length; i += 2)
        {
            if (i + 1 < phoneNumber.Length)
            {
                semiOctets += phoneNumber[i + 1].ToString() + phoneNumber[i].ToString();
            }
            else
            {
                semiOctets += "F" + phoneNumber[i].ToString();
            }
        }
        return semiOctets;
    }

finally when i pass number and long persian text it first converted to pdu and into multiparts for sending long message then the number will be converdet into sem octet format after that the system will send your message and destination number

the expected result will be

like this

سلام علیکم ګرانه وروره ستاسی کالي په ښه ډول تیار شوي دي، کله چی تاسو ته مناسب وی، راشۍ جوړه مو تر لاسه کړی مننه.

发布评论

评论列表(0)

  1. 暂无评论