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