001package jmri.jmrix.dcc4pc.serialdriver; 002 003import java.io.DataInputStream; 004import java.io.DataOutputStream; 005import java.io.IOException; 006import java.io.InputStream; 007import java.util.ArrayList; 008import java.util.List; 009 010import jmri.SystemConnectionMemo; 011import jmri.jmrix.dcc4pc.Dcc4PcConnectionTypeList; 012import jmri.jmrix.dcc4pc.Dcc4PcPortController; 013import jmri.jmrix.dcc4pc.Dcc4PcSystemConnectionMemo; 014import jmri.jmrix.dcc4pc.Dcc4PcTrafficController; 015 016import org.slf4j.Logger; 017import org.slf4j.LoggerFactory; 018 019import jmri.jmrix.purejavacomm.CommPortIdentifier; 020import jmri.jmrix.purejavacomm.NoSuchPortException; 021import jmri.jmrix.purejavacomm.PortInUseException; 022import jmri.jmrix.purejavacomm.UnsupportedCommOperationException; 023 024/** 025 * Implements SerialPortAdapter for the Dcc4Pc system. 026 * <p> 027 * This connects an Dcc4Pc command station via a serial com port. 028 * 029 * @author Kevin Dickerson Copyright (C) 2012 030 */ 031public class SerialDriverAdapter extends Dcc4PcPortController { 032 033 public SerialDriverAdapter() { 034 super(new Dcc4PcSystemConnectionMemo()); 035 option1Name = "Programmer"; // NOI18N 036 options.put(option1Name, new Option("Programmer : ", validOption1())); 037 setManufacturer(Dcc4PcConnectionTypeList.DCC4PC); 038 } 039 040 jmri.jmrix.purejavacomm.SerialPort activeSerialPort = null; 041 042 @Override 043 public String openPort(String portName, String appName) { 044 045 try { 046 CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(portName); 047 try { 048 activeSerialPort = portID.open(appName, 2000); 049 } catch (PortInUseException p) { 050 return handlePortBusy(p, portName, log); 051 } 052 try { 053 activeSerialPort.setSerialPortParams(115200, 054 jmri.jmrix.purejavacomm.SerialPort.DATABITS_8, 055 jmri.jmrix.purejavacomm.SerialPort.STOPBITS_1, 056 jmri.jmrix.purejavacomm.SerialPort.PARITY_NONE); 057 configureLeadsAndFlowControl(activeSerialPort, 058 jmri.jmrix.purejavacomm.SerialPort.FLOWCONTROL_NONE); 059 } catch (UnsupportedCommOperationException e) { 060 log.error("Cannot set serial parameters on port {}: {}", portName, e.getMessage()); 061 } 062 log.debug("Serial timeout was observed as: {} {}", activeSerialPort.getReceiveTimeout(), activeSerialPort.isReceiveTimeoutEnabled()); 063 064 serialStream = activeSerialPort.getInputStream(); 065 // purge contents, if any 066 purgeStream(serialStream); 067 068 // report status? 069 if (log.isInfoEnabled()) { 070 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()); 071 } 072 073 opened = true; 074 075 } catch (NoSuchPortException p) { 076 return handlePortNotFound(p, portName, log); 077 } catch (IOException ex) { 078 log.error("Unexpected exception while opening port {}", portName, ex); 079 return "Unexpected error while opening port " + portName + ": " + ex; 080 } 081 return null; // indicates OK return 082 } 083 084 public void setHandshake(int mode) { 085 try { 086 activeSerialPort.setFlowControlMode(mode); 087 } catch (UnsupportedCommOperationException ex) { 088 log.error("Unexpected exception while setting COM port handshake mode", ex); 089 } 090 } 091 092 public jmri.jmrix.purejavacomm.SerialPort getSerialPort() { 093 return activeSerialPort; 094 } 095 096 /** 097 * Option 1 controls the connection used for programming. 098 * @return array with options for programming. 099 */ 100 public String[] validOption1() { 101 List<SystemConnectionMemo> connList = jmri.InstanceManager.getList(SystemConnectionMemo.class); 102 if (!connList.isEmpty()) { 103 ArrayList<String> progConn = new ArrayList<>(); 104 progConn.add(""); 105 String userName = "Dcc4Pc"; 106 if (this.getSystemConnectionMemo() != null) { 107 userName = this.getSystemConnectionMemo().getUserName(); 108 } 109 for (int i = 0; i < connList.size(); i++) { 110 SystemConnectionMemo scm = connList.get(i); 111 if ((scm.provides(jmri.AddressedProgrammerManager.class) || scm.provides(jmri.GlobalProgrammerManager.class)) 112 && (!scm.getUserName().equals(userName))) { 113 progConn.add(scm.getUserName()); 114 } 115 } 116 return progConn.toArray(new String[progConn.size()]); 117 } else { 118 return new String[]{""}; 119 } 120 } 121 122 /** 123 * Get a String that says what Option 2 represents May be an empty string, 124 * but will not be null 125 * @return option to match detected locos to roster. 126 */ 127 public String option2Name() { 128 return "Match Detected Locos to Roster: "; 129 } 130 131 /** 132 * Set the second port option. Only to be used after construction, but 133 * before the openPort call 134 */ 135 @Override 136 public void configureOption2(String value) { 137 super.configureOption2(value); 138 log.debug("configureOption2: {}", value); 139 //Not yet implemented 140 /*boolean enable = true; 141 if(value.equals("No")) 142 enable = false; 143 adaptermemo.getRailCommManager().setRosterEntryDiscoveryAllowed(enable);*/ 144 } 145 146 // base class methods for the Dcc4PcPortController interface 147 @Override 148 public DataInputStream getInputStream() { 149 if (!opened) { 150 log.error("getInputStream called before load(), stream not available"); 151 return null; 152 } 153 return new DataInputStream(serialStream); 154 } 155 156 @Override 157 public DataOutputStream getOutputStream() { 158 if (!opened) { 159 log.error("getOutputStream called before load(), stream not available"); 160 } 161 try { 162 return new DataOutputStream(activeSerialPort.getOutputStream()); 163 } catch (java.io.IOException e) { 164 log.error("getOutputStream exception", e); 165 } 166 return null; 167 } 168 169 /** 170 * {@inheritDoc} 171 * 172 * Currently only 115,200 bps 173 */ 174 @Override 175 public String[] validBaudRates() { 176 return new String[]{"115,200 bps"}; 177 } 178 179 /** 180 * {@inheritDoc} 181 */ 182 @Override 183 public int[] validBaudNumbers() { 184 return new int[]{115200}; 185 } 186 187 @Override 188 public int defaultBaudIndex() { 189 return 0; 190 } 191 192 InputStream serialStream = null; 193 194 /** 195 * set up all of the other objects to operate with an Dcc4Pc command station 196 * connected to this port 197 */ 198 @Override 199 public void configure() { 200 // connect to the traffic controller 201 Dcc4PcTrafficController control = new Dcc4PcTrafficController(); 202 this.getSystemConnectionMemo().setDcc4PcTrafficController(control); 203 control.connectPort(this); 204 this.getSystemConnectionMemo().configureManagers(); 205 206 } 207 208 private final static Logger log = LoggerFactory.getLogger(SerialDriverAdapter.class); 209 210}