作 者: so1127


时 间: 2013-5-21 16:30:27


链 接:




一、SMSLib简介




SMSLib是一个开放源代码的短信猫二次开发包,有JAVA和.Net两个版本,目前最新版为v3.5.2。



java 短信软件下载 java sms短信接收_串口


 


                                                                            图1-1


二、Window平台




1、在smslib官网下载“SMSLib for Java v3.5.2”开发包,并解压,目录结构如下图所示:




 


                                                                                    图2-1




 


                                                                                                            图2-2




lib:存放二次开发包(smslib-3.5.2.jar)和运行时的依赖包(slf4j、log4j、commons-net、jsmpp等)(重要)



dist:存放短信猫服务开发包(smsserver-3.5.2.jar),该包包括了smslib-3.5.2.jar中的所有核心类。如果是将短信猫作为服务的方式部署,不需要额外写代码开发短信发送和接收的接口,直接部署短信服务即可,详细的步聚,可以参考《短信猫服务安装与配置指南》。(重要)



doc:smslib介绍、使用指南、smsserver安装与配置等文档(重要)



javadoc:二次开发包API



src:存放二次开发包源码和示例源码



misc:smslib日志(log4j)配置配置模板、smsserver数据库建库脚本及服务接口等文件



build:项目管理相关文件(不重要)



2、下载SUN JavaComm v2 (Win32)动态库,并解压,目录结构如下图所示:




 


                                                                                        图3-1


3、运行环境配置



复制“图3-1”中javax.comm.properties文件到%JAVA_HOME%\jre\lib目录下,win32com.dll文件到%JAVA_HOME%\jre\bin目录下


复制“图3-1”中comm.jar和图2-2中所有jar文件到CLASSPATH目录下(如果是用eclipse等IDE工具,将这些jar包导入到工程中)


       注意: win32com.dll只支持32位jdk



4、运行示例程序并测试



主要代码如下:

Level_Final_Serial.java

package com.serial;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 作用: 串口读写数据(底层)
 * ①串口文件位置放置: rxtxSerial.dll 放在%java_home%\bin下<br>
 * ②类使用介绍:	初始化:getInstance->setPortName->initialize
 * 				打开串口:openPort
 *				读写数据:writePort->readPackData
 *				关闭串口:ClosePort
 *				枚举全部串口名称:getAllComPorts
 * 注意事项: 无
 */
public class Level_Final_Serial {
	/**
	 * 数据包长度
	 */
	public static final int PACKET_LENGTH = 500;

	private Logger log = LoggerFactory.getLogger(Level_Final_Serial.class);
	public static Level_Final_Serial final_Level;

	SerialPort serialPort;
	CommPortIdentifier identifier;
	String PortName; // 串口名.如:COM3
	OutputStream out; // 串口输出流
	InputStream in; // 串口输入流
	String appname = "SerialBean"; // 程序名
	int timeOut; // 延迟时间(毫秒数)
	int baudrate; // 波特率
	int dataBits; // 数据位
	int stopBits; // 停止位
	int parity; // 奇偶检验

	/**
	 * @describe: 获取SerialBeanl类单例
	 * @date:2009-11-5
	 */
	public static Level_Final_Serial getInstance() {
		if (final_Level == null) {
			final_Level = new Level_Final_Serial();
		}
		return final_Level;
	}

	/**
	 * 构造函数
	 */
	public Level_Final_Serial() {
	}

	/**
	 * @describe: 设置 串口程序名
	 * @date:2010-3-2
	 */
	public void setAppname(String appname) {
		this.appname = appname;
	}

	/**
	 * @describe: 初始化类
	 * @param timeOut  等待时间
	 * @param baudrate	波特率
	 * @param dataBits	数据位
	 * @param stopBits	停止位
	 * @param parity	奇偶检验
	 * @date:2009-11-5
	 */
	public void initialize(int timeOut, int baudrate, int dataBits,
			int stopBits, int parity) {
		this.timeOut = timeOut;
		this.baudrate = baudrate;
		this.dataBits = dataBits;
		this.stopBits = stopBits;
		this.parity = parity;
	}

	/**
	 * @describe: 初始化串口详细信息
	 * @return true : 初始化串口成功 false: 初始化串口失败 
	 * @date:2009-11-5
	 */
	public boolean openPort(String portName) {
		boolean rsBool = false;
		this.PortName = portName;

		try {
			//获取串口
			identifier = getCommPort();

			if (identifier == null) {
				// null
			} else {
				if (identifier.isCurrentlyOwned()) {
					log.info(PortName + ": 串口已经被"
							+ identifier.getCurrentOwner() + "占用...");
				} else {
					// open方法打开通讯端口
					serialPort = (SerialPort) identifier.open(appname, timeOut);

					// 获取端口的输入,输出流对象 
					in = serialPort.getInputStream();
					out = serialPort.getOutputStream();

					// 设置串口初始化参数,依次是波特率,数据位,停止位和校验 
					serialPort.setSerialPortParams(baudrate, dataBits,
							stopBits, parity);
					serialPort.setDTR(true);
					serialPort.setRTS(true);

					rsBool = true;
				}
			}
		} catch (PortInUseException e) {
			log.info(PortName + ": 串口已经被" + identifier.getCurrentOwner()
					+ "占用...");
		} catch (Exception e) {
			log.info(PortName + "--初始化串口出错:" + e.toString());
		}

		return rsBool;
	}

	/**
	 * @describe: 列举并得到需要用串口
	 * @date:2009-11-5
	 */
	public CommPortIdentifier getCommPort() throws Exception {
		CommPortIdentifier portIdRs = null;
		portIdRs = CommPortIdentifier.getPortIdentifier(PortName);
		return portIdRs;
	}

	/**
	 * @describe: 读取串口数据
	 * @date:2009-11-5
	 */
	public char[] readPackData() throws Exception {
		byte[] readBuffer = new byte[PACKET_LENGTH];
		char[] msgPack = null;
		int numBytes = 0;

		while (in.available() > 0) {
			numBytes = in.read(readBuffer);
			msgPack = null;
			msgPack = new char[numBytes];
			for (int i = 0; i < numBytes; i++) {
				msgPack[i] = (char) (readBuffer[i] & 0xFF);
			}
		}
		return msgPack;
	}

	/**
	 * @describe: 向串口写数据 char[] bytes
	 * @date:2009-11-5
	 */
	public void writePort(char[] bytes) throws IOException {
		for (char b : bytes) {
			writePort(b);
		}
	}

	/**
	 * @describe: 向串口写数据 char bytes
	 * @date:2009-11-5
	 */
	public void writePort(char b) throws IOException {
		out.write(b);
		out.flush();
	}

	/**
	 * @describe: 关闭串口,释放资源
	 * @date:2009-11-5
	 */
	public void closePort() {
		if (out != null) {
			try {
				out.close();
				in.close();
				out = null;
				in = null;
			} catch (IOException e) {
				log.info("关闭串口时出错:" + e.toString());
			}
		}
		if (serialPort != null) {
			serialPort.close();
			serialPort = null;
		}
	}

