您的位置:首页 > 编程语言 > C#

c#实现wavecom短信猫发送长短信

2016-07-11 11:12 441 查看
长短信是有规约的,协议头部分如果是0x40以下,则说明是普通短信,如果是0x40以上,则是长短信,然后在短信内容部分,有六个字节分别定义短信唯一标识以及该短信是第几条,所以长短信发送时每条实际为67个汉字。手机接收到之后,都会按照标准规约自动组合为一条短信,而不是显示多条。

我做了一个AT指令操作wavecom短信猫的类,可以接收和发送超长短信,并且接收到的短信会直接通知电脑。

超长短信:短信内容超过70个汉字,提交给网关时候需要分成多条,但是用户手机接收时候是一条(sp角度,手机发送长短信概念一样)。

  在cmpp协议里,CMPP-_SUBMIT消息定义中有相应的参数配置:   

TP_udhi :0代表内容体里不含有协议头信息 1代表内容含有协议头信息(长短信,push短信等都是在内容体上含有头内容的)当设置内容体包含协议头,需要根据协议写入相应的信息,长短信协议头有两种:

               6位协议头格式:05 00 03 XX MM NN

                     byte 1 : 05, 表示剩余协议头的长度

                     byte 2 : 00, 这个值在GSM 03.40规范9.2.3.24.1中规定,表示随后的这批超长短信的标识位长度为1(格式中的XX值)。

                     byte 3 : 03, 这个值表示剩下短信标识的长度

                     byte 4 : XX,这批短信的唯一标志(被拆分的多条短信,此值必需一致),事实上,SME(手机或者SP)把消息合并完之后,就重新记录,所以这个标志是否唯

                                 一并不是很 重要。

                     byte 5 : MM, 这批短信的数量。如果一个超长短信总共5条,这里的值就是5。

                     byte 6 : NN, 这批短信的数量。如果当前短信是这批短信中的第一条的值是1,第二条的值是2。
                     例如:05 00 03 39 02 01

 7位的协议头格式:06 08 04 XX XX MM NN                     byte 1 : 06, 表示剩余协议头的长度

                     byte 2 : 08, 这个值在GSM 03.40规范9.2.3.24.1中规定,表示随后的这批超长短信的标识位长度为2(格式中的XX值)。

                     byte 3 : 04, 这个值表示剩下短信标识的长度

                     byte 4-5 : XX XX,这批短信的唯一标志,事实上,SME(手机或者SP)把消息合并完之后,就重新记录,所以这个标志是否唯一并不是很重要。

                     byte 6 : MM, 这批短信的数量。如果一个超长短信总共5条,这里的值就是5。

                     byte 7 : NN, 这批短信的数量。如果当前短信是这批短信中的第一条的值是1,第二条的值是2。

                     例如:06 08 04 00 39 02 01       

            到此,长短信的发送设置基本完成,但是有一点要注意:Src_Id 协议里这个字段在一条长短信中必须要一样,不然手机会解析成三条,   

      并三条都 是错误短信。    

            对于sp来说,长短信上行,按照协议反过来解析:

                       1byte[] contentBytes = msg.getMsgContent();

2int headLen = contentBytes[0]; // 内容头的长度

3// 超长短信总条数

4int pk_total = contentBytes[headLen - 1];

5// 超长短信第几条

6int pk_num = contentBytes[headLen]; 

7// 超长短信序号
8byte serial = contentBytes[headLen - 2]; 

