查看: 5803|回复: 0
打印 上一主题 下一主题

c#实现wavecom短信收发设备发送长短信

[复制链接]
跳转到指定楼层
楼主
发表于 2016-7-11 10:45:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
长短信是有规约的,协议头部分如果是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];


  1.     class DuanXin
  2.     {
  3.         public string phnum;
  4.         public string message;
  5.         public DuanXin()
  6.         {

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

  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, null, null);
  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, null, null);
  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(null, null);
  105.                 }
  106.             }
  107.         }
  108.         public void release()
  109.         {
  110.             sp.Close();
  111.         }
  112.     }
复制代码



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|小黑屋|未来时代科技 ( 粤ICP备12044031号-1

GMT+8, 2024-4-25 12:49 , Processed in 0.057250 second(s), 31 queries .

Powered by WLSD X3.1

© 2013-2014 WLSD Inc.

快速回复 返回顶部 返回列表
 
【电话】(15118131494)
【QQ】 未来时代科技01 售前咨询
【QQ】 未来时代科技02 售后技术
【旺旺】 请问有什么可以帮到您?不在线可留言.
【邮箱】
inextera@sina.com
【地址】 (深圳市龙岗坂田扬马小区)