	/**
	 * @describe: 列举全部串口名称
	 * @date:2009-11-22
	 */
	@SuppressWarnings("unchecked")
	public static List<String> getAllComPorts() {
		List<String> comList = new ArrayList<String>();
		Enumeration en = CommPortIdentifier.getPortIdentifiers();
		CommPortIdentifier portIdRs = null;

		while (en.hasMoreElements()) {
			portIdRs = (CommPortIdentifier) en.nextElement();
			if (portIdRs.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				comList.add(portIdRs.getName());
			}
		}
		return comList;
	}

}
package com.serial;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 作用: 串口读写数据(底层)
 * ①串口文件位置放置: rxtxSerial.dll 放在%java_home%\bin下<br>
 * ②类使用介绍:	初始化:getInstance->setPortName->initialize
 * 				打开串口:openPort
 *				读写数据:writePort->readPackData
 *				关闭串口:ClosePort
 *				枚举全部串口名称:getAllComPorts
 * 注意事项: 无
 */
public class Level_Final_Serial {
	/**
	 * 数据包长度
	 */
	public static final int PACKET_LENGTH = 500;

	private Logger log = LoggerFactory.getLogger(Level_Final_Serial.class);
	public static Level_Final_Serial final_Level;

	SerialPort serialPort;
	CommPortIdentifier identifier;
	String PortName; // 串口名.如:COM3
	OutputStream out; // 串口输出流
	InputStream in; // 串口输入流
	String appname = "SerialBean"; // 程序名
	int timeOut; // 延迟时间(毫秒数)
	int baudrate; // 波特率
	int dataBits; // 数据位
	int stopBits; // 停止位
	int parity; // 奇偶检验

	/**
	 * @describe: 获取SerialBeanl类单例
	 * @date:2009-11-5
	 */
	public static Level_Final_Serial getInstance() {
		if (final_Level == null) {
			final_Level = new Level_Final_Serial();
		}
		return final_Level;
	}

	/**
	 * 构造函数
	 */
	public Level_Final_Serial() {
	}

	/**
	 * @describe: 设置 串口程序名
	 * @date:2010-3-2
	 */
	public void setAppname(String appname) {
		this.appname = appname;
	}

	/**
	 * @describe: 初始化类
	 * @param timeOut  等待时间
	 * @param baudrate	波特率
	 * @param dataBits	数据位
	 * @param stopBits	停止位
	 * @param parity	奇偶检验
	 * @date:2009-11-5
	 */
	public void initialize(int timeOut, int baudrate, int dataBits,
			int stopBits, int parity) {
		this.timeOut = timeOut;
		this.baudrate = baudrate;
		this.dataBits = dataBits;
		this.stopBits = stopBits;
		this.parity = parity;
	}

	/**
	 * @describe: 初始化串口详细信息
	 * @return true : 初始化串口成功 false: 初始化串口失败 
	 * @date:2009-11-5
	 */
	public boolean openPort(String portName) {
		boolean rsBool = false;
		this.PortName = portName;

		try {
			//获取串口
			identifier = getCommPort();

			if (identifier == null) {
				// null
			} else {
				if (identifier.isCurrentlyOwned()) {
					log.info(PortName + ": 串口已经被"
							+ identifier.getCurrentOwner() + "占用...");
				} else {
					// open方法打开通讯端口
					serialPort = (SerialPort) identifier.open(appname, timeOut);

					// 获取端口的输入,输出流对象 
					in = serialPort.getInputStream();
					out = serialPort.getOutputStream();

					// 设置串口初始化参数,依次是波特率,数据位,停止位和校验 
					serialPort.setSerialPortParams(baudrate, dataBits,
							stopBits, parity);
					serialPort.setDTR(true);
					serialPort.setRTS(true);

					rsBool = true;
				}
			}
		} catch (PortInUseException e) {
			log.info(PortName + ": 串口已经被" + identifier.getCurrentOwner()
					+ "占用...");
		} catch (Exception e) {
			log.info(PortName + "--初始化串口出错:" + e.toString());
		}

		return rsBool;
	}

	/**
	 * @describe: 列举并得到需要用串口
	 * @date:2009-11-5
	 */
	public CommPortIdentifier getCommPort() throws Exception {
		CommPortIdentifier portIdRs = null;
		portIdRs = CommPortIdentifier.getPortIdentifier(PortName);
		return portIdRs;
	}

	/**
	 * @describe: 读取串口数据
	 * @date:2009-11-5
	 */
	public char[] readPackData() throws Exception {
		byte[] readBuffer = new byte[PACKET_LENGTH];
		char[] msgPack = null;
		int numBytes = 0;

		while (in.available() > 0) {
			numBytes = in.read(readBuffer);
			msgPack = null;
			msgPack = new char[numBytes];
			for (int i = 0; i < numBytes; i++) {
				msgPack[i] = (char) (readBuffer[i] & 0xFF);
			}
		}
		return msgPack;
	}

	/**
	 * @describe: 向串口写数据 char[] bytes
	 * @date:2009-11-5
	 */
	public void writePort(char[] bytes) throws IOException {
		for (char b : bytes) {
			writePort(b);
		}
	}

	/**
	 * @describe: 向串口写数据 char bytes
	 * @date:2009-11-5
	 */
	public void writePort(char b) throws IOException {
		out.write(b);
		out.flush();
	}

	/**
	 * @describe: 关闭串口,释放资源
	 * @date:2009-11-5
	 */
	public void closePort() {
		if (out != null) {
			try {
				out.close();
				in.close();
				out = null;
				in = null;
			} catch (IOException e) {
				log.info("关闭串口时出错:" + e.toString());
			}
		}
		if (serialPort != null) {
			serialPort.close();
			serialPort = null;
		}
	}

	/**
	 * @describe: 列举全部串口名称
	 * @date:2009-11-22
	 */
	@SuppressWarnings("unchecked")
	public static List<String> getAllComPorts() {
		List<String> comList = new ArrayList<String>();
		Enumeration en = CommPortIdentifier.getPortIdentifiers();
		CommPortIdentifier portIdRs = null;

		while (en.hasMoreElements()) {
			portIdRs = (CommPortIdentifier) en.nextElement();
			if (portIdRs.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				comList.add(portIdRs.getName());
			}
		}
		return comList;
	}

}

Serial_For_Smslib.java


package com.serial;

import javax.comm.SerialPort;

/**
 * 作用 : 串口操作:封装底层
 * 类使用介绍:
 * 		获取实例:getInstance
 * 		打开串口:openPort
 * 		读写数据:writeByte->readByte
 * 		关闭串口:closePort
 * 注意事项 : 无
 */
public class Serial_For_Smslib {
	public static Serial_For_Smslib sms_serial;
	public static Level_Final_Serial final_Level;

	//需要设置的参数
	int portId; // 串口号:如:com1,则portId为1
	int baudrate; // 波特率

