|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
手机短信息SMS的程序开发
$ K5 C, v5 U6 a9 E
% R% {* b! ~ V5 j& g( [$ M$ n目前手机短信息的应用越来越广泛,互联网上提供短信息发送的站点也越来越多,但一些站点的服务并不尽如人意,往往发出去的短信息石沉大海。最可靠的发送方法当然是用手中的手机了,如果设置了状态报告,更能确切知道对方是否收到了此条信息。手机发送尽管比较可靠, 但也存在输入麻烦、效率低的问题。本文介绍一种方法,只要手机能够与电脑相连(通过红外端口或用手机数据线连接串行口,同时手机支持GSM AT指令集),就可以通过自行编制的短信息发送软件,实现短信息的发送。
( i) z) K$ q8 R5 k2 j% _; Z
% g' W" }) ?0 E0 I, O现在市场上的大多数手机均支持类似于Modem控制的GSM AT指令集,该指令集是由诺基亚、爱立信、摩托罗拉和HP等厂家共同为GSM系统研制的,其中包含了对SMS(Short Message Service)的控制。
$ x' i% U* Z j- I, |3 A' SGSM AT相关指令的介绍
: ^& `; Q: E, Z, j5 y' a, a与SMS有关的GSM AT指令如表1所示:" ^/ c. H. F9 p" M Q% i1 e
表1 相关的GSM AT指令1 L. b3 U' w- d/ P' L1 S
对SMS的控制共有三种实现途径:
8 b: s& O/ F* ~+ uBlock Mode; + v0 N; {. G* K2 b
基于AT命令的Text Mode; % b7 d9 C& e. u8 [. K2 a
基于AT命令的PDU Mode。 # T5 H2 P4 r$ p* f
Text Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因此本文主要探讨PDU模式的发送。 8 Q& V" n/ h7 W; G+ b% l- v
计算机和手机的通信 * v# p# w5 N" S7 ^" p+ d
本文以西门子 S3568i为例,介绍如何实现短信息的发送。 " o' [' `0 V! C# Z/ G4 a
数据线连接 ! s8 [8 q6 i: U- ~9 w( _+ T2 C0 w
首先,通过S35/25数据线将手机与电脑串行口相连。然后,打开超级终端,选择直接串行口连接,端口参数设为19200速率、无校验、数据位8、停止位1。
$ k! |& M- D. M4 t0 `红外线连接
6 m- h' A' E9 b& n如果使用带红外端口的计算机,可以设置与手机的无线连接。首先确认计算机红外端口已打开,并将手机的红外线和收传真/数据功能打开,对接红外端口,计算机系统托盘上应当出现一个红外设备西门子S35(如果没有安装红外监视器,则不显示)。然后,打开超级终端,选择IrDa上的串行口。
$ j' ?' r7 \+ t# e连接测试
5 n, ]4 ], z7 z8 f# ~% K点击超级终端工具条上的呼叫按钮,输入AT并回车,屏幕上如果出现OK则表明计算机与手机的连接成功,这时就可以输入各类GSM AT指令了。 - Q5 q1 I& Z% T; G/ M S9 a3 J
如:查询手机厂家,输入AT+CGMI=<CR>,屏幕显示Siemens。
" p9 R0 B6 ?' c通常情况下,执行测试命令AT+CMGS=?<CR>,如果返回OK,表明手机支持此指令。该指令的完整语法格式如下:
# X7 a; o, M% D0 YIf PDU mode (+CMGF=0)+CMGS=<length><CR> DU is given <ctrl-Z/ESC> 3 `2 G) {* ^ M" j) E
如果短信息格式指令AT+CMGF返回的是0,则SMS格式为PDU模式,再执行AT+CMGS=<数据长度>命令后,手机返回“>”符号并等待输入,输入PDU数据并以^Z或Esc键结束。
7 k' i! `+ k( h: p* `) I7 m如果信息发送成功,则返回OK,并显示信息号:
) m% M: y6 M6 n' e# l1 U/ H# s7 m+CMGS: <mr> 0 }8 K1 ~' u) z C; n
如果发送失败,则返回如下信息: , J/ `8 s) G, r: l: k2 C" F0 u
+CMS ERROR: <err>
3 a, i) Z; Y8 H8 N' E! {PDU数据格式的分析 ( I2 ~: _9 b! I. _6 N
下面通过对存储在手机中的待发信息的分析,来介绍SMS PDU的数据格式。首先,用手机写一条短信息,发送手机号码为13605696031,信息内容为“Hello World!”。通过执行AT+CMGL=2可以读出此条信息。
' y1 k* [; W" Z( a* q: b. m操作过程如下(斜体字符为响应信息,{}内为注释):
. d- R5 k$ D) |$ D' ~AT 8 y; e7 d, a- W2 W( @
OK
( Q# A& l/ o9 F |0 U3 b8 W7 {; vAT+CMGL=2 {读未发短信息} . D$ K' }2 g, {3 V2 c
+CMGL: 1,2,,24 {1表示信息个数,2表示未发信息,24表示信息总容量} 7 U, O Z& }6 f4 |
08 91 683108501505F0 11 00 0B 81 3106656930F1 0000A7 0B E8329BFD06DDDF723619
+ T6 ]! Q. o A4 _2 XOK
2 P. }4 f0 X6 n) K: I, n; c下面分析这条信息: ! M* C2 V) D2 q+ y7 s
08:短信息中心地址长度。 ( S: ^* W f2 r0 g
91:短信息中心号码类型,91是TON/NPI。TON/NPI遵守International/E.164标准,指在号码前需加‘+’号;此外还可有其他数值,但91最常用。
. i0 S7 ^- r Y683108501505F0:短信息号码,是所使用的服务中心地址。由于位置上略有处理,实际号码应为:8613805515500(字母F意指长度减1),这是作者所在地GSM短信息中心的号码。 2 L# [$ K4 c; _5 R& G
11:文件头字节(header byte,是一种bitmask)。这里11指正常地发送短信息。 : p9 U' ]6 t- C+ ]" J
00:信息类型。
8 H( L- }3 u- V) R0 ~6 @5 n0B:被叫号码长度。 6 i5 a- e- E6 J' `9 v! |
81:被叫号码类型。 9 Y9 m C! j; p$ K3 g9 s# ]7 W( F. D
3106656930F1:被叫号码,也经过了移位处理,实际号码为13605696031。
9 `* i5 I0 A2 `# f- Y0000A7:短信息编码类型GSM Default Alphabet,如为中文则是000010。 X6 |' V; H( W
0B:短信息长度。 + E0 `0 [9 z( }' A' a! g( T8 u
E8329BFD06DDDF723619:短信息内容“Hello World!”。
: }& y. h7 o/ q6 X4 E短信息的编码方法及编程实现 # H1 t! o7 \+ L9 [: Y2 h# @5 ]/ ?! e
下面我们介绍纯英文和纯中文的信息编码方法。通过测试我们发现,每条发送的短信息前面部分均相同,只是被叫号码和短信息内容有变化。 8 L/ `# ]/ L# [- f2 H; p: {
1.英文编码 0 y) o1 D- C2 S$ a t+ u' G8 I, \
参见表2,设短信息内容为“Hello World!”。缺省的GSM 字符集为7位编码,可以简单地理解为ASCII码(ASCII值小于80Hex,因此,Bit8被忽略),依次将下一7位编码的后几位逐次移至前面,形成新的8位编码,参见表2箭头指示。需要注意的是第9行,移位计数已达7位,则直接将本编码前加0。GSM并非支持所有的ASCII字符显示。 + V) g! V. Y& h7 a1 s3 S
表2 英文编码的实现过程
/ R* e1 e8 X1 {4 V下面是实现英文编码的部分Delphi 5代码:
, d" s2 M# b. |0 V0 l6 k//英文格式编码,s为String
7 s* x9 Z& w$ Z8 S$ K- T% bfunction Encode1(var s:String):String;
1 {. c! K6 X8 mvar 9 [/ C* ?7 @' C
i,j,len:Integer; : S/ p7 f: X. U* p; F5 w9 H
cur:Integer; 7 I! `5 k4 r& b' m( D* W% a3 L
t:String;
: a8 e; B% [3 i v% lbegin 3 L7 q8 G, S9 S, ^5 ^
Result:=‘’; ) Y9 C! b$ _% ~$ ~$ x
len:=Length(s);
& w1 X4 T1 ?' \//j 用于移位计数
5 f; J; y- ]# u* D0 v" \4 C; x; a) `i:=1;j:=0; 5 ]% r% W8 D1 Z0 M1 n
while i<=len do ( L0 p- O5 p& [% S" X
begin
% {- f. w1 N. }4 n- Lif i<len then
; R' c# y5 k7 q0 x+ E//数据变换 2 z, E& Z' S/ o2 T. o! N9 G
cur:=(ord(s) shr j) or ((ord(s[i+1]) shl (7-j)) and $ff) 2 H! ^1 D6 \# g. G# T$ w
else - R' b2 K1 P9 h) Z
cur:=(ord(s) shr j) and $7f;
* o) X @: Q0 s# _ S/ tFmtStr(t,‘%2.2X’,[cur]);
3 \) B+ `1 j3 H7 ^9 S5 j5 v& xResult:=Result+t; 4 p @ D, B ^) D- C
inc(i);
' I ^2 ?3 E& [. Q" T) z7 y# C//移位计数达到7位的特别处理 " Z# V/ {/ L) T% [
j:=(j+1) mod 7;if j=0 then inc(i);
7 D8 s, r2 n; h5 `5 xend; " r) d; ]9 G, h+ k7 I) I8 N0 a
end;
6 J2 v) {8 r5 {7 Z' O2.中文编码 : I* _8 n6 j8 l( N# x
参见表3,设短信息内容为“中文短信息”。中文短信息的实现较简单,只需将GB2312的中文编码转换为代码页为CP936的Unicode编码即可。
" @8 ]- \8 J# O3 b5 J% {0 D5 @表3 中文编码的实现过程
) t W0 e {# ^* P4 k, \8 T( v0 X- L3 S& Y通过Delphi的WideString类型转换,可以巧妙地实现GB2312到Unicode的编码转换(注意代码页和操作系统相关联)。下面是实现中文编码的部分Delphi 5代码:
% o$ }" |, O3 @6 b3 ]9 |// 中文格式编码,s为Unicode String
5 B/ a* [8 Q' M3 ofunction Encode2(var s:WideString):String;
$ o9 B% B" _( Avar ; q% A9 h$ M2 g. |6 @1 T
i,len:Integer; / r* I: G. h. p/ T6 x, a
cur:Integer;
: }, M5 Y9 _' i" h- Ct:String; 6 B5 H# U) j# ~1 V
begin
' Z2 w4 z& X# x/ A) wResult:=‘’; % i" R# m. N0 q1 N2 ?2 _
len:=Length(s); 3 h0 B% t& A% ~; a
i:=1; 3 [8 d8 H3 _9 G4 q
while i<=len do
1 x# b! C: W' E7 p. d$ Lbegin
+ A# b4 S5 v% z0 Ucur:=ord(s); + [6 w" e$ v+ k: J, E
//BCD转换 ) t0 a- Z3 f/ K7 ~9 j$ Y; i1 O
FmtStr(t,‘%4.4X’,[cur]); 7 I$ X* N. x% P& K6 [( u# h/ y
Result:=Result+t; 5 o1 ~& F7 G \& X# n& N7 ?
inc(i); ! ^( M/ }; K; s* \! u, p
end;
, G% @3 E1 y4 s/ c% E1 ?! g% Lend; # d; X) H# L. u; ^4 }
小 结
% P6 R# m" r% o以上介绍了PDU格式的短信息编码。建议英文信息长度不超过140个字符,中文信息不要超过54个汉字。如果使用能够支持文本方式的手机进行发送,实现起来更简单。如发送“Hello World!”,用如下的AT指令即可:
1 ?' X6 w! I! O& X2 Z1 eAT+CGMF=1<CR>AT+CGMS=“13605696031”,129<CR>
0 n" T, U6 c, _) d! A y( C- e>Hello World!<^Z> 5 H% M2 l& e7 x* G. ?1 _$ z7 I
# \! l x$ c ~# G3 d9 m
|
|