class DuanXin
{
public string phnum;
public string message;
public DuanXin()
{

}
public DuanXin(string ph, string msg)
{
phnum = ph;
message = msg;
}
}
class CDuanXin
{
public byte biaozhi;
public byte tiaoshu;
public byte dqtiaoshu;
public string dianhua;
public string msg;
public DateTime datetime;
public CDuanXin(byte bz, byte ts, byte dqts, string dh, string mg, DateTime dt)
{
biaozhi = bz;
tiaoshu = ts;
dqtiaoshu = dqts;
dianhua = dh;
msg = mg;
datetime = dt;
}
}
public class WaveComMsg
{
public int Port;
public int error;
readonly string zhongzhi = new string((char)26, 1);
const string head = "00";
const string quyu = "000D9168";
const string bianma = "000801";
const string shujutou = "050003";
const string ddx = "11";
const string cdx = "55";
StringBuilder fszifu = new StringBuilder(350);
Queue<DuanXin> duanxins = new Queue<DuanXin>(60);
Object listobj = new Object();
List<string> items = new List<string>(8);
public Action<int, string, string, int> Fsjieguo = null;
public Action<string, string, DateTime> RcvMsg = null;
public Action DuQu = null;
bool kongxian = true;
bool duqu = true;
Action<DuanXin> Sendmsg = null;
Random rd = new Random();
SerialPort sp = null;
List<CDuanXin> recvcd = new List<CDuanXin>(20);
public WaveComMsg(int port)
{
Port = port;
sp = new SerialPort("COM"+port);
sp.RtsEnable = true;
sp.DtrEnable = true;
DuQu = ksduqu;
sp.Open();
Sendmsg = sendmessage;
}
public bool Chushihua()
{
string ss = string.Empty;
try
{
sp.Write("AT+CMGF=0" + "\r");
while (true)
{
ss = sp.ReadLine();
if (ss.Contains("OK"))
break;
else if (ss.Contains("ERROR"))
return false;
}
}
catch
{
return false;
}
try
{
sp.Write("AT+CNMI=2,2,0,0,1" + "\r");
while (true)
{
ss = sp.ReadLine();
if (ss.Contains("OK"))
{
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
return true;
}
else if (ss.Contains("ERROR"))
return false;
}
}
catch
{
return false;
}
}
public void DoWork(string phnumber, string msg)
{
DuanXin dx = new DuanXin(phnumber, msg);
bool busy = false;
lock (listobj)
{
if (duanxins.Count > 0)
busy = true;
duanxins.Enqueue(dx);
}
if (!busy)
Sendmsg.BeginInvoke(dx, null, null);
}
void sendmessage(DuanXin dx)
{
byte[] msgs = Encoding.BigEndianUnicode.GetBytes(dx.message);
if (dx.message.Length <= 70)
{
fszifu.Append(head);
fszifu.Append(ddx);
fszifu.Append(quyu);
fszifu.Append(phonedecode(dx.phnum));
fszifu.Append(bianma);
fszifu.Append(Convert.ToString((dx.message.Length) * 2, 16).PadLeft(2, '0'));
for (int i = 0; i < msgs.Length; i++)
fszifu.Append(Convert.ToString(msgs[i], 16).PadLeft(2, '0'));
fszifu.Append(zhongzhi);
items.Add(fszifu.ToString());
fszifu.Clear();
}
else
{
string h = Convert.ToString(rd.Next(1, 127), 16);
int lnum = dx.message.Length / 67 + 1;
for (int i = 0; i < lnum; i++)
{
int sjl = i + 1 == lnum ? msgs.Length % 134 + 6 : 140;
fszifu.Append(head);
fszifu.Append(cdx);
fszifu.Append(quyu);
fszifu.Append(phonedecode(dx.phnum));
fszifu.Append(bianma);
fszifu.Append(Convert.ToString(sjl, 16).PadLeft(2, '0'));
fszifu.Append(shujutou);
fszifu.Append(h.PadLeft(2, '0'));
fszifu.Append(Convert.ToString(lnum, 16).PadLeft(2, '0'));
fszifu.Append(Convert.ToString(i + 1, 16).PadLeft(2, '0'));
for (int x = 0; x < sjl - 6; x++)
fszifu.Append(Convert.ToString(msgs[i * 134 + x], 16).PadLeft(2, '0'));
fszifu.Append(zhongzhi);
items.Add(fszifu.ToString());
fszifu.Clear();
}
}
string ss;
int success = 0;
kongxian = false;
for (int m = 0; m < items.Count; m++)
{
try
{
sp.Write("AT+CMGS=" + (items[m].Length / 2 - 1).ToString().PadLeft(3, '0') + "\r");
sp.Write(items[m]);
while (true)
{
ss = sp.ReadLine();
if (ss.StartsWith("0891"))
readmsg(ref ss);
else if (ss.Contains("OK"))
{
success = 1;
break;
}
else if (ss.Contains("ERROR"))
{
success = 0;
break;
}
}
}
catch
{
success = 0;
}
}
kongxian = true;
if (success == 0)
error++;
if (Fsjieguo != null)
Fsjieguo.BeginInvoke(Port, dx.phnum, dx.message, success, null, null);
items.Clear();
bool busy = false;
lock (listobj)
{
duanxins.Dequeue();
if (duanxins.Count > 0)
busy = true;
}
if (busy)
Sendmsg.BeginInvoke(duanxins.Peek(), null, null);
}
unsafe string phonedecode(string ph)
{
int x = ph.Length % 2 == 0 ? ph.Length : ph.Length + 1;
char* ca = stackalloc char[x];
for (int i = 0; i < x; i++)
if (i % 2 == 0)
*(ca + i) = (i + 1) == ph.Length ? 'F' : ph[i + 1];
else
*(ca + i) = ph[i - 1];
return new string(ca, 0, x);
}
unsafe string phoneencode(string ph)
{
int x = ph.Length;
char* ca = stackalloc char[x];
for (int i = 0; i < x; i++)
if (i % 2 == 0)
*(ca + i) = ph[i + 1];
else
*(ca + i) = ph[i - 1];
if (*(ca + x - 1) == 'F')
x--;
return new string(ca, 0, x);
}
unsafe DateTime fsshijian(string sj)
{
DateTime dt = new DateTime();
if (sj.Length == 10)
{
char* ca = stackalloc char[16];
ca[0] = '2';
ca[1] = '0';
ca[2] = sj[1];
ca[3] = sj[0];
ca[4] = '/';
ca[5] = sj[3];
ca[6] = sj[2];
ca[7] = '/';
ca[8] = sj[5];
ca[9] = sj[4];
ca[10] = ' ';
ca[11] = sj[7];
ca[12] = sj[6];
ca[13] = ':';
ca[14] = sj[9];
ca[15] = sj[8];
DateTime.TryParse(new string(ca, 0, 16), out dt);
}
return dt;
}
unsafe void ksduqu()
{
bool ydx = false;
string s = string.Empty;
while (true)
{
try
{
s = sp.ReadLine();
}
catch
{
ydx = false;
break;
}
if (s.StartsWith("0891"))
{
ydx = true;
break;
}
}
duqu = true;
if (ydx)
readmsg(ref s);
}
        void readmsg(ref string s)
        {
            s = s.Trim();
            string mmsg = string.Empty;
            int cd = Convert.ToInt32(s.Substring(18, 2), 16);
            int hmcd = Convert.ToInt32(s.Substring(20, 2), 16);
            if (hmcd % 2 == 1)
                hmcd++;
            string phonum = phoneencode(s.Substring(24, hmcd));
            string bm = s.Substring(24 + hmcd, 4);
            DateTime fssj = fsshijian(s.Substring(28 + hmcd, 10));
            int len = Convert.ToByte(s.Substring(42 + hmcd, 2), 16);
            if (cd < 64)
            {
                byte[] b = new byte[len];
                if (bm == "0000")//text
                {
                    byte y = 0;
                    int l = 0;
                    for (int t = 0; t < len; t++)
                    {
                        if (t % 8 == 7)
                        {
                            l++;
                            b[t] = y;
                            y = 0;
                        }
                        else
                        {
                            byte x = Convert.ToByte(s.Substring(2 * (t - l) + 44 + hmcd, 2), 16);
                            b[t] = (byte)((((byte)(x << ((t - l) % 7) + 1)) >> 1) + y);
                            y = (byte)(x >> (7 - ((t - l) % 7)));
                        }
                    }
                    mmsg = Encoding.ASCII.GetString(b);
                }
                else if (bm == "0008")//tpdu
                {
                    for (int i = 0; i < len; i++)
                        b[i] = Convert.ToByte(s.Substring(44 + hmcd + i * 2, 2), 16);
                    mmsg = Encoding.BigEndianUnicode.GetString(b);
                }
                if (RcvMsg != null)
                    RcvMsg.BeginInvoke(phonum, mmsg, fssj, null, null);
            }
            else
            {
                byte[] b = new byte[len];
                if (bm == "0000")//text
                {
                    byte y = 0;
                    int l = 0;
                    for (int t = 0; t < len; t++)
                    {
                        if (t % 8 == 7)
                        {
                            l++;
                            b[t] = y;
                            y = 0;
                        }
                        else
                        {
                            byte x = Convert.ToByte(s.Substring(2 * (t - l) + 44 + hmcd, 2), 16);
                            b[t] = (byte)((((byte)(x << ((t - l) % 7) + 1)) >> 1) + y);
                            y = (byte)(x >> (7 - ((t - l) % 7)));
                        }
                    }
                    mmsg = Encoding.ASCII.GetString(b, 7, len - 7);
                }
                else if (bm == "0008")//tpdu
                {
                    for (int i = 0; i < len - 6; i++)
                        b[i] = Convert.ToByte(s.Substring(56 + hmcd + i * 2, 2), 16);
                    mmsg = Encoding.BigEndianUnicode.GetString(b, 0, len - 6);
                }
                byte bz = Convert.ToByte(s.Substring(50 + hmcd, 2), 16);
                byte ts = Convert.ToByte(s.Substring(52 + hmcd, 2), 16);
                byte dqts = Convert.ToByte(s.Substring(54 + hmcd, 2), 16);
                recvcd.Add(new CDuanXin(bz, ts, dqts, phonum, mmsg, DateTime.Now));
                var cx = (from c in recvcd where c.biaozhi == bz && c.dianhua == phonum orderby c.dqtiaoshu select c).Distinct();
                if (cx.Count() == ts)
                {
                    string hjmsg = null;
                    foreach (var m in cx)
                    {
                        hjmsg += m.msg;
                        recvcd.Remove(m);
                    }
                    if (RcvMsg != null)
                        RcvMsg.BeginInvoke(phonum, hjmsg, fssj, null, null);
                }
                var ccx = from c in recvcd where (DateTime.Now - c.datetime).Minutes > 30 select c;
                foreach (var n in ccx)
                    recvcd.Remove(n);
            }
        }
        void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (kongxian)
            {
                if (duqu)
                {
                    duqu = false;
                    DuQu.BeginInvoke(null, null);
                }
            }
        }
        public void release()
        {
            sp.Close();
        }
    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  长短信