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