分享

用AT命令发送PDU短信(转)

 百草园404 2014-12-19

我用一个例子说明整个过程~
    短信中心:+8613800100500
    收信号码:+8613401041516
    短信内容:我爱听评书

第一步——格式化短信中心号码
1 - 要去掉“+”号,然后看看长度要是奇数的话就在末尾追加一个“F”。
    +8613800200500 >>>> 8613800100500F
2 - 将奇数位和偶数位交换位置。
    8613800100500F >>>> 683108100005F0
3 - 在前面加上“91”,是国际化的意思。
    683108100005F0 >>>> 91683108100005F0
4 - 最后算一算它有多长了,把长度除于2,再把结果转换为2位的16进制数,加在最前面。
    91683108100005F0长16 16/2=8 8的16进制“08” 一定要注意是2位
    91683108100005F0 >>>> 0891683108100005F0
短信中心号码就处理完了,下几一步有类似的算法,现在我感觉就像做菜一样……

第二步——格式化收信号码
1 - 要去掉“+”号,然后看看长度要是奇数的话就在末尾追加一个“F”。
    +8613401041516 >>>> 8613401041516F
2 - 将奇数位和偶数位交换位置。
    8613401041516F >>>> 683104011415F6

第三步——格式化发送内容
1 - 把字符串转换为Unicode格式。(转换函数我写过了,直接拿去用好了)
    我爱听评书 >>>> 62117231542C8BC44E66
2 - 把串Unicode码的长度除于2,再把结果转换为2位的16进制数,加在最前面。
    62117231542C8BC44E66长20 20/2=10 10的16进制“0A”
    62117231542C8BC44E66 >>>> 0A62117231542C8BC44E66

先看看我们都准备什么了,再继续~
    格式化后的短信中心:0891683108100005F0
    格式化后的收信号码:683104011415F6
    格式化后的发送内容:0A62117231542C8BC44E66

第四步——组合处理
1 - 算一下收信号码的长度,不包括“+”号。这个收信号码指的是+8613401041516,而不是683104011415F6。
    +8613401041516 >>>> 8613401041516 长度为“OD”(2位16进制数表示)
2 - 在长度前后分别加“1100”。
    OD >>>> 1100OD
3 - 如果收信号码是手机的话就在后面追加“91”,如果是小灵通的话就要追加“81”。
    +8613401041516是手机号码所以加“91”
    11000D >>>> 11000D91
4 - 11000D91 + 格式化后的收信号码 + “000800” + 格式化后的发送内容
    11000D91 >>>> 11000D91683104011415F60008000A62117231542C8BC44E66
5 - 计算上面那一大字符串的长度除于2,10进制表示。
    11000D91683104011415F6008000A62117231542C8BC44E66长50 50/2=25

嗯,咱再看看手里都有啥了~
    格式化后的短信中心:0891683108100005F0
    实际的发送内容:11000D91683104011415F60008000A62117231542C8BC44E66
    发送内容的长度:25
都准备好了我们可以发短信了 ^_^

最后一步——通过AT命令发送PDU短信
    AT+CMGF=0 <Enter> (告诉它你要发的是PDU类的短信)
    OK (这是它返回的它说:“我已经准备好了”)
    AT+CMGS=25 <Enter> (告诉它你要发的实际长度)
    >0891683108100005F011000D91683104011415F60008000A62117231542C8BC44E66 <Ctrl+Z> (看到它返回“>” 在后面输入格式化的短信中心+实际的发送内容最后按Ctrl+Z发送)
如果最后返回不是“ERROR”,那就是发送成功咯
~!

==============================================================

Linux开发中SMS PDU编码原理及实现
SMS是由Esti 所制定的一个规范(GSM 03.40 和 GSM 03.38)。有两种方式来发送和接收SMS消息:文本模式或者PDU(protocol description unit)模式。文本模式只能发送普通的ASCII字符,而要发送图片、铃声、其它编码的字符(如中文)就必须采用PDU模式。 Ftx平坦软件园

        PDU模式中,可以采用三种编码方式来编码要发送的内容,分别是 7-bit编码、8-bit编码、16-bit编码。7-bit编码用于发送普通的ASCII字符;8-bit编码通常用于发送数据消息,比如图片和铃声等;而16-bit编码用于发送Unicode字符。在这三种编码方式下,可以发送的最大字符数分别是 160、 140、70。Ftx平坦软件园
