一、SMSLib简介
SMSLib是一个开放源代码的短信猫二次开发包,有JAVA和.Net两个版本,目前最新版为v3.5.2。
图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、运行示例程序并测试
修改图2-1中src\java\examples\modem目录下的SendMessage.java和ReadMessages.java程序发送短信的参数配置,编译并运行。如下图所示:
-
-
-
-
-
-
-
-
- package examples.modem;
-
- import org.smslib.AGateway;
- import org.smslib.IOutboundMessageNotification;
- import org.smslib.Library;
- import org.smslib.OutboundMessage;
- import org.smslib.Service;
- import org.smslib.modem.SerialModemGateway;
-
- public class SendMessage
- {
- public void doIt() throws Exception
- {
- OutboundNotification outboundNotification = new OutboundNotification();
- System.out.println("Example: Send message from a serial gsm modem.");
- System.out.println(Library.getLibraryDescription());
- System.out.println("Version: " + Library.getLibraryVersion());
-
-
-
-
-
-
-
- SerialModemGateway gateway = new SerialModemGateway("modem.com1", "COM4", 115200, "Huawei", "");
- gateway.setInbound(true);
- gateway.setOutbound(true);
- gateway.setSimPin("0000");
-
-
- gateway.setSmscNumber("+306942190000");
- Service.getInstance().setOutboundMessageNotification(outboundNotification);
- Service.getInstance().addGateway(gateway);
- Service.getInstance().startService();
- System.out.println();
-
- 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() + " dBm");
- System.out.println(" Battery Level: " + gateway.getBatteryLevel() + "%");
- System.out.println();
-
- OutboundMessage msg = new OutboundMessage("306974000000", "Hello from SMSLib!");
- Service.getInstance().sendMessage(msg);
- System.out.println(msg);
-
-
-
-
-
-
-
-
-
-
-
- System.out.println("Now Sleeping - Hit <enter> to terminate.");
- System.in.read();
- Service.getInstance().stopService();
- }
-
-
-
-
- public class OutboundNotification implements IOutboundMessageNotification
- {
- public void process(AGateway gateway, OutboundMessage msg)
- {
- System.out.println("Outbound handler called from Gateway: " + gateway.getGatewayId());
- System.out.println(msg);
- }
- }
-
- public static void main(String args[])
- {
- SendMessage app = new SendMessage();
- try
- {
- app.doIt();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package examples.modem;
-
- import java.util.ArrayList;
- import java.util.List;
- import javax.crypto.spec.SecretKeySpec;
- import org.smslib.AGateway;
- import org.smslib.AGateway.GatewayStatuses;
- import org.smslib.AGateway.Protocols;
- import org.smslib.ICallNotification;
- import org.smslib.IGatewayStatusNotification;
- import org.smslib.IInboundMessageNotification;
- import org.smslib.IOrphanedMessageNotification;
- import org.smslib.InboundMessage;
- import org.smslib.InboundMessage.MessageClasses;
- import org.smslib.Library;
- import org.smslib.Message.MessageTypes;
- import org.smslib.Service;
- import org.smslib.crypto.AESKey;
- import org.smslib.modem.SerialModemGateway;
-
- public class ReadMessages
- {
- public void doIt() throws Exception
- {
-
- List<InboundMessage> msgList;
-
-
- InboundNotification inboundNotification = new InboundNotification();
-
- CallNotification callNotification = new CallNotification();
-
- GatewayStatusNotification statusNotification = new GatewayStatusNotification();
- OrphanedMessageNotification orphanedMessageNotification = new OrphanedMessageNotification();
- try
- {
- System.out.println("Example: Read messages from a serial gsm modem.");
- System.out.println(Library.getLibraryDescription());
- System.out.println("Version: " + Library.getLibraryVersion());
-
- SerialModemGateway gateway = new SerialModemGateway("modem.com4", "COM4", 115200, "Huawei", "E160");
-
- gateway.setProtocol(Protocols.PDU);
-
- gateway.setInbound(true);
-
- gateway.setOutbound(true);
-
- gateway.setSimPin("0000");
-
- Service.getInstance().setInboundMessageNotification(inboundNotification);
- Service.getInstance().setCallNotification(callNotification);
- Service.getInstance().setGatewayStatusNotification(statusNotification);
- Service.getInstance().setOrphanedMessageNotification(orphanedMessageNotification);
-
- Service.getInstance().addGateway(gateway);
-
-
-
- Service.getInstance().startService();
-
- System.out.println();
- 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() + " dBm");
- System.out.println(" Battery Level: " + gateway.getBatteryLevel() + "%");
- System.out.println();
-
-
-
-
- Service.getInstance().getKeyManager().registerKey("+306948494037",
- new AESKey(new SecretKeySpec("0011223344556677".getBytes(), "AES")));
-
-
-
- msgList = new ArrayList<InboundMessage>();
- Service.getInstance().readMessages(msgList, MessageClasses.ALL);
- for (InboundMessage msg : msgList)
- System.out.println(msg);
-
-
- System.out.println("Now Sleeping - Hit <enter> to stop service.");
- System.in.read();
- System.in.read();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- finally
- {
- Service.getInstance().stopService();
- }
- }
-
- public class InboundNotification implements IInboundMessageNotification
- {
- public void process(AGateway gateway, MessageTypes msgType, InboundMessage msg)
- {
- if (msgType == MessageTypes.INBOUND) System.out.println(">>> New Inbound message detected from Gateway: "
- + gateway.getGatewayId());
- else if (msgType == MessageTypes.STATUSREPORT) System.out.println(">>> New Inbound Status " +
- "Report message detected from Gateway: " + gateway.getGatewayId());
- System.out.println(msg);
- }
- }
-
- public class CallNotification implements ICallNotification
- {
- public void process(AGateway gateway, String callerId)
- {
- System.out.println(">>> New call detected from Gateway: " + gateway.getGatewayId() + " : " + callerId);
- }
- }
-
- public class GatewayStatusNotification implements IGatewayStatusNotification
- {
- public void process(AGateway gateway, GatewayStatuses oldStatus, GatewayStatuses newStatus)
- {
- System.out.println(">>> Gateway Status change for " + gateway.getGatewayId() + ", OLD: " + oldStatus + " -> NEW: " + newStatus);
- }
- }
-
- public class OrphanedMessageNotification implements IOrphanedMessageNotification
- {
- public boolean process(AGateway gateway, InboundMessage msg)
- {
- System.out.println(">>> Orphaned message part detected from " + gateway.getGatewayId());
- System.out.println(msg);
-
- return false;
- }
- }
-
- public static void main(String args[])
- {
- ReadMessages app = new ReadMessages();
- try
- {
- app.doIt();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
三、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、修改示例程序,编译并运行
四、短信猫设备可用端口检测程序
- import gnu.io.*;
- import java.util.*;
- import java.io.*;
-
- public class CommTest
- {
- static CommPortIdentifier portId;
- static Enumeration portList;
- static int bauds[] = { 9600, 19200, 57600, 115200 };
-
- public static void main(String[] args)
- {
- portList = CommPortIdentifier.getPortIdentifiers();
- System.out.println("短信设备端口连接测试...");
- while (portList.hasMoreElements())
- {
- portId = (CommPortIdentifier) portList.nextElement();
- if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)
- {
- System.out.println("找到串口: " + portId.getName());
- for (int i = 0; i < bauds.length; i++)
- {
- System.out.print(" Trying at " + bauds[i] + "...");
- try
- {
- SerialPort serialPort;
- InputStream inStream;
- OutputStream outStream;
- int c;
- String response;
- serialPort = (SerialPort) portId.open("SMSLibCommTester", 1971);
- serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN);
- serialPort.setSerialPortParams(bauds[i], SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
- inStream = serialPort.getInputStream();
- outStream = serialPort.getOutputStream();
- serialPort.enableReceiveTimeout(1000);
- c = inStream.read();
- while (c != -1)
- c = inStream.read();
- outStream.write('A');
- outStream.write('T');
- outStream.write('\r');
- try
- {
- Thread.sleep(1000);
- }
- catch (Exception e)
- {
- }
- response = "";
- c = inStream.read();
- while (c != -1)
- {
- response += (char) c;
- c = inStream.read();
- }
- if (response.indexOf("OK") >= 0)
- {
- try
- {
- System.out.print(" 获取设备信息...");
- outStream.write('A');
- outStream.write('T');
- outStream.write('+');
- outStream.write('C');
- outStream.write('G');
- outStream.write('M');
- outStream.write('M');
- outStream.write('\r');
- response = "";
- c = inStream.read();
- while (c != -1)
- {
- response += (char) c;
- c = inStream.read();
- }
- System.out.println(" 发现设备: " + response.replaceAll("\\s+OK\\s+", "").replaceAll("\n", "").replaceAll("\r", ""));
- }
- catch (Exception e)
- {
- System.out.println(" 没有发现设备!");
- }
- }
- else System.out.println(" 没有发现设备!");
- serialPort.close();
- }
- catch (Exception e)
- {
- System.out.println(" 没有发现设备!");
- }
- }
- }
- }
- }
- }
五、短信猫设备使用minicom检测
1、linux下端口配置
软件安装完毕后,采用minicom进行配置
执行sudo minicom -s,进入配置界面,
在第三项『串口配置』,设置端口为全面查询到的端口,速率是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是最常遇到的一个异常,解决方案请参考:短信猫JAVA二次开发包SMSLib,org.smslib.TimeoutException: No response from device解决方案