问题
I use HUAWEI USB stick modem and code below to send SMS successfully but under 140 of length (see the code pls -- double lenMes = textsms.Length / 2;
).
But nowdays I see the really big SMS messages.
So I am wondering what's wrong with AT commnds or may me hardware is old so I cannot send big SMS.
Please any clue?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
namespace sendSMSPDU
{
class Program
{
static SerialPort port;
static void Main(string[] args)
{
port = new SerialPort();
Console.WriteLine("Sending SMS");
OpenPort();
bool result;
result = sendSMS("Some text that less 140 is gonna sending OK", " +75434355544");
if (result == true)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("ERROR");
}
Console.ReadLine();
port.Close();
}
private static bool sendSMS(string textsms, string telnumber)
{
if (!port.IsOpen) return false;
try
{
System.Threading.Thread.Sleep(500);
port.WriteLine("AT\r\n");
System.Threading.Thread.Sleep(500);
port.Write("AT+CMGF=0\r\n");
System.Threading.Thread.Sleep(500);
}
catch
{
return false;
}
try
{
telnumber = telnumber.Replace("-", "").Replace(" ", "").Replace("+", "");
telnumber = "01" + "00" + telnumber.Length.ToString("X2") + "91" + EncodePhoneNumber(telnumber);
textsms = StringToUCS2(textsms);
string leninByte = (textsms.Length / 2).ToString("X2");
textsms = telnumber + "00" + "08" + leninByte + textsms;
double lenMes = textsms.Length / 2;
if (lenMes < 140) // It sends OK
{
port.Write("AT+CMGS=" + (Math.Ceiling(lenMes)).ToString() + "\r\n");
System.Threading.Thread.Sleep(500);
textsms = "00" + textsms;
port.Write(textsms + char.ConvertFromUtf32(26) + "\r\n");
System.Threading.Thread.Sleep(500);
}
else
{
return false;
}
}
catch
{
return false;
}
try
{
string recievedData;
recievedData = port.ReadExisting();
if (recievedData.Contains("ERROR"))
{
return false;
}
}
catch { }
return true;
}
private static void OpenPort()
{
port.BaudRate = 9600;
port.DataBits = 7;
port.StopBits = StopBits.One;
port.Parity = Parity.Odd;
port.ReadTimeout = 500;
port.WriteTimeout = 500;
//port.Handshake = Handshake.RequestToSend;
//port.DtrEnable = true;
//port.RtsEnable = true;
//port.NewLine = Environment.NewLine;
port.Encoding = Encoding.GetEncoding("windows-1252");
port.PortName = "COM7";
if (port.IsOpen)
port.Close();
try
{
port.Open();
}
catch { }
}
public static string EncodePhoneNumber(string PhoneNumber)
{
string result = "";
if ((PhoneNumber.Length % 2) > 0) PhoneNumber += "F";
int i = 0;
while (i < PhoneNumber.Length)
{
result += PhoneNumber[i + 1].ToString() + PhoneNumber[i].ToString();
i += 2;
}
return result.Trim();
}
public static string StringToUCS2(string str)
{
UnicodeEncoding ue = new UnicodeEncoding();
byte[] ucs2 = ue.GetBytes(str);
int i = 0;
while (i < ucs2.Length)
{
byte b = ucs2[i + 1];
ucs2[i + 1] = ucs2[i];
ucs2[i] = b;
i += 2;
}
return BitConverter.ToString(ucs2).Replace("-", "");
}
}
}
回答1:
Single SMS message is limited to 160 (or 152 in PDU mode) symbols in GSM-7
encoding. More than that, if there is any symbol not listed here you need to use UCS-2
encoding and your messages now limit to 67 symbols. If you need to send longer messages, you are welcome to the "bright and shiny world" of SMS PDU mode.
So sending a long sms is as easy as:
- Split it to parts of 67 (or 152) symbols;
- Convert this parts to
UCS-2
orGSM-7
encoding; - Transform them to
PDU
messages; - Send them sequentially with use of additional AT-command (
AT+CMGF=0
)
Edit
The one who designed a PDU format is a true evil person. It is really mind breaking thing and I don't want to write a convertion code, sorry. But, I can point you with this stub:
protected void SendMessage(string phoneNumber, string message)
{
const char CR = '\r'; // "Carage Return"
const char CtrlZ = (char)26; // Ctrl+Z character
var header = GeneratePDUHeader(phoneNumber);
foreach (var messagePart in SplitSMSMessage(message))
{
SendToCOM("AT+CMGF=0" + CR);
SendToCOM("AT+CMGS=42" + CR);
SendToCOM($"{header}{messagePart}" + CtrlZ);
}
}
// should return something like "0041000B910000000000F000088C"
protected string GeneratePDUHeader(string phoneNumber) { }
// split long message to parts
protected IEnumerable<string> SplitSMSMessage(string message)
{
var useUCSEncoding = IsUCSEncodingNeeded(message);
var partLength = useUCSEncoding ? 67 : 152;
var messageParts = Enumerable.Range(0, message.Length / partLength)
.Select(i => message.Substring(i * partLength, partLength))
.ToArray();
var referenceNumber = $"{GenerateReferenceNumber():X2}"; // convert to HEX, i.e. "01"
var totalMessagesCount = $"{messageParts.Length:X2}"; // convert to HEX, i.e. "01"
var udhBase = $"050003{referenceNumber}{totalMessagesCount}";
var messageNumber = (char)0;
foreach (var messagePart in messageParts)
{
var udh = $"{udhBase}{++messageNumber}";
var messagePartText = useUCSEncoding ? StringToUCS(messagePart) : StringToGSM7(messagePart);
yield return $"{udh}{messagePartText}";
}
}
private void SendToCOM(string message) { } // writes message to COM port
private bool IsUCSEncodingNeeded(string message) { } // determine if UCS-2 convert is required
private char GenerateReferenceNumber() { } // random number 0-255
private string StringToUCS(string message) { } // convert string to UCS encoding
private string StringToGSM7(string message) { } // convert string to GSM7 encoding (don't forget about padding!)
You may also find this links are useful:
- https://en.wikipedia.org/wiki/Concatenated_SMS
- https://www.developershome.com/sms/cmgsCommand4.asp
回答2:
The best answer to my question is here
How to concat long SMS in GSMComm Library?
https://github.com/welly87/GSMComm
https://www.nuget.org/packages/GSMComm/
It work fine with my HUAWEI GSM modem! WOW!
来源:https://stackoverflow.com/questions/51053983/cannot-send-sms-more-then-140-via-huawei-usb-stick-modem