Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: fi/kvanttisofta/sms/SmsTerminal.java


1   //
2   // Copyright (c) 2001 Kvanttisofta oy.  All rights reserved.
3   //
4   //
5   // a class modeling the communication with a SMS terminal device.
6   // (mikko.syrjalahti@iki.fi, aspa@users.sourceforge.net).
7   //
8   // $Id: SmsTerminal.java,v 1.1.1.1 2001/04/18 04:19:00 aspa Exp $.
9   //
10  // TODO:
11  // - error handling. how should errors be communicated to the user?
12  // - lineReceived: error handling
13  //
14  
15  package fi.kvanttisofta.sms;
16  
17  import java.io.*;
18  import java.util.*;
19  import javax.comm.*;
20  import fi.kvanttisofta.sms.*;
21  
22  public class SmsTerminal implements SerialPortEventListener {
23      public static final int SC_OK = 0;
24      public static final int SC_ERROR = 1;
25      public static final int SC_PDU_PARSE_ERROR = 2;
26  
27      private SerialPort serialPort;
28      private OutputStream outStream;
29      private InputStream inStream;
30      private SmsListenerInterface smsListener;
31  
32      /* CMGF=0  --  SMS messages in PDU mode
33         AT+CNMI new mssage indications to DTE
34         - AT+CNMI=[<mode>[,<mt>[,<bm>[,<ds>[,<bfr>]]]]]
35           <mode> -- no indications when DTE-DCE link reserved
36     <mt>   -- received messages (not class 2) routed to DTE with +CMT
37     <bm>   -- no cell breadcast indications
38     <ds>   -- no status reports
39     <bfr>  -- flush indication buffer if <mode> = {1,2}
40         CSCS    --  select DTE character set
41       */
42      private static final String initcmd1 = "ATV1E0Q0X5+CMGF=0";
43      private static final String initcmd2 = "AT+CNMI=1,2,0,0,0";
44      private static final String initcmd3 = "AT+CSCS=\"8859-1\"";
45      private static final String initcmd4 = "AT+CMEE=2";
46      private static final String lfcr = "\015";
47  
48      private int portStatus = OK;
49      private Boolean portStatusLock = new Boolean(true);
50      private String portStatusMsg = "";
51      private static final int OK = 1;
52      private static final int WAIT = 2;
53      private static final int ERROR = 3;
54      private static final int WMSG = 4;
55      private static final int RMSG = 5;
56  
57      private byte[] readBuffer = new byte[500]; // serialEvent
58      private int bufferOffset = 0;              // serialEvent
59  
60      private boolean should_run = true; // not used
61  
62      public SmsTerminal(String portName, SmsListenerInterface smsListener)
63    throws Exception {
64  
65    CommPortIdentifier portId = null;
66    Enumeration portList = CommPortIdentifier.getPortIdentifiers();
67  
68    /* initialize variables */
69    this.smsListener = smsListener;
70  
71    /* find the requested port */
72    while (portList.hasMoreElements()) {
73        portId = (CommPortIdentifier) portList.nextElement();
74  
75        if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
76      if (portId.getName().equals(portName)) {
77          try {
78        serialPort = (SerialPort)
79            portId.open(SmsTerminal.class.getName(), 2000);
80          } catch (PortInUseException e) {
81        //throw new PortInUseException("Already opened: " + e);
82        throw new IOException("port "+portName+" in use: "+e);
83          }
84      }
85        }
86    }
87  
88    /* port not found */
89    if(serialPort == null) {
90        //throw new NoSuchPortException();
91        throw new IOException("NoSuchPortException: '"+portName+"'");
92    }
93  
94    /* Open streams to the port */
95    try {
96        outStream = serialPort.getOutputStream();
97        inStream = serialPort.getInputStream();
98    } catch (IOException e) {
99        serialPort.close();
100       throw new IOException("Cannot get a stream to port: " + e);
101   }
102 
103   /* Configure port */
104   try {
105       serialPort.setSerialPortParams(9600,
106              SerialPort.DATABITS_8,
107              SerialPort.STOPBITS_1,
108              SerialPort.PARITY_NONE);
109   } catch (UnsupportedCommOperationException e) {
110       serialPort.close();
111       throw new IOException ("Operation not supported: " + e);
112   }
113 
114   
115   /* Start a thread for handling comminication with the terminal */
116   serialPort.addEventListener(this);
117 
118   /*Add handler for serial events*/
119   serialPort.notifyOnDataAvailable(true);
120   atCmd(initcmd1);
121   atCmd(initcmd2);
122   atCmd(initcmd3);
123 
124     }
125 
126     private int atCmd(String cmd) {
127   boolean gotTimeout = false;
128 
129   synchronized(portStatusLock) {
130       portStatus = WAIT;
131       try {
132     outStream.write((cmd + lfcr).getBytes());
133       } catch (IOException e) { ; }
134 
135       /* wait for response from device */
136       try {
137     portStatusLock.wait(500); // millis
138       } catch (InterruptedException e) { gotTimeout=true; }
139       if(portStatus != OK) {
140     // port not ok
141       }
142   } // end: synchronized(portStatusLock) {
143       
144   // failed to get device
145   if(gotTimeout) {
146       //System.err.println("SmsTerminal: timeout");
147   }
148 
149   return OK;
150     }
151 
152     private void close() {
153         serialPort.close();
154         should_run = false;
155     }
156 
157 
158     public void serialEvent(SerialPortEvent event) {
159 
160   switch (event.getEventType()) {
161       
162   case SerialPortEvent.BI:      
163   case SerialPortEvent.OE:
164   case SerialPortEvent.FE:
165   case SerialPortEvent.PE:
166   case SerialPortEvent.CD:
167   case SerialPortEvent.CTS:
168   case SerialPortEvent.DSR:
169   case SerialPortEvent.RI:
170   case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
171       break;
172       
173   case SerialPortEvent.DATA_AVAILABLE:
174       int n;
175 
176       try {
177     while ( (n = inStream.available()) > 0) {
178         n = inStream.read(readBuffer, bufferOffset, n);
179         bufferOffset += n;
180 
181         // lfcr detected, line ready
182         if((readBuffer[bufferOffset-1] == 10) &&
183            (readBuffer[bufferOffset-2] == 13)) {
184 
185       String sbuf = new String(readBuffer,0,bufferOffset-2);
186       lineReceived(sbuf);
187       bufferOffset = 0;
188         }
189     }
190       } catch (IOException e) { ; }
191       break; // end: case SerialPortEvent.DATA_AVAILABLE:
192   }
193     }
194     
195     private void lineReceived(String buffer) {
196   String response;
197   StringTokenizer st = new StringTokenizer(buffer, "\r\n");
198 
199   synchronized(portStatusLock) {
200       while (st.hasMoreTokens()) {
201     response = st.nextToken();
202 
203     if (response.equals("")) {
204         portStatus = OK;
205     } else if (response.startsWith("OK")) {
206         portStatus = OK;
207     } else if (response.startsWith(">")) {
208         portStatus = WMSG;
209     } else if (response.startsWith("ERROR")) {
210         portStatus = ERROR;
211     } else if (response.startsWith("+CME ERROR") ||
212          response.startsWith("+CMS ERROR")) {
213         portStatus = ERROR;
214         portStatusMsg = response;
215     } else if (response.startsWith("04")) { // NB: BUG!
216         SmsMsgIncoming msg = null;
217         try {
218       msg = new SmsMsgIncoming(response);
219         } catch (PduParseException e) {
220       smsListener.receiveSms(SC_PDU_PARSE_ERROR,
221                  "unable to parse PDU: '"+
222                  response+"'", null);
223         }
224         portStatus = OK;
225         smsListener.receiveSms(SC_OK, null, msg);
226     } else {
227         // unknown response from terminal
228         //System.err.println("unknown response: '"+response+"'");
229     }
230       } // end: while (st.hasMoreTokens()) {
231       portStatusLock.notify();
232   } // end: synchronized(portStatusLock) {
233   
234   return;
235     }
236 
237     public synchronized boolean sendMessage(String number, String msg) {
238   if(number.startsWith("+"))
239       number = number.substring(1);
240   
241   SmsMsgOutgoing pdumsg = new SmsMsgOutgoing(number, msg);
242   
243   String pdu = pdumsg.toString().toUpperCase();
244   String cmd = "AT+CMGS=" + (pdu.length()/2);
245   
246   atCmd("");
247   atCmd(cmd);
248   
249   atCmd(pdu);
250   atCmd("\032");
251   
252   return true;
253     }
254 
255 }