	//	不一定要设定的参数(有默认值)
	int timeOut; // 延迟时间(毫秒数)
	int dataBits; // 数据位
	int stopBits; // 停止位
	int parity; // 奇偶检验
	int funCode; // 功能码	
	int dataLen; // 数据长度
	int appendMillsec; // 计算发送间隔用---附加毫秒数
	int bytes; // 计算发送间隔用---发送字节数	

	// 自动计算--发送间隔
	int frameInterval; // 根据波特率,数据倍率和数据量,自动设置发送间隔

	// 构造方法
	public Serial_For_Smslib() {
		final_Level = new Level_Final_Serial();
		timeOut = 60;

		// 延迟时间(毫秒数)
		dataBits = SerialPort.DATABITS_8; // 数据位
		stopBits = SerialPort.STOPBITS_1; // 停止位
		parity = SerialPort.PARITY_NONE; // 奇偶检验
		funCode = 3;

		//	读取当前寄存器内一个或多个二进制值
		dataLen = 4;

		//	假设 需要获取4个数据
		appendMillsec = 38;

		//	附加毫秒数(需要自己测试调整)
		bytes = 20;

		//  发送是字节数
	}

	/**
	 * @describe:  获取程序单例
	 * @date:2009-11-5
	 */
	public static Serial_For_Smslib getInstance() {
		if (sms_serial == null) {
			sms_serial = new Serial_For_Smslib();
		}
		return sms_serial;
	}

	/**
	 * @describe: 打开串口
	 * @param portStr 串口号. 如: COM3
	 * @param baudrate 波特率
	 * @param appName 串口占用程序的命名
	 * @return: true:打开串口正常 false:打开串口异常
	 */
	public boolean openPort(String portStr, int baudrate, String

	appName) {
		boolean rsBool = false;

		// 初始化串口
		final_Level.initialize(timeOut, baudrate, dataBits,

		stopBits, parity);
		final_Level.setAppname(appName.toUpperCase());
		// 打开串口
		if (final_Level.openPort(portStr)) {
			rsBool = true;
			// 设置帧之间的发送间隔
			this.frameInterval = getFrameInterval

			(appendMillsec, bytes, baudrate);
		}
		return rsBool;
	}

	/**
	 * @describe: 写串口命令 - 发送AT这个指令
	 * @param rs 发送的数据
	 */
	public void writeByte(char[] rs) throws Exception {
		final_Level.writePort(rs);
		// 打印发送的串口数据-16进制显示
		// System.out.println(bytesToHexString(rs));

		//等待一段时间, 以保证数据,有足够的时间发送和接收
		//Thread.sleep(frameInterval);			
		Thread.sleep(frameInterval);
	}

	/**
	 * @describe: .读串口命令 - 对发送AT这个指令,返回OK就是成功
	 * @return: true:成功 false:失败 
	 */
	public boolean readByte(String portStr) throws Exception {
		boolean rsbool = false;
		String rsStr = "";

		// 读取数据
		char[] rsByte = final_Level.readPackData();
		if (rsByte != null) {
			// 打印收到的串口数据-16进制显示
			for (char c : rsByte) {
				rsStr += c;
			}
			if (rsStr.indexOf("OK") > 0) {
				System.out.println("找到" + portStr +

				":短信模块串口");
				rsbool = true;
			}
		} else {
			System.out.println(portStr + ":不是短信模块串口");
		}
		// 处理收到的数据

		return rsbool;
	}

	/**
	 * @describe: 关闭串口,释放资源
	 * @date:2009-11-5
	 */
	public void closePort() {
		final_Level.closePort();
	}

	//---------------工具方法---------------//
	/**
	 * @describe: 获取需要帧之间需要间隔的时间(毫秒) 功能公式(1*12(

	位)*数据长度*1000/波特率 + 附加毫秒数)--根据自己的程序动态调整
	 * @param appendMillsec	附加毫秒数
	 * @param dataLen	数据区数据长度
	 * @param baudrate	波特率
	 * @return 得到合适的帧发送,间隔毫秒数
	 * @date:2009-11-5
	 */
	public static int getFrameInterval(int appendMillsec, int

	dataLen, int baudrate) {
		int rsInt = (int) Math.ceil(1 * 12 * (dataLen + 4) *

		1000 / (float) baudrate) + appendMillsec;
		return rsInt;
	}

	/**
	 * @describe:	把char类型转换成16进制字符串
	 * @param bArray  char类型数组
	 * @date:2009-11-7
	 */
	public static final String bytesToHexString(char[] bArray) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;

		for (int i = 0; i < bArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2) {
				sb.append(0);
			}
			sb.append(sTemp.toUpperCase() + " ");
		}
		return sb.toString();
	}

}
package com.serial;

import javax.comm.SerialPort;

/**
 * 作用 : 串口操作:封装底层
 * 类使用介绍:
 * 		获取实例:getInstance
 * 		打开串口:openPort
 * 		读写数据:writeByte->readByte
 * 		关闭串口:closePort
 * 注意事项 : 无
 */
public class Serial_For_Smslib {
	public static Serial_For_Smslib sms_serial;
	public static Level_Final_Serial final_Level;

	//需要设置的参数
	int portId; // 串口号:如:com1,则portId为1
	int baudrate; // 波特率

	//	不一定要设定的参数(有默认值)
	int timeOut; // 延迟时间(毫秒数)
	int dataBits; // 数据位
	int stopBits; // 停止位
	int parity; // 奇偶检验
	int funCode; // 功能码	
	int dataLen; // 数据长度
	int appendMillsec; // 计算发送间隔用---附加毫秒数
	int bytes; // 计算发送间隔用---发送字节数	

	// 自动计算--发送间隔
	int frameInterval; // 根据波特率,数据倍率和数据量,自动设置发送间隔

	// 构造方法
	public Serial_For_Smslib() {
		final_Level = new Level_Final_Serial();
		timeOut = 60;

		// 延迟时间(毫秒数)
		dataBits = SerialPort.DATABITS_8; // 数据位
		stopBits = SerialPort.STOPBITS_1; // 停止位
		parity = SerialPort.PARITY_NONE; // 奇偶检验
		funCode = 3;

		//	读取当前寄存器内一个或多个二进制值
		dataLen = 4;

		//	假设 需要获取4个数据
		appendMillsec = 38;

		//	附加毫秒数(需要自己测试调整)
		bytes = 20;

		//  发送是字节数
	}

	/**
	 * @describe:  获取程序单例
	 * @date:2009-11-5
	 */
	public static Serial_For_Smslib getInstance() {
		if (sms_serial == null) {
			sms_serial = new Serial_For_Smslib();
		}
		return sms_serial;
	}

