View Javadoc

1   /* ***** BEGIN LICENSE BLOCK *****
2    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3    *
4    * The contents of this file are subject to the Mozilla Public License Version
5    * 1.1 (the "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    * http://www.mozilla.org/MPL/
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis,
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11   * for the specific language governing rights and limitations under the
12   * License.
13   *
14   * The Original Code is "SMS Library for the Java platform".
15   *
16   * The Initial Developer of the Original Code is Markus Eriksson.
17   * Portions created by the Initial Developer are Copyright (C) 2002
18   * the Initial Developer. All Rights Reserved.
19   *
20   * Contributor(s):
21   *   Boris von Loesch
22   *
23   * Alternatively, the contents of this file may be used under the terms of
24   * either the GNU General Public License Version 2 or later (the "GPL"), or
25   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26   * in which case the provisions of the GPL or the LGPL are applicable instead
27   * of those above. If you wish to allow use of your version of this file only
28   * under the terms of either the GPL or the LGPL, and not to allow others to
29   * use your version of this file under the terms of the MPL, indicate your
30   * decision by deleting the provisions above and replace them with the notice
31   * and other provisions required by the GPL or the LGPL. If you do not delete
32   * the provisions above, a recipient may use your version of this file under
33   * the terms of any one of the MPL, the GPL or the LGPL.
34   *
35   * ***** END LICENSE BLOCK ***** */
36  package org.marre.sms.transport.gsm;
37  
38  import java.io.IOException;
39  import java.util.Properties;
40  
41  import javax.comm.PortInUseException;
42  
43  import org.marre.sms.SmsAddress;
44  import org.marre.sms.SmsConstants;
45  import org.marre.sms.SmsException;
46  import org.marre.sms.SmsMessage;
47  import org.marre.sms.SmsPdu;
48  import org.marre.sms.transport.SmsTransport;
49  import org.marre.sms.transport.gsm.commands.MessageFormatSetReq;
50  import org.marre.sms.transport.gsm.commands.PduSendMessageReq;
51  import org.marre.sms.transport.gsm.commands.PduSendMessageRsp;
52  import org.marre.sms.transport.gsm.commands.PingReq;
53  import org.marre.util.StringUtil;
54  import org.slf4j.Logger;
55  import org.slf4j.LoggerFactory;
56  
57  /***
58   * An SmsTransport that sends the SMS from an GSM phone that is attached
59   * to the serial port.
60   * <p>
61   * This transport supports the following parameters:
62   * <br>
63   * <pre>
64   * <b>sms.gsm.appname</b> - Application name to use when registering the comport
65   * <b>sms.gsm.serialport</b> - Serial port where the GSM phone is located. Ex: "COM1"
66   * <b>sms.gsm.bitrate</b> - Bits per second
67   * <b>sms.gsm.bit</b> - Databits
68   * <b>sms.gsm.parity</b> - Parity (NONE, EVEN, ODD, MARK, SPACE)
69   * <b>sms.gsm.stopbits</b> - Stopbits (1, 1.5, 2)
70   * <b>sms.gsm.echo</b> - Is the device echoing the input?
71   * <b>sms.gsm.flowcontrol</b> - FlowControl (XONXOFF, RTSCTS, NONE)
72   * <b>
73   * </pre>
74   * <p>
75   * <i>This transport cannot set the sending "address" to anything else
76   * than the sending phone's phonenumber.</i>
77   *
78   * @author Markus Eriksson, Boris von Loesch
79   * @version $Id: GsmTransport.java,v 1.27 2005/11/26 16:39:33 c95men Exp $
80   */
81  public class GsmTransport implements SmsTransport
82  {
83      private static Logger log_ = LoggerFactory.getLogger(SerialComm.class);
84      
85      private static String DEFAULT_SERIAL_PORT_APP_NAME = "SMSJ";
86      
87      private static final int RESPONSE_OK = 1;
88      private static final int RESPONSE_ERROR = 2;
89      private static final int RESPONSE_EMPTY_LINE = 4;
90      private static final int RESPONSE_TEXT = 8;
91      private static final int RESPONSE_CONTINUE = 16;
92      
93      private SerialComm serialComm_ = null;
94  
95      /***
96       * Creates a GsmTransport.
97       * 
98       */
99      public GsmTransport()
100     {
101         // Empty
102     }
103 
104     /***
105      * Initializes this transport.
106      * 
107      * @param props 
108      */
109     public void init(Properties props)
110     {
111         String appName = props.getProperty("sms.gsm.appname", DEFAULT_SERIAL_PORT_APP_NAME); 
112         String portName = props.getProperty("sms.gsm.serialport", "COM1");
113 
114         serialComm_ = new SerialComm(appName, portName);
115 
116         serialComm_.setBitRate(props.getProperty("sms.gsm.bitrate", "19200"));
117         serialComm_.setDataBits(props.getProperty("sms.gsm.bit", "8"));
118         serialComm_.setStopBits(props.getProperty("sms.gsm.stopbits", "8"));
119         serialComm_.setParity(props.getProperty("sms.gsm.parity", "NONE"));
120         serialComm_.setFlowControl(props.getProperty("sms.gsm.flowcontrol", "NONE"));
121         serialComm_.setEcho(props.getProperty("sms.gsm.echo", "1").equals("1"));
122     }
123     
124     /***
125      * Initializes the communication with the GSM phone.
126      * 
127      * @throws SmsException
128      * @throws IOException 
129      */
130     public void connect() 
131         throws SmsException, IOException
132     {
133         try
134         {
135             log_.debug("Open serial port.");
136             serialComm_.open();
137             log_.debug("Serial port opened.");
138             
139             // Init
140             MessageFormatSetReq messageFormatSetReq = new MessageFormatSetReq(MessageFormatSetReq.MODE_PDU);
141             messageFormatSetReq.send(serialComm_);
142         }
143         catch (GsmException e)
144         {
145             log_.debug("Close serial port.");
146             serialComm_.close();
147             log_.debug("Serial port closed.");
148             
149             throw new SmsException("Connect failed: " + e.getMessage() + " Last response:" + e.getResponse(), e);
150         }
151     }
152 
153     /***
154      * Sends the SMS message to the given recipients.
155      * 
156      * Note: The sending address is ignored for the GSM transport.
157      *
158      * @param msg The message to send
159      * @param dest The reciever
160      * @param sender The sending address, ignored
161      * @return Returns a local message id
162      * @throws SmsException Thrown if we fail to send the SMS
163      * @throws IOException 
164      */
165     public String send(SmsMessage msg, SmsAddress dest, SmsAddress sender) throws SmsException, IOException
166     {
167         if (dest.getTypeOfNumber() == SmsConstants.TON_ALPHANUMERIC)
168         {
169             throw new SmsException("Cannot sent SMS to an ALPHANUMERIC address");
170         }
171 
172         try
173         {
174             SmsPdu[] msgPdu = msg.getPdus();
175             for(int i=0; i < msgPdu.length; i++)
176             {
177                 byte[] data = GsmEncoder.encodePdu(msgPdu[i], dest, sender);
178                 PduSendMessageReq sendMessageReq = new PduSendMessageReq(data);
179                 PduSendMessageRsp sendMessageRsp = sendMessageReq.send(serialComm_);
180             }
181         }
182         catch (GsmException e)
183         {
184             throw new SmsException("Send failed: " + e.getMessage() + " Last response:" + e.getResponse(), e);
185         }
186         
187         // TODO: Return a real message id
188         return null;
189     }
190 
191     /***
192      * Sends a "AT" command to keep the connection alive.
193      *
194      * @throws IOException 
195      */
196     public void ping()
197         throws IOException
198     {
199         try
200         {
201             PingReq pingReq = new PingReq();
202             pingReq.send(serialComm_);
203         }
204         catch (GsmException e)
205         {
206             String msg = "Ping failed: " + e.getMessage() + 
207                          " Last response: " + e.getResponse();
208             throw (IOException) new IOException(msg).initCause(e);
209         }
210     }
211 
212     /***
213      * Closes the serial connection to the phone.
214      * 
215      * @throws IOException 
216      */
217     public void disconnect()
218     {
219         serialComm_.close();
220     }
221 }