Subversion Repositories Programming Utils

Rev

Rev 17 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.rm5248.terminal;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.FontMetrics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;
import javax.swing.text.BadLocationException;

import com.rm5248.serial.NoSuchPortException;
import com.rm5248.serial.NotASerialPortException;
import com.rm5248.serial.SerialPort;
import com.rm5248.serial.SerialPort.BaudRate;
import com.rm5248.serial.SerialPort.DataBits;
import com.rm5248.serial.SerialPort.FlowControl;
import com.rm5248.serial.SerialPort.Parity;
import com.rm5248.serial.SerialPort.StopBits;

/**
 * JavaTerminal is a Java-based terminal emulator to open serial ports.
 * It is designed to be similar to GTKTerm for Linux.
 * GTKTerm's webpage is at https://fedorahosted.org/gtkterm/
 *
 *
 */

public class JavaTerminal implements KeyListener {

        private SerialPort thePort;
        private InputStream portInput;
        private OutputStream portOutput;
        private String currentOpenPort;
        private boolean localEcho;

        private JFrame theFrame;
        private JLabel portInfoLeft;
        private JLabel portStatus;
        private JTextArea text;

        private final static String NEWLINE = System.getProperty("line.separator");

        public JavaTerminal( String portToOpen, BaudRate baud, DataBits data, StopBits stop, Parity parity, FlowControl flow, boolean localEcho ){
                this.localEcho = localEcho;
                try{
                        UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
                }catch( Exception e ){}

                try {
                        thePort = new SerialPort( portToOpen, baud, data, stop, parity, flow );
                        currentOpenPort = portToOpen;
                } catch (NoSuchPortException e) {
                        System.err.println( e.getMessage() );
                        System.err.println( "ERROR: No Such Port( " + portToOpen + " )" );
                        System.exit( 0 );
                } catch (NotASerialPortException e) {
                        System.err.println( e.getMessage() );
                        System.err.println( "ERROR: Not a serial port( " + portToOpen + " )" );
                        System.exit( 0 );
                }

                portInput = thePort.getInputStream();
                portOutput = thePort.getOutputStream();

                makeGUI();
        }

