GSM MODEM发PUSHMMS 的具体实现

    技术2022-05-20  47

    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");

          }

    发表于 @ 2007年07月06日 20:07:00 | 评论( 8 ) | 编辑| 举报| 收藏

    旧一篇:支持smil文件的MMS PDU打包方式. | 新一篇:对声卡输出进行录音的设置.-查看最新精华文章 请访问博客首页相关文章 RandomAccessFile一例系列WAPPUSH代码-更新版本读取资源文件MD5加密AES加解密think in java第十五章关于网络编程的读书笔记文件压缩C#中 B/S模式和C/S模式进行通讯----Socket通讯axman 发表于2007年7月12日 21:59:19  IP:举报回复删除工程文件已经重传1.增加了发书签的打包方式.2.将push,bookmark,mms打包方式全部改成根据内容长度自动分包.3.修改了发送的示例对单包和多包的通用.

    4.对于市场拥有量最多的SE GC75的GPRS卡,在发送时增加一条指令.如果不增加CFUN=1,无论是超级终端还是程序,无论是Text还是PDU模式都无法发送.为了兼容该卡,对cmgs指令的响应处理做了优化.

    5.因为push/bookmark/mms打包的工作量和技术强度已经大大超过了PDUdecoding原有的内容,所以去掉了原作者信息.因为PDU编码本身是一个非常简单的过程.自己完全重写也不过十分钟的事.scrow 发表于2007年7月17日 16:40:28  IP:举报回复删除你好,拜读了您的文章,收益颇多~,想请教您个问题,我有移动sp短信端口,现在可以用这个端口给用户发短信、wap push,想通过这个端口也能发彩信(通知),但是不知道怎么设置,恳请您能指点一下,不胜感谢!axman 发表于2007年7月17日 18:19:18  IP:举报回复删除你既然能发PUSH就可以发彩信通知啊,发送的内容就是smsDecodedNumber(strNumber)出来的内容,不包括0051000D91{0}00F5A7{1}的内容.

    向SP网关提交的应该不是toHexString的二进制形式.应该是原始的byte的字节数组.scrow 发表于2007年7月19日 10:14:01  IP:举报回复删除好的,我试试,十分感谢~xiaoyunchen 发表于2009年2月25日 15:10:00  IP:举报回复删除弱弱的问一下,可以通过GPRS分配给手机的IP地址,直接PUSH到手机上么,怎么实现!非常感谢 axman 发表于2009年2月25日 15:50:32  IP:举报回复删除回复 xiaoyunchen:这个问题有些搞笑,如果对方的手机从来就没有开通GPRS呢?或者你怎么知道对方的GPRS连结的IP地址呢?zhuago 发表于2009年3月17日 15:22:18  IP:举报回复删除您好,我最近正在研究push,我根据网上流传的push消息体构造了一个串,如下:0051000BA13158714092F400F5A7380B05040B8423F0000303010181060603AE81EA8DCA02056A0045C6080C037777772E6269616F67616E2E636E000103E6B58BE8AF95000101现在我有两个问题想请教一下:一、这个串有没有问题,如果有,是哪里出了问题?二、向串口写指令at+cmgs=length,这个length是上面整个串的长度/2-1呢还是其他?多谢指教dandeyu 发表于2009年4月24日 17:37:46  IP:举报回复删除您好,我想问一下,这个pdu编码,有格式说明吗?到底怎么拼呢?谢谢了!!�?d=0.5637763406882681jimmylam 发表于2010年7月26日 17:39:18  IP:举报回复删除您好,下载链接已失效,可以再发一次吗?谢谢!cutemouse 发表于2011年2月27日 11:17:51  IP:119.144.147.*举报回复删除是啊,能否给个下载啊。谢谢

    本文来自博客,转载请标明出处:http://blog.csdn.net/axman/archive/2007/07/06/1681406.aspx


    最新回复(0)