001package jmri.jmrix.easydcc.serialdriver; 002 003import java.io.DataInputStream; 004import java.io.DataOutputStream; 005import java.io.IOException; 006import java.io.InputStream; 007import jmri.jmrix.easydcc.EasyDccPortController; 008import jmri.jmrix.easydcc.EasyDccSystemConnectionMemo; 009import org.slf4j.Logger; 010import org.slf4j.LoggerFactory; 011import purejavacomm.CommPortIdentifier; 012import purejavacomm.NoSuchPortException; 013import purejavacomm.PortInUseException; 014import purejavacomm.SerialPort; 015import purejavacomm.UnsupportedCommOperationException; 016 017/** 018 * Implements SerialPortAdapter for the EasyDCC system. 019 * <p> 020 * This connects an EasyDCC command station via a serial com port. 021 * Normally controlled by the SerialDriverFrame class. 022 * <p> 023 * The current implementation only handles the 9,600 baud rate, and does not use 024 * any other options at configuration time. 025 * 026 * @author Bob Jacobsen Copyright (C) 2001, 2002 027 */ 028public class SerialDriverAdapter extends EasyDccPortController { 029 030 public SerialDriverAdapter() { 031 super(new EasyDccSystemConnectionMemo("E", "EasyDCC via Serial")); // pass customized user name 032 setManufacturer(jmri.jmrix.easydcc.EasyDccConnectionTypeList.EASYDCC); 033 } 034 035 SerialPort activeSerialPort = null; 036 037 @Override 038 public String openPort(String portName, String appName) { 039 // open the port, check ability to set moderators 040 try { 041 // get and open the primary port 042 CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(portName); 043 try { 044 activeSerialPort = (SerialPort) portID.open(appName, 2000); // name of program, msec to wait 045 } catch (PortInUseException p) { 046 return handlePortBusy(p, portName, log); 047 } 048 049 // try to set it for communication via SerialDriver 050 try { 051 activeSerialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); 052 } catch (UnsupportedCommOperationException e) { 053 log.error("Cannot set serial parameters on port {}: {}", portName, e.getMessage()); 054 return "Cannot set serial parameters on port " + portName + ": " + e.getMessage(); 055 } 056 057 // disable flow control; hardware lines used for signaling, XON/XOFF might appear in data 058 configureLeadsAndFlowControl(activeSerialPort, 0); 059 060 // set timeout 061 // activeSerialPort.enableReceiveTimeout(1000); 062 log.debug("Serial timeout was observed as: {} {}", activeSerialPort.getReceiveTimeout(), activeSerialPort.isReceiveTimeoutEnabled()); 063 064 // get and save stream 065 serialStream = activeSerialPort.getInputStream(); 066 067 // purge contents, if any 068 purgeStream(serialStream); 069 070 // report status? 071 if (log.isInfoEnabled()) { 072 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()); 073 } 074 075 opened = true; 076 077 } catch (NoSuchPortException p) { 078 return handlePortNotFound(p, portName, log); 079 } catch (IOException ex) { 080 log.error("Unexpected exception while opening port {}", portName, ex); 081 return "Unexpected error while opening port " + portName + ": " + ex; 082 } 083 084 return null; // indicates OK return 085 } 086 087 /** 088 * Set up all of the other objects to operate with an EasyDCC command 089 * station connected to this port. 090 */ 091 @Override 092 public void configure() { 093 // connect to the traffic controller, which is provided via the memo 094 log.debug("set tc for memo {}", getSystemConnectionMemo().getUserName()); 095 096 getSystemConnectionMemo().getTrafficController().connectPort(this); 097 098 // do the common manager config 099 getSystemConnectionMemo().configureManagers(); 100 } 101 102 // Base class methods for the EasyDccPortController interface 103 104 /** 105 * {@inheritDoc} 106 */ 107 @Override 108 public DataInputStream getInputStream() { 109 if (!opened) { 110 log.error("getInputStream called before load(), stream not available"); 111 return null; 112 } 113 return new DataInputStream(serialStream); 114 } 115 116 /** 117 * {@inheritDoc} 118 */ 119 @Override 120 public DataOutputStream getOutputStream() { 121 if (!opened) { 122 log.error("getOutputStream called before load(), stream not available"); 123 } 124 try { 125 return new DataOutputStream(activeSerialPort.getOutputStream()); 126 } catch (java.io.IOException e) { 127 log.error("getOutputStream exception", e); 128 } 129 return null; 130 } 131 132 /** 133 * {@inheritDoc} 134 */ 135 @Override 136 public boolean status() { 137 return opened; 138 } 139 140 /** 141 * {@inheritDoc} 142 * Currently only 9,600 bps. 143 */ 144 @Override 145 public String[] validBaudRates() { 146 return new String[]{Bundle.getMessage("Baud9600")}; 147 } 148 149 /** 150 * {@inheritDoc} 151 */ 152 @Override 153 public int[] validBaudNumbers() { 154 return new int[]{9600}; 155 } 156 157 @Override 158 public int defaultBaudIndex() { 159 return 0; 160 } 161 162 // private control members 163 private boolean opened = false; 164 InputStream serialStream = null; 165 166 private final static Logger log = LoggerFactory.getLogger(SerialDriverAdapter.class); 167 168}