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