GSM MODEM发PUSH/MMS 的具体实现.

GSM MODEM发PUSH/MMS的原理请搜索网上的很多文章.这里只提供实现代码.我在原来发SMS的PDULib中加了

两个组装PUSH和MMS通知的方法.然后直接利用发SMS的方法发出去.代码都是调用通过的.不过我用SE的GPRS卡插在本本上调用,无论是通过超级终端直接发AT指令还是用程序都不行,好象最后的结束符26(ctrl+z)发不出去.但用MOTO的手机连接本本,无论超级终端还是程序都很顺利.

 项目文件在:http://dl2.csdn.net/down4/20070712/12214323168.rar

连结串口的JustInIO包文件中定义了CommPort类,PUDLib文件中定义了PDUdecoding类,这两个文件搜索一下可以找到N个下载地址.篇幅原因我不贴了.只把在PDUdecoding中加的两个方法(另有两个辅助方法)贴上来:

        private static string getUTF8Text(string str)
        {
            byte[] buf = Encoding.UTF8.GetBytes(str);
            StringBuilder sb = new StringBuilder(buf.Length * 2);
            for (int i = 0; i < buf.Length; i++)
            {
                sb.Append(buf[i].ToString("X2"));
            }
            return sb.ToString();

        }
        private static string getAsciiText(string str)
        {
            byte[] buf = Encoding.ASCII.GetBytes(str);
            StringBuilder sb = new StringBuilder(buf.Length * 2);
            for (int i = 0; i < buf.Length; i++)
            {
                sb.Append(buf[i].ToString("X2"));
            }
            return sb.ToString();

        }
        private string uintToString(int n)
        {
            byte[] buf = new byte[8];
            int l = 0;
            while (n >= 128)
            {
                byte b = (byte)(n & 0x7F);
                n = n >> 7;
                buf[l++] = b;
            }
            buf[l++] = (byte)n;
            StringBuilder sb = new StringBuilder();
            byte[] retBys = new byte[l];
            for (int i = 0; i < l; ++i)
            {
                retBys[i] = (byte)(buf[l - i - 1] | 0x80);
            }
            retBys[l - 1] &= 0x7F;
            for (int i = 0; i < l; i++)
            {
                sb.Append(retBys[i].ToString("X2"));
            }
            return sb.ToString();

        }

