|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
手机短信息SMS的程序开发 + t8 p8 Y+ W6 G6 Z! h9 b- j3 _, s( c
9 d! q: E* a9 V4 f" j) j" E1 h目前手机短信息的应用越来越广泛,互联网上提供短信息发送的站点也越来越多,但一些站点的服务并不尽如人意,往往发出去的短信息石沉大海。最可靠的发送方法当然是用手中的手机了,如果设置了状态报告,更能确切知道对方是否收到了此条信息。手机发送尽管比较可靠, 但也存在输入麻烦、效率低的问题。本文介绍一种方法,只要手机能够与电脑相连(通过红外端口或用手机数据线连接串行口,同时手机支持GSM AT指令集),就可以通过自行编制的短信息发送软件,实现短信息的发送。3 s3 R8 i. g( ]( y
# `( h* M# ?- \! o) ^现在市场上的大多数手机均支持类似于Modem控制的GSM AT指令集,该指令集是由诺基亚、爱立信、摩托罗拉和HP等厂家共同为GSM系统研制的,其中包含了对SMS(Short Message Service)的控制。 8 r g* w$ k, k4 l+ ?+ i
GSM AT相关指令的介绍
! i4 t6 {8 U# ~; y9 m$ P3 K' D与SMS有关的GSM AT指令如表1所示:
8 `( F k; D5 P2 |* U表1 相关的GSM AT指令
$ u; r+ ?1 ^# z% g0 Y4 k对SMS的控制共有三种实现途径:
" [+ n( c* W7 r! |Block Mode; % Y+ d4 } p- _
基于AT命令的Text Mode;
! R9 r5 L, _- i! l( U4 }基于AT命令的PDU Mode。 8 b, A8 U4 S& w+ k7 N$ a
Text Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因此本文主要探讨PDU模式的发送。 % g1 k* C2 y! R0 G: ~' W% ~3 j
计算机和手机的通信
0 c. H+ C( G* z# ~, s本文以西门子 S3568i为例,介绍如何实现短信息的发送。
n/ `% I' w, ^0 k3 O数据线连接
. H% [4 c9 ^. a& w! ^9 h& b( x9 i" i* B: M首先,通过S35/25数据线将手机与电脑串行口相连。然后,打开超级终端,选择直接串行口连接,端口参数设为19200速率、无校验、数据位8、停止位1。
# f- a( M1 m/ M7 p" P7 s' d8 u红外线连接 - p: `9 O/ C* M3 p E( }
如果使用带红外端口的计算机,可以设置与手机的无线连接。首先确认计算机红外端口已打开,并将手机的红外线和收传真/数据功能打开,对接红外端口,计算机系统托盘上应当出现一个红外设备西门子S35(如果没有安装红外监视器,则不显示)。然后,打开超级终端,选择IrDa上的串行口。 / e; J! ?5 S$ T. f
连接测试
0 i0 F3 I) z/ p0 D. F点击超级终端工具条上的呼叫按钮,输入AT并回车,屏幕上如果出现OK则表明计算机与手机的连接成功,这时就可以输入各类GSM AT指令了。 8 R3 Y) ]6 n1 {: k% h9 `; S* }
如:查询手机厂家,输入AT+CGMI=<CR>,屏幕显示Siemens。
" a4 _, D7 {! C- B5 t通常情况下,执行测试命令AT+CMGS=?<CR>,如果返回OK,表明手机支持此指令。该指令的完整语法格式如下:
) p3 ~: W, W4 O) i- ^8 O k. aIf PDU mode (+CMGF=0)+CMGS=<length><CR> DU is given <ctrl-Z/ESC>
4 M% p( a7 F4 T9 P3 |如果短信息格式指令AT+CMGF返回的是0,则SMS格式为PDU模式,再执行AT+CMGS=<数据长度>命令后,手机返回“>”符号并等待输入,输入PDU数据并以^Z或Esc键结束。
; Q/ H, M0 `; H. e# `& ^* N: M如果信息发送成功,则返回OK,并显示信息号:
7 q ?: {6 ]' u9 P( K7 w+ H+CMGS: <mr>
% o7 k& z# j5 s% s6 l如果发送失败,则返回如下信息:
) t, Q0 l9 Y& e3 f9 ^+CMS ERROR: <err> ) \5 \; @9 \) S
PDU数据格式的分析 : e' W) R$ V) _& ?% j- c Y
下面通过对存储在手机中的待发信息的分析,来介绍SMS PDU的数据格式。首先,用手机写一条短信息,发送手机号码为13605696031,信息内容为“Hello World!”。通过执行AT+CMGL=2可以读出此条信息。 ! _4 F/ p3 w9 c: \0 ?, K
操作过程如下(斜体字符为响应信息,{}内为注释): % B+ o2 C% R# U' p& h4 H
AT 8 H. j1 v) Y/ {4 D
OK
4 l' m0 l5 [: vAT+CMGL=2 {读未发短信息}
( E5 }7 \7 ?8 s" `. m5 u+CMGL: 1,2,,24 {1表示信息个数,2表示未发信息,24表示信息总容量} 2 t5 W) ^- o$ p0 k
08 91 683108501505F0 11 00 0B 81 3106656930F1 0000A7 0B E8329BFD06DDDF723619 6 N4 h2 Q9 X+ W
OK
% b8 q* s; c- I% W下面分析这条信息:
- e5 { T" \' f8 I/ N! Z0 G08:短信息中心地址长度。
7 Q" V# O, |7 Q: L# _91:短信息中心号码类型,91是TON/NPI。TON/NPI遵守International/E.164标准,指在号码前需加‘+’号;此外还可有其他数值,但91最常用。
* R. W$ ~0 k% @5 I# }6 C683108501505F0:短信息号码,是所使用的服务中心地址。由于位置上略有处理,实际号码应为:8613805515500(字母F意指长度减1),这是作者所在地GSM短信息中心的号码。 ! S+ V K% F8 W
11:文件头字节(header byte,是一种bitmask)。这里11指正常地发送短信息。
. j1 d1 B$ S! C7 |, N4 U00:信息类型。
- \9 v( Q7 q0 v5 Y. w% v0 i T0B:被叫号码长度。
' P5 R J; j1 R81:被叫号码类型。 ! G' o6 o1 W" I9 \
3106656930F1:被叫号码,也经过了移位处理,实际号码为13605696031。 - r5 \2 v1 o# x7 d$ A
0000A7:短信息编码类型GSM Default Alphabet,如为中文则是000010。
7 T8 }3 `/ e$ |; I8 u5 Y0B:短信息长度。 ! c/ ~3 t* l: B0 a
E8329BFD06DDDF723619:短信息内容“Hello World!”。
; v4 G2 Q/ w s; i4 j短信息的编码方法及编程实现
: p' |7 Y4 y' o0 T下面我们介绍纯英文和纯中文的信息编码方法。通过测试我们发现,每条发送的短信息前面部分均相同,只是被叫号码和短信息内容有变化。
- }8 U7 d, D( j G4 J1 u1.英文编码 ) T$ Q( e6 q3 X, H0 z
参见表2,设短信息内容为“Hello World!”。缺省的GSM 字符集为7位编码,可以简单地理解为ASCII码(ASCII值小于80Hex,因此,Bit8被忽略),依次将下一7位编码的后几位逐次移至前面,形成新的8位编码,参见表2箭头指示。需要注意的是第9行,移位计数已达7位,则直接将本编码前加0。GSM并非支持所有的ASCII字符显示。
( P" n1 p; s/ c2 z/ ^, Y表2 英文编码的实现过程
6 U& X' d d' @. I下面是实现英文编码的部分Delphi 5代码:
3 n9 y0 C* W) g2 E+ D: q7 U//英文格式编码,s为String . Z$ ^; \) n1 }6 J. _+ n. D
function Encode1(var s:String):String; 7 i2 m' g) ^' b" q: ~! f6 ] [5 l
var . f( l% f# m& K# P
i,j,len:Integer;
, G3 ^1 J4 D6 G% g/ N' H1 y4 jcur:Integer;
) E& V, t. {; Rt:String;
8 o- _: X* w( q- z' zbegin
8 t8 x9 a2 V! o5 ~Result:=‘’;
# @7 \& R2 [8 Y: Z' Dlen:=Length(s); ! ~) Z# e5 V/ [# n* B
//j 用于移位计数 ?% f5 g$ m7 V' v/ z9 ~+ I
i:=1;j:=0;
$ ?- @. O0 ~9 t$ @# L7 \while i<=len do
2 L; E- {2 o$ a2 pbegin * K$ f8 |/ V/ b1 a8 Q- ]- P
if i<len then
: ^3 K# t! j |$ I* d* l4 O) z//数据变换
4 j# g. N9 I( o# N% w- N% Kcur:=(ord(s) shr j) or ((ord(s[i+1]) shl (7-j)) and $ff) 9 i3 R3 M1 k" R% ]4 d
else # a S5 G/ ] A. a( p
cur:=(ord(s) shr j) and $7f; 1 o |0 ^# l# _' N9 x3 o( n- B2 y
FmtStr(t,‘%2.2X’,[cur]);
: O# C2 _ t0 O hResult:=Result+t;
+ a) V) Y4 b }, j- F' minc(i);
& T7 @; Z5 W: Y//移位计数达到7位的特别处理 ) t: f7 N" t* P; G. T
j:=(j+1) mod 7;if j=0 then inc(i); 3 `0 w) M) i5 K9 y7 h2 a9 q0 X
end;
. y) j1 D5 R. t/ g# M$ bend;
" ~0 M0 v5 D, _' w; X2.中文编码
- \! U% J0 B; e! H* G参见表3,设短信息内容为“中文短信息”。中文短信息的实现较简单,只需将GB2312的中文编码转换为代码页为CP936的Unicode编码即可。
$ `. E; l2 Z! F$ x8 A表3 中文编码的实现过程
2 Y6 @' P2 K! i; @$ n+ Z/ b" u通过Delphi的WideString类型转换,可以巧妙地实现GB2312到Unicode的编码转换(注意代码页和操作系统相关联)。下面是实现中文编码的部分Delphi 5代码:
; a# t3 z% c5 f1 I/ C// 中文格式编码,s为Unicode String
8 u: d! T* r: U5 }0 d1 Yfunction Encode2(var s:WideString):String; + s* X: P* f2 P! q; k4 \
var ( |) A+ \& {% u+ {
i,len:Integer;
8 F+ ~# ~* |+ T$ S0 R% H) Q) Ncur:Integer;
$ q$ x- R8 x3 e9 X5 Ot:String;
! y+ ^! Q' v K2 jbegin
; f8 \6 A/ E/ B: D* r5 DResult:=‘’; ; V Y. z. O9 C8 q! n
len:=Length(s); ; v( X" {- P, [
i:=1;
! Y9 v, c6 w1 bwhile i<=len do `8 M0 l8 S& y$ r7 I- f8 T! g( [
begin
) Z$ ~# W6 e( E7 b: j4 ncur:=ord(s);
( K. x2 v1 N5 C- T//BCD转换
9 u# b8 r: {6 b! V, eFmtStr(t,‘%4.4X’,[cur]);
% M7 d k; Q7 H0 b4 fResult:=Result+t;
" q5 f$ O- g& n) e! B( \: }inc(i); - k7 S. W1 q, T: s' |" `
end;
1 e0 Z# `8 |$ zend; 5 K8 t/ X( g) ?8 s! |
小 结 * d& S6 v2 [1 n0 e8 D n2 `
以上介绍了PDU格式的短信息编码。建议英文信息长度不超过140个字符,中文信息不要超过54个汉字。如果使用能够支持文本方式的手机进行发送,实现起来更简单。如发送“Hello World!”,用如下的AT指令即可: % q8 C; B4 i1 J/ {6 Y; {
AT+CGMF=1<CR>AT+CGMS=“13605696031”,129<CR>
# H0 Y4 t1 k& a% a3 J>Hello World!<^Z> , _' `" R" o9 ~# `" p$ u
/ t+ G: D( ?* n |
|