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

来源:互联网 发布:flash player mac下载 编辑:程序博客网 时间:2024/05/29 04:16
长短信是有规约的,协议头部分如果是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]; 

[csharp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class DuanXin  
  2. {  
  3.     public string phnum;  
  4.     public string message;  
  5.     public DuanXin()  
  6.     {  
  7.   
  8.     }  
  9.     public DuanXin(string ph, string msg)  
  10.     {  
  11.         phnum = ph;  
  12.         message = msg;  
  13.     }  
  14. }  
  15. class CDuanXin  
  16. {  
  17.     public byte biaozhi;  
  18.     public byte tiaoshu;  
  19.     public byte dqtiaoshu;  
  20.     public string dianhua;  
  21.     public string msg;  
  22.     public DateTime datetime;  
  23.     public CDuanXin(byte bz, byte ts, byte dqts, string dh, string mg, DateTime dt)  
  24.     {  
  25.         biaozhi = bz;  
  26.         tiaoshu = ts;  
  27.         dqtiaoshu = dqts;  
  28.         dianhua = dh;  
  29.         msg = mg;  
  30.         datetime = dt;  
  31.     }  
  32. }  
  33. public class WaveComMsg  
  34. {  
  35.     public int Port;  
  36.     public int error;  
  37.     readonly string zhongzhi = new string((char)26, 1);  
  38.     const string head = "00";  
  39.     const string quyu = "000D9168";  
  40.     const string bianma = "000801";  
  41.     const string shujutou = "050003";  
  42.     const string ddx = "11";  
  43.     const string cdx = "55";  
  44.     StringBuilder fszifu = new StringBuilder(350);  
  45.     Queue<DuanXin> duanxins = new Queue<DuanXin>(60);  
  46.     Object listobj = new Object();  
  47.     List<string> items = new List<string>(8);  
  48.     public Action<intstringstringint> Fsjieguo = null;  
  49.     public Action<stringstring, DateTime> RcvMsg = null;  
  50.     public Action DuQu = null;  
  51.     bool kongxian = true;  
  52.     bool duqu = true;  
  53.     Action<DuanXin> Sendmsg = null;  
  54.     Random rd = new Random();  
  55.     SerialPort sp = null;  
  56.     List<CDuanXin> recvcd = new List<CDuanXin>(20);  
  57.     public WaveComMsg(int port)  
  58.     {  
  59.         Port = port;  
  60.         sp = new SerialPort("COM"+port);  
  61.         sp.RtsEnable = true;  
  62.         sp.DtrEnable = true;  
  63.         DuQu = ksduqu;  
  64.         sp.Open();  
  65.         Sendmsg = sendmessage;  
  66.     }  
  67.     public bool Chushihua()  
  68.     {  
  69.         string ss = string.Empty;  
  70.         try  
  71.         {  
  72.             sp.Write("AT+CMGF=0" + "\r");  
  73.             while (true)  
  74.             {  
  75.                 ss = sp.ReadLine();  
  76.                 if (ss.Contains("OK"))  
  77.                     break;  
  78.                 else if (ss.Contains("ERROR"))  
  79.                     return false;  
  80.             }  
  81.         }  
  82.         catch  
  83.         {  
  84.             return false;  
  85.         }  
  86.         try  
  87.         {  
  88.             sp.Write("AT+CNMI=2,2,0,0,1" + "\r");  
  89.             while (true)  
  90.             {  
  91.                 ss = sp.ReadLine();  
  92.                 if (ss.Contains("OK"))  
  93.                 {  
  94.                     sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);  
  95.                     return true;  
  96.                 }  
  97.                 else if (ss.Contains("ERROR"))  
  98.                     return false;  
  99.             }  
  100.         }  
  101.         catch  
  102.         {  
  103.             return false;  
  104.         }  
  105.     }  
  106.     public void DoWork(string phnumber, string msg)  
  107.     {  
  108.         DuanXin dx = new DuanXin(phnumber, msg);  
  109.         bool busy = false;  
  110.         lock (listobj)  
  111.         {  
  112.             if (duanxins.Count > 0)  
  113.                 busy = true;  
  114.             duanxins.Enqueue(dx);  
  115.         }  
  116.         if (!busy)  
  117.             Sendmsg.BeginInvoke(dx, nullnull);  
  118.     }  
  119.     void sendmessage(DuanXin dx)  
  120.     {  
  121.         byte[] msgs = Encoding.BigEndianUnicode.GetBytes(dx.message);  
  122.         if (dx.message.Length <= 70)  
  123.         {  
  124.             fszifu.Append(head);  
  125.             fszifu.Append(ddx);  
  126.             fszifu.Append(quyu);  
  127.             fszifu.Append(phonedecode(dx.phnum));  
  128.             fszifu.Append(bianma);  
  129.             fszifu.Append(Convert.ToString((dx.message.Length) * 2, 16).PadLeft(2, '0'));  
  130.             for (int i = 0; i < msgs.Length; i++)  
  131.                 fszifu.Append(Convert.ToString(msgs[i], 16).PadLeft(2, '0'));  
  132.             fszifu.Append(zhongzhi);  
  133.             items.Add(fszifu.ToString());  
  134.             fszifu.Clear();  
  135.         }  
  136.         else  
  137.         {  
  138.             string h = Convert.ToString(rd.Next(1, 127), 16);  
  139.             int lnum = dx.message.Length / 67 + 1;  
  140.             for (int i = 0; i < lnum; i++)  
  141.             {  
  142.                 int sjl = i + 1 == lnum ? msgs.Length % 134 + 6 : 140;  
  143.                 fszifu.Append(head);  
  144.                 fszifu.Append(cdx);  
  145.                 fszifu.Append(quyu);  
  146.                 fszifu.Append(phonedecode(dx.phnum));  
  147.                 fszifu.Append(bianma);  
  148.                 fszifu.Append(Convert.ToString(sjl, 16).PadLeft(2, '0'));  
  149.                 fszifu.Append(shujutou);  
  150.                 fszifu.Append(h.PadLeft(2, '0'));  
  151.                 fszifu.Append(Convert.ToString(lnum, 16).PadLeft(2, '0'));  
  152.                 fszifu.Append(Convert.ToString(i + 1, 16).PadLeft(2, '0'));  
  153.                 for (int x = 0; x < sjl - 6; x++)  
  154.                     fszifu.Append(Convert.ToString(msgs[i * 134 + x], 16).PadLeft(2, '0'));  
  155.                 fszifu.Append(zhongzhi);  
  156.                 items.Add(fszifu.ToString());  
  157.                 fszifu.Clear();  
  158.             }  
  159.         }  
  160.         string ss;  
  161.         int success = 0;  
  162.         kongxian = false;  
  163.         for (int m = 0; m < items.Count; m++)  
  164.         {  
  165.             try  
  166.             {  
  167.                 sp.Write("AT+CMGS=" + (items[m].Length / 2 - 1).ToString().PadLeft(3, '0') + "\r");  
  168.                 sp.Write(items[m]);  
  169.                 while (true)  
  170.                 {  
  171.                     ss = sp.ReadLine();  
  172.                     if (ss.StartsWith("0891"))  
  173.                         readmsg(ref ss);  
  174.                     else if (ss.Contains("OK"))  
  175.                     {  
  176.                         success = 1;  
  177.                         break;  
  178.                     }  
  179.                     else if (ss.Contains("ERROR"))  
  180.                     {  
  181.                         success = 0;  
  182.                         break;  
  183.                     }  
  184.                 }  
  185.             }  
  186.             catch  
  187.             {  
  188.                 success = 0;  
  189.             }  
  190.         }  
  191.         kongxian = true;  
  192.         if (success == 0)  
  193.             error++;  
  194.         if (Fsjieguo != null)  
  195.             Fsjieguo.BeginInvoke(Port, dx.phnum, dx.message, success, nullnull);  
  196.         items.Clear();  
  197.         bool busy = false;  
  198.         lock (listobj)  
  199.         {  
  200.             duanxins.Dequeue();  
  201.             if (duanxins.Count > 0)  
  202.                 busy = true;  
  203.         }  
  204.         if (busy)  
  205.             Sendmsg.BeginInvoke(duanxins.Peek(), nullnull);  
  206.     }  
  207.     unsafe string phonedecode(string ph)  
  208.     {  
  209.         int x = ph.Length % 2 == 0 ? ph.Length : ph.Length + 1;  
  210.         char* ca = stackalloc char[x];  
  211.         for (int i = 0; i < x; i++)  
  212.             if (i % 2 == 0)  
  213.                 *(ca + i) = (i + 1) == ph.Length ? 'F' : ph[i + 1];  
  214.             else  
  215.                 *(ca + i) = ph[i - 1];  
  216.         return new string(ca, 0, x);  
  217.     }  
  218.     unsafe string phoneencode(string ph)  
  219.     {  
  220.         int x = ph.Length;  
  221.         char* ca = stackalloc char[x];  
  222.         for (int i = 0; i < x; i++)  
  223.             if (i % 2 == 0)  
  224.                 *(ca + i) = ph[i + 1];  
  225.             else  
  226.                 *(ca + i) = ph[i - 1];  
  227.         if (*(ca + x - 1) == 'F')  
  228.             x--;  
  229.         return new string(ca, 0, x);  
  230.     }  
  231.     unsafe DateTime fsshijian(string sj)  
  232.     {  
  233.         DateTime dt = new DateTime();  
  234.         if (sj.Length == 10)  
  235.         {  
  236.             char* ca = stackalloc char[16];  
  237.             ca[0] = '2';  
  238.             ca[1] = '0';  
  239.             ca[2] = sj[1];  
  240.             ca[3] = sj[0];  
  241.             ca[4] = '/';  
  242.             ca[5] = sj[3];  
  243.             ca[6] = sj[2];  
  244.             ca[7] = '/';  
  245.             ca[8] = sj[5];  
  246.             ca[9] = sj[4];  
  247.             ca[10] = ' ';  
  248.             ca[11] = sj[7];  
  249.             ca[12] = sj[6];  
  250.             ca[13] = ':';  
  251.             ca[14] = sj[9];  
  252.             ca[15] = sj[8];  
  253.             DateTime.TryParse(new string(ca, 0, 16), out dt);  
  254.         }  
  255.         return dt;  
  256.     }  
  257.     unsafe void ksduqu()  
  258.     {  
  259.         bool ydx = false;  
  260.         string s = string.Empty;  
  261.         while (true)  
  262.         {  
  263.             try  
  264.             {  
  265.                 s = sp.ReadLine();  
  266.             }  
  267.             catch  
  268.             {  
  269.                 ydx = false;  
  270.                 break;  
  271.             }  
  272.             if (s.StartsWith("0891"))  
  273.             {  
  274.                 ydx = true;  
  275.                 break;  
  276.             }  
  277.         }  
  278.         duqu = true;  
  279.         if (ydx)  
  280.             readmsg(ref s);  
  281.     }  
[csharp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.         void readmsg(ref string s)  
  2.         {  
  3.             s = s.Trim();  
  4.             string mmsg = string.Empty;  
  5.             int cd = Convert.ToInt32(s.Substring(18, 2), 16);  
  6.             int hmcd = Convert.ToInt32(s.Substring(20, 2), 16);  
  7.             if (hmcd % 2 == 1)  
  8.                 hmcd++;  
  9.             string phonum = phoneencode(s.Substring(24, hmcd));  
  10.             string bm = s.Substring(24 + hmcd, 4);  
  11.             DateTime fssj = fsshijian(s.Substring(28 + hmcd, 10));  
  12.             int len = Convert.ToByte(s.Substring(42 + hmcd, 2), 16);  
  13.             if (cd < 64)  
  14.             {  
  15.                 byte[] b = new byte[len];  
  16.                 if (bm == "0000")//text  
  17.                 {  
  18.                     byte y = 0;  
  19.                     int l = 0;  
  20.                     for (int t = 0; t < len; t++)  
  21.                     {  
  22.                         if (t % 8 == 7)  
  23.                         {  
  24.                             l++;  
  25.                             b[t] = y;  
  26.                             y = 0;  
  27.                         }  
  28.                         else  
  29.                         {  
  30.                             byte x = Convert.ToByte(s.Substring(2 * (t - l) + 44 + hmcd, 2), 16);  
  31.                             b[t] = (byte)((((byte)(x << ((t - l) % 7) + 1)) >> 1) + y);  
  32.                             y = (byte)(x >> (7 - ((t - l) % 7)));  
  33.                         }  
  34.                     }  
  35.                     mmsg = Encoding.ASCII.GetString(b);  
  36.                 }  
  37.                 else if (bm == "0008")//tpdu  
  38.                 {  
  39.                     for (int i = 0; i < len; i++)  
  40.                         b[i] = Convert.ToByte(s.Substring(44 + hmcd + i * 2, 2), 16);  
  41.                     mmsg = Encoding.BigEndianUnicode.GetString(b);  
  42.                 }  
  43.                 if (RcvMsg != null)  
  44.                     RcvMsg.BeginInvoke(phonum, mmsg, fssj, nullnull);  
  45.             }  
  46.             else  
  47.             {  
  48.                 byte[] b = new byte[len];  
  49.                 if (bm == "0000")//text  
  50.                 {  
  51.                     byte y = 0;  
  52.                     int l = 0;  
  53.                     for (int t = 0; t < len; t++)  
  54.                     {  
  55.                         if (t % 8 == 7)  
  56.                         {  
  57.                             l++;  
  58.                             b[t] = y;  
  59.                             y = 0;  
  60.                         }  
  61.                         else  
  62.                         {  
  63.                             byte x = Convert.ToByte(s.Substring(2 * (t - l) + 44 + hmcd, 2), 16);  
  64.                             b[t] = (byte)((((byte)(x << ((t - l) % 7) + 1)) >> 1) + y);  
  65.                             y = (byte)(x >> (7 - ((t - l) % 7)));  
  66.                         }  
  67.                     }  
  68.                     mmsg = Encoding.ASCII.GetString(b, 7, len - 7);  
  69.                 }  
  70.                 else if (bm == "0008")//tpdu  
  71.                 {  
  72.                     for (int i = 0; i < len - 6; i++)  
  73.                         b[i] = Convert.ToByte(s.Substring(56 + hmcd + i * 2, 2), 16);  
  74.                     mmsg = Encoding.BigEndianUnicode.GetString(b, 0, len - 6);  
  75.                 }  
  76.                 byte bz = Convert.ToByte(s.Substring(50 + hmcd, 2), 16);  
  77.                 byte ts = Convert.ToByte(s.Substring(52 + hmcd, 2), 16);  
  78.                 byte dqts = Convert.ToByte(s.Substring(54 + hmcd, 2), 16);  
  79.                 recvcd.Add(new CDuanXin(bz, ts, dqts, phonum, mmsg, DateTime.Now));  
  80.                 var cx = (from c in recvcd where c.biaozhi == bz && c.dianhua == phonum orderby c.dqtiaoshu select c).Distinct();  
  81.                 if (cx.Count() == ts)  
  82.                 {  
  83.                     string hjmsg = null;  
  84.                     foreach (var m in cx)  
  85.                     {  
  86.                         hjmsg += m.msg;  
  87.                         recvcd.Remove(m);  
  88.                     }  
  89.                     if (RcvMsg != null)  
  90.                         RcvMsg.BeginInvoke(phonum, hjmsg, fssj, nullnull);  
  91.                 }  
  92.                 var ccx = from c in recvcd where (DateTime.Now - c.datetime).Minutes > 30 select c;  
  93.                 foreach (var n in ccx)  
  94.                     recvcd.Remove(n);  
  95.             }  
  96.         }  
  97.         void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)  
  98.         {  
  99.             if (kongxian)  
  100.             {  
  101.                 if (duqu)  
  102.                 {  
  103.                     duqu = false;  
  104.                     DuQu.BeginInvoke(nullnull);  
  105.                 }  
  106.             }  
  107.         }  
  108.         public void release()  
  109.         {  
  110.             sp.Close();  
  111.         }  
  112.     }  
0 0