发送PUSH和MMS通知的DECODE方法:

        public string smsEncodePushMessage(string strNumber, string strTitle, string strURL)
        {

            string[] content = getPushContents(strTitle, strURL);
            StringBuilder sb = new StringBuilder();
            nLength = "";
            for (int i = 00; i < content.Length; i++)
            {
                string s = String.Format("0051000D91{0}00F5A7{1}{2}", smsDecodedNumber(strNumber), (content[i].Length / 2).ToString("X2"), content[i]);
                sb.Append(s);
                int len = (s.Length / 2) - 1;//10进制
                nLength += len.ToString();
                if (i != content.Length - 1)
                {
                    sb.Append(";");
                    nLength += ";";
                }
            }
            return sb.ToString();
        }

 

         public string smsEncodeMMSMessage(string strNumber, string sendNumber, string strTitle, string strURL)
        {
            string[] content = getMMSContents(sendNumber, strTitle, strURL);
            StringBuilder sb = new StringBuilder();
            nLength = "";
            for (int i = 00; i < content.Length; i++)
            {
                string s = String.Format("0051000D91{0}00F5A7{1}{2}", smsDecodedNumber(strNumber), (content[i].Length / 2).ToString("X2"), content[i]);
                sb.Append(s);
                int len = (s.Length / 2) - 1;//10进制
                nLength += len.ToString();
                if (i != content.Length - 1)
                {
                    sb.Append(";");
                    nLength += ";";
                }
            }
            return sb.ToString();

        }

 

 

        private string[] getPushContents(string title, string url)
        {

            string singleHead = "0605040B840000";
            string MoreHead = "0B05040B840000000301";

            string pud = "01060403AE81EA";
            string pushUrlBegin = "02056A0045C6080B03";
            string pushTitleBegin = "000103";
            string pushEnd = "000101";

            StringBuilder content = new StringBuilder();
            content.Append(pud);
            content.Append(pushUrlBegin);
            content.Append(getAsciiText(url));
            content.Append(pushTitleBegin);
            content.Append(getUTF8Text(title));
            content.Append(pushEnd);

            string contentStr = content.ToString();

            if ((contentStr.Length + singleHead.Length) < 140 * 2)
            {
                string[] messages = new string[1];
                messages[0] = singleHead + contentStr;
                return messages;
            }
            else
            {
                int packSize = 140 * 2 - MoreHead.Length - 2 * 2;//总包数加当前包数两个字节
                int packCount = (contentStr.Length / packSize) + (contentStr.Length % packSize == 0 ? 0 : 1);
                string[] messages = new string[packCount];
                for (int i = 0; i < packCount; i++)
                {
                    StringBuilder buf = new StringBuilder();
                    buf.Append(MoreHead);
                    buf.Append(packCount.ToString("X2"));
                    buf.Append((i + 1).ToString("X2"));
                    if (i == (packCount - 1))
                        buf.Append(contentStr.Substring(i * packSize));
                    else
                        buf.Append(contentStr.Substring(i * packSize, packSize));
                    messages[i] = buf.ToString();
                }
                return messages;
            }
        }
        private string[] getMMSContents(string sendNumber,string title, string url)
        {

            string singleHead = "0605040B840000";
            string MoreHead = "0B05040B840000000301";

            title = getUTF8Text(title);
            url = getAsciiText(url);

            StringBuilder content = new StringBuilder();
           
            content.Append("25")             //Transaction ID
                .Append("0622")         //type,header-len
                .Append(getAsciiText("application/vnd.wap.mms-message"))
                .Append("AF84")     //X-Wap-Application-ID type=2F (+80),x-wap-application:mms.ua=04 (+80)
                .Append("8C82")     //Message Type :m-notification.ind
                .Append("98");       //X-MMS-Transaction-Id
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1);
            int x = (int)(ts.TotalMilliseconds / 1000);
            content.Append(getAsciiText(x.ToString()))
                .Append("00")
                .Append("8D90")        //version 1.0
                .Append("89");         //From
            string from = getAsciiText(sendNumber);
            int fromLen = from.Length / 2 + 2;
            string strFromLen = fromLen.ToString("X2");
            content.Append(strFromLen)
                .Append("80")           //from begin
                .Append(from)
                .Append("00")
                .Append("96");           //subject
            int subLen = title.Length / 2 + 2;  //EA,00编码和结束符
            content.Append(subLen.ToString("X2"))
                .Append("EA")
                .Append(title)
                .Append("00");
            content.Append("8A80");              //Message-Class:Personal
            content.Append("8E");                 //Message-size
            int msgSize = 12345;
            string strMsgSize = msgSize.ToString("X4");
            int sizeLen = strMsgSize.Length / 2;
            content.Append(sizeLen.ToString("X2"))
                .Append(strMsgSize)
                .Append("88")               //有效期
                .Append("058103093A80");    //总长度5,相对格式.秒数长度3,093A80为604800秒,一周.
            content.Append("83")                 //X-MMS-Content-Location
                .Append(url)
                .Append("00");
            string contentStr = content.ToString();
            if ((contentStr.Length + singleHead.Length) < 140 * 2)
            {
                string[] messages = new string[1];
                messages[0] = singleHead + contentStr;
                return messages;
            }
            else
            {
                int packSize = 140 * 2 - MoreHead.Length - 2 * 2;//总包数加当前包数两个字节
                int packCount = (contentStr.Length / packSize) + (contentStr.Length % packSize == 0 ? 0 : 1);
                string[] messages = new string[packCount];
                for (int i = 0; i < packCount; i++)
                {
                    StringBuilder buf = new StringBuilder();
                    buf.Append(MoreHead);
                    buf.Append(packCount.ToString("X2"));
                    buf.Append((i + 1).ToString("X2"));
                    if (i == (packCount - 1))
                        buf.Append(contentStr.Substring(i * packSize));
                    else
                        buf.Append(contentStr.Substring(i * packSize, packSize));
                    messages[i] = buf.ToString();
                }
                return messages;
            }

注意上面两个私有支持方法因为支持分包所以都返回了字符串数组.两个公开的接口方法对返回的数组进行了重组装.这样在发送时要根据多包的特点多次发送.有了这两个方法.按正常发送SMS的方法就可以发送了:

