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