0 引 言
目前基于GSM网络的短消息应用越来越多。由于采用短消息进行数据传输可以直接利用现有的GSM网络的资源,不需要组建专用的通信网络。另外,采用短消息进行数据通信具有费用低等特点,因此基于GSM短消息功能可以做成传输各种检测、监控数据信号和控制命令的数据通信系统,这些系统能广泛用于远程监控、定位导航、个人通信终端等。目前,利用JAVA语言实现的手机短消息收发系统基本没有。针对目前这种情况,本文介绍一种采用JAVA语言实现的手机短消息收发系统,该系统能够正确的收发短消息,并能长时间的稳定运行,因此该系统在办公系统、物流系统中有广阔的应用前景。另外,由于JAVA语言能够实现跨平台运行,因此该系统不仅可以在Windows平台下运行,而且还可以在Unix平台下运行,从而进一步扩展了系统的应用空间。
1 实现的原理
一般PC机都有串口,手机也有数据口,利用手机的数据线将PC机的串口与手机的数据口连接起来,为PC机与手机间提供了数据通信的物理链路。PC机通过向手机发送AT命令来控制手机,在此基础上实现短消息的收发操作。手机收发短消息的AT命令主要有:AT+CMGS和AT+CMGR,具体的AT命令参考GSM07.05规范。该系统软件在设计时采用分层实现的思想,这样可以将任务分层处理,使软件具有模块性和伸缩性,也为软件升级和功能扩展提供良好的接口。图1为软件的分层模型。
串口通信层主要是完成数据通信的任务,这一层包括通信帧格式、通信速度等的处理,该层为它的上一层提供数据通信的通道,进行数据的收发处理。AT命令分析层主要完成各个AT命令的分析,即按照AT命令进行数据封装,将封装后的数据交给下一层进行数据发送;接收来自下层的数据,并对接收到的数据进行解包,将接收到的数据交给上层处理。用户应用处理层主要是完成所有用户有关的操作,该层可以根据不同的应用实现不同的处理,该层还可以根据用户新的需要进行相应的扩充,使软件具有很大的处理灵活性。
2 串口通信层的实现
采用JAVA实现的串口通信与其它语言实现的串口通信概念上一致,都需要打开串口,然后操作串口,处理串口事件,从而实现数据的收发。采用JAVA语言实现的串口通信需要引入适当的jar文件,因此在import部分需要加入“import javax.comm.*”和“import com.sun.comm.*”两个语句,从而能使用低层的资源。串口通信是全双工的通信,在软件设计的时候采用异步通信的方式,即收发不同步。在接收数据的时候是根据串口的事件来进行数据获取。为了避免在接收数据的时候出现“脏读”和“脏写”的情况发生,在此使用“生产者-消费者”模型,并结合JAVA语言的同步机制实现串口通信层与AT命令分析层的数据交互。串口通信层的实现框图如图2所示。
图2 串口通信层实现框图
通过图2可以看出,串口通信层主要包括串口的初始化,获得串口的实例,并设置好通信的格式。在串口初始化后,需要打开串口事件的监听,并启动发送数据的线程,以实现分别对接收和发送的检测。当有数据到达或者有数据需要发送时,则进行相应的接收或者发送处理,如果没有数据到达或者没有数据需要发送,则继续监听和检测处理。在数据接收或者数据发送的时候,需要与AT命令层进行数据交互,为了保证数据的有效性,数据交互采用“生产者-消费者”模型处理。下面具体分析采用JAVA语言实现串口通信的程序片段。以下代码基本上都需要进行相应的异常处理,这里限于篇幅不进行详细的介绍。
下面给出串口初始化的代码片段。在打开串口之前需要加载驱动程序,使用以下语句实现串口的打开:
//驱动加载
Win32Driver wDriver = new Win32Driver();
wDriver.initialize();
portId = CommPortIdentifier.getPortIdentifier
(strName);
//打开串口
m_Port=(SerialPort)portId.open("SMSAPP", 2000);
//获得数据输入流
m_InStream = m_Port.getInputStream();
//获得数据输出流
m_OutStream = m_Port.getOutputStream();
以上的语句主要用于打开串口,获得串口的实例。其中“Win32Driver wDriver = new Win32Driver();wDriver.initialize();”语句实现加载驱动程序,该语句是必须的,如果没有的话,在有的机器上不能正确运行。
m_Port.setSerialPortParams(19200, DATABITS_8, STOPBITS_1, PARITY_NONE);
m_Port.setRTS(true);
m_Port.addEventListener(this);
m_Port.notifyOnDataAvailable(true);
以上的语句实现串口的参数的设置,即设置串口的通信速率、数据位、停止位以及奇偶校验位等,并添加串口事件,当有数据到达时则触发事件。
下面介绍串口收发数据的程序代码片段,这里只是介绍串口通信的读写操作,而关于其它的操作这里不作详细介绍。以下代码可以实现串口通信的数据的收发。
private void SendData(byte []m_nInData) throws IOException
{
try
{
//通过输出流实现数据发送
for(int i = 0;i < m_nInData.length;i++)
{
m_OutStream.write(m_nInData[i]);
}
}
catch(IOException e) { throw e; }
}
public void serialEvent(SerialPortEvent event)
{
int nLen = 0;
switch(event.getEventType())
{
//数据到达
case SerialPortEvent.DATA_AVAILABLE:
{
byte[] readBuffer = new byte[20];
try
{
while(m_InStream.available()>0)
{
//通过输入流接收数据
nLen=m_InStream.read(readBuffer);
}
}
catch (IOException e) {}
break;
}
default:break; //其它事件暂时没有处理
}
}
通过上面的程序代码可以看出:串口数据的发送和接收都是基于输出流和输入流进行处理的。以上代码只是简单实现了串口数据的收发操作,串口数据的接收在串口事件里面进行处理。在实际的应用中,需要考虑数据的有效性,即实现数据的保护与交互。在串口通信层使用了专门的一个类(Semaphore)来实现与其它层之间进行数据交互时的数据保护,并利用一个类(DataStruct)来实现数据的交互,具体的程序代码,这里不进行详细介绍。
3 AT命令分析层的实现
PC机通过串口向手机发送用于短消息操作的AT命令,从而实现控制手机收发短消息的操作。通常情况下,AT命令以字母“AT”开头,以ASCII码为13的字符结尾,比如“AT+CMGS=<length><CR> PDU is given <ctrl-Z/ESC>”命令就用于实现PDU格式的短消息的发送。AT命令分析层位于串口通信层之上,因此该层只是实现短消息AT命令的封装和解析。短消息的发送有文本模式和PDU模式,考虑到系统应用的广泛性,这里只讨论PDU模式。该层主要实现短消息相关操作的命令。在短消息的操作命令中,主要是发送短消息命令和读短消息命令相对复杂,这里主要对这两个操作进行分析。
3.1 短消息发送的实现
PDU格式的短消息发送的AT命令为“AT+CMGS=<length><CR> PDU is given <ctrl-Z/ESC>”。先发送完长度字节后,必须等待手机模块的响应,当响应为“>”时,则继续发送PDU数据包,最后以“ctrl-Z”结束。PDU数据包有具体的帧结构,因此必须按照PDU数据包的格式进行封装数据。图3为手机侧发送PDU数据包的帧格式。
图3(a)给出了发送时帧的格式。在PDU数据包的帧结构中,“SMSC”字段为短消息中心的地址;“PDU类型”来指明数据包的类型;“MR”数据包是表示发出信息;“DA”为目的地址;“PID”为协议识别号;“DCS”为短消息的编码格式,对于数字或者字符采用编码值为“00”,如果内容是汉字的话,则采用的编码值为“08”,采用的是UNICODE编码方式;“VP”表示短消息的有效时间;“UDL”表示数据内容的长度;“UD”为具体的短消息内容。这里需要强调的是:在PDU数据包里面,所有的数字是以字符形式发送的,也就是需要将整数转换成字符形式发送(比如整数23需要转换成‘2’和‘3’进行分别发送)。在帧中,“SMSC”和“DA”字段的每个字节按照BCD编码,每个字节高低顺序交换,如“683108200305F0”表示的实际SMSC的号码为“8613800230500”。
3.2 短消息接收的实现
PDU格式的短消息接收的AT命令为“AT+CMGR=index”,这里index为短消息存储的具体位置,发送的时候必须将该整数值转换成字符形式。在发送完了读取短消息的AT命令后,手机会给出响应,响应的数据就包括短消息的内容。同样,响应数据也是PDU格式的数据帧。接收数据PDU格式包与发送数据的PDU格式包中的字段有所不同,图3(b)为手机侧接收PDU数据包的帧格式。
在接收PDU数据包的帧结构中,“SMSC”字段为短消息中心的地址;“PDU类型”来指明数据包的类型;“OA”为源地址;“SCTS” 表示短消息到达业务中心的时间;其余的各个字段与发送时的帧格式时一样的。在PDU数据包里面,所有的内容也是是以字符形式存在的。同样,在帧中,“SMSC”和“OA”字段的每个字节按照BCD编码,每个字节高低顺序交换。按照帧格式中各个字段,对响应数据进行解析就可以得到短消息的内容。
以上分析了短消息的发送和接收。在具体程序的实现的时候,严格按照帧格式进行封装数据或者解析就可以了。
4用户应用处理层的实现
用户应用处理层主要是针对不同的应用处理提供不同的功能,用户也可以在这层上增加自己的功能,这样可以保证软件的伸缩性和开放性。在应用层必须要完成几个基本的功能,即:短消息内容的编码功能、字节转换成字符串、字符串转换成字节流等功能模块。为了考虑到任务的突发性,应用层采用排队机制并结合“生产者-消费者”模型来进行处理。图5为应用层的处理框图。
图4 应用层处理框图
由图4可以看出,应用层将需要发送的数据放入到入队列里,然后利用“生产者-消费者”模型保证数据的有效性,防止数据的“脏读”和“脏写”。应用层取出需要发送的数据进行相应的处理(比如编码等)后,将数据交给AT命令分析层处理。应用层从AT命令分析层获得数据,进行相应处理(比如解码等),处理完后,将处理的最终数据放入到出队列里,供用户使用,同样这里也需要借助“生产者-消费者”模型来保证数据的有效性。
在该层中,主要是根据具体的应用来实现相应的代码。通过该层软件,完成特定的用户处理,将处理后的数据交给AT命令分析层进行数据封装,将封装后的数据交给通信层进行发送,从而实现数据以短消息的形式发送;对接收到的数据按照相反的处理就可以获得接收到的数据。基于以上通信过程,可以实现数据点对点的通信。
5 结束语
以上介绍了采用JAVA语言实现的手机短消息的收发系统。该系统在软件设计的时候按照分层设计,这样既可以保证整个软件模块性,又能保证软件的伸缩性,便于将来对软件进行扩展和升级。在该系统软件中,通信层能实现数据的收发,并且加入监视线程,使该层具有非常高的健壮性,可以长时间运行。AT命令分析层能实现AT命令的封装和解析,也可以增加对其它AT命令的封装和解析,使该层能适应将来功能的扩展。应用层能根据不同的应用进行相应的处理,保证软件的开发性,也便于开展新的功能和业务。经过长时间的运行测试,该系统能够稳定运行,不会造成数据丢失,因此该系统已经成功用于一家公司的物流平台。另外由于该系统的软件具有伸缩性和开放性,因此该系统将会在远程监控、无线办公等应用领域有非常广阔的应用前景。