1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
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
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
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 }