Main Page | Packages | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SerialIO.java

Go to the documentation of this file.
00001 /*
00002  * SerialIO.java
00003  *
00004  * Copyright (C) 2005 Project SQUID, http://www.cs.helsinki.fi/group/squid/
00005  *
00006  * This file is part of Ikayaki.
00007  *
00008  * Ikayaki is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * Ikayaki is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Ikayaki; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00021  */
00022 
00023 package ikayaki.squid;
00024 
00025 import ikayaki.Ikayaki;
00026 
00027 import javax.comm.*;
00028 import javax.swing.*;
00029 import javax.swing.event.EventListenerList;
00030 import java.io.*;
00031 import java.text.DateFormat;
00032 import java.text.SimpleDateFormat;
00033 import java.util.Calendar;
00034 import java.util.Date;
00035 import java.util.TooManyListenersException;
00036 import java.util.Vector;
00037 
00043 public class SerialIO implements SerialPortEventListener {
00044 /*
00045 Event A: On new SerialPortEvent - generates new SerialMessageArrivedEvent if a data
00046 message from serial port is received.
00047 */
00048 
00049     private static final boolean DEBUG = false; // Writes log-file
00050     private static final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
00051 
00055     private static Vector<SerialIO> openPorts = new Vector<SerialIO>();
00056 
00060     private EventListenerList listenerList = new EventListenerList();
00061 
00065     private SerialPort sPort;
00066 
00070     private OutputStream os;
00071 
00075     private InputStream is;
00076 
00080     private String portName;
00081 
00085     private BufferedWriter logWriter;
00086 
00090     private boolean logWriterTriedCreate = false;
00091 
00095     private enum LogEvent {
00096         SESSION_START, SEND, REVEIVE
00097     };
00098 
00105     private SerialIO(SerialParameters parameters) throws SerialIOException {
00106         CommPortIdentifier portId;
00107         SerialPort sPort;
00108 
00109         try {
00110             portId = CommPortIdentifier.getPortIdentifier(parameters.getPortName());
00111         } catch (NoSuchPortException e) {
00112             throw new SerialIOException("No such port exists:" + parameters.getPortName());
00113         }
00114 
00115         // Open the port and give it a timeout of 4 seconds
00116         try {
00117             sPort = (SerialPort) portId.open("SerialPort", 4000);
00118         } catch (PortInUseException e) {
00119             throw new SerialIOException("The port " + parameters.getPortName() + " is already in use");
00120         }
00121 
00122         // if debug mode, make own logfile for port
00123         debug(LogEvent.SESSION_START, sPort.getName());
00124 
00125         // Set the parameters of the connection
00126         try {
00127             sPort.setSerialPortParams(parameters.getBaudRate(),
00128                     parameters.getDatabits(),
00129                     parameters.getStopbits(),
00130                     parameters.getParity());
00131         } catch (UnsupportedCommOperationException e) {
00132             sPort.close();
00133             throw new SerialIOException("Unsupported parameter");
00134         }
00135 
00136         // Set flow control
00137         try {
00138             sPort.setFlowControlMode(parameters.getFlowControlIn()
00139                     | parameters.getFlowControlOut());
00140         } catch (UnsupportedCommOperationException e) {
00141             sPort.close();
00142             throw new SerialIOException("Unsupported flow control");
00143         }
00144 
00145         // open the streams
00146         try {
00147             this.os = sPort.getOutputStream();
00148             this.is = sPort.getInputStream();
00149         } catch (IOException e) {
00150             sPort.close();
00151             throw new SerialIOException("Error opening i/o streams");
00152         }
00153 
00154         // add this object to be listener for the com port
00155         try {
00156             sPort.addEventListener(this);
00157         } catch (TooManyListenersException ex) {
00158             throw new SerialIOException("Too many listeners");
00159         }
00160 
00161         // Set notifyOnDataAvailable to true to allow event driven input.
00162         sPort.notifyOnDataAvailable(true);
00163 
00164         // Set receive timeout to allow breaking out of polling loop during
00165         // input handling.
00166         try {
00167             sPort.enableReceiveTimeout(30);
00168         } catch (UnsupportedCommOperationException e) {
00169             throw new SerialIOException("Unsupported operation");
00170         }
00171 
00172         this.sPort = sPort;
00173         this.portName = sPort.getName();
00174 
00175         return;
00176     }
00177 
00178     public static SerialIO openPort(SerialParameters parameters) throws SerialIOException {
00179         //System.out.println("Let's try to open port: " + parameters.getPortName());  //DEBUG
00180 
00181         SerialIO newPort = null;
00182 
00183         // Check if given port is already open
00184         // if it is then return it instead of creating a new one.
00185         for (int i = 0; i < openPorts.size(); i++) {
00186             if (parameters.getPortName().equals(openPorts.elementAt(i).portName)) {
00187                 return openPorts.elementAt(i);
00188             }
00189         }
00190         newPort = new SerialIO(parameters);
00191         openPorts.add(newPort);
00192 
00193         System.out.println("Port: " + parameters.getPortName() + " opened");
00194         return newPort;
00195     }
00196 
00203     public void writeMessage(String message) throws SerialIOException {
00204 
00205         byte[] asciiMsg;
00206 
00207         // convert a message to ASCII
00208         try {
00209             asciiMsg = message.getBytes("US-ASCII");
00210         } catch (UnsupportedEncodingException e) {
00211             throw new SerialIOException("ASCII charset not supported");
00212         }
00213 
00214         // send a message to outputstream
00215         try {
00216             try {
00217                 Thread.sleep(50); // Let's wait a bit so we won't flood the system wtih too many messages
00218                 // 50 msecs seems to work fine with baudrate of 1200..
00219             } catch (InterruptedException ex) {
00220             }
00221             debug(LogEvent.SEND, message);
00222             os.write(asciiMsg);
00223             os.flush(); // flush the buffer
00224         } catch (IOException e) {
00225             throw new SerialIOException("Couldn't write to outputstream of" + this.portName);
00226         }
00227 
00228         return;
00229     }
00230 
00234     public void closePort() {
00235         if (sPort != null) {
00236             this.sPort.close();
00237             try {
00238                 this.is.close();
00239             } catch (IOException ex) {
00240                 System.err.println("Could not close inputstream for COM port");
00241             }
00242             try {
00243                 this.os.close();
00244             } catch (IOException ex1) {
00245                 System.err.println("Could not close outputstream for COM port");
00246             }
00247         }
00248     }
00249 
00253     public static void closeAllPorts() {
00254         for (int i = 0; i < openPorts.size(); i++) {
00255             openPorts.elementAt(i).closePort();
00256         }
00257     }
00258 
00262     public void serialEvent(SerialPortEvent event) {
00263         //System.out.println("New message arrived to port: " + this.portName); //DEBUG
00264         switch (event.getEventType()) {
00265         case SerialPortEvent.BI:
00266         case SerialPortEvent.OE:
00267         case SerialPortEvent.FE:
00268         case SerialPortEvent.PE:
00269         case SerialPortEvent.CD:
00270         case SerialPortEvent.CTS:
00271         case SerialPortEvent.DSR:
00272         case SerialPortEvent.RI:
00273         case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
00274             break;
00275         case SerialPortEvent.DATA_AVAILABLE:
00276             StringBuffer inputBuffer = new StringBuffer();
00277             int newData = 0;
00278             byte[] newByte = new byte[1];
00279 
00280             while (newData != -1) {
00281                 try {
00282                     newData = is.read();
00283                     if (newData == -1) {
00284                         break;
00285                     }
00286                     newByte[0] = new Integer(newData).byteValue();
00287                     inputBuffer.append(new String(newByte, "US-ASCII"));
00288 
00289                 } catch (IOException ex) {
00290                     System.err.println(ex);
00291                     return;
00292                 }
00293             }
00294 
00295             fireSerialIOEvent(new String(inputBuffer));
00296 
00297             //System.out.println("sending: " + new String(inputBuffer)); //debug
00298             debug(LogEvent.REVEIVE, inputBuffer.toString());
00299 
00300             break;
00301         }
00302         return;
00303     }
00304 
00310     public synchronized void addSerialIOListener(SerialIOListener l) {
00311         listenerList.add(SerialIOListener.class, l);
00312     }
00313 
00319     public synchronized void removeSerialIOListener(SerialIOListener l) {
00320         listenerList.remove(SerialIOListener.class, l);
00321     }
00322 
00328     private synchronized void fireSerialIOEvent(String message) {
00329         final SerialIOEvent event = new SerialIOEvent(this, message);
00330         final SerialIOListener[] listeners = listenerList.getListeners(SerialIOListener.class);
00331         SwingUtilities.invokeLater(new Runnable() {
00332             public void run() {
00333                 for (SerialIOListener l : listeners) {
00334                     try {
00335                         l.serialIOEvent(event);
00336                     } catch (Throwable t) {
00337                         t.printStackTrace();
00338                     }
00339                 }
00340             }
00341         });
00342     }
00343 
00350     private void debug(LogEvent e, String message) {
00351         // do nothing if debug mode is off
00352         if (DEBUG == false) return;
00353 
00354         // create new log writer if not yet tried
00355         if (!logWriterTriedCreate) {
00356             logWriterTriedCreate = true;
00357 
00358             Calendar now = Calendar.getInstance();
00359             int y = now.get(Calendar.YEAR), m = now.get(Calendar.MONTH) + 1, d = now.get(Calendar.DAY_OF_MONTH);
00360             String port = e == LogEvent.SESSION_START ? message : portName;
00361             File file = new File(Ikayaki.DEBUG_LOG_DIR, y + "-" + padn(m) + "-" + padn(d) + "-" + port + ".log");
00362 
00363             boolean oldFile = file.exists();
00364             if (!Ikayaki.DEBUG_LOG_DIR.exists()) Ikayaki.DEBUG_LOG_DIR.mkdir();
00365 
00366             try {
00367                 logWriter = new BufferedWriter(new FileWriter(file, true));
00368                 // an empty line after previous session
00369                 if (oldFile) logWriter.newLine();
00370             } catch (IOException ex1) {
00371                 System.err.println("Error creating log file: " + ex1);
00372             }
00373         }
00374 
00375         // no working log writer :(
00376         if (logWriter == null) return;
00377 
00378         // OK, now write the log message...
00379         String time = dateFormat.format(new Date());
00380         try {
00381             logWriter.write(time + " " + e + ": " + message);
00382             logWriter.newLine();
00383             logWriter.flush();
00384         } catch (IOException ex1) {
00385             System.err.println(ex1);
00386         }
00387     }
00388 
00395     private String padn(int n) {
00396         return (n < 10 ? "0" : "") + n;
00397     }
00398 
00399     public String getPortName() {
00400         return portName;
00401     }
00402 }

Generated on Fri May 6 16:00:33 2005 for Squid by  doxygen 1.4.1