Java 使用SMSLib通过串口通讯收发短信

Java 使用SMSLib通过串口通讯收发短信


原文发表于我的blog:https://uglytroll.ycool.com/post.3226216.html


1、简介:
这里要说的SMSLib和飞信之类的软件有所不同的是他是使用串口通讯来控制手机来进行短信的收发以及其他各类操作。
要说明的是,SMSLib底层还是使用AT命令和手机进行通讯,也就是说,其实这套框架可以干手机任何可以干的事情,只是要看现有的类库是否支持或者你也可以自己扩展这套类库来实现自己所需要的功能。使用起来和用户直接在手机上操作的效果是完全一样的,换句话说,收发短信还是要按照运营商的标准支付费用等。
按照官方自己的说法,SMSLib is a Java library which allows you tosend/receive SMS messages via a compatible GSM modem or GSM phone.SMSLib also supports some bulk sms operators (for outbound messagingonly).
SMSLib是一个开源项目,其源代码和包都可以在https://code.google.com/p/smslib/上下载到,其运行时需要slf4j 和Javacomm的支持,前者是类似log4j的项目,可以在https://www.slf4j.org/下载到,后者是Java串口通讯的基础包,如果是非win32系统也可以使用RXTXcomm来代替,他们可以在smslib上面下载到。
SMSLib缺陷是现在找不到完全的API文档,只能看着examples一点一点摸索。
2、开始:
唯一需要注意的是comm或者RXTX的安装问题
comm:

    * File comm.jar should go under JDKDIR/jre/lib/ext/
    * File javax.comm.properties should go under JDKDIR/jre/lib/
    * Library files (i.e. win32com.dll for Win32 or the .so Linux library files) should go under JDKDIR/jre/bin

RXTX:

    * File RXTXcomm.jar should go under JDKDIR/jre/lib/ext/
    * The necessary library (e.g.. for Linux 32bit, the librxtxSerial.so) should go under JDKDIR/jre/bin/

3、直接看代码:
初始化:         
            // Create new Service object - the parent of all and the main interface
            // to you.
            this.srv = new Service();

            // Create the Gateway representing the serial GSM modem.
            SerialModemGateway gateway = new SerialModemGateway("SMS","COM7",19200,"Nokia","6070");

            // Set the modem protocol to PDU (alternative is TEXT). PDU is the default, anyway...
            gateway.setProtocol(Protocols.PDU);

            // Do we want the Gateway to be used for Inbound messages?
            gateway.setInbound(true);

            // Do we want the Gateway to be used for Outbound messages?
            gateway.setOutbound(true);

            // Let SMSLib know which is the SIM PIN.
            gateway.setSimPin("0000");

            // Set up the notification methods.
            this.srv.setInboundNotification(inboundNotification);
            this.srv.setCallNotification(callNotification);
            this.srv.setGatewayStatusNotification(statusNotification);

            // Add the Gateway to the Service object.
            this.srv.addGateway(gateway);

            // Similarly, you may define as many Gateway objects, representing
            // various GSM modems, add them in the Service object and control all of them.

            // Start! (i.e. connect to all defined Gateways)
            this.srv.startService();
初始化首先就是建立一个Service和Gateway
SMSLib v3 has introduced the concept of the Gateway, which is aninterface to a device or service that can send and/or receive SMSmessages. A gateway could be a GSM modem or a supported bulk smsprovider.
Gateway的初始化里,要说明串口设备的信息比如端口号和baud rate
然后在Service里加入这个Gateway
然后startService()即可
连接以后,可以在Gateway中读取连接的相关信息,如手机类型,电池电量,信号强度什么的:
         System.out.println("Mobile Device Information: ");
        System.out.println("    Manufacturer  : " + gateway.getManufacturer());
        System.out.println("    Model         : " + gateway.getModel());
            System.out.println("    Serial No     : " + gateway.getSerialNo());
            System.out.println("    IMSI          : " + gateway.getImsi());
            System.out.println("    S/W Version   : " + gateway.getSwVersion());
            System.out.println("    Battery Level : " + gateway.getBatteryLevel() + "%");
           System.out.println("    Signal Level  : " + gateway.getSignalLevel() + "%");