        private void makeGUI(){
                Font monoFont;
                Font sansFont;
               
               
                //First let's get the fonts that we want to use
                try {
                        InputStream is = this.getClass().getResourceAsStream( "/fonts/LiberationMono-Regular.ttf" );
                        monoFont = Font.createFont( Font.TRUETYPE_FONT, is );
                        monoFont = monoFont.deriveFont( 18.0f );
                } catch ( Exception e ){
                        monoFont = new Font( "monospaced", Font.PLAIN, 18 );
                }
               
                try{
                        InputStream is = this.getClass().getResourceAsStream( "/fonts/LiberationSans-Regular.ttf" );
                        sansFont = Font.createFont( Font.TRUETYPE_FONT, is );
                        sansFont = sansFont.deriveFont( 12.0f );
                }catch( Exception e){
                        sansFont = new Font( "serif", Font.PLAIN, 12 );
                }
               
                theFrame = new JFrame( "JavaTerminal" );

                JPanel mainPanel = new JPanel( new BorderLayout() );

                JPanel statusPanel = new JPanel( new BorderLayout() );
                statusPanel.add( portInfoLeft = new JLabel(), BorderLayout.WEST );
                statusPanel.add( portStatus = new JLabel( "sdf" ), BorderLayout.EAST );
                statusPanel.setPreferredSize( new Dimension( 20, 20 ) );

                portInfoLeft.setFont( sansFont );
                portInfoLeft.setForeground( Color.DARK_GRAY );

                portStatus.setBorder( new BevelBorder( BevelBorder.LOWERED) );

                text = new JTextArea();
                text.setBackground( Color.BLACK );
                text.setForeground( Color.LIGHT_GRAY );

                text.setFont( monoFont );
                text.setColumns( 80 );
                text.setEditable( false );
                text.addKeyListener( this );

                JScrollPane scrollPane = new JScrollPane( text );
                scrollPane.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
                scrollPane.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
                mainPanel.add( scrollPane );
                mainPanel.add( statusPanel, BorderLayout.SOUTH );
               
                //Make our menus
                JMenuBar menuBar = new JMenuBar();
                JMenu fileMenu = new JMenu( "File" );
                fileMenu.setMnemonic( KeyEvent.VK_F );
                JMenuItem exitItem = new JMenuItem( "Exit" );
                exitItem.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_Q, KeyEvent.VK_ALT ) );
                exitItem.addActionListener( new ActionListener() {
                       
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                System.exit( 0 );
                        }
                });
                fileMenu.add( exitItem );
                menuBar.add( fileMenu );
                JMenu configMenu = new JMenu( "Configuration" );
                configMenu.setMnemonic( KeyEvent.VK_C );
               
                //add everything to the frame
                theFrame.setJMenuBar( menuBar );
                theFrame.add( mainPanel );
                theFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                theFrame.setVisible( true );

                //Let's figure out how wide we should be in order to be 80 characters wide
                //We can only do this after the frame is visible.
                //85 characters wide because of the width of the window and scroll bar
                int width = 0;
                FontMetrics font = text.getGraphics().getFontMetrics( monoFont );
                width = font.charWidth( 'a' ) * 85;

                theFrame.setSize( width, 600 );
               
                updatePortInformation();
        }

        /**
         * @param args
         */

        public static void main(String[] args) {
                //Make defaults, then parse our arguments
                BaudRate baud = BaudRate.B9600;
                DataBits data = DataBits.DATABITS_8;
                StopBits stop = StopBits.STOPBITS_1;
                Parity parity = Parity.NONE;
                FlowControl flow = FlowControl.NONE;
                String portToOpen;
                boolean echo = false;

                if( System.getProperty( "os.name" ).toLowerCase().indexOf( "win" ) >= 0 ){
                        portToOpen = "COM1";
                }else{
                        portToOpen = "/dev/ttyS0";
                }

                for( int x = 0; x < args.length; x++ ){
                        if( args[ x ].equals( "--help" ) ||
                                        args[ x ].equals( "-h" ) ){
                                //Print out help
                                System.out.println( "JavaTerminal" );
                                System.out.println();
                                System.out.println( "Program Homepage: http://www.rm5248.com/JavaSerial" );
                                System.out.println();
                                System.out.println( "Command Line Options: " );
                                System.out.println( "--help or -h : This help screen" );
                                System.out.println( "--port=<port> or -p : Device to open (Default: " + portToOpen + ")" );
                                System.out.println( "--speed=<speed> or -s : Port Speed (Default: 9600)" );
                                System.out.println( "--bits=<bits> or -b : Number of bits (Default: 8)" );
                                System.out.println( "--stopbits=<bits> or -t : Number of stop bits (Defaults: 1)" );
                                System.out.println( "--parity=<odd|even|none> or -a : Parity (Default: None)" );
                                System.out.println( "--flow=<xon|cts|none> or -w : Flow Control (Default: None)" );
                                System.out.println( "--echo or -e : Switch on local echo" );
                                System.exit( 1 );
                        }else if( args[ x ].startsWith( "--port=" ) ){
                                portToOpen = args[ x ].substring( args[ x ].indexOf( '=' ) + 1 );
                        }else if( args[ x ].equals( "-p" ) && x < args.length ){
                                portToOpen = args[ ++x ];
                        }else if( args[ x ].startsWith( "--speed=" ) ){
                                int speed = 9600;

                                try{
                                        speed = Integer.parseInt( args[ x ].substring( args[ x ].indexOf( '=' ) + 1 ) );
                                }catch( Exception e ){
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
                                        speed = 9600;
                                }

                                switch( speed ){
                                case 0     :  baud = BaudRate.B0     ; break;
                                case 50    :  baud = BaudRate.B50    ; break;
                                case 75    :  baud = BaudRate.B75    ; break;
                                case 110   :  baud = BaudRate.B110   ; break;
                                case 134   :  baud = BaudRate.B134   ; break;
                                case 150   :  baud = BaudRate.B150   ; break;
                                case 200   :  baud = BaudRate.B200   ; break;
                                case 300   :  baud = BaudRate.B300   ; break;
                                case 600   :  baud = BaudRate.B600   ; break;
                                case 1200  :  baud = BaudRate.B1200  ; break;
                                case 1800  :  baud = BaudRate.B1800  ; break;
                                case 2400  :  baud = BaudRate.B2400  ; break;
                                case 4800  :  baud = BaudRate.B4800  ; break;
                                case 9600  :  baud = BaudRate.B9600  ; break;
                                case 38400 :  baud = BaudRate.B38400 ; break;
                                case 115200:  baud = BaudRate.B115200; break;
                                default:
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
                                        baud = BaudRate.B9600;
                                }
                        }else if( args[ x ].equals( "-s" ) ){
                                int speed = 9600;

                                try{
                                        speed = Integer.parseInt( args[ ++x ] );
                                }catch( Exception e ){
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
                                        speed = 9600;
                                }

                                switch( speed ){
                                case 0     :  baud = BaudRate.B0     ; break;
                                case 50    :  baud = BaudRate.B50    ; break;
                                case 75    :  baud = BaudRate.B75    ; break;
                                case 110   :  baud = BaudRate.B110   ; break;
                                case 134   :  baud = BaudRate.B134   ; break;
                                case 150   :  baud = BaudRate.B150   ; break;
                                case 200   :  baud = BaudRate.B200   ; break;
                                case 300   :  baud = BaudRate.B300   ; break;
                                case 600   :  baud = BaudRate.B600   ; break;
                                case 1200  :  baud = BaudRate.B1200  ; break;
                                case 1800  :  baud = BaudRate.B1800  ; break;
                                case 2400  :  baud = BaudRate.B2400  ; break;
                                case 4800  :  baud = BaudRate.B4800  ; break;
                                case 9600  :  baud = BaudRate.B9600  ; break;
                                case 38400 :  baud = BaudRate.B38400 ; break;
                                case 115200:  baud = BaudRate.B115200; break;
                                default:
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
                                        baud = BaudRate.B9600;
                                }
                        }else if( args[ x ].startsWith( "--bits=" ) ){
                                int bits = 8;

                                try{
                                        bits = Integer.parseInt( args[ x ].substring( args[ x ].indexOf( '=' ) + 1 ) );
                                }catch( Exception e ){
                                        System.err.println( "ERROR: Bits were incorrect, assuming 8" );
                                        bits = 8;
                                }

                                switch( bits ){
                                case 8:
                                        data = DataBits.DATABITS_8; break;
                                case 7:
                                        data = DataBits.DATABITS_7; break;
                                case 6:
                                        data = DataBits.DATABITS_6; break;
                                case 5:
                                        data = DataBits.DATABITS_5; break;
                                default:
                                        data = DataBits.DATABITS_8;
                                }

                        }else if( args[ x ].equals( "-b" ) ){
                                int bits = 8;

                                try{
                                        bits = Integer.parseInt( args[ ++x ] );
                                }catch( Exception e ){
                                        System.err.println( "ERROR: Bits were incorrect, assuming 8" );
                                        bits = 8;
                                }

                                switch( bits ){
                                case 8:
                                        data = DataBits.DATABITS_8; break;
                                case 7:
                                        data = DataBits.DATABITS_7; break;
                                case 6:
                                        data = DataBits.DATABITS_6; break;
                                case 5:
                                        data = DataBits.DATABITS_5; break;
                                default:
                                        data = DataBits.DATABITS_8;
                                }
                        }else if( args[ x ].startsWith( "--stopbits=" ) ){
                                int stopBits = 1;

                                try{
                                        stopBits = Integer.parseInt( args[ x ].substring( args[ x ].indexOf( '=' ) + 1 ) );
                                }catch( Exception e ){
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
                                        stopBits = 1;
                                }

                                switch( stopBits ){
                                case 2:
                                        stop = StopBits.STOPBITS_2; break;
                                case 1:
                                        stop = StopBits.STOPBITS_1; break;
                                default:
                                        stop = StopBits.STOPBITS_1;
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
                                }
                        }else if( args[ x ].equals( "-t" ) ){
                                int stopBits = 1;

                                try{
                                        stopBits = Integer.parseInt( args[ ++x ] );
                                }catch( Exception e ){
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
                                        stopBits = 1;
                                }

                                switch( stopBits ){
                                case 2:
                                        stop = StopBits.STOPBITS_2; break;
                                case 1:
                                        stop = StopBits.STOPBITS_1; break;
                                default:
                                        stop = StopBits.STOPBITS_1;
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
                                }
                        }else if( args[ x ].startsWith( "--parity=" ) ){
                                String parityName = args[ x ].substring( args[ x ].indexOf( '=' ) );

                                if( parityName.equals( "odd" ) ){
                                        parity = Parity.ODD;
                                }else if( parityName.equals( "none" ) ){
                                        parity = Parity.NONE;
                                }else if( parityName.equals( "even" ) ){
                                        parity = Parity.EVEN;
                                }else{
                                        System.err.println( "ERROR: Parity was incorrect, assuming none" );
                                }
                        }else if( args[ x ].equals( "-a" ) ){
                                String parityName = args[ ++x ];

                                if( parityName.equals( "odd" ) ){
                                        parity = Parity.ODD;
                                }else if( parityName.equals( "none" ) ){
                                        parity = Parity.NONE;
                                }else if( parityName.equals( "even" ) ){
                                        parity = Parity.EVEN;
                                }else{
                                        System.err.println( "ERROR: Parity was incorrect, assuming none" );
                                }
                        }else if( args[ x ].startsWith( "--flow=" ) ){
                                String flowName = args[ x ].substring( args[ x ].indexOf( '=' ) );

                                if( flowName.equals( "xon" ) ){
                                        flow = FlowControl.SOFTWARE;
                                }else if( flowName.equals( "cts" ) ){
                                        flow = FlowControl.HARDWARE;
                                }else if( flowName.equals( "none" ) ){
                                        flow = FlowControl.NONE;
                                }else{
                                        System.err.println( "ERROR: Flow Control was incorrect, assuming none" );
                                }
                        }else if( args[ x ].equals( "-w" ) ){
                                String flowName = args[ ++x ];

                                if( flowName.equals( "xon" ) ){
                                        flow = FlowControl.SOFTWARE;
                                }else if( flowName.equals( "cts" ) ){
                                        flow = FlowControl.HARDWARE;
                                }else if( flowName.equals( "none" ) ){
                                        flow = FlowControl.NONE;
                                }else{
                                        System.err.println( "ERROR: Flow Control was incorrect, assuming none" );
                                }
                        }else if( args[ x ].equals( "--echo" ) || args[ x ].equals( "-e" ) ){
                                echo = true;
                        }
                } // end for loop

                new JavaTerminal( portToOpen, baud, data, stop, parity, flow, echo );
        }

        @Override
        public void keyPressed(KeyEvent arg0) {}

        @Override
        public void keyReleased(KeyEvent arg0) {}

        @Override
        public void keyTyped(KeyEvent arg0) {
                if( localEcho ){
                        appendCharacter( arg0.getKeyChar() );
                }
               
                try {
                        portOutput.write( (int)arg0.getKeyChar() );
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
        }

        private void appendCharacter( char c ){
                try {
                        String lastLine = text.getText().substring( text.getLineStartOffset( text.getLineCount() - 1 ) );
                        if( lastLine.length() == 80 ){
                                text.append( NEWLINE );
                        }
                } catch (BadLocationException e) {}

                text.append( c + "" );
        }
       
        /**
         * Update the information in the lower left corner.
         */

        private void updatePortInformation(){
                String txt = currentOpenPort + " : ";
                //txt += thePort.getBaudRate();
               
                portInfoLeft.setText( txt );
        }

}