001package jmri.jmrix.bachrus.serialdriver; 002 003import java.io.DataInputStream; 004import java.io.DataOutputStream; 005import java.io.IOException; 006import java.io.InputStream; 007import java.util.TooManyListenersException; 008import jmri.jmrix.bachrus.SpeedoConnectionTypeList; 009import jmri.jmrix.bachrus.SpeedoPortController; 010import jmri.jmrix.bachrus.SpeedoSystemConnectionMemo; 011import jmri.jmrix.bachrus.SpeedoTrafficController; 012import org.slf4j.Logger; 013import org.slf4j.LoggerFactory; 014import purejavacomm.CommPortIdentifier; 015import purejavacomm.NoSuchPortException; 016import purejavacomm.PortInUseException; 017import purejavacomm.SerialPort; 018import purejavacomm.UnsupportedCommOperationException; 019 020/** 021 * Implements SerialPortAdapter for the Bachrus speedo. 022 * <p> 023 * This connects a bachrus speedo reader interface via a serial com port. 024 * Normally controlled by the SerialDriverFrame class. 025 * <p> 026 * The current implementation only handles the 9,600 baud rate, and does not use 027 * any other options at configuration time. 028 * 029 * Updated January 2010 for gnu io (RXTX) - Andrew Berridge. Comments tagged 030 * with "AJB" indicate changes or observations by me 031 * 032 * @author Bob Jacobsen Copyright (C) 2001, 2002 033 * @author Andrew Crosland Copyright (C) 2010 034 */ 035public class SerialDriverAdapter extends SpeedoPortController { 036 037 public SerialDriverAdapter() { 038 super(new SpeedoSystemConnectionMemo()); 039 setManufacturer(SpeedoConnectionTypeList.BACHRUS); 040 this.getSystemConnectionMemo().setSpeedoTrafficController(new SpeedoTrafficController(this.getSystemConnectionMemo())); 041 } 042 043 SerialPort activeSerialPort = null; 044 045 @Override 046 public String openPort(String portName, String appName) { 047 // open the port, check ability to set moderators 048 try { 049 // get and open the primary port 050 CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(portName); 051 try { 052 activeSerialPort = (SerialPort) portID.open(appName, 2000); // name of program, msec to wait 053 } catch (PortInUseException p) { 054 return handlePortBusy(p, portName, log); 055 } 056 057 // try to set it for communication via SerialDriver 058 try { 059 activeSerialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); 060 } catch (UnsupportedCommOperationException e) { 061 log.error("Cannot set serial parameters on port {}: {}", portName, e.getMessage()); 062 return "Cannot set serial parameters on port " + portName + ": " + e.getMessage(); 063 } 064 065 // set RTS high, DTR high 066 // disable flow control; hardware lines used for signaling, XON/XOFF might appear in data 067 //AJB: Removed Jan 2010 - 068 //Setting flow control mode to zero kills comms - SPROG doesn't send data 069 //Concern is that will disabling this affect other SPROGs? Serial ones? 070 configureLeadsAndFlowControl(activeSerialPort, 0); 071 072 // set timeout 073 // activeSerialPort.enableReceiveTimeout(1000); 074 log.debug("Serial timeout was observed as: {} {}", activeSerialPort.getReceiveTimeout(), activeSerialPort.isReceiveTimeoutEnabled()); 075 076 // get and save stream 077 serialStream = activeSerialPort.getInputStream(); 078 079 // purge contents, if any 080 purgeStream(serialStream); 081 082 // report status? 083 if (log.isInfoEnabled()) { 084 log.info("{} port opened at {} baud, sees DTR: {} RTS: {} DSR: {} CTS: {} CD: {}", portName, activeSerialPort.getBaudRate(), activeSerialPort.isDTR(), activeSerialPort.isRTS(), activeSerialPort.isDSR(), activeSerialPort.isCTS(), activeSerialPort.isCD()); 085 } 086 087 //AJB - add Sprog Traffic Controller as event listener 088 try { 089 activeSerialPort.addEventListener(this.getSystemConnectionMemo().getTrafficController()); 090 } catch (TooManyListenersException e) { 091 } 092 setManufacturer(SpeedoConnectionTypeList.BACHRUS); 093 094 // AJB - activate the DATA_AVAILABLE notifier 095 activeSerialPort.notifyOnDataAvailable(true); 096 097 opened = true; 098 099 } catch (NoSuchPortException p) { 100 return handlePortNotFound(p, portName, log); 101 } catch (IOException ex) { 102 log.error("Unexpected exception while opening port {}", portName, ex); 103 return "Unexpected error while opening port " + portName + ": " + ex; 104 } 105 106 return null; // indicates OK return 107 108 } 109 110 public void setHandshake(int mode) { 111 try { 112 activeSerialPort.setFlowControlMode(mode); 113 } catch (UnsupportedCommOperationException ex) { 114 log.error("Unexpected exception while setting COM port handshake mode", ex); 115 } 116 117 } 118 119 /** 120 * set up all of the other objects to operate with an Sprog command station 121 * connected to this port 122 */ 123 @Override 124 public void configure() { 125 // connect to the traffic controller 126 this.getSystemConnectionMemo().getTrafficController().connectPort(this); 127 128 this.getSystemConnectionMemo().configureManagers(); 129 } 130 131 // base class methods for the SprogPortController interface 132 @Override 133 public DataInputStream getInputStream() { 134 if (!opened) { 135 log.error("getInputStream called before load(), stream not available"); 136 return null; 137 } 138 return new DataInputStream(serialStream); 139 } 140 141 @Override 142 public DataOutputStream getOutputStream() { 143 if (!opened) { 144 log.error("getOutputStream called before load(), stream not available"); 145 } 146 try { 147 return new DataOutputStream(activeSerialPort.getOutputStream()); 148 } catch (java.io.IOException e) { 149 log.error("getOutputStream exception", e); 150 } 151 return null; 152 } 153 154 @Override 155 public boolean status() { 156 return opened; 157 } 158 159 /** 160 * {@inheritDoc} 161 * Currently only 9,600 bps 162 */ 163 @Override 164 public String[] validBaudRates() { 165 return new String[]{"9,600 bps"}; 166 } 167 168 /** 169 * {@inheritDoc} 170 */ 171 @Override 172 public int[] validBaudNumbers() { 173 return new int[]{9600}; 174 } 175 176 @Override 177 public int defaultBaudIndex() { 178 return 0; 179 } 180 181 private boolean opened = false; 182 InputStream serialStream = null; 183 184 private final static Logger log = LoggerFactory.getLogger(SerialDriverAdapter.class); 185 186}