如果想在收到短信,接到电话或者Gateway的状态有变化时做出反应,那么就需要在Service里加入三个Listener接口的实现的类的对象。。。他们分别是IInboundMessageNotification,ICallNotification以及IGatewayStatusNotification,并且实现其中的Process方法
看个例子:
    public class CallNotification implements ICallNotification
    {
        public void process(String gatewayId, String callerId)
        {
            System.out.println(">>> New call detected from Gateway: " + gatewayId + " : " + callerId);
        }
    }
然后将这个类的实现加到Service里面就可以了

读取短信:
初始化完成后,
            msgList = new ArrayList<InboundMessage>();
            this.srv.readMessages(msgList, MessageClasses.ALL);
            for (InboundMessage msg : msgList)
                System.out.println(msg);
三行代码,非常简单
其实读取短信的方法只需要readMessages即可,两个参数指定要保存的位置和要读取的短信的类型,如已读,未读,信息报告等。

发送短信也是类似:
            sendSms("1397xxxxxx74","Hello world");
两个参数分别是对方号码和信息内容

给出一个完整的发短信的例子:
/*
* Service.java
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/

package testsms;

import org.smslib.IOutboundMessageNotification;
import org.smslib.Message.MessageEncodings;
import org.smslib.OutboundMessage;
import org.smslib.modem.SerialModemGateway;

public class Main
{
    private static org.smslib.Service srv=new org.smslib.Service();;

    public static void creatService()
    {
         SerialModemGateway gateway  = new SerialModemGateway("SMS","COM7",19200,"Nokia","6070");
          gateway.setInbound(true);
  gateway.setOutbound(true);
         try
        {
               srv.addGateway(gateway);
             srv.startService();
            System.out.println("Modem connected.");
            sendSms("1397xxxxxx74","Hello world");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    public static org.smslib.Service getService()
    {
        if (srv == null)
        {
            creatService();
        }
        return srv;
    }

    public static void disconnect()
    {
        try
        {
            //srv.disconnect();

            System.out.println("Modem disconnected.");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

    }
public static void main(String args[]){
    creatService();
}
public static boolean sendSms(String mobile,String content) {
        OutboundMessage msg = new OutboundMessage(mobile, content);
  msg.setEncoding(MessageEncodings.ENCUCS2);
  try {
   srv.sendMessage(msg);
   System.out.println(msg);
  }
  catch (Exception ex) {
   //log.error(ex);
   return false;
  }
  return true;
}

public void close() {
  try {
   srv.stopService();
  }
  catch (Exception ex) {
   //log.error(ex);
  }
}
  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);
  }
}
}

4、可以看出,使用SMSLib通过串口连接手机设备之后可以非常方便的使用Java来对收发短信进行控制
现在的版本的SMSLib提供对以下设备的支持:

The following models are reported to be compatible:

    * Billionton: PCMCIA PCGPRSQ-B.
    * EagleTec: GSM modems.
    * Fargo Maestro 20.
    * ITengo: 3000, WM1080A.
    * Janus: GSM864Q.
    * Nokia: 6070, 6100, 6210, 6310, 6310i, 6230, 6230i, 6681,8250, 8310, 6610, 6800, 7210, 6810, 7250i, 6103, 6020, 3220, 6822,5140, 5140i, 30 (terminal).
    * Multitech: Multimodem GPRS (SMSLib for Java can also drive the Multitech Multimodem via its IP port).
    * Sharp: GX30, GX32.
    * Siemens: MC35i, M35, M50, M65, C45, TC35i, C65, M55, TC65t.
    * SIMCOM Ltd: SIMCOM_SIM100S.
    * Sony Ericsson: K300i, SE K800i, K700i, K750i, SE W850i, W880i, GC89, Z550a, W800, W580i, W810, i320, GT48.
    * Ubinetics: GDC201.
    * Wavecom: M1206B, M1306B, WMOD2 Wismo, Fastrack Supreme 10, WISMOQCDMA CDMA.
    * Huawei: E220 (may require the forced setting of SMSC address).
    * Motorola: V3.
    * Teltonika: ModemUSB.
    * Motorola: V3, L6.
    * Samsung: D520.
    * Samba: 55-SET GSM/GPRS USB modem.

上面的列表估计也不是很全,大家可以自行尝试,有兴趣的也可以继续研究下SMSLib的源代码,里面还有个SMSServer的类库估计可以用来建立一个短信服务器来进行大规模的短信收发,还有很多类和方法文中也没有提到。

评论