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