001package jmri.jmrix.powerline.cm11; 002 003import java.io.DataInputStream; 004import java.io.DataOutputStream; 005import java.io.IOException; 006import java.io.InputStream; 007import java.util.Arrays; 008import jmri.jmrix.powerline.SerialPortController; 009import jmri.jmrix.powerline.SerialTrafficController; 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012import purejavacomm.CommPortIdentifier; 013import purejavacomm.NoSuchPortException; 014import purejavacomm.PortInUseException; 015import purejavacomm.SerialPort; 016import purejavacomm.UnsupportedCommOperationException; 017 018/** 019 * Provide access to Powerline devices via a serial com port. 020 * Derived from the Oaktree code. 021 * 022 * @author Bob Jacobsen Copyright (C) 2006, 2007, 2008 023 * @author Ken Cameron, (C) 2009, sensors from poll replies Converted to 024 * multiple connection 025 * @author kcameron Copyright (C) 2011 026 */ 027public class SpecificDriverAdapter extends SerialPortController { 028 029 SerialPort activeSerialPort = null; 030 031 public SpecificDriverAdapter() { 032 super(new SpecificSystemConnectionMemo()); 033 } 034 035 @Override 036 public String openPort(String portName, String appName) { 037 try { 038 // get and open the primary port 039 CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(portName); 040 try { 041 activeSerialPort = (SerialPort) portID.open(appName, 2000); // name of program, msec to wait 042 } catch (PortInUseException p) { 043 return handlePortBusy(p, portName, log); 044 } 045 // try to set it for serial 046 try { 047 setSerialPort(); 048 } catch (UnsupportedCommOperationException e) { 049 log.error("Cannot set serial parameters on port {}: {}", portName, e.getMessage()); 050 return "Cannot set serial parameters on port " + portName + ": " + e.getMessage(); 051 } 052 053 // set framing (end) character 054 try { 055 log.debug("Serial framing was observed as: {} {}", activeSerialPort.isReceiveFramingEnabled(), 056 activeSerialPort.getReceiveFramingByte()); 057 } catch (Exception ef) { 058 log.debug("failed to set serial framing: ", ef); 059 } 060 061 // set timeout; framing should work before this anyway 062 try { 063 activeSerialPort.enableReceiveTimeout(10); 064 log.debug("Serial timeout was observed as: {} {}", activeSerialPort.getReceiveTimeout(), 065 activeSerialPort.isReceiveTimeoutEnabled()); 066 } catch (Exception et) { 067 log.info("failed to set serial timeout: ", et); 068 } 069 070 // get and save stream 071 serialStream = activeSerialPort.getInputStream(); 072 073 // purge contents, if any 074 purgeStream(serialStream); 075 076 // report status? 077 if (log.isInfoEnabled()) { 078 // report now 079 log.info("{} port opened at {} baud with DTR: {} RTS: {} DSR: {} CTS: {} CD: {}", portName, activeSerialPort.getBaudRate(), activeSerialPort.isDTR(), activeSerialPort.isRTS(), activeSerialPort.isDSR(), activeSerialPort.isCTS(), activeSerialPort.isCD()); 080 } 081 if (log.isDebugEnabled()) { 082 // report additional status 083 log.debug(" port flow control shows {}", // NOI18N 084 (activeSerialPort.getFlowControlMode() == SerialPort.FLOWCONTROL_RTSCTS_OUT ? "hardware flow control" : "no flow control")); // NOI18N 085 086 // log events 087 setPortEventLogging(activeSerialPort); 088 } 089 090 opened = true; 091 092 } catch (NoSuchPortException p) { 093 return handlePortNotFound(p, portName, log); 094 } catch (IOException ex) { 095 log.error("Unexpected exception while opening port {}: ", portName, ex); 096 return "Unexpected error while opening port " + portName + ": " + ex; 097 } 098 099 return null; // normal operation 100 } 101 102 /** 103 * set up all of the other objects to operate connected to this port 104 */ 105 @Override 106 public void configure() { 107 SerialTrafficController tc = null; 108 // create a CM11 port controller 109 //adaptermemo = new jmri.jmrix.powerline.cm11.SpecificSystemConnectionMemo(); 110 tc = new SpecificTrafficController(this.getSystemConnectionMemo()); 111 112 // connect to the traffic controller 113 this.getSystemConnectionMemo().setTrafficController(tc); 114 tc.setAdapterMemo(this.getSystemConnectionMemo()); 115 this.getSystemConnectionMemo().configureManagers(); 116 tc.connectPort(this); 117 // Configure the form of serial address validation for this connection 118 this.getSystemConnectionMemo().setSerialAddress(new jmri.jmrix.powerline.SerialAddress(this.getSystemConnectionMemo())); 119 } 120 121 /** 122 * {@inheritDoc} 123 */ 124 @Override 125 public String[] validBaudRates() { 126 return Arrays.copyOf(validSpeeds, validSpeeds.length); 127 } 128 129 /** 130 * {@inheritDoc} 131 */ 132 @Override 133 public int[] validBaudNumbers() { 134 return Arrays.copyOf(validSpeedValues, validSpeedValues.length); 135 } 136 137 // base class methods for the SerialPortController 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.getMessage()); 156 } 157 return null; 158 } 159 160 @Override 161 public boolean status() { 162 return opened; 163 } 164 // private control members 165 private boolean opened = false; 166 InputStream serialStream = null; 167 168 /** 169 * Local method to do specific port configuration. 170 * 171 * @throws purejavacomm.UnsupportedCommOperationException invalid connection or options 172 */ 173 protected void setSerialPort() throws UnsupportedCommOperationException { 174 // find the baud rate value, configure comm options 175 int baud = currentBaudNumber(mBaudRate); 176 177 activeSerialPort.setSerialPortParams(baud, SerialPort.DATABITS_8, 178 SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); 179 180 // find and configure flow control 181 int flow = SerialPort.FLOWCONTROL_NONE; // default 182 configureLeadsAndFlowControl(activeSerialPort, flow); 183 } 184 185 protected String[] validSpeeds = new String[]{Bundle.getMessage("BaudAutomatic")}; 186 protected int[] validSpeedValues = new int[]{4800}; 187 188 @Override 189 public int defaultBaudIndex() { 190 return 0; 191 } 192 193 private final static Logger log = LoggerFactory.getLogger(SpecificDriverAdapter.class); 194 195}