|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
手机短信息SMS的程序开发
# ~ d( k+ h0 F- O# }' L8 [, y$ K* R M9 F& W: h
目前手机短信息的应用越来越广泛,互联网上提供短信息发送的站点也越来越多,但一些站点的服务并不尽如人意,往往发出去的短信息石沉大海。最可靠的发送方法当然是用手中的手机了,如果设置了状态报告,更能确切知道对方是否收到了此条信息。手机发送尽管比较可靠, 但也存在输入麻烦、效率低的问题。本文介绍一种方法,只要手机能够与电脑相连(通过红外端口或用手机数据线连接串行口,同时手机支持GSM AT指令集),就可以通过自行编制的短信息发送软件,实现短信息的发送。/ S& g7 I) N6 w; Q4 M
1 |( K( e+ q; b6 `$ E* e9 G& e现在市场上的大多数手机均支持类似于Modem控制的GSM AT指令集,该指令集是由诺基亚、爱立信、摩托罗拉和HP等厂家共同为GSM系统研制的,其中包含了对SMS(Short Message Service)的控制。
% w# \( q5 g% `GSM AT相关指令的介绍 + y7 D6 N( l5 A+ j
与SMS有关的GSM AT指令如表1所示:3 V# m# k& [$ o* b
表1 相关的GSM AT指令
# W* N) [( x6 j4 I5 A2 k! x对SMS的控制共有三种实现途径: ( x$ s: R F+ a* W3 I+ X1 v- Z
Block Mode; " v# |5 Z! Y# G* ?0 l n
基于AT命令的Text Mode; $ D$ U$ r- W# K! E% s1 P
基于AT命令的PDU Mode。
$ X$ |# `# J9 v9 p/ fText Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因此本文主要探讨PDU模式的发送。 6 g, L8 Y8 m" E p
计算机和手机的通信
8 F" R- ~" K, f0 g9 ?- G7 I本文以西门子 S3568i为例,介绍如何实现短信息的发送。 3 `0 R) C* Q H( ^# d7 v- G
数据线连接 2 W5 V4 U; m$ P! {1 p8 X
首先,通过S35/25数据线将手机与电脑串行口相连。然后,打开超级终端,选择直接串行口连接,端口参数设为19200速率、无校验、数据位8、停止位1。
( J0 e: y" I( h$ Z) y* j& ?6 M红外线连接
; T+ l& k1 {, x" t如果使用带红外端口的计算机,可以设置与手机的无线连接。首先确认计算机红外端口已打开,并将手机的红外线和收传真/数据功能打开,对接红外端口,计算机系统托盘上应当出现一个红外设备西门子S35(如果没有安装红外监视器,则不显示)。然后,打开超级终端,选择IrDa上的串行口。 8 F) a, l$ @* q
连接测试 4 m' c9 B8 \2 S! J' B
点击超级终端工具条上的呼叫按钮,输入AT并回车,屏幕上如果出现OK则表明计算机与手机的连接成功,这时就可以输入各类GSM AT指令了。 ]0 S- ~. z% M% Y% V. c
如:查询手机厂家,输入AT+CGMI=<CR>,屏幕显示Siemens。 8 J1 I6 N k) K# d
通常情况下,执行测试命令AT+CMGS=?<CR>,如果返回OK,表明手机支持此指令。该指令的完整语法格式如下: ' ?* H) x. x2 X0 F; G. W3 Y
If PDU mode (+CMGF=0)+CMGS=<length><CR> DU is given <ctrl-Z/ESC> * c+ M K0 N% ~6 B
如果短信息格式指令AT+CMGF返回的是0,则SMS格式为PDU模式,再执行AT+CMGS=<数据长度>命令后,手机返回“>”符号并等待输入,输入PDU数据并以^Z或Esc键结束。
5 A7 U( l) k4 H. f z如果信息发送成功,则返回OK,并显示信息号:
' W; F6 `( ?8 o. ~+ O3 W) ?+CMGS: <mr> 4 J: b/ X. P9 E% j5 g% _7 S
如果发送失败,则返回如下信息:
- v8 L2 P( Y" T: j+CMS ERROR: <err>
- h6 a9 z* D6 z1 u3 RPDU数据格式的分析 % j" ?; L# _) n! O
下面通过对存储在手机中的待发信息的分析,来介绍SMS PDU的数据格式。首先,用手机写一条短信息,发送手机号码为13605696031,信息内容为“Hello World!”。通过执行AT+CMGL=2可以读出此条信息。
8 [! v1 s/ h* }' G- q操作过程如下(斜体字符为响应信息,{}内为注释): . ^: E; I7 i$ m7 E
AT
! c% }/ H+ A+ B" p% rOK 4 i$ w2 d9 ]7 g" T( _1 g/ @4 {
AT+CMGL=2 {读未发短信息}
' @3 w( X1 h' D. y% T. R+CMGL: 1,2,,24 {1表示信息个数,2表示未发信息,24表示信息总容量}
U6 B; e: F7 c* h) A8 J4 @# H, D08 91 683108501505F0 11 00 0B 81 3106656930F1 0000A7 0B E8329BFD06DDDF723619 - C$ _7 T- z! V6 |* t
OK 9 E4 l2 a& Y/ E, ^8 a
下面分析这条信息:
$ x/ |6 P+ W1 f0 A; ?, K$ ~08:短信息中心地址长度。
8 `5 e- V! o/ c; d8 h+ w3 p91:短信息中心号码类型,91是TON/NPI。TON/NPI遵守International/E.164标准,指在号码前需加‘+’号;此外还可有其他数值,但91最常用。 & [( K5 [1 g0 }: @
683108501505F0:短信息号码,是所使用的服务中心地址。由于位置上略有处理,实际号码应为:8613805515500(字母F意指长度减1),这是作者所在地GSM短信息中心的号码。 ' Z7 H! K" [2 Q
11:文件头字节(header byte,是一种bitmask)。这里11指正常地发送短信息。 2 k3 b# u& ?3 C: h4 I
00:信息类型。 $ l; L) ?. ]8 h4 M$ T
0B:被叫号码长度。 , y* X. r! d7 H$ \. q
81:被叫号码类型。 5 I$ Q( G& U' y) m, t Q
3106656930F1:被叫号码,也经过了移位处理,实际号码为13605696031。
7 W# d; ^& O8 o2 ?2 W; o1 F2 `) W o0000A7:短信息编码类型GSM Default Alphabet,如为中文则是000010。
' e: {2 M( m, g1 ]0B:短信息长度。
# b% j: A. ~+ J1 [6 V; B! VE8329BFD06DDDF723619:短信息内容“Hello World!”。
" E* Q- j$ ] |3 W" t3 h短信息的编码方法及编程实现
* ~1 e$ W: n/ F6 L+ t下面我们介绍纯英文和纯中文的信息编码方法。通过测试我们发现,每条发送的短信息前面部分均相同,只是被叫号码和短信息内容有变化。
: Q6 v7 x( W* W7 ^, L1.英文编码 3 g* T! J( v; Q) V- K+ u- |& ?
参见表2,设短信息内容为“Hello World!”。缺省的GSM 字符集为7位编码,可以简单地理解为ASCII码(ASCII值小于80Hex,因此,Bit8被忽略),依次将下一7位编码的后几位逐次移至前面,形成新的8位编码,参见表2箭头指示。需要注意的是第9行,移位计数已达7位,则直接将本编码前加0。GSM并非支持所有的ASCII字符显示。
+ H. `- {+ I1 L0 x( o0 d表2 英文编码的实现过程, h5 I" D5 s& C7 x: e7 e: l: N
下面是实现英文编码的部分Delphi 5代码:
* D& K, M5 N# l% |( s//英文格式编码,s为String
+ J) w% ^9 Y0 a3 ofunction Encode1(var s:String):String;
( B$ u: m5 O9 j0 ]9 W: i+ e, p2 Rvar : |# T4 _2 @! K% u, A) K
i,j,len:Integer; / h0 L* @& f, |1 P' m+ k
cur:Integer;
( I4 j( E7 I2 Q' F0 Y4 Mt:String;
) w1 b. l" }+ P5 @: l% Ibegin
2 A- X5 A: B" R" }5 `Result:=‘’; , h& f4 W3 J2 Q- T, N M
len:=Length(s);
1 `7 }% ~ t7 y. \7 g( n# y' n//j 用于移位计数
+ |5 R. s. ?! F( E4 C- n: Ji:=1;j:=0; ' X% c# Y& x5 n5 _* g5 V
while i<=len do
9 Y+ b% G! K/ o/ H2 zbegin : E5 l6 L8 M2 _4 J, a
if i<len then ' w9 N) c" i' W8 S# {- Q4 [
//数据变换 + {* ?. q' G, [" z7 M4 u- L
cur:=(ord(s) shr j) or ((ord(s[i+1]) shl (7-j)) and $ff)
# g) Z1 P+ t# @. A; X% selse ; q2 Z1 f. r- g# N Z1 G
cur:=(ord(s) shr j) and $7f;
2 u! z' e: `6 J8 ~: \, BFmtStr(t,‘%2.2X’,[cur]); , \; P, J1 z( R( G6 [1 ?
Result:=Result+t;
8 ~! j3 {$ a9 J! {7 T. Tinc(i); ) k3 q; L; a) x" V
//移位计数达到7位的特别处理 4 R) a. Z3 b6 l# k% u
j:=(j+1) mod 7;if j=0 then inc(i);
8 ?$ }5 w% O1 `end; 1 F: W+ A2 O$ ?( a! B
end;
0 ^6 J' ?$ ~9 ]5 t- @9 |4 M6 z2.中文编码
5 `( j2 G8 s/ ?$ V% z9 T0 _参见表3,设短信息内容为“中文短信息”。中文短信息的实现较简单,只需将GB2312的中文编码转换为代码页为CP936的Unicode编码即可。 ; ^0 h1 |& \5 ?$ Y) Y& A% t
表3 中文编码的实现过程
% K4 G6 l8 j: f3 t$ J7 ^( }6 B通过Delphi的WideString类型转换,可以巧妙地实现GB2312到Unicode的编码转换(注意代码页和操作系统相关联)。下面是实现中文编码的部分Delphi 5代码: ' J5 Z; ]5 l5 X! B/ |: F
// 中文格式编码,s为Unicode String
* ]) H* D0 ]0 u0 L4 r( _8 m2 Vfunction Encode2(var s:WideString):String;
' Y9 L$ |* [3 J4 h1 N6 Ivar
% ^- }# h" K/ Ai,len:Integer;
$ C! r5 s* Q2 N. m, ccur:Integer;
. N. y. D, y$ L9 l6 P" Kt:String; + [2 @9 ~* V% m, Q
begin 3 U7 Y3 M( x( `) M
Result:=‘’;
( g& G& T( H" e1 M5 Llen:=Length(s);
' q/ U- \8 _+ Q8 ?# X1 v2 mi:=1;
: S4 X8 M+ i0 t; v. Z0 y) ?while i<=len do 0 S8 p( I1 U/ d! J: b0 Z
begin % I/ ]! j4 s; ]4 ]0 S: d5 u, W. g
cur:=ord(s);
1 m' C' _! }! ]) G0 m5 x8 z$ J//BCD转换
. r- {$ P8 J6 B" i# T4 i* { U( UFmtStr(t,‘%4.4X’,[cur]);
2 |6 t" A* }1 PResult:=Result+t;
: u0 H. C U5 C z1 n* |inc(i);
: ?9 U" ^5 n r9 E# U+ p* e- U; Eend;
% L* A7 D. o2 a, r6 yend; 2 B' `! i1 X" Z8 u2 I% d- I$ |
小 结
4 m/ \1 P; X/ X4 L以上介绍了PDU格式的短信息编码。建议英文信息长度不超过140个字符,中文信息不要超过54个汉字。如果使用能够支持文本方式的手机进行发送,实现起来更简单。如发送“Hello World!”,用如下的AT指令即可:
7 `+ a: E# F% l8 s# t3 _- l; i1 SAT+CGMF=1<CR>AT+CGMS=“13605696031”,129<CR> ( [( A Q% `) I
>Hello World!<^Z>
5 y8 M2 c, t4 X1 z, n5 E( b) D
0 I& s. K; M: M# I |
|