连接COM口的方法:

        private void connect_Click(object sender, EventArgs e)
        {
            if (this.InitCom("COM7", 9600))
            {
                this.connect.Enabled = false;
                ss_port.Write(Encoding.ASCII.GetBytes("AT+CSCA?/r"));//获取手机短信中心号
                bool flag = false;
                for (int i = 0; i < retryCount; i++)
                {
                    Thread.Sleep(retryTimeOut);
                    string readBuffer = Encoding.ASCII.GetString(ss_port.Read(128));
                    this.log.AppendText(readBuffer + "/r/n");
                    int start = readBuffer.IndexOf("86");
                    if (start != -1)
                    {
                        this.smsCenter.Text = readBuffer.Substring(start, 13);
                        flag = true;
                        break;
                    }
                }
                if (flag)
                {
                    ss_port.Write(Encoding.ASCII.GetBytes("AT+CMGF=0/r"));
                    for (int i = 0; i < retryCount; i++)
                    {
                        Thread.Sleep(retryTimeOut);
                        string readBuffer = Encoding.ASCII.GetString(ss_port.Read(128));
                        this.log.AppendText(readBuffer + "/r/n");
                        if (readBuffer.IndexOf("OK") != -1)
                        {
                            this.log.AppendText("CMGF:"+readBuffer);
                            break;
                        }

                    }
                }

                //以下为SE的GC75 GPRS必须加的指令,此卡默认CFUN=0,无论Text还是Pdu都不能发.
                ss_port.Write(Encoding.ASCII.GetBytes("AT+CFUN=1/r"));
                for (int i = 0; i < retryCount; i++)
                {
                    Thread.Sleep(retryTimeOut);
                    string readBuffer = Encoding.ASCII.GetString(ss_port.Read(128));
                    this.log.AppendText(readBuffer + "/r/n");
                    if (readBuffer.IndexOf("OK") != -1)
                    {
                        this.log.AppendText("CFUN:" + readBuffer);
                        break;
                    }

                }
            }
        }

 

发送,根据选择框MODE控制选择的结果发送SMS/PUSH/MMS通知:

        private void sendSMS_Click(object sender, EventArgs e)
        {

            PDUdecoding pud = new PDUdecoding();
            string decodedSMS = "";

            if (this.mode.SelectedIndex == 0)
            {
                decodedSMS = pud.smsDecodedsms(this.smsCenter.Text, this.destination.Text, this.content.Text);
            }
            else if (this.mode.SelectedIndex == 1)
            {
                decodedSMS = pud.smsEncodePushMessage(this.destination.Text, this.content.Text, this.pushurl.Text.Replace("http://", ""));
            }
            else if (this.mode.SelectedIndex == 2)
            {
                decodedSMS = pud.smsEncodeMMSMessage(this.destination.Text, "8888", this.content.Text, this.pushurl.Text);
            }
            else if (this.mode.SelectedIndex == 3)
            {
                decodedSMS = pud.smsEncodeBookMarkMessage(this.destination.Text, this.content.Text, this.pushurl.Text);
            }
            string[] contents = decodedSMS.Split(';');
            string[] nLens = pud.nLength.Split(';');
            for (int x = 0; x < contents.Length; x++)
            {
                byte[] buf = Encoding.ASCII.GetBytes(String.Format("AT+CMGS={0}/r", nLens[x]));
                Console.WriteLine(decodedSMS);
                ss_port.Write(buf);
                bool isSucc = false;
                string readBuffer = "";
                for (int i = 0; i < retryCount; i++)
                {
                    Thread.Sleep(retryTimeOut);
                    readBuffer += Encoding.ASCII.GetString(ss_port.Read(128));
                    this.log.AppendText(readBuffer + "/r/n");
                    if (readBuffer.Length > 0 && readBuffer.EndsWith("> "))
                    {
                        isSucc = true;
                        break;
                    }


                }
                if (!isSucc)
                {
                    MessageBox.Show("send cmgs ERROR!");
                    return;

                }
                isSucc = false;
                byte[] sendbyte = Encoding.ASCII.GetBytes(contents[x]);

                ss_port.Write(sendbyte);
                ss_port.Write(new byte[] { 0x1A });
                readBuffer = "";
                int mark = 0;
                //因为GC75卡响应内容太多,且分为多行,所以为了通用彩用mark标记响应
                //内容中有CMGS和OK的内容.
                for (int i = 0; i < retryCount; i++)
                {
                    Thread.Sleep(retryTimeOut);
                    readBuffer = Encoding.ASCII.GetString(ss_port.Read(128));
                    this.log.AppendText(readBuffer + "/r/n");
                    if (readBuffer.IndexOf("CMGS:") != -1)  mark++;

                    if (readBuffer.IndexOf("OK") != -1) mark++;
                    if(mark == 2)
                    {
                        isSucc = true;
                        break;
                    }
                }
                if (!isSucc)
                {
                    MessageBox.Show("ERROR");
                    return;
                }
            }
            MessageBox.Show("OK");

      }

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值