|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
手机短信息SMS的程序开发 5 M- P# B) d; O9 N& `
0 D* U' f3 o* H! n- R
目前手机短信息的应用越来越广泛,互联网上提供短信息发送的站点也越来越多,但一些站点的服务并不尽如人意,往往发出去的短信息石沉大海。最可靠的发送方法当然是用手中的手机了,如果设置了状态报告,更能确切知道对方是否收到了此条信息。手机发送尽管比较可靠, 但也存在输入麻烦、效率低的问题。本文介绍一种方法,只要手机能够与电脑相连(通过红外端口或用手机数据线连接串行口,同时手机支持GSM AT指令集),就可以通过自行编制的短信息发送软件,实现短信息的发送。
6 G0 Y4 `6 I7 T- h/ \/ h! [, X1 ^
( S2 W$ W: @1 r b. ^) I/ `现在市场上的大多数手机均支持类似于Modem控制的GSM AT指令集,该指令集是由诺基亚、爱立信、摩托罗拉和HP等厂家共同为GSM系统研制的,其中包含了对SMS(Short Message Service)的控制。
! t O# }+ d% C- j2 XGSM AT相关指令的介绍 ! d6 @( M" U' k5 Q& O! M. M
与SMS有关的GSM AT指令如表1所示:) w& I5 z$ |6 f, l/ k3 D, E
表1 相关的GSM AT指令/ B' _! c" P* n
对SMS的控制共有三种实现途径: * r+ x E. U4 J( z m( Y1 m$ ^
Block Mode;
' R+ B- d# L. y2 q基于AT命令的Text Mode; . K: @6 E" R& J, ^
基于AT命令的PDU Mode。 2 @8 I& `) f9 @2 J/ t4 G" W! q
Text Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因此本文主要探讨PDU模式的发送。 ' o7 i; r1 Q% D4 z
计算机和手机的通信
4 ^# k5 [1 j: ?1 d本文以西门子 S3568i为例,介绍如何实现短信息的发送。 $ m" t# Q- _7 G& C# V Q9 q
数据线连接
& T$ E+ x1 n% Y2 S- o* M9 z首先,通过S35/25数据线将手机与电脑串行口相连。然后,打开超级终端,选择直接串行口连接,端口参数设为19200速率、无校验、数据位8、停止位1。 2 Z8 |5 J* v1 V+ K; Z
红外线连接
) d0 `* L u2 N: v6 x+ g ]" {) Z$ v如果使用带红外端口的计算机,可以设置与手机的无线连接。首先确认计算机红外端口已打开,并将手机的红外线和收传真/数据功能打开,对接红外端口,计算机系统托盘上应当出现一个红外设备西门子S35(如果没有安装红外监视器,则不显示)。然后,打开超级终端,选择IrDa上的串行口。
: ^/ L- i, ~! k! K, ~3 [2 I1 a连接测试
! q, x+ ~6 H5 q( E6 ?5 s3 e点击超级终端工具条上的呼叫按钮,输入AT并回车,屏幕上如果出现OK则表明计算机与手机的连接成功,这时就可以输入各类GSM AT指令了。 5 r1 E, c0 y; {! [
如:查询手机厂家,输入AT+CGMI=<CR>,屏幕显示Siemens。 5 Y) |, g1 m- }& ?; Q& d
通常情况下,执行测试命令AT+CMGS=?<CR>,如果返回OK,表明手机支持此指令。该指令的完整语法格式如下: 6 ^' p" R0 q @; _
If PDU mode (+CMGF=0)+CMGS=<length><CR> DU is given <ctrl-Z/ESC> ' x' ?; A8 }! a6 M" w
如果短信息格式指令AT+CMGF返回的是0,则SMS格式为PDU模式,再执行AT+CMGS=<数据长度>命令后,手机返回“>”符号并等待输入,输入PDU数据并以^Z或Esc键结束。 8 ?3 g- Q! \+ A f2 \
如果信息发送成功,则返回OK,并显示信息号:
( }* u- ~* g- ~0 q! e4 G% z+CMGS: <mr>
5 ]' m- s: Q% a. K如果发送失败,则返回如下信息:
, ?7 ^# u. r t& E+CMS ERROR: <err> $ r( y7 H$ r9 v
PDU数据格式的分析
, W+ W% B$ E9 R8 W D5 A5 g下面通过对存储在手机中的待发信息的分析,来介绍SMS PDU的数据格式。首先,用手机写一条短信息,发送手机号码为13605696031,信息内容为“Hello World!”。通过执行AT+CMGL=2可以读出此条信息。 % R; u2 k; k+ A7 B7 s
操作过程如下(斜体字符为响应信息,{}内为注释): 7 K' o% X6 t2 O
AT
, L% h% ~: c: ~. p3 v7 b- sOK
8 a, K) x1 m0 |2 q1 I9 D) gAT+CMGL=2 {读未发短信息}
( {+ r' a/ U* O/ r( t" D, x+CMGL: 1,2,,24 {1表示信息个数,2表示未发信息,24表示信息总容量}
: b% {4 ~& A& T/ Z* ?7 d4 D08 91 683108501505F0 11 00 0B 81 3106656930F1 0000A7 0B E8329BFD06DDDF723619 4 w4 @& T" x: h* j# |( L5 P
OK ) q$ v" g* x7 J: C* d; Q( h1 j
下面分析这条信息: 4 ^9 H6 E" e* \ O
08:短信息中心地址长度。
4 }0 a. @1 }6 c+ b91:短信息中心号码类型,91是TON/NPI。TON/NPI遵守International/E.164标准,指在号码前需加‘+’号;此外还可有其他数值,但91最常用。 ! Y# |' E Q V( }8 ?
683108501505F0:短信息号码,是所使用的服务中心地址。由于位置上略有处理,实际号码应为:8613805515500(字母F意指长度减1),这是作者所在地GSM短信息中心的号码。
o% D( h2 E1 \+ j11:文件头字节(header byte,是一种bitmask)。这里11指正常地发送短信息。
5 ]$ Z5 f) v& q& ]" p00:信息类型。
4 |. i+ S& _$ x7 y) ?/ U4 }. ^; X C0B:被叫号码长度。 8 f# H) s8 A) K- ~$ e: H! \
81:被叫号码类型。
& E& x- F; r! F1 h0 Z3106656930F1:被叫号码,也经过了移位处理,实际号码为13605696031。
/ b" N6 I1 @ z3 U) H/ ^0000A7:短信息编码类型GSM Default Alphabet,如为中文则是000010。 % R6 b- I2 y; U- l- ?
0B:短信息长度。 0 b. S* `$ B1 M
E8329BFD06DDDF723619:短信息内容“Hello World!”。
# ?2 N; G0 O- Q短信息的编码方法及编程实现
# J: f5 s% T% U5 T9 u" ~: j下面我们介绍纯英文和纯中文的信息编码方法。通过测试我们发现,每条发送的短信息前面部分均相同,只是被叫号码和短信息内容有变化。
. i& E8 P E4 x/ Z7 Z$ w- m1.英文编码 ; Y) n; Y7 m* P) Q5 c3 [3 C4 x: O
参见表2,设短信息内容为“Hello World!”。缺省的GSM 字符集为7位编码,可以简单地理解为ASCII码(ASCII值小于80Hex,因此,Bit8被忽略),依次将下一7位编码的后几位逐次移至前面,形成新的8位编码,参见表2箭头指示。需要注意的是第9行,移位计数已达7位,则直接将本编码前加0。GSM并非支持所有的ASCII字符显示。 . o( F, c& n% g* ]& p* G
表2 英文编码的实现过程
/ K2 R* |8 s" O1 G, Q下面是实现英文编码的部分Delphi 5代码: # h* I/ d( J# Y* `7 r$ e" [0 L
//英文格式编码,s为String - Q" p6 A) p4 U; e# n' `
function Encode1(var s:String):String; $ }& R: W( `7 V
var 0 P8 ~" g. o/ S1 U
i,j,len:Integer;
) k% D) @- Y. J% Wcur:Integer;
0 ^! W6 y1 `+ Q3 M7 xt:String;
" A2 Y$ Q5 E0 i* y0 B7 [8 a+ e. i" Abegin 7 ~/ U7 e) f1 D" M9 o! d
Result:=‘’; " K% B5 I+ G/ z+ j8 }. W
len:=Length(s);
: I0 V5 y+ R8 Z% p% w5 U0 J//j 用于移位计数 " L" ?$ V! k9 n+ s( \: m0 J% R3 |" N
i:=1;j:=0; 5 C6 ]9 m) p2 a: o1 y5 [8 \! Q7 U
while i<=len do 2 a) c$ x) k& U% A$ b& y
begin / P* {$ g/ | e* B
if i<len then # F6 D# d. @& C& s& i$ n8 ? I* p2 Q
//数据变换
; F# s& `$ J; w9 lcur:=(ord(s) shr j) or ((ord(s[i+1]) shl (7-j)) and $ff) 5 X$ E% c) S, A* ~8 d" |
else L/ a$ Y: R2 q" l) @: y
cur:=(ord(s) shr j) and $7f; , m1 p/ M& {# R6 G& e
FmtStr(t,‘%2.2X’,[cur]);
- Q5 w9 `* O; U2 ~Result:=Result+t;
" M8 m. X( [$ C/ Q, \inc(i);
! z: }- E. Z. P( @0 B//移位计数达到7位的特别处理 - ` }6 L* m: C0 u, P9 e
j:=(j+1) mod 7;if j=0 then inc(i);
, @( B, A2 N( e8 Mend;
% @9 K6 V V5 eend;
* B: E" w" S8 P1 \ f3 B2.中文编码
+ k7 G$ Q8 j4 n1 K& e0 C: T& N6 Z参见表3,设短信息内容为“中文短信息”。中文短信息的实现较简单,只需将GB2312的中文编码转换为代码页为CP936的Unicode编码即可。
/ n) h, C8 `* W" _- ^! `表3 中文编码的实现过程; s- U6 c8 F7 v% A3 e, z0 Y
通过Delphi的WideString类型转换,可以巧妙地实现GB2312到Unicode的编码转换(注意代码页和操作系统相关联)。下面是实现中文编码的部分Delphi 5代码: ) Q( J( y. |. _0 l4 ]
// 中文格式编码,s为Unicode String
5 K4 R5 d% a' P9 O3 Ufunction Encode2(var s:WideString):String; ! P& l C9 H! Y8 ?- x' F) M
var
+ j& v* T& N9 g! Ii,len:Integer;
5 h& K0 m* {4 i' kcur:Integer; ' b1 Z1 |- L3 Y ]2 Y4 j
t:String;
5 _8 x4 U/ L; r( P0 U$ Y+ p( _/ c/ ^begin
) T" ^$ R v0 OResult:=‘’; * g/ h& G0 e4 R, y6 o+ a1 A8 \$ C
len:=Length(s);
6 n P! g7 I j! ui:=1; / G, G/ b2 G" f$ h9 b0 b2 t
while i<=len do
- @: v6 f+ Y* [7 R9 T7 z/ K# Hbegin
A6 @/ Z. {, ?) ucur:=ord(s); , K A5 K# ^" i( e: q" f
//BCD转换
: h' W; v# r% L( v* s R) g4 qFmtStr(t,‘%4.4X’,[cur]); ; l# [$ T g$ }9 N4 ^! l# j
Result:=Result+t;
" c. o" \/ e0 y1 e1 P' rinc(i); # D0 T0 |& T d$ `9 r# l
end;
E0 G4 @' `! e/ kend;
2 W+ Y* J$ E& c+ F; p" r小 结
; |+ i1 k4 u7 n8 A/ Q以上介绍了PDU格式的短信息编码。建议英文信息长度不超过140个字符,中文信息不要超过54个汉字。如果使用能够支持文本方式的手机进行发送,实现起来更简单。如发送“Hello World!”,用如下的AT指令即可: ( L% ~ G- _ n& O
AT+CGMF=1<CR>AT+CGMS=“13605696031”,129<CR>
8 {$ S U$ D7 l U# q>Hello World!<^Z>
/ y( x1 d: ~$ i# | Y
+ R9 Q1 j0 |+ a, f) Y; [3 Y2 d) G) G |
|