若要发送中文(或日文等),必须采用PDU模式的Unicode编码方式。Ftx平坦软件园

        最近参与了一个在linux下收发短信的项目。其中,需要实现中文的发送和接收。由于原来没有中文编码、Unicode编码的经验,所以查了一些资料,也在一些论坛上提了一些问题。现在把它整理出来,希望对以后再做类似项目的朋友有个帮助。我写的比较简单,关于PDU的规范,可以看这里:http://www./sustain/SMS_PDU-mode.pdf ,或者去wavecom的网站上找找看。Ftx平坦软件园

        1、GB2312 编码到Unicode 编码的转换Ftx平坦软件园

        在 Redhat 7.3系统上,默认是用GB2312编码保存中文字符的(对于中英文混合的文本也是如此)。所以首先需要把 GB2312 编码的字符串转换到 Unicode编码的字符串。Ftx平坦软件园

        GB2312编码是一种多字节编码方式,对于中文,用2个字节表示,对于英文,用1个字节表示,就是英文的ascii码。(注:我没有仔细看过 GB2312编码的规范,以上理解是实际开发中得出来的,不能保证正确性)。Unicode编码是双字节编码方式,对所有字符,都采用2个字节编码。在 linux平台上,GB2312编码到Unicode编码的转换,可以有三种实现方式(或者更多):Ftx平坦软件园

        1)、用 mbstowcs () 函数。就是多字节编码到宽字符的转换。我试过它,可以正确的转换,但是这个函数可能不是很可靠。Ftx平坦软件园
        2)、用 GB2312 à Unicode 的转换表,手动查表转换。网上有这样的转换表,你需要对每一个GB2312字符,根据它是中文字符还是英文字符,分别转换。Ftx平坦软件园
        3)、用 iconv () 函数。这可能是linux上的标准的方法,不仅可以转换GB2312到Unicode,还可以在任意的两种编码之间转换(前提是linux系统要支持这些编码)。Ftx平坦软件园

        首先要用 iconv_open(), 打开一个转换句柄,指定两种转换前的编码和转换后的编码。然后用 icnov() 作转换。最后用 iconv_close()关闭句柄,释放资源。Ftx平坦软件园

#include <iconv.h>Ftx平坦软件园
#define BUFLEN 200Ftx平坦软件园

char inbuf[BUFLEN];Ftx平坦软件园
char outbuf[BUFLEN];Ftx平坦软件园
char* pin = inbuf;Ftx平坦软件园
char* pout = outbuf;Ftx平坦软件园

//打开文件,读入GB2312数据到inbuf,数据长度为 lenFtx平坦软件园
int inleft = len;Ftx平坦软件园
int outleft = BUFLEN;Ftx平坦软件园
iconv_t cd;Ftx平坦软件园

if((cd = iconv_open(“gb2312”, “unicode”)) == (iconv_t)-1)Ftx平坦软件园
          return 1;Ftx平坦软件园

if(iconv(cd, &pin, &inleft, &pout, &outleft) == (size_t)-1)Ftx平坦软件园
          return 1;Ftx平坦软件园

iconv_close(cd);Ftx平坦软件园

        使用 iconv () 时,需要注意参数的使用,inleft 是输入缓冲区数据数据长度,outleft是输出缓冲区大小。(需要保证输出缓冲区足够大)。转换以后,outleft 是outbuf中空闲空间的大小,所以 BUFLEN-outleft 才是真正的Unicode数据长度。Ftx平坦软件园

        注意:不论是GB2312编码,还是Unicode编码,在内存中都是一些字节序列,所以我们可以统一用 类型为 char(或者unsigned char)的字符数组来保存。所以,BUFLEN-outleft是 字符(char)个数,而不是Unicode字符个数。Ftx平坦软件园

        2、    Unicode 编码到 16-bit 编码的转换Ftx平坦软件园

        在得到 Unicode编码以后,还需要转换到 PDU 的16-bit 编码,才可以正确的发送。在这个转换过程中,需要注意两点:Ftx平坦软件园

        1)、Unicode 编码最开始的 0xFEFF标志要被去除,在0xFEFF之后的内容,才是真正的Unicode字符。(至于为什么有这个0xfeff标志,知道的朋友告诉我一声,呵呵)。Ftx平坦软件园
        2)、Unicode 是双字节字符,由于我的系统是小端字节序(little-endian),也就是说,在存储的时候,是先低位,后高位,例如“中”的Unicode编码是 0x4E2D,存储的时候是 2D4E,在转换到 16-bit编码的时候,要注意这个顺序的不同。当然,如果你的系统是大端字节序(big-endian),那么就不用这样做了。Ftx平坦软件园
        3)、为了将0x4E2D 的Unicode编码转换到 “4E2D” 的16-bit编码,可以用 sprintf(buf,    “%02X”,    outbuf[i]) 对每一个字节作转换。Ftx平坦软件园

        3、正确计算16-bit 编码的消息体长度Ftx平坦软件园

PDU规范中,需要包括消息体的长度,这里你要小心计算。Ftx平坦软件园

        4、正确设置 First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VPFtx平坦软件园

        在PDU格式中,First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP的设置正确与否,对能否发送 Unicode 至关重要。根据协议规范以及我的调试结果,以上几个标志的正确设置分别为(都是16进制):Ftx平坦软件园

First-Octet : 11    Ftx平坦软件园
TP-MR:          00Ftx平坦软件园
TP-PID:          00Ftx平坦软件园
TP-DCS:        08      (编码方式,16-bit)Ftx平坦软件园
TP-VP:           A7 Ftx平坦软件园

经过以上步骤,已经可以做到发送中文字符了。Ftx平坦软件园

/r/n/n本文来自CSDN博客,转载请标明出处:http://www./article/program/linux/2011-05-08/24696.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多