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
{
}
|