/Users/lyon/j4p/src/serialPorts/SNComHandler.java

1    package serialPorts; 
2     
3    //  Generated by P Bennett: Monday, 4 October 1999 at: 05:24:32 pm 
4    //  Com Port Handler. 
5    //  I have released this code as a guide only. 
6    //  It will not run without the supporting classes. 
7    //  It was origanally written to communicate with a development prototype 
8    //  and runs under Slackware Linux Version 4 with Blackdown jdk1.1.7_v3 
9    //  Green Threads and rxtx version 3.4 with Java Comms API V2.0 
10   //  This thread is controlled by a thread that implements a queue 
11   //  and methods for controlling the queue and allocating the resources (modems) 
12   //  The modem used for development was a Siemens M20 Cellular modem. 
13   //  The remote equipment dumped its data upon connection and then hangs up. 
14   //  The protocol has changed somewhat now. (A Subset of HDLC) 
15   //  I have added extra comments for your benefit. 
16   //  It is free to use. 
17   //  Just a quick note. I have no formal training therefor the programming techniques 
18   //  may not be the best ones to use. However the technique I use has been developed 
19   //  through experience and it seems to work for me. 
20    
21   import gnu.io.*; 
22    
23   import java.io.IOException; 
24   import java.io.InputStream; 
25   import java.io.OutputStream; 
26   import java.util.TooManyListenersException; 
27    
28   //Comms Extensions 
29    
30   /** Class To Talk To A GSM Cellular Modem, Dial an SNU and retrieve the data. 
31    * Uses Java Comm API 2.0 
32    * @author P Bennett 
33    * @version 1.0 
34    * @see serialPorts.SNComThread 
35    */ 
36    
37   public class SNComHandler extends java.lang.Thread implements 
38           SerialPortEventListener { 
39    
40       private static serialPorts.SNComThread comThread;           // A reference back to the parent. 
41       private static serialPorts.SNLogger comLog;             // Log handler 
42       private static serialPorts.SNConfig serverConfig;               // Server Configuration object 
43       private String comName = "Nil";             // The com port name to use as in /dev/ttyS0 
44       private boolean process = false;                // Process a request 
45       private String requestId = "Nil";               // Request ID 
46       private String num = "Nil";                 // The phone number to dial 
47       private boolean running = true;             // Make it go around 
48       private CommPortIdentifier portId;              // Port Identifier 
49       private SerialPort serialPort = null;               // Serial Port object 
50       private OutputStream outputStream = null;           // The streams 
51       private InputStream inputStream = null; 
52       private String errMessage = "";             // An error message 
53       private boolean fatalErr = false;               // Big problems call the emergency team :-( 
54       private boolean waitForInput = true;                // Wait for incoming data 
55    
56       /** Construct a new SNComHandler Object.. 
57        * For initialising the array of Com Handlers. 
58        * @see serialPorts.SNComThread 
59        */ 
60       public SNComHandler() { 
61       } 
62    
63       /** Construct a new SNComHandler Object. 
64        * Created with the following parameters. 
65        * @param cThread The parent thread. 
66        * @param sLog The Logging object. 
67        * @param sConfig The server config object. 
68        * @param cName The Com Port name eg. /dev/ttyS0 
69        * @see serialPorts.SNLogger 
70        * @see serialPorts.SNConfig 
71        */ 
72       public SNComHandler(serialPorts.SNComThread cThread, serialPorts.SNLogger sLog, serialPorts.SNConfig 
73               sConfig, String cName) throws NoSuchPortException { 
74           this.comThread = cThread;               // Parent thread 
75           this.comLog = sLog;                 // Log object 
76           this.serverConfig = sConfig;                // Config object 
77           this.comName = cName;               // The com port name 
78           portId = 
79                   (CommPortIdentifier) CommPortIdentifier.getPortIdentifier(this.comName); 
80           // Set up the ID 
81           this.comLog.log("Com Handler Initialised For " + comName);  // Log start 
82       } 
83    
84       /** Thread run method 
85        * Call unit num, when requested and 
86        * pass the recieved data back to 
87        * the parent thread que. 
88        */ 
89       public void run() { 
90   //      comLog.debugInfo("Com Handler Run Method Started For " + comName); 
91           int resetCount = 0;             // Reset attempts 
92           int resetCount2 = 0;                // And again. There must be a better way 
93           int resetCount3 = 0;                // And again. of doing this!!!! They are all the same. 
94           while (running) {               // While we are doin it. 
95               if (fatalErr) {             // Big problems 
96                   comThread.queRequest(requestId, errMessage, "Error");   // Tell the parent 
97                   comLog.log(errMessage + " " + comName + " " + num); // Tell everyone 
98                   num = "Nil";                            // Reset some variables 
99                   resetCount = 0;                         // The error resets process 
100                  resetCount2 = 0;                        // Round we go again. 
101                  resetCount3 = 0; 
102                  fatalErr = false; 
103              } 
104              if (!process) {                             // Nothing to do 
105                  try { 
106                      Thread.sleep(500);                  // Have a sleep 
107                  } catch (InterruptedException e) { 
108                  } 
109                  continue;                           // Round we go again. 
110              } 
111              comLog.debugInfo("**********We Are Processing***********"); 
112              if (num.equals("Nil")) {                    // Can't dial Nil! 
113                  try {                       // Just a catch never tested 
114                      Thread.sleep(500);          // Have a sleep 
115                  } catch (InterruptedException e) { 
116                  }       // Prolly does not work as intended 
117                  continue;                   // Round we go again. 
118              } 
119              comLog.debugInfo("**********Trying To Open Port***********"); 
120              if (!openPort()) {                  // Try to open port 
121                  closePort();                    // Try to close it then 
122                  try { 
123                      Thread.sleep(500);          // Have a sleep 
124                  } catch (InterruptedException e) { 
125                  } 
126                  resetCount++;                   // Up the counter 
127                  //***************** 3 goes in serverconfig ************************8 
128                  if (resetCount > 3) {               // Check the counter 
129                      process = false;            // We got problems 
130                      errMessage = "Error! Could Not Open Port"; 
131                      fatalErr = true;                // We got big problems 
132                  } 
133                  continue;                   // Round we go to sort it out 
134              } 
135              comLog.debugInfo("**********Trying To Reset Modem***********"); 
136              if (!reset()) {                     // We got the port now reset the modem 
137                  try { 
138                      Thread.sleep(500);          // Have a sleep 
139                  } catch (InterruptedException e) { 
140                  } 
141                  resetCount2++;              // Up the counter 
142                  //***************** 3 goes in serverconfig ************************8 
143                  if (resetCount2 > 3) {              // Check the counter 
144                      process = false;            // We got problems 
145                      errMessage = "Error! Could Not Reset Modem"; 
146                      fatalErr = true;                // We got big problems 
147                  } 
148                  continue;                   // Round we go to sort it out 
149              } 
150              comLog.debugInfo("**********Trying To Dial***********"); 
151              if (!dial()) {                      // The modem reset OK now dial 
152                  comLog.debugInfo("**********" + errMessage + "***********"); 
153                  try { 
154                      Thread.sleep(500);          // Have a sleep 
155                  } catch (InterruptedException e) { 
156                  } 
157                  resetCount3++;              // Up the count 
158                  //***************** 3 goes in serverconfig ************************8 
159                  if (resetCount3 > 2) {              // Check the count 
160                      process = false;            // We got problems 
161                      errMessage = "Error! Could Not Dial"; 
162                      fatalErr = true;                // We got big problems 
163                  } 
164                  continue;                   // Round we go to sort it out 
165              } 
166              int numBytes = 0;                   // Number of bytes read from input 
167              byte[] readBuffer = new byte[20];           // Tmp Read buffer of 20 bytes 
168              String sReadBuff = "";                  // Read Buffer 
169              boolean dLoop = true;                   // Loop 
170              while (dLoop) {                     // Wait for incoming data 
171                  try { 
172                      while (inputStream.available() > 0) {       // While there is something to read 
173                          numBytes = inputStream.read(readBuffer);   // Get the bytes 
174                          String tmpR = new String(readBuffer);             // Set up a string 
175                          sReadBuff += tmpR.substring(0, numBytes);  // Add to read buffer 
176                      } 
177                  } catch (IOException e) { 
178                      dLoop = false;                  // Problems 
179                      process = false;                // This has never occured 
180                  } 
181                  if (sReadBuff.indexOf("NO CARRIER") != -1) {        // Test incoming data 
182                      errMessage = "";                // Unit hangs up once it 
183                      dLoop = false;                  // dumps its data 
184                  } else if (sReadBuff.indexOf("ERROR") != -1) {  // Check for error 
185                      errMessage = "Error! Recieved Data Not Clean " + num + " " + comName; 
186                      dLoop = false; 
187                  } else if (sReadBuff.length() > 5000) {         // Check for receive runnaway 
188                      errMessage = ""; 
189                      dLoop = false; 
190                  } 
191              } 
192              if (errMessage.equals("")) {            // No error occured 
193                  comThread.queRequest(requestId, sReadBuff, "Ready");    // Tell the parent the result 
194                  comLog.log("Data Recieved " + " " + requestId + " " + num); // Log it 
195                  System.out.println("*********" + sReadBuff + "*********");  // Raw Debug code 
196              } else { 
197                  if (!fatalErr) {                // Error 
198                      comThread.queRequest(requestId, errMessage, "Error");   // Tell parent 
199                      comLog.log(errMessage + " " + comName + " " + num); // Log 
200                      System.out.println("*********" + errMessage + "*********"); // Raw debug 
201                  } 
202              } 
203              closePort();                    // Close the port 
204              resetCount = 0;                 // Reset the variables ready for next request 
205              resetCount2 = 0; 
206              resetCount3 = 0; 
207              num = "Nil"; 
208              process = false; 
209          } 
210      } 
211   
212      /** Open Com Port 
213       * @return true if succesfull 
214       */ 
215      private boolean openPort() { 
216          if (serialPort == null) {                   // Set up serial port object if need be 
217              comLog.debugInfo("**********Open Port Routine***********"); 
218              try { 
219                  serialPort = (SerialPort) portId.open("SimpleReadApp", 2000); // Open serial port 
220                  comLog.debugInfo("**********Port Open***********"); 
221              } catch (PortInUseException e) { 
222                  return false;               // Hmm its in use 
223              } 
224              if (inputStream == null) {          // Set up the input stream if need be 
225                  try { 
226                      inputStream = serialPort.getInputStream();      // Get the stream 
227                  } catch (IOException e) { 
228                      return false; 
229                  } 
230              } 
231              if (outputStream == null) {         // Set up the output stream if need be 
232                  try { 
233                      outputStream = serialPort.getOutputStream();        // Get the stream 
234                  } catch (IOException e) { 
235                      return false; 
236                  } 
237              } 
238              try { 
239                  serialPort.addEventListener(this);  // Add the event listener 
240              } catch (TooManyListenersException e) { 
241                  return false; 
242              } 
243              serialPort.notifyOnDataAvailable(true); // Set the port to notify on incoming data 
244              //********* Maybe this goes in serverconfig maybe on a per port basis 
245              // Set the port parameters 
246              try { 
247                  serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8, 
248                          SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); 
249              } catch (UnsupportedCommOperationException e) { 
250                  return false; 
251              } 
252          } 
253          return true;        // Everything went ok 
254      } 
255   
256      /** Close Com Port. */ 
257   
258      private void closePort() { 
259          if (serialPort != null) {                   // Check that the serial port is not null 
260              serialPort.notifyOnDataAvailable(false);    // Close down notification 
261              serialPort.removeEventListener();       // Remove the event listener 
262              if (inputStream != null) {          // Check for null 
263                  try { 
264                      inputStream.close();        // Close it 
265                      inputStream = null;     // Clean up 
266                  } catch (IOException e) { 
267                  } 
268              } 
269              if (outputStream != null) {         // Check for null 
270                  try { 
271                      outputStream.close();       // Close it 
272                      outputStream = null;        // Clean up 
273                  } catch (IOException e) { 
274                  } 
275              } 
276              serialPort.close();             // Close the serial port 
277              serialPort = null;              // Clean up 
278          } 
279      } 
280   
281      /** Reset The Modem 
282       * @return true if succesfull. 
283       */ 
284      private boolean reset() { 
285          try { 
286              outputStream.write(new String("atz").getBytes());       // Send the modem atz 
287              outputStream.write((byte) 0x0D);                // And the other stuff 
288              outputStream.write((byte) 0x0A);                // <CR> <LF> 
289          } catch (IOException e) { 
290              return false; 
291          } 
292          int waitingCount = 0;                           // Heres another counter 
293          waitForInput = true;                            // We are waiting 
294          while (waitForInput) {                          // Yes we are 
295              try { 
296                  Thread.sleep(100);                  // We have a little rest 
297              } catch (InterruptedException e) { 
298              } 
299              waitingCount++;                     // We count 
300              //***************** 20 goes in serverconfig ************************ 
301              if (waitingCount > 20) {                        // We have counted to much 
302                  return false;                       // Could not reset 
303              } 
304          } 
305          int numBytes = 0;                           // Set up number of bytes read 
306          byte[] readBuffer = new byte[20];                   // And a buffer 
307          String sReadBuff = "";                          // And another buffer 
308          try { 
309              while (inputStream.available() > 0) { 
310                  numBytes = inputStream.read(readBuffer);        // Read from the port 
311                  String tmpR = new String(readBuffer); 
312                  sReadBuff += tmpR.substring(0, numBytes); 
313              } 
314          } catch (IOException e) { 
315              return false; 
316          } 
317          //********************Maybe for serverconfig 
318          if (sReadBuff.indexOf("OK") != -1) {            // Test for OK response from modem 
319              try { 
320                  Thread.sleep(1000);         // We have another sleep to allow things 
321              } catch (InterruptedException e) { 
322              }       // to settle 
323              return true; 
324          } 
325          return false;                       // We did not reset OK 
326      } 
327   
328      /** Dial number requested 
329       * @return true if connected 
330       */ 
331      private boolean dial() { 
332          try { 
333              comLog.debugInfo("**********" + num + "***********"); 
334              outputStream.write(new String("atd").getBytes());       // Send atd 
335              outputStream.write(num.getBytes());             // And the number 
336              outputStream.write((byte) 0x0D);                // And the other stuff 
337              outputStream.write((byte) 0x0A); 
338          } catch (IOException e) { 
339              errMessage = "Error! Could Not Write To Port "; 
340              comLog.debugInfo("**********Error Writing***********"); 
341              return false;                           // Bad could not write 
342          } 
343          int waitingCount = 0;                           // We are counting again 
344          waitForInput = true;                            // Waiting 
345          while (waitForInput) { 
346              try { 
347                  Thread.sleep(100);                  // Have a sleep 
348              } catch (InterruptedException e) { 
349              } 
350              waitingCount++;                     // Counting 
351              //**************** For serverconfig ************************ 
352              if (waitingCount > 200) {                   // Counted to much 
353                  errMessage = "Error! Timed Out Waiting For Response"; 
354                  return false;                       // Timed out 
355              } 
356          } 
357          int numBytes = 0;                   // Set up for reading 
358          byte[] readBuffer = new byte[20];           // Youve seen it before 
359          String sReadBuff = "";                  // The comments are getting thinner 
360          boolean dLoop = true;                   // No need to repeat 
361          while (dLoop) { 
362              try { 
363                  while (inputStream.available() > 0) { 
364                      numBytes = inputStream.read(readBuffer); 
365                      String tmpR = new String(readBuffer); 
366                      sReadBuff += tmpR.substring(0, numBytes);       // We read it 
367                  } 
368                  if (sReadBuff.indexOf("NO CARRIER") != -1) {            // Out of area 
369                      errMessage = "Error! No Carrier"; 
370                      return false; 
371                  } else if (sReadBuff.indexOf("BUSY") != -1) {           // Busy 
372                      errMessage = "Error! Busy";             // Who is ringing our units 
373                      return false;                       // Maybe it is dialing out 
374                  } else if (sReadBuff.indexOf("NO DIAL TONE") != -1) {       // Bad no signal 
375                      errMessage = "Error! No Dial Tone";         // Were has the ariel gone 
376                      return false; 
377                  } else if (sReadBuff.indexOf("OK") != -1) {         // Hmm voice call no good 
378                      errMessage = "Error! Voice Call"; 
379                      return false; 
380                  } else if (sReadBuff.indexOf("CONNECT") != -1) {        // Ah this is what we want 
381                      return true;                        // Return true 
382                  } 
383              } catch (IOException e) { 
384                  errMessage = "Error! Could Not Read From Com Port"; 
385                  return false;           // Bad but never happened yet 
386              } 
387          } 
388          errMessage = "Error! Invalid Data " + sReadBuff; 
389          return false;               // Something has gone wrong 
390      } 
391   
392      /** Serial Event Routine 
393       * Set waitForInput to false when data ready 
394       */ 
395      public void serialEvent(SerialPortEvent event) { 
396          switch (event.getEventType()) { 
397              case SerialPortEvent.BI: 
398              case SerialPortEvent.OE: 
399              case SerialPortEvent.FE: 
400              case SerialPortEvent.PE: 
401              case SerialPortEvent.CD: 
402              case SerialPortEvent.CTS: 
403              case SerialPortEvent.DSR: 
404              case SerialPortEvent.RI: 
405              case SerialPortEvent.OUTPUT_BUFFER_EMPTY: 
406                  break; 
407              case SerialPortEvent.DATA_AVAILABLE: 
408                  waitForInput = false;               // We got incoming 
409                  break;                      // Thats it for serial events 
410          } 
411      } 
412   
413      /** Process Request To Call SNU. 
414       * Request that a call be made and the data 
415       * returned to the controlling thread. 
416       * @see serialPorts.SNComThread 
417       */ 
418      public void processRequest(String req, String num) { 
419          requestId = req;                    // Set ID 
420          this.num = num;                 // Set the phone number 
421          process = true;                     // Make it go 
422      } 
423   
424      /** Is Processing Call 
425       * @return true if thread is busy 
426       * @see serialPorts.SNComThread 
427       */ 
428      public boolean isProcessing() { 
429          return process;                     // Are you busy 
430      } 
431   
432      /** Is Processing This Q Id. 
433       * @param qID The ID to test for 
434       * @return true if the thread is processing qID 
435       * @see serialPorts.SNComThread 
436       */ 
437      public boolean isProcessing(String qID) { 
438          return requestId.equals(qID);               // Are you busy doing this job 
439      } 
440  } 
441   
442  /* the following was added so the code will compile.  Its not proper */ 
443   
444  class SNLogger { 
445      public void debugInfo(java.lang.String it) { 
446      } 
447   
448      public void log(java.lang.String it) { 
449      } 
450  } 
451   
452  class SNComThread { 
453      public void queRequest(java.lang.String a, java.lang.String b, java.lang.String c) { 
454      } 
455  } 
456   
457  class SNConfig { 
458  } 
459