File: SNComHandler.java

package info (click to toggle)
rxtx 2.2pre2%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster
  • size: 6,960 kB
  • sloc: ansic: 14,367; sh: 10,742; java: 7,629; cpp: 2,717; makefile: 143
file content (445 lines) | stat: -rw-r--r-- 16,205 bytes parent folder | download | duplicates (8)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
//	Generated by P Bennett: Monday, 4 October 1999 at: 05:24:32 pm
//	Com Port Handler.
//	I have released this code as a guide only.
//	It will not run without the supporting classes.
//	It was origanally written to communicate with a development prototype 
//	and runs under Slackware Linux Version 4 with Blackdown jdk1.1.7_v3 
//	Green Threads and rxtx version 3.4 with Java Comms API V2.0
//	This thread is controlled by a thread that implements a queue
//	and methods for controlling the queue and allocating the resources (modems)
//	The modem used for development was a Siemens M20 Cellular modem.
//	The remote equipment dumped its data upon connection and then hangs up. 
//	The protocol has changed somewhat now. (A Subset of HDLC)
//	I have added extra comments for your benefit.
//	It is free to use.
//	Just a quick note. I have no formal training therefor the programming techniques
//	may not be the best ones to use. However the technique I use has been developed
//	through experience and it seems to work for me.

import java.util.*;
import java.io.*;
import gnu.io.*;		//Comms Extensions

/** Class To Talk To A GSM Cellular Modem, Dial an SNU and retrieve the data.
* Uses Java Comm API 2.0
* @author P Bennett
* @version 1.0
* @see SNServerIO
* @see SNComThread
*/

