|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
手机短信息SMS的程序开发
) m9 K p/ _* S8 [& a( \2 R y5 D0 n
目前手机短信息的应用越来越广泛,互联网上提供短信息发送的站点也越来越多,但一些站点的服务并不尽如人意,往往发出去的短信息石沉大海。最可靠的发送方法当然是用手中的手机了,如果设置了状态报告,更能确切知道对方是否收到了此条信息。手机发送尽管比较可靠, 但也存在输入麻烦、效率低的问题。本文介绍一种方法,只要手机能够与电脑相连(通过红外端口或用手机数据线连接串行口,同时手机支持GSM AT指令集),就可以通过自行编制的短信息发送软件,实现短信息的发送。
/ `1 }8 v w; G( H3 G
7 H% I4 S$ e' R4 B; W7 x现在市场上的大多数手机均支持类似于Modem控制的GSM AT指令集,该指令集是由诺基亚、爱立信、摩托罗拉和HP等厂家共同为GSM系统研制的,其中包含了对SMS(Short Message Service)的控制。 $ W' D8 R5 n+ e8 ]
GSM AT相关指令的介绍 # Y! R' u( X" }
与SMS有关的GSM AT指令如表1所示:6 P" M0 s$ N$ X- ^+ o2 f. i: `
表1 相关的GSM AT指令# C, _6 g. L- V) T3 b
对SMS的控制共有三种实现途径:
) I! ?2 l, u$ T) r! _Block Mode;
/ a& f4 I! S* V8 U! M+ K" V+ `基于AT命令的Text Mode; - o* Z# @& U9 A x4 s% L* k
基于AT命令的PDU Mode。
3 T" {4 R) H6 hText Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因此本文主要探讨PDU模式的发送。
) h5 c% V& V+ Y; s, ^- n: a/ Z2 }计算机和手机的通信 ' x' o+ T. I4 @
本文以西门子 S3568i为例,介绍如何实现短信息的发送。 - T1 ]2 U5 h2 l3 \
数据线连接 6 `4 j% \: X, N- r
首先,通过S35/25数据线将手机与电脑串行口相连。然后,打开超级终端,选择直接串行口连接,端口参数设为19200速率、无校验、数据位8、停止位1。
8 z4 o) n/ A4 \& [红外线连接 5 `, e1 a1 B D Z6 C
如果使用带红外端口的计算机,可以设置与手机的无线连接。首先确认计算机红外端口已打开,并将手机的红外线和收传真/数据功能打开,对接红外端口,计算机系统托盘上应当出现一个红外设备西门子S35(如果没有安装红外监视器,则不显示)。然后,打开超级终端,选择IrDa上的串行口。
, G1 F% Y& l" q连接测试
4 Z/ c2 z: t3 @" s点击超级终端工具条上的呼叫按钮,输入AT并回车,屏幕上如果出现OK则表明计算机与手机的连接成功,这时就可以输入各类GSM AT指令了。 * k- ~8 s/ O+ y; H; d w, b! c0 ^$ m
如:查询手机厂家,输入AT+CGMI=<CR>,屏幕显示Siemens。
* g, A' O) l2 a# q( f& f" O通常情况下,执行测试命令AT+CMGS=?<CR>,如果返回OK,表明手机支持此指令。该指令的完整语法格式如下:
" a6 k6 _% o( WIf PDU mode (+CMGF=0)+CMGS=<length><CR> DU is given <ctrl-Z/ESC>
7 I4 U0 t1 A2 r如果短信息格式指令AT+CMGF返回的是0,则SMS格式为PDU模式,再执行AT+CMGS=<数据长度>命令后,手机返回“>”符号并等待输入,输入PDU数据并以^Z或Esc键结束。 & _2 m+ n$ E4 W' p$ g; x
如果信息发送成功,则返回OK,并显示信息号:
$ U- A; J" x$ D) L" @7 w+CMGS: <mr>
( O$ r5 x. a# c' C0 r. Y如果发送失败,则返回如下信息: - A. |7 W" `& s9 z# n+ N
+CMS ERROR: <err> & F0 w& z9 {2 f* f2 |
PDU数据格式的分析 $ f; D, n! Z% a9 q1 _8 H# T
下面通过对存储在手机中的待发信息的分析,来介绍SMS PDU的数据格式。首先,用手机写一条短信息,发送手机号码为13605696031,信息内容为“Hello World!”。通过执行AT+CMGL=2可以读出此条信息。
* `) D% J0 h# n/ @" p+ N* n操作过程如下(斜体字符为响应信息,{}内为注释): 8 w/ Q. V" b- j; X, e1 w# G2 [- ^
AT , c% {2 z/ Z) {; e
OK * P+ s( y' H9 [! }' c% b7 H% Y3 V
AT+CMGL=2 {读未发短信息} ) a3 s- d& e( t% g( I( |
+CMGL: 1,2,,24 {1表示信息个数,2表示未发信息,24表示信息总容量} 4 V8 p8 d) u# L$ {8 i9 X' J1 f# K
08 91 683108501505F0 11 00 0B 81 3106656930F1 0000A7 0B E8329BFD06DDDF723619
- P- K" I/ M" p7 n- hOK
6 h% i& j. x- m下面分析这条信息:
. S& M$ y2 h0 G9 @8 S1 M9 u4 X08:短信息中心地址长度。 # F- p9 D" o7 n7 x( T
91:短信息中心号码类型,91是TON/NPI。TON/NPI遵守International/E.164标准,指在号码前需加‘+’号;此外还可有其他数值,但91最常用。
0 _2 A( B4 M+ @$ s683108501505F0:短信息号码,是所使用的服务中心地址。由于位置上略有处理,实际号码应为:8613805515500(字母F意指长度减1),这是作者所在地GSM短信息中心的号码。 % H q4 ^1 y. t7 e
11:文件头字节(header byte,是一种bitmask)。这里11指正常地发送短信息。 ! p+ e$ Q' Y2 y$ z- h5 q* a
00:信息类型。
7 ~- o6 U, j4 P# a4 {4 L, o0B:被叫号码长度。 ) r7 W! Y" K) ^6 Q& q
81:被叫号码类型。
) J. L- ^( ~, u3106656930F1:被叫号码,也经过了移位处理,实际号码为13605696031。
# w6 B, c* E# _- k0000A7:短信息编码类型GSM Default Alphabet,如为中文则是000010。 ! S$ ~, [/ Z8 h! ~! f
0B:短信息长度。
! ^4 X1 w* N7 |0 ~8 {E8329BFD06DDDF723619:短信息内容“Hello World!”。
# P5 q# T) k- X, ~/ j- T短信息的编码方法及编程实现
$ m# v" Y0 H4 J% _5 Q; A4 c下面我们介绍纯英文和纯中文的信息编码方法。通过测试我们发现,每条发送的短信息前面部分均相同,只是被叫号码和短信息内容有变化。
+ z0 ], ?4 f& j# {7 t1 J% ]5 b1.英文编码 - s: P, g$ y8 s- c- t/ E7 ]* U# i
参见表2,设短信息内容为“Hello World!”。缺省的GSM 字符集为7位编码,可以简单地理解为ASCII码(ASCII值小于80Hex,因此,Bit8被忽略),依次将下一7位编码的后几位逐次移至前面,形成新的8位编码,参见表2箭头指示。需要注意的是第9行,移位计数已达7位,则直接将本编码前加0。GSM并非支持所有的ASCII字符显示。 0 h/ e! y* S/ } c( Y! e( x7 T
表2 英文编码的实现过程. `# [# S: I4 T+ d, F
下面是实现英文编码的部分Delphi 5代码:
0 f0 ^' q) [6 A9 T* m//英文格式编码,s为String
2 z% Y0 g! ^8 \# O, Gfunction Encode1(var s:String):String;
, Y \) Z$ G4 X, `var 6 s5 h5 P% Z' [: |, u) R; r
i,j,len:Integer;
9 G" f, }* \, u# B# N$ [$ \3 q% z* wcur:Integer; , u& }+ z& d6 R8 V( {5 R8 N
t:String; & W6 L) p1 Z* v2 z% ~
begin 1 V+ @2 U( [4 n3 j$ Z" `
Result:=‘’; ! B" j2 p" d! M: {6 k$ X: r
len:=Length(s); 0 [: ^9 @9 I m
//j 用于移位计数 # v. v8 M* J/ C9 I2 Y
i:=1;j:=0; ) o0 ]1 h0 ?* L; ^4 I3 S7 V
while i<=len do ; I: I, d% R2 S) v
begin : H8 ]/ }/ U% t& U! i& K
if i<len then ' L7 V, R2 B# i' k" }
//数据变换 1 f; ?; Q1 b8 {! V+ H; F
cur:=(ord(s) shr j) or ((ord(s[i+1]) shl (7-j)) and $ff) $ |0 h9 ~& [. J
else ( |3 f( f7 L' m3 J
cur:=(ord(s) shr j) and $7f;
. K/ J' }2 a4 R5 J$ h' kFmtStr(t,‘%2.2X’,[cur]);
% q' G) x- q, ~4 C1 ?4 U, o( \6 ]Result:=Result+t;
6 [* E2 r1 V) U, r, t9 Einc(i);
* L i7 e; Y4 c. S4 y0 S' r6 T//移位计数达到7位的特别处理 5 p2 {. w% |7 R2 p, Z
j:=(j+1) mod 7;if j=0 then inc(i); - d7 j# q2 X" \5 c
end; * o: k6 d1 L$ b" q2 I- L8 k# D/ d
end; % v5 ~- ^3 W' c. q1 Z
2.中文编码
2 S- ]+ W+ q" S, J8 O参见表3,设短信息内容为“中文短信息”。中文短信息的实现较简单,只需将GB2312的中文编码转换为代码页为CP936的Unicode编码即可。 ( A: B3 K) x9 x( \- w4 D7 m9 S
表3 中文编码的实现过程
$ e E! x, E: |7 _/ X通过Delphi的WideString类型转换,可以巧妙地实现GB2312到Unicode的编码转换(注意代码页和操作系统相关联)。下面是实现中文编码的部分Delphi 5代码: / B2 B. r8 |3 ^# f5 n
// 中文格式编码,s为Unicode String , s3 a4 R2 r' \. q/ D5 z- c, C
function Encode2(var s:WideString):String; ; ` c) I2 M/ t+ T3 L8 |
var , V, E0 l3 d( G
i,len:Integer; 8 u; G% ^' Z. N
cur:Integer;
5 N6 u1 ^) \$ C0 }+ @+ ct:String; & b- c# R2 Z! i% O- o, D% R: f; u! D
begin
4 i, @1 d: `2 x& T: mResult:=‘’;
4 s% G( Y' ^+ B+ }( ]len:=Length(s);
$ D) D0 O* p! hi:=1; ( T' H: m# \9 z9 `/ w
while i<=len do
$ p1 j7 a: x+ R& E- L2 M+ s* [+ [begin 8 f3 f2 l3 m9 k a/ j: m1 g' [
cur:=ord(s); ) q5 s9 d: O6 V* X
//BCD转换 # T* b' S& e5 p! a1 @5 a' M( P
FmtStr(t,‘%4.4X’,[cur]);
/ w7 Y/ D2 l+ z& [( y) w# }- z8 F0 cResult:=Result+t;
- T# R0 l0 e" x, @& A# f C3 \inc(i); 7 Q) U3 o, s: H' K9 f; Z+ F
end;
+ C ^6 E7 Q e* [# h+ cend; + q! t* r* W0 S: W. W9 m. o4 P; }" [8 u
小 结 % X6 L: w' p, S8 C3 [* c
以上介绍了PDU格式的短信息编码。建议英文信息长度不超过140个字符,中文信息不要超过54个汉字。如果使用能够支持文本方式的手机进行发送,实现起来更简单。如发送“Hello World!”,用如下的AT指令即可:
, ]: k0 @$ K$ y" b6 n- zAT+CGMF=1<CR>AT+CGMS=“13605696031”,129<CR> 9 d6 O6 h0 j! Y
>Hello World!<^Z>
$ {. I3 }1 \/ J$ c7 h6 X4 v6 r- `. l9 \1 b' M
|
|