	/**
	 * @describe: 打开串口
	 * @param portStr 串口号. 如: COM3
	 * @param baudrate 波特率
	 * @param appName 串口占用程序的命名
	 * @return: true:打开串口正常 false:打开串口异常
	 */
	public boolean openPort(String portStr, int baudrate, String

	appName) {
		boolean rsBool = false;

		// 初始化串口
		final_Level.initialize(timeOut, baudrate, dataBits,

		stopBits, parity);
		final_Level.setAppname(appName.toUpperCase());
		// 打开串口
		if (final_Level.openPort(portStr)) {
			rsBool = true;
			// 设置帧之间的发送间隔
			this.frameInterval = getFrameInterval

			(appendMillsec, bytes, baudrate);
		}
		return rsBool;
	}

	/**
	 * @describe: 写串口命令 - 发送AT这个指令
	 * @param rs 发送的数据
	 */
	public void writeByte(char[] rs) throws Exception {
		final_Level.writePort(rs);
		// 打印发送的串口数据-16进制显示
		// System.out.println(bytesToHexString(rs));

		//等待一段时间, 以保证数据,有足够的时间发送和接收
		//Thread.sleep(frameInterval);			
		Thread.sleep(frameInterval);
	}

	/**
	 * @describe: .读串口命令 - 对发送AT这个指令,返回OK就是成功
	 * @return: true:成功 false:失败 
	 */
	public boolean readByte(String portStr) throws Exception {
		boolean rsbool = false;
		String rsStr = "";

		// 读取数据
		char[] rsByte = final_Level.readPackData();
		if (rsByte != null) {
			// 打印收到的串口数据-16进制显示
			for (char c : rsByte) {
				rsStr += c;
			}
			if (rsStr.indexOf("OK") > 0) {
				System.out.println("找到" + portStr +

				":短信模块串口");
				rsbool = true;
			}
		} else {
			System.out.println(portStr + ":不是短信模块串口");
		}
		// 处理收到的数据

		return rsbool;
	}

	/**
	 * @describe: 关闭串口,释放资源
	 * @date:2009-11-5
	 */
	public void closePort() {
		final_Level.closePort();
	}

	//---------------工具方法---------------//
	/**
	 * @describe: 获取需要帧之间需要间隔的时间(毫秒) 功能公式(1*12(

	位)*数据长度*1000/波特率 + 附加毫秒数)--根据自己的程序动态调整
	 * @param appendMillsec	附加毫秒数
	 * @param dataLen	数据区数据长度
	 * @param baudrate	波特率
	 * @return 得到合适的帧发送,间隔毫秒数
	 * @date:2009-11-5
	 */
	public static int getFrameInterval(int appendMillsec, int

	dataLen, int baudrate) {
		int rsInt = (int) Math.ceil(1 * 12 * (dataLen + 4) *

		1000 / (float) baudrate) + appendMillsec;
		return rsInt;
	}

	/**
	 * @describe:	把char类型转换成16进制字符串
	 * @param bArray  char类型数组
	 * @date:2009-11-7
	 */
	public static final String bytesToHexString(char[] bArray) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;

		for (int i = 0; i < bArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2) {
				sb.append(0);
			}
			sb.append(sTemp.toUpperCase() + " ");
		}
		return sb.toString();
	}

}

SmsSendJob.java


package com.serial;

import java.util.ArrayList;
import java.util.List;

/**
 * 作用 : smslib 发送短信,自动匹配串口 <br>
 * 类使用介绍: 获取实例:<code>getInstance</code> 
 * 设置波特率: <code>setBaudrate</code><br>
 * 启动服务: <code>startService</code>已经
 * 
 * 启动短信接收事件<br>
 * 结束服务: <code>stopService</code><br>
 * 打印网络信息: <code>smsInfo</code><br>
 * 
 * 发送短信: <code>sendMessage</code><br>
 * 注意事项 : 无
 */
public class SmsSendJob {

	private static SmsSendJob smsSendJob = new SmsSendJob(); // 本类单例
	/**
	 * 用于动态测试短信串口号
	 */
	private Serial_For_Smslib smslib_test = new Serial_For_Smslib

	();
	/**
	 * 发送短信的服务
	 */
	private SmsService smsService = new SmsService();
	/**
	 * 短信发送模块专用的端口名
	 */
	private static String SMSAPPNAME = "sms_port";
	/**
	 * 波特率
	 */
	private int baudrate = 9600;
	/**
	 * 串口字符(如:COM1)
	 */
	private String comStr = "com1";

	/*---------------------------测试合适的串口号-------------------------------*/
	/**
	 * @describe: 获取SerialBeanl类单例
	 * @date:2009-11-5
	 */
	public static SmsSendJob getInstance() {
		return smsSendJob;
	}

	/**
	 * @describe: 设置波特率 和 串口字符
	 * @param baudrate:
	 *            波特率
	 * @param comStr:
	 *            串口字符
	 * @date:2010-3-2
	 */
	public void initial(int baudrate, String comStr) {
		this.baudrate = baudrate;
		this.comStr = comStr;
	}

	/**
	 * @describe: 动态检测适合短信模块的-串口字符(如:COM1)
	 * @date:2009-11-22
	 */
	public String getRightComStr() {
		String rsCom = null;

		// 获取final_Serial实例--扫描端口数量,并逐个测试
		List<String> portList =	Level_Final_Serial.getAllComPorts();
		if (portList.size() <= 0) {
			// 没有发现任何串口
		} else {
			// 逐个扫描测试连通性
			for (String portStr : portList) {
				// 测试串口的是否适合短信模块
				if (testSms(portStr)) {
					rsCom = portStr;
					break;
				}
			}
		}
		return rsCom;
	}