public class SNComHandler extends java.lang.Thread implements
SerialPortEventListener {

private static SNComThread comThread;			// A reference back to the parent.	
private static SNLogger comLog;				// Log handler
private static SNConfig serverConfig;				// Server Configuration object
private String comName = "Nil";				// The com port name to use as in /dev/ttyS0
private boolean process = false;				// Process a request
private String requestId = "Nil";				// Request ID
private String num = "Nil";					// The phone number to dial
private boolean running = true;				// Make it go around
private CommPortIdentifier portId;				// Port Identifier
private SerialPort serialPort = null;				// Serial Port object
private OutputStream outputStream = null;			// The streams
private InputStream inputStream = null;
private String errMessage = "";				// An error message
private boolean fatalErr = false;				// Big problems call the emergency team :-(
private boolean waitForInput = true;				// Wait for incoming data

/** Construct a new SNComHandler Object.. 
* For initialising the array of Com Handlers.
* @see SNComThread
*/
	public SNComHandler() {
	}

/** Construct a new SNComHandler Object.
* Created with the following parameters.
* @param cThread The parent thread.
* @param sLog The Logging object.
* @param sConfig The server config object.
* @param cName The Com Port name eg. /dev/ttyS0
* @see SNLogger
* @see SNConfig
*/
	public SNComHandler(SNComThread cThread, SNLogger sLog, SNConfig
sConfig, String cName) throws NoSuchPortException {
		this.comThread = cThread;				// Parent thread
		this.comLog = sLog;					// Log object
		this.serverConfig = sConfig;				// Config object
		this.comName = cName;				// The com port name
		portId =
(CommPortIdentifier)CommPortIdentifier.getPortIdentifier(this.comName);
 // Set up the ID
		this.comLog.log("Com Handler Initialised For " + comName);	// Log start
	}

/** Thread run method
* Call unit num, when requested and
* pass the recieved data back to
* the parent thread que.
*/
	public void run() {
//		comLog.debugInfo("Com Handler Run Method Started For " + comName);
		int resetCount = 0;				// Reset attempts
		int resetCount2 = 0;				// And again. There must be a better way  
		int resetCount3 = 0;				// And again. of doing this!!!! They are all the same. 
		while (running) {				// While we are doin it.
			if (fatalErr) {				// Big problems
				comThread.queRequest(requestId, errMessage, "Error"); 	// Tell the parent
				comLog.log(errMessage  + " " + comName + " " + num);	// Tell everyone
				num = "Nil";							// Reset some variables
				resetCount = 0;							// The error resets process
				resetCount2 = 0;						// Round we go again.
				resetCount3 = 0;
				fatalErr = false;
			}
			if (!process) {								// Nothing to do
				try {
	            			Thread.sleep(500);					// Have a sleep
        				} catch (InterruptedException e) {}
				continue;							// Round we go again.
			}
			comLog.debugInfo("**********We Are Processing***********");
			if (num.equals("Nil")) {					// Can't dial Nil!
				try {						// Just a catch never tested
	            			Thread.sleep(500);			// Have a sleep
        				} catch (InterruptedException e) {}		// Prolly does not work as intended
				continue;					// Round we go again.
			}
			comLog.debugInfo("**********Trying To Open Port***********");
			if (!openPort()) {					// Try to open port
				closePort();					// Try to close it then
				try {						
	            			Thread.sleep(500);			// Have a sleep
        				} catch (InterruptedException e) {}
				resetCount ++;					// Up the counter
				//***************** 3 goes in serverconfig ************************8
				if (resetCount > 3) {				// Check the counter
					process = false;			// We got problems
					errMessage = "Error! Could Not Open Port";
					fatalErr = true;				// We got big problems
				}
				continue;					// Round we go to sort it out
			}
			comLog.debugInfo("**********Trying To Reset Modem***********");
			if (!reset()) {						// We got the port now reset the modem
				try {
	            			Thread.sleep(500);			// Have a sleep
        				} catch (InterruptedException e) {}
				resetCount2 ++;				// Up the counter
				//***************** 3 goes in serverconfig ************************8
				if (resetCount2 > 3) {				// Check the counter
					process = false;			// We got problems
					errMessage = "Error! Could Not Reset Modem";
					fatalErr = true;				// We got big problems	
				}
				continue;					// Round we go to sort it out
			}
			comLog.debugInfo("**********Trying To Dial***********");
			if (!dial()) {						// The modem reset OK now dial
				comLog.debugInfo("**********" + errMessage + "***********");
				try {
	            			Thread.sleep(500);			// Have a sleep
        				} catch (InterruptedException e) {}
				resetCount3 ++;				// Up the count
				//***************** 3 goes in serverconfig ************************8
				if (resetCount3 > 2) {				// Check the count
					process = false;			// We got problems
					errMessage = "Error! Could Not Dial";
					fatalErr = true;				// We got big problems	
				}
				continue;					// Round we go to sort it out
			}
			int numBytes = 0;					// Number of bytes read from input
			byte[] readBuffer = new byte[20];			// Tmp Read buffer of 20 bytes
			String sReadBuff = "";					// Read Buffer
			boolean dLoop = true;					// Loop
			while (dLoop) {						// Wait for incoming data
				try {
					while (inputStream.available() > 0) {		// While there is something to read
						numBytes = inputStream.read(readBuffer);   // Get the bytes
						String tmpR = new String(readBuffer);	          // Set up a string	
						sReadBuff += tmpR.substring(0, numBytes);  // Add to read buffer
					}
				} catch (IOException e) {
					dLoop = false;					// Problems	
					process = false;				// This has never occured
				}
				if (sReadBuff.indexOf("NO CARRIER") != -1) {		// Test incoming data
					errMessage = "";				// Unit hangs up once it
					dLoop = false;					// dumps its data
				} else if (sReadBuff.indexOf("ERROR") != -1) {	// Check for error
					errMessage = "Error! Recieved Data Not Clean " + num + " " + comName;
					dLoop = false;					
				} else if (sReadBuff.length() > 5000) {			// Check for receive runnaway
					errMessage = "";
					dLoop = false;
				}
			}
			if (errMessage.equals("")) { 			// No error occured
				comThread.queRequest(requestId, sReadBuff, "Ready");	// Tell the parent the result
				comLog.log("Data Recieved " + " " + requestId + " " + num);	// Log it
				System.out.println("*********" + sReadBuff + "*********");	// Raw Debug code
			} else {
				if (!fatalErr) {				// Error
					comThread.queRequest(requestId, errMessage, "Error"); 	// Tell parent
					comLog.log(errMessage  + " " + comName + " " + num);	// Log
					System.out.println("*********" + errMessage + "*********");	// Raw debug
				}
			}
			closePort();					// Close the port
			resetCount = 0;					// Reset the variables ready for next request
			resetCount2 = 0;
			resetCount3 = 0;
			num = "Nil";
			process = false;
		}
	}

/** Open Com Port
* @return true if succesfull
*/
	private boolean openPort() {
		if (serialPort == null) {					// Set up serial port object if need be
			comLog.debugInfo("**********Open Port Routine***********");			
			try {
				serialPort = (SerialPort) portId.open("SimpleReadApp", 2000); // Open serial port
			comLog.debugInfo("**********Port Open***********");
			} catch (PortInUseException e) {
				return false;				// Hmm its in use
			}
			if (inputStream == null) {			// Set up the input stream if need be
				try {
					inputStream = serialPort.getInputStream(); 		// Get the stream
				} catch (IOException e) {
					return false;	
				}
			}
			if (outputStream == null) {			// Set up the output stream if need be
				try {
					outputStream = serialPort.getOutputStream();		// Get the stream
				} catch (IOException e) {
					return false;			
				}
			}
			try {
				serialPort.addEventListener(this);	// Add the event listener
			} catch (TooManyListenersException e) {
				return false;	
			}
			serialPort.notifyOnDataAvailable(true);	// Set the port to notify on incoming data
			//********* Maybe this goes in serverconfig maybe on a per port basis
			// Set the port parameters
			try {
serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
			} catch (UnsupportedCommOperationException e) {
				return false;
			}
		}
		return true;		// Everything went ok
	}

/** Close Com Port. */

	private void closePort() {
		if (serialPort != null) {					// Check that the serial port is not null
			serialPort.notifyOnDataAvailable(false);	// Close down notification
			serialPort.removeEventListener();		// Remove the event listener
			if (inputStream != null) {			// Check for null
				try {
					inputStream.close();		// Close it
					inputStream = null;		// Clean up
				}
				catch (IOException e) {}
			}
			if (outputStream != null) {			// Check for null
				try {
					outputStream.close();		// Close it
					outputStream = null;		// Clean up
				}
				catch (IOException e) {}
			}
			serialPort.close();				// Close the serial port
			serialPort = null;				// Clean up
		}
	}

/** Reset The Modem 
* @return true if succesfull.
*/
	private boolean reset() {
		try {
			outputStream.write(new String("atz").getBytes());		// Send the modem atz
			outputStream.write((byte)0x0D); 				// And the other stuff
			outputStream.write((byte)0x0A); 				// <CR> <LF>
		} catch (IOException e) {
			return false;
		}
		int waitingCount = 0;							// Heres another counter
		waitForInput = true;							// We are waiting
		while (waitForInput) {							// Yes we are
			try {
	           			Thread.sleep(100);					// We have a little rest
			} catch (InterruptedException e) {}
			waitingCount ++;						// We count
			//***************** 20 goes in serverconfig ************************
			if (waitingCount > 20) {						// We have counted to much
				return false;						// Could not reset
			}
		}
		int numBytes = 0;							// Set up number of bytes read
		byte[] readBuffer = new byte[20];					// And a buffer
		String sReadBuff = "";							// And another buffer
		try {
			while (inputStream.available() > 0) {
				numBytes = inputStream.read(readBuffer);		// Read from the port
				String tmpR = new String(readBuffer);
				sReadBuff += tmpR.substring(0, numBytes); 
			}
		} catch (IOException e) {
			return false;
		}
		//********************Maybe for serverconfig
		if (sReadBuff.indexOf("OK") != -1) {			// Test for OK response from modem
			try {
	           			Thread.sleep(1000);			// We have another sleep to allow things
			} catch (InterruptedException e) {}		// to settle
			return true;
		}
		return false;						// We did not reset OK
	}

/** Dial number requested
* @return true if connected
*/
	private boolean dial() {
		try {
			comLog.debugInfo("**********" + num + "***********");
			outputStream.write(new String("atd").getBytes());		// Send atd	
			outputStream.write(num.getBytes());				// And the number
			outputStream.write((byte)0x0D);				// And the other stuff
			outputStream.write((byte)0x0A);  
		} catch (IOException e) {
			errMessage = "Error! Could Not Write To Port ";
			comLog.debugInfo("**********Error Writing***********");
			return false;							// Bad could not write
		}
		int waitingCount = 0;							// We are counting again
		waitForInput = true;							// Waiting
		while (waitForInput) {							
			try {
	           			Thread.sleep(100);					// Have a sleep
			} catch (InterruptedException e) {}
			waitingCount ++;						// Counting
			//**************** For serverconfig ************************
			if (waitingCount > 200) {					// Counted to much
				errMessage = "Error! Timed Out Waiting For Response";
				return false;						// Timed out
			}
		}
		int numBytes = 0;					// Set up for reading
		byte[] readBuffer = new byte[20];			// Youve seen it before
		String sReadBuff = "";					// The comments are getting thinner
		boolean dLoop = true;					// No need to repeat
		while (dLoop) {
			try {
				while (inputStream.available() > 0) {
					numBytes = inputStream.read(readBuffer);
					String tmpR = new String(readBuffer);
					sReadBuff += tmpR.substring(0, numBytes); 		// We read it
				}
				if (sReadBuff.indexOf("NO CARRIER") != -1) {			// Out of area
					errMessage = "Error! No Carrier";
					return false;
				} else if (sReadBuff.indexOf("BUSY") != -1) {			// Busy
					errMessage = "Error! Busy";				// Who is ringing our units
					return false;						// Maybe it is dialing out
				} else if (sReadBuff.indexOf("NO DIAL TONE") != -1) {		// Bad no signal
					errMessage = "Error! No Dial Tone";			// Were has the ariel gone
					return false;
				} else if (sReadBuff.indexOf("OK") != -1) {			// Hmm voice call no good
					errMessage = "Error! Voice Call";
					return false;
				} else if (sReadBuff.indexOf("CONNECT") != -1) {		// Ah this is what we want
					return true;						// Return true
				}
			} catch (IOException e) {
				errMessage = "Error! Could Not Read From Com Port";
				return false;			// Bad but never happened yet
			}
		}
		errMessage = "Error! Invalid Data " + sReadBuff;
		return false;				// Something has gone wrong	
	}

/** Serial Event Routine
* Set waitForInput to false when data ready
*/
	public void serialEvent(SerialPortEvent event) {
		switch(event.getEventType()) {
			case SerialPortEvent.BI:
			case SerialPortEvent.OE:
			case SerialPortEvent.FE:
			case SerialPortEvent.PE:
			case SerialPortEvent.CD:
			case SerialPortEvent.CTS:
			case SerialPortEvent.DSR:
			case SerialPortEvent.RI:
			case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
				break;
			case SerialPortEvent.DATA_AVAILABLE:
				waitForInput = false;				// We got incoming
            			break;						// Thats it for serial events
        		}
    	}

/** Process Request To Call SNU.
* Request that a call be made and the data
* returned to the controlling thread.
* @see SNComThread
*/		
	public void processRequest(String req, String num) {
		requestId = req;					// Set ID
		this.num = num;					// Set the phone number
		process = true;						// Make it go
	}

/** Is Processing Call
* @return true if thread is busy
* @see SNComThread
*/
	public boolean isProcessing() {
		return process;						// Are you busy
	}

/** Is Processing This Q Id.
* @param qID The ID to test for
* @return true if the thread is processing qID
* @see SNComThread
*/
	public boolean isProcessing(String qID) {
		return	requestId.equals(qID);				// Are you busy doing this job
	}
}
/* the following was added so the code will compile.  Its not proper */
class SNLogger
{
	public void debugInfo(java.lang.String it)
	{
	}
	public void log(java.lang.String it)
	{
	}
}
class SNComThread
{
	public void queRequest(java.lang.String a, java.lang.String b, java.lang.String c)
	{
	} 
}
class SNConfig
{
}