/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