	/**
	 * @describe: 测试串口的是否适合短信模块
	 * @param portStr:
	 *            串口号. 如:COM3
	 * @return: null:失败 其他:成功
	 */
	public boolean testSms(String portStr) {
		boolean rsBool = false;
		try {
			// ① 打开端口
			rsBool = smslib_test.openPort(portStr,

			baudrate, SMSAPPNAME);
			// ② 串口写
			String atCommand = "AT\r"; // 发送AT指令(加换行符号\r)
			char[] atOrder = atCommand.toCharArray();
			if (rsBool)
				smslib_test.writeByte(atOrder);
			if (rsBool) {
				// ③ 串口读(根据得到的数据,判断返回数据的连通性{返回字符包含OK表示成功})
				rsBool = smslib_test.readByte(portStr);
				// ④ 关闭串口
				smslib_test.closePort();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return rsBool;
	}

	/*---------------------------发送短信-------------------------------*/

	public char[] strToCharArrary(String str) {
		char[] rsChar = str.toCharArray();
		return rsChar;
	}

	/**
	 * @describe: 为发送和接收短信做好准备
	 * @return: true:成功 false:失败
	 * @date:2010-3-2
	 */
	public boolean readyToSendMsg() {
		boolean rsbool = false;
		rsbool = smsService.initial(comStr, baudrate, "0000");
		if (rsbool)
			rsbool = smsService.startService();
		return rsbool;
	}

	/**
	 * @describe: 给指定的一组手机号码,发送短信
	 * @param phoneList
	 *            手机号码列表
	 * @param message
	 *            信息内容
	 * @return: true:成功 false:失败
	 * @date:2010-3-2
	 */
	public boolean sendMessage(List<String> phoneList, String

	message) {
		boolean rsbool = smsService.sendMessage(phoneList,

		message);
		return rsbool;
	}

	/**
	 * @describe: 打印sms信息
	 * @date:2010-3-2
	 */
	public void printSmsInof() throws Exception {
		smsService.smsInfo();
	}

	/**
	 * @describe: 停止服务
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public void stopService() {
		smsService.stopService();
	}

	public static void main(String[] args) throws Exception {

		SmsSendJob smsSendJob = SmsSendJob.getInstance();

		// 运行实例
		String comName = smsSendJob.getRightComStr();

		// 获取合适短信模块的 串口字符

		if (comName != null) {
			smsSendJob.initial(9600, comName);

			// 设置波特率和串口字符
			if (smsSendJob.readyToSendMsg()) {

				// 准备 - ok
				// smsSendJob.printSmsInof();

				// 打印sms信息
				List<String> phoneList = new

				ArrayList<String>();
				phoneList.add("18631129982");
				String message = "我是一条测试短信!"; // 给10086发一条查询余额的短信
				smsSendJob.sendMessage(phoneList, message);
				Thread.sleep(60 * 1000);

				// 一分钟后,关闭短信服务
				// 接收短信在SmsService中已经注册,InboundNotification中process会处理
				// 收短信后,默认会删除收到的短信,也可以通过setRec_msg_remove(boolean)修改
			}
			smsSendJob.stopService();
		} else {
			System.out.println("没有找到合适的串口号");
		}
	}

}
package com.serial;

import java.util.ArrayList;
import java.util.List;

/**
 * 作用 : smslib 发送短信,自动匹配串口 <br>
 * 类使用介绍: 获取实例:<code>getInstance</code> 
 * 设置波特率: <code>setBaudrate</code><br>
 * 启动服务: <code>startService</code>已经
 * 
 * 启动短信接收事件<br>
 * 结束服务: <code>stopService</code><br>
 * 打印网络信息: <code>smsInfo</code><br>
 * 
 * 发送短信: <code>sendMessage</code><br>
 * 注意事项 : 无
 */
public class SmsSendJob {

	private static SmsSendJob smsSendJob = new SmsSendJob(); // 本类单例
	/**
	 * 用于动态测试短信串口号
	 */
	private Serial_For_Smslib smslib_test = new Serial_For_Smslib

	();
	/**
	 * 发送短信的服务
	 */
	private SmsService smsService = new SmsService();
	/**
	 * 短信发送模块专用的端口名
	 */
	private static String SMSAPPNAME = "sms_port";
	/**
	 * 波特率
	 */
	private int baudrate = 9600;
	/**
	 * 串口字符(如:COM1)
	 */
	private String comStr = "com1";

	/*---------------------------测试合适的串口号-------------------------------*/
	/**
	 * @describe: 获取SerialBeanl类单例
	 * @date:2009-11-5
	 */
	public static SmsSendJob getInstance() {
		return smsSendJob;
	}

	/**
	 * @describe: 设置波特率 和 串口字符
	 * @param baudrate:
	 *            波特率
	 * @param comStr:
	 *            串口字符
	 * @date:2010-3-2
	 */
	public void initial(int baudrate, String comStr) {
		this.baudrate = baudrate;
		this.comStr = comStr;
	}

	/**
	 * @describe: 动态检测适合短信模块的-串口字符(如:COM1)
	 * @date:2009-11-22
	 */
	public String getRightComStr() {
		String rsCom = null;

		// 获取final_Serial实例--扫描端口数量,并逐个测试
		List<String> portList =	Level_Final_Serial.getAllComPorts();
		if (portList.size() <= 0) {
			// 没有发现任何串口
		} else {
			// 逐个扫描测试连通性
			for (String portStr : portList) {
				// 测试串口的是否适合短信模块
				if (testSms(portStr)) {
					rsCom = portStr;
					break;
				}
			}
		}
		return rsCom;
	}

	/**
	 * @describe: 测试串口的是否适合短信模块
	 * @param portStr:
	 *            串口号. 如:COM3
	 * @return: null:失败 其他:成功
	 */
	public boolean testSms(String portStr) {
		boolean rsBool = false;
		try {
			// ① 打开端口
			rsBool = smslib_test.openPort(portStr,

			baudrate, SMSAPPNAME);
			// ② 串口写
			String atCommand = "AT\r"; // 发送AT指令(加换行符号\r)
			char[] atOrder = atCommand.toCharArray();
			if (rsBool)
				smslib_test.writeByte(atOrder);
			if (rsBool) {
				// ③ 串口读(根据得到的数据,判断返回数据的连通性{返回字符包含OK表示成功})
				rsBool = smslib_test.readByte(portStr);
				// ④ 关闭串口
				smslib_test.closePort();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return rsBool;
	}

	/*---------------------------发送短信-------------------------------*/

	public char[] strToCharArrary(String str) {
		char[] rsChar = str.toCharArray();
		return rsChar;
	}

	/**
	 * @describe: 为发送和接收短信做好准备
	 * @return: true:成功 false:失败
	 * @date:2010-3-2
	 */
	public boolean readyToSendMsg() {
		boolean rsbool = false;
		rsbool = smsService.initial(comStr, baudrate, "0000");
		if (rsbool)
			rsbool = smsService.startService();
		return rsbool;
	}

	/**
	 * @describe: 给指定的一组手机号码,发送短信
	 * @param phoneList
	 *            手机号码列表
	 * @param message
	 *            信息内容
	 * @return: true:成功 false:失败
	 * @date:2010-3-2
	 */
	public boolean sendMessage(List<String> phoneList, String

	message) {
		boolean rsbool = smsService.sendMessage(phoneList,

		message);
		return rsbool;
	}

	/**
	 * @describe: 打印sms信息
	 * @date:2010-3-2
	 */
	public void printSmsInof() throws Exception {
		smsService.smsInfo();
	}

	/**
	 * @describe: 停止服务
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public void stopService() {
		smsService.stopService();
	}

	public static void main(String[] args) throws Exception {

		SmsSendJob smsSendJob = SmsSendJob.getInstance();

		// 运行实例
		String comName = smsSendJob.getRightComStr();

		// 获取合适短信模块的 串口字符

		if (comName != null) {
			smsSendJob.initial(9600, comName);

			// 设置波特率和串口字符
			if (smsSendJob.readyToSendMsg()) {

				// 准备 - ok
				// smsSendJob.printSmsInof();

				// 打印sms信息
				List<String> phoneList = new

				ArrayList<String>();
				phoneList.add("18631129982");
				String message = "我是一条测试短信!"; // 给10086发一条查询余额的短信
				smsSendJob.sendMessage(phoneList, message);
				Thread.sleep(60 * 1000);

				// 一分钟后,关闭短信服务
				// 接收短信在SmsService中已经注册,InboundNotification中process会处理
				// 收短信后,默认会删除收到的短信,也可以通过setRec_msg_remove(boolean)修改
			}
			smsSendJob.stopService();
		} else {
			System.out.println("没有找到合适的串口号");
		}
	}

}

SmsService.java


package com.serial;

import java.util.List;

import org.smslib.AGateway;
import org.smslib.GatewayException;
import org.smslib.ICallNotification;
import org.smslib.IGatewayStatusNotification;
import org.smslib.IInboundMessageNotification;
import org.smslib.IOrphanedMessageNotification;
import org.smslib.IOutboundMessageNotification;
import org.smslib.InboundMessage;
import org.smslib.Library;
import org.smslib.OutboundMessage;
import org.smslib.Service;
import org.smslib.AGateway.GatewayStatuses;
import org.smslib.AGateway.Protocols;
import org.smslib.Message.MessageEncodings;
import org.smslib.Message.MessageTypes;
import org.smslib.modem.SerialModemGateway;

/**
 * @ SmsService.java 作用 : smslib 应用- 发送短信(可以群发) 服务<br>
 *   类使用介绍: 初始化: <code>initial</code><br>
 *   启动服务:<code>startService</code>已经
 * 
 * 启动短信接收事件<br>
 * 结束服务:<code>stopService</code><br>
 * 打印网络信息:<code>smsInfo</code><br>
 * 
 * 发送短信: <code>sendMessage</code><br>
 * 注意事项 : 无 VERSION DATE BY CHANGE/COMMENT 1.0 2010-3-1 YANGZHONLI create
 */
public class SmsService {

	private static String SEND_SMS_GROUP = "smsgruop"; // 用于发送短信的组名
	private Service srv;

	// 短信服务对象
	private SerialModemGateway gateway;

	// 网关
	private boolean rec_msg_remove = true;

	// 收到,处理短信之后,是否删除当前短信.默认删除

	InboundNotification inbound = new InboundNotification();

	// 接收短信的监听
	OrphanedMessageNotification Orphaned = new OrphanedMessageNotification();

	// 中断短信处理(短信字数较多时,会用2条以上是短信,这时候就用到这个了)-好像有点问题,还需要测试

	/**
	 * @describe: 设置:收到,处理短信之后,是否删除当前短信.默认删除
	 * @param rec_msg_flag:
	 *            true:删除 false:不删除
	 * @date:2010-3-2
	 */
	public void setRec_msg_remove(boolean rec_msg_remove) {
		this.rec_msg_remove = rec_msg_remove;
	}

	/**
	 * @describe: 初始化短信模块
	 * @param com
	 *            串口号
	 * @param baudRate
	 *            波特率
	 * @param pin
	 *            pin值
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean initial(String com, int baudRate, String pin) {
		boolean rsbool = true;

		this.srv = Service.getInstance();
		this.gateway = new SerialModemGateway("SMSLINK", com,

		baudRate, "", "");
		this.gateway.setOutbound(true);
		this.gateway.setInbound(true);
		this.gateway.setProtocol(Protocols.PDU);
		this.gateway.setSimPin(pin);

		try {
			this.srv.addGateway(gateway);
		} catch (GatewayException e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * @describe: ①启动服务 ②创建一个用于发送短信的组(名为: smsgruop) ③创建事件监听(接收和中断短信处理)
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean startService() {
		boolean rsbool = true;
		try {
			this.srv.startService();
			this.srv.createGroup(SEND_SMS_GROUP);
			// 注册启动短信接收事件 -- 小短信
			this.srv.setInboundMessageNotification

			(inbound);
			// 注册启动短信接收事件 -- 大短信
			this.srv.setOrphanedMessageNotification

			(Orphaned);
			// ... 还可以注册其他事件
		} catch (Exception e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * @describe: 停止服务
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean stopService() {
		boolean rsbool = true;
		try {
			this.srv.stopService();
		} catch (Exception e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * @describe: 打印sms信息
	 * @date:2010-3-1
	 */
	public void smsInfo() throws Exception {
		System.out.println();
		System.out.println("smslib Version: " +

		Library.getLibraryVersion());
		System.out.println("Modem Information:");
		System.out.println("  Manufacturer: " +

		gateway.getManufacturer());
		System.out.println("  Model: " + gateway.getModel());
		System.out.println("  Serial No: " +

		gateway.getSerialNo());
		System.out.println("  SIM IMSI: " + gateway.getImsi());
		System.out.println("  Signal Level: " +

		gateway.getSignalLevel() + "%");
		System.out.println("  Battery Level: " +

		gateway.getBatteryLevel() + "%");
		System.out.println("  SmscNumber: " +

		gateway.getSmscNumber());
		System.out.println();
	}

	/**
	 * @describe: 给指定的一组手机号码,发送短信
	 * @param phoneList
	 *            手机号码列表
	 * @param message
	 *            信息内容
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean sendMessage(List<String> phoneList, String

	message) {
		boolean rsbool = true;

		// 把手机号码逐个加入到短信发送组中
		for (String phone : phoneList) {
			this.srv.addToGroup(SEND_SMS_GROUP, phone);
		}
		OutboundMessage msg = new OutboundMessage

		(SEND_SMS_GROUP, message);
		msg.setEncoding(MessageEncodings.ENCUCS2);

		try {
			this.srv.sendMessage(msg);

			// 发送完短信,把手机号码逐个从短信发送组中移除
			for (String phone : phoneList) {
				this.srv.removeFromGroup

				(SEND_SMS_GROUP, phone);
			}
		} catch (Exception e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * 作用 : 收短信的监听,并删除收到的短信
	 */
	public class InboundNotification implements

	IInboundMessageNotification {
		public void process(String gatewayId, MessageTypes

		msgType, InboundMessage msg) {
			if (msgType == MessageTypes.INBOUND)
				System.out
						.println(">>>收到短信① New Inbound message detected from Gateway: "
								+ gatewayId);
			else if (msgType == MessageTypes.STATUSREPORT)
				System.out
						.println(">>>收到短信② New Inbound Status Report message detected from Gateway: "
								+ gatewayId);
			System.out.println(msg);
			// System.out.println("时间:" + msg.getDate().toLocaleString());
			// System.out.println("短信内容:" + msg.getText());
			// System.out.println("发件号码:" + msg.getOriginator());
			try {
				if (rec_msg_remove) { // 删除收到的短信
					srv.deleteMessage(msg);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		@Override
		public void process(AGateway arg0, MessageTypes arg1,
				InboundMessage arg2) {
			// TODO Auto-generated method stub

		}
	}

	/**
	 * 作用 : 当有人向您发送一个大消息,这个消息来的部分。有时,网
	 * 
	 * 络的原因不明,<br>
	 * 一个大消息的某些部分没有到达你的,所以这个问题的消息是
	 * 
	 * 完全没有收到。<br>
	 * 这些孤儿的消息部分留在您的手机,消耗内存。 <br>
	 * 如果您收到太多的“不完整”的消息部分,这些都可能需要您的调
	 * 
	 * 制解调器的内存 <br>
	 * 有效地禁用接收它的任何其他消息。<br>
	 * 
	 * 具体通知方法需要返回<code>true或false</code> :如果您返回
	 * 
	 * true ,该邮件的部分将被删除 ,以夺回失去的调制解调器内存<br>
	 */
	public class OrphanedMessageNotification implements

	IOrphanedMessageNotification {
		public boolean process(String gatewayId, InboundMessage

		msg) {
			System.out.println(">>> 大消息接收 Orphaned message part detected from "
					+ gatewayId);
			System.out.println(msg);
			// Since we are just testing, return FALSE and keep the orphaned
			// message part.
			return false;
		}

		@Override
		public boolean process(AGateway arg0, InboundMessage arg1) {
			// TODO Auto-generated method stub
			return false;
		}
	}

	/**
	 * 作用 : 发短信的监测
	 */
	public class OutboundNotification implements

	IOutboundMessageNotification {
		public void process(String gatewayId, OutboundMessage

		msg) {
			System.out.println("Outbound handler called from Gateway: "
					+ gatewayId);
			System.out.println(msg);
		}

		@Override
		public void process(AGateway arg0, OutboundMessage arg1) {
			// TODO Auto-generated method stub

		}
	}

	/**
	 * 作用 : 接到电话的监听
	 */
	public class CallNotification implements ICallNotification {
		public void process(String gatewayId, String callerId)

		{
			System.out.println(">>> New call detected from Gateway: "
					+ gatewayId + " : " + callerId);
		}

		@Override
		public void process(AGateway arg0, String arg1) {
			// TODO Auto-generated method stub

		}
	}

	/**
	 * 作用 : 网关变动的监听
	 */
	public class GatewayStatusNotification implements

	IGatewayStatusNotification {
		public void process(String gatewayId, GatewayStatuses

		oldStatus, GatewayStatuses newStatus) {
			System.out.println(">>> Gateway Status change for " + gatewayId
					+ ", OLD: " + oldStatus + " -> NEW: " + newStatus);
		}

		@Override
		public void process(AGateway arg0, GatewayStatuses arg1,
				GatewayStatuses arg2) {
			// TODO Auto-generated method stub

		}
	}

}
package com.serial;

import java.util.List;

import org.smslib.AGateway;
import org.smslib.GatewayException;
import org.smslib.ICallNotification;
import org.smslib.IGatewayStatusNotification;
import org.smslib.IInboundMessageNotification;
import org.smslib.IOrphanedMessageNotification;
import org.smslib.IOutboundMessageNotification;
import org.smslib.InboundMessage;
import org.smslib.Library;
import org.smslib.OutboundMessage;
import org.smslib.Service;
import org.smslib.AGateway.GatewayStatuses;
import org.smslib.AGateway.Protocols;
import org.smslib.Message.MessageEncodings;
import org.smslib.Message.MessageTypes;
import org.smslib.modem.SerialModemGateway;

/**
 * @ SmsService.java 作用 : smslib 应用- 发送短信(可以群发) 服务<br>
 *   类使用介绍: 初始化: <code>initial</code><br>
 *   启动服务:<code>startService</code>已经
 * 
 * 启动短信接收事件<br>
 * 结束服务:<code>stopService</code><br>
 * 打印网络信息:<code>smsInfo</code><br>
 * 
 * 发送短信: <code>sendMessage</code><br>
 * 注意事项 : 无 VERSION DATE BY CHANGE/COMMENT 1.0 2010-3-1 YANGZHONLI create
 */
public class SmsService {

	private static String SEND_SMS_GROUP = "smsgruop"; // 用于发送短信的组名
	private Service srv;

	// 短信服务对象
	private SerialModemGateway gateway;

	// 网关
	private boolean rec_msg_remove = true;

	// 收到,处理短信之后,是否删除当前短信.默认删除

	InboundNotification inbound = new InboundNotification();

	// 接收短信的监听
	OrphanedMessageNotification Orphaned = new OrphanedMessageNotification();

	// 中断短信处理(短信字数较多时,会用2条以上是短信,这时候就用到这个了)-好像有点问题,还需要测试

	/**
	 * @describe: 设置:收到,处理短信之后,是否删除当前短信.默认删除
	 * @param rec_msg_flag:
	 *            true:删除 false:不删除
	 * @date:2010-3-2
	 */
	public void setRec_msg_remove(boolean rec_msg_remove) {
		this.rec_msg_remove = rec_msg_remove;
	}

	/**
	 * @describe: 初始化短信模块
	 * @param com
	 *            串口号
	 * @param baudRate
	 *            波特率
	 * @param pin
	 *            pin值
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean initial(String com, int baudRate, String pin) {
		boolean rsbool = true;

		this.srv = Service.getInstance();
		this.gateway = new SerialModemGateway("SMSLINK", com,

		baudRate, "", "");
		this.gateway.setOutbound(true);
		this.gateway.setInbound(true);
		this.gateway.setProtocol(Protocols.PDU);
		this.gateway.setSimPin(pin);

		try {
			this.srv.addGateway(gateway);
		} catch (GatewayException e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * @describe: ①启动服务 ②创建一个用于发送短信的组(名为: smsgruop) ③创建事件监听(接收和中断短信处理)
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean startService() {
		boolean rsbool = true;
		try {
			this.srv.startService();
			this.srv.createGroup(SEND_SMS_GROUP);
			// 注册启动短信接收事件 -- 小短信
			this.srv.setInboundMessageNotification

			(inbound);
			// 注册启动短信接收事件 -- 大短信
			this.srv.setOrphanedMessageNotification

			(Orphaned);
			// ... 还可以注册其他事件
		} catch (Exception e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * @describe: 停止服务
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean stopService() {
		boolean rsbool = true;
		try {
			this.srv.stopService();
		} catch (Exception e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * @describe: 打印sms信息
	 * @date:2010-3-1
	 */
	public void smsInfo() throws Exception {
		System.out.println();
		System.out.println("smslib Version: " +

		Library.getLibraryVersion());
		System.out.println("Modem Information:");
		System.out.println("  Manufacturer: " +

		gateway.getManufacturer());
		System.out.println("  Model: " + gateway.getModel());
		System.out.println("  Serial No: " +

		gateway.getSerialNo());
		System.out.println("  SIM IMSI: " + gateway.getImsi());
		System.out.println("  Signal Level: " +

		gateway.getSignalLevel() + "%");
		System.out.println("  Battery Level: " +

		gateway.getBatteryLevel() + "%");
		System.out.println("  SmscNumber: " +

		gateway.getSmscNumber());
		System.out.println();
	}

	/**
	 * @describe: 给指定的一组手机号码,发送短信
	 * @param phoneList
	 *            手机号码列表
	 * @param message
	 *            信息内容
	 * @return: true:成功 false:失败
	 * @date:2010-3-1
	 */
	public boolean sendMessage(List<String> phoneList, String

	message) {
		boolean rsbool = true;

		// 把手机号码逐个加入到短信发送组中
		for (String phone : phoneList) {
			this.srv.addToGroup(SEND_SMS_GROUP, phone);
		}
		OutboundMessage msg = new OutboundMessage

		(SEND_SMS_GROUP, message);
		msg.setEncoding(MessageEncodings.ENCUCS2);

		try {
			this.srv.sendMessage(msg);

			// 发送完短信,把手机号码逐个从短信发送组中移除
			for (String phone : phoneList) {
				this.srv.removeFromGroup

				(SEND_SMS_GROUP, phone);
			}
		} catch (Exception e) {
			rsbool = false;
			e.printStackTrace();
		}
		return rsbool;
	}

	/**
	 * 作用 : 收短信的监听,并删除收到的短信
	 */
	public class InboundNotification implements

	IInboundMessageNotification {
		public void process(String gatewayId, MessageTypes

		msgType, InboundMessage msg) {
			if (msgType == MessageTypes.INBOUND)
				System.out
						.println(">>>收到短信① New Inbound message detected from Gateway: "
								+ gatewayId);
			else if (msgType == MessageTypes.STATUSREPORT)
				System.out
						.println(">>>收到短信② New Inbound Status Report message detected from Gateway: "
								+ gatewayId);
			System.out.println(msg);
			// System.out.println("时间:" + msg.getDate().toLocaleString());
			// System.out.println("短信内容:" + msg.getText());
			// System.out.println("发件号码:" + msg.getOriginator());
			try {
				if (rec_msg_remove) { // 删除收到的短信
					srv.deleteMessage(msg);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		@Override
		public void process(AGateway arg0, MessageTypes arg1,
				InboundMessage arg2) {
			// TODO Auto-generated method stub

		}
	}

	/**
	 * 作用 : 当有人向您发送一个大消息,这个消息来的部分。有时,网
	 * 
	 * 络的原因不明,<br>
	 * 一个大消息的某些部分没有到达你的,所以这个问题的消息是
	 * 
	 * 完全没有收到。<br>
	 * 这些孤儿的消息部分留在您的手机,消耗内存。 <br>
	 * 如果您收到太多的“不完整”的消息部分,这些都可能需要您的调
	 * 
	 * 制解调器的内存 <br>
	 * 有效地禁用接收它的任何其他消息。<br>
	 * 
	 * 具体通知方法需要返回<code>true或false</code> :如果您返回
	 * 
	 * true ,该邮件的部分将被删除 ,以夺回失去的调制解调器内存<br>
	 */
	public class OrphanedMessageNotification implements

	IOrphanedMessageNotification {
		public boolean process(String gatewayId, InboundMessage

		msg) {
			System.out.println(">>> 大消息接收 Orphaned message part detected from "
					+ gatewayId);
			System.out.println(msg);
			// Since we are just testing, return FALSE and keep the orphaned
			// message part.
			return false;
		}

		@Override
		public boolean process(AGateway arg0, InboundMessage arg1) {
			// TODO Auto-generated method stub
			return false;
		}
	}

	/**
	 * 作用 : 发短信的监测
	 */
	public class OutboundNotification implements

	IOutboundMessageNotification {
		public void process(String gatewayId, OutboundMessage

		msg) {
			System.out.println("Outbound handler called from Gateway: "
					+ gatewayId);
			System.out.println(msg);
		}

		@Override
		public void process(AGateway arg0, OutboundMessage arg1) {
			// TODO Auto-generated method stub

		}
	}

	/**
	 * 作用 : 接到电话的监听
	 */
	public class CallNotification implements ICallNotification {
		public void process(String gatewayId, String callerId)

		{
			System.out.println(">>> New call detected from Gateway: "
					+ gatewayId + " : " + callerId);
		}

		@Override
		public void process(AGateway arg0, String arg1) {
			// TODO Auto-generated method stub

		}
	}

	/**
	 * 作用 : 网关变动的监听
	 */
	public class GatewayStatusNotification implements

	IGatewayStatusNotification {
		public void process(String gatewayId, GatewayStatuses

		oldStatus, GatewayStatuses newStatus) {
			System.out.println(">>> Gateway Status change for " + gatewayId
					+ ", OLD: " + oldStatus + " -> NEW: " + newStatus);
		}

		@Override
		public void process(AGateway arg0, GatewayStatuses arg1,
				GatewayStatuses arg2) {
			// TODO Auto-generated method stub

		}
	}

}



三、Linux、Unix、Solaris平台




与window平台不同的地方就在于动态库和二次开发包不一致,其它基本类似


rxtx与comm的编码方式是不一样的。


1、下载RxTx v2.1.7 R2


2、解压,目录结构如下图所示:


 



                                                                                                        图4-1


3、运行环境配置


复制图4-1中Linux目录下的librxtxSerial.so文件至$JAVA_HOME/jre/lib/$(ARCH)/目录下,


复制RXTXcomm.jar到应用程序的CLASSPATH或$JAVA_HOME/jre/lib/ext目录下,


复制图3-1中的javax.comm.properties文件至$JAVA_HOME/jre/lib目录下,


并将文件中的Driver=com.sun.comm.Win32Driver改成Driver=gnu.io.CommDriver。文件内容如下图所示:


 




4、修改示例程序,编译并运行




五、短信猫设备使用minicom检测




1、linux下端口配置


软件安装完毕后,采用minicom进行配置



执行sudo minicom -s,进入配置界面:



java 短信软件下载 java sms短信接收_java 短信软件下载_02


 


在第三项『串口配置』,设置端口为全面查询到的端口,速率是9600(根据短信猫设备来定,不同的厂家可能会不一样)




 


Serial Device :/dev/ttyS1(此为串口端口,可以在ttyS0~~ttyS4中挨个试)


然后在主菜单Save setup as dfl



可选择Exit推出配置进入minicom,就可以使用at命令测试配置是否成功;也可选择Exit from Minicom推出minicom。



接下在再次执行minicom,进入主界面,这时候应该就可以输入AT指令了。要注意的是,我是重新插拔了一下短信猫才成功连上的



六、minicom使用方法



1、启动minicom命令



   sudo miniscom



2、输入命令



   同时按Ctrl+a 后按e键,不按e键不能输入命令。



   输入at回车,会输出OK。证明短信猫连接成功。如果没有返回可以修改端口再试



  at发短信命令 at+cmgs=手机号码



  ctrl+z发送短信



3、退出命令



   同时按Ctrl+a 后按x键



七、linux虚拟机需要注意是否共享串口





配置成功后会在“vm”菜单中看到共享的端口




八、java环境变量



注意事项:



1、使用smslib库之前,如果你的设备是usb数据线,先检查系统中该设备驱动程序是否已安装,在window环境下,厂商一般会提供设备的驱动程序,在linux环境下,内核2.6.32或以上版本,预装了常用设备的USB转串口驱动,如果系统未自动识别该设备,就需要自行安装该设备的驱动程序了。



2、在开发过程中,org.smslib.TimeoutException: No response from device是最常遇到的一个异常,解决方案请参考: