001package jmri.jmrix.loconet.locobuffer; 002 003import java.util.Arrays; 004import java.util.Vector; 005import jmri.jmrix.loconet.LnCommandStationType; 006import jmri.jmrix.loconet.LnPacketizer; 007import jmri.jmrix.loconet.LnPacketizerStrict; 008import jmri.jmrix.loconet.LnPortController; 009import jmri.jmrix.loconet.LocoNetSystemConnectionMemo; 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013/** 014 * Provide access to LocoNet via a LocoBuffer attached to a serial com port. 015 * <p> 016 * Normally controlled by the LocoBufferFrame class. 017 * 018 * @author Bob Jacobsen Copyright (C) 2001, 2008, 2010 019 */ 020public class LocoBufferAdapter extends LnPortController { 021 022 public LocoBufferAdapter() { 023 this(new LocoNetSystemConnectionMemo()); 024 } 025 026 public LocoBufferAdapter(LocoNetSystemConnectionMemo adapterMemo) { 027 super(adapterMemo); 028 option1Name = "FlowControl"; // NOI18N 029 option2Name = "CommandStation"; // NOI18N 030 option3Name = "TurnoutHandle"; // NOI18N 031 option4Name = "PacketizerType"; // NOI18N 032 options.put(option1Name, new Option(Bundle.getMessage("XconnectionUsesLabel", Bundle.getMessage("TypeSerial")), validOption1)); // NOI18N 033 options.put(option2Name, new Option(Bundle.getMessage("CommandStationTypeLabel"), getCommandStationListWithStandaloneLN(), false)); // NOI18N 034 options.put(option3Name, new Option(Bundle.getMessage("TurnoutHandling"), 035 new String[]{Bundle.getMessage("HandleNormal"), Bundle.getMessage("HandleSpread"), Bundle.getMessage("HandleOneOnly"), Bundle.getMessage("HandleBoth")})); // I18N 036 options.put(option4Name, new Option(Bundle.getMessage("PacketizerTypeLabel"), packetizerOptions())); // NOI18N 037 options.put("TranspondingPresent", new Option(Bundle.getMessage("TranspondingPresent"), 038 new String[]{Bundle.getMessage("ButtonNo"), Bundle.getMessage("ButtonYes")} )); // NOI18N 039 options.put("InterrogateOnStart", new Option(Bundle.getMessage("InterrogateOnStart"), 040 new String[]{Bundle.getMessage("ButtonYes"), Bundle.getMessage("ButtonNo")} )); // NOI18N 041 options.put("LoconetProtocolAutoDetect", new Option(Bundle.getMessage("LoconetProtocolAutoDetectLabel"), 042 new String[]{Bundle.getMessage("ButtonNo"),Bundle.getMessage("LoconetProtocolAutoDetect")} )); // NOI18N 043 } 044 045 /** 046 * Create a list of possible command stations and append "Standalone LocoNet" 047 * 048 * Note: This is not suitable for use by any class which extends this class if 049 * the hardware interface is part of a command station. 050 * 051 * @return String[] containing the array of command stations, plus "Standalone 052 * LocoNet" 053 */ 054 public String[] getCommandStationListWithStandaloneLN() { 055 String[] result = new String[commandStationNames.length + 1]; 056 for (int i = 0 ; i < result.length-1; ++i) { 057 result[i] = commandStationNames[i]; 058 } 059 result[commandStationNames.length] = LnCommandStationType.COMMAND_STATION_STANDALONE.getName(); 060 return result; 061 } 062 063 Vector<String> portNameVector = null; 064 065 @Override 066 public String openPort(String portName, String appName) { 067 // get and open the primary port 068 currentSerialPort = activatePort(portName, log); 069 if (currentSerialPort == null) { 070 log.error("failed to connect LocoBuffer to {}", portName); 071 return Bundle.getMessage("SerialPortNotFound", portName); 072 } 073 reportOpen(portName); 074 075 // try to set it for communication via SerialDriver 076 // find the baud rate value, configure comm options 077 int baud = currentBaudNumber(mBaudRate); 078 setBaudRate(currentSerialPort, baud); 079 configureLeads(currentSerialPort, true, true); 080 setLocalFlowControl(); 081 082 // report status 083 reportPortStatus(log, portName); 084 085 opened = true; 086 087 return null; // indicates OK return 088 } 089 090 /** 091 * Allow subtypes to change the opening message 092 * @param portName To appear in message 093 */ 094 protected void reportOpen(String portName) { 095 log.info("Connecting LocoBuffer via {} {}", portName, currentSerialPort); 096 } 097 098 /** 099 * Allow subtypes to change the flow control algorithm 100 */ 101 protected void setLocalFlowControl() { 102 FlowControl flow = FlowControl.RTSCTS; 103 if (getOptionState(option1Name).equals(validOption1[1])) { 104 flow = FlowControl.NONE; 105 } 106 setFlowControl(currentSerialPort, flow); 107 } 108 109 /** 110 * Can the port accept additional characters? The state of CTS determines 111 * this, as there seems to be no way to check the number of queued bytes and 112 * buffer length. This might go false for short intervals, but it might also 113 * stick off if something goes wrong. 114 * 115 * @return an indication of whether the interface is accepting transmit messages. 116 */ 117 @Override 118 public boolean okToSend() { 119 return currentSerialPort.getCTS(); 120 } 121 122 /** 123 * Set up all of the other objects to operate with a LocoBuffer connected to 124 * this port. 125 */ 126 @Override 127 public void configure() { 128 129 setCommandStationType(getOptionState(option2Name)); 130 setTurnoutHandling(getOptionState(option3Name)); 131 setTranspondingAvailable(getOptionState("TranspondingPresent")); 132 setInterrogateOnStart(getOptionState("InterrogateOnStart")); 133 setLoconetProtocolAutoDetect(getOptionState("LoconetProtocolAutoDetect")); 134 // connect to a packetizing traffic controller 135 LnPacketizer packets = getPacketizer(getOptionState(option4Name)); 136 packets.connectPort(this); 137 138 // create memo 139 this.getSystemConnectionMemo().setLnTrafficController(packets); 140 // do the common manager config 141 142 this.getSystemConnectionMemo().configureCommandStation(commandStationType, 143 mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable, mInterrogateAtStart, mLoconetProtocolAutoDetect); 144 this.getSystemConnectionMemo().configureManagers(); 145 146 // start operation 147 packets.startThreads(); 148 } 149 150 @Override 151 public boolean status() { 152 return opened; 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 @Override 159 public String[] validBaudRates() { 160 return Arrays.copyOf(validSpeeds, validSpeeds.length); 161 } 162 163 /** 164 * {@inheritDoc} 165 */ 166 @Override 167 public int[] validBaudNumbers() { 168 return Arrays.copyOf(validSpeedValues, validSpeedValues.length); 169 } 170 171 protected String[] validSpeeds = new String[]{Bundle.getMessage("Baud19200LB"), Bundle.getMessage("Baud57600LB")}; 172 protected int[] validSpeedValues = new int[]{19200, 57600}; 173 174 @Override 175 public int defaultBaudIndex() { 176 return 0; 177 } 178 179 // meanings are assigned to these above, so make sure the order is consistent 180 protected String[] validOption1 = new String[]{Bundle.getMessage("FlowOptionHwRecomm"), Bundle.getMessage("FlowOptionNo")}; 181 182 /** 183 * Define the readable data and internal code 184 */ 185 private static String[][] packetizers = { {Bundle.getMessage("PacketizerTypelnPacketizer"),"lnPacketizer" }, 186 {Bundle.getMessage("PacketizerTypelnPacketizerStrict"),"lnPacketizerStrict"} }; 187 188 /** 189 * 190 * @return String array of readable choices 191 */ 192 private String[] packetizerOptions() { 193 String[] retval = new String[packetizers.length]; 194 for (int i=0;i < packetizers.length; i++) { 195 retval[i] = packetizers[i][0]; 196 } 197 return retval; 198 } 199 /** 200 * for a given readable choice return internal value 201 * or the default 202 * 203 * @param s string containing ?a packetizer name? 204 * @return internal value 205 */ 206 protected String getPacketizerOption(String s) { 207 for (int i=0;i < packetizers.length; i++) { 208 if (packetizers[i][0].equals(s)) { 209 return packetizers[i][1]; 210 } 211 } 212 return "lnPacketizer"; 213 } 214 /** 215 * 216 * @param s the packetizer to use in its readable form. 217 * @return a LnPacketizer 218 */ 219 protected LnPacketizer getPacketizer(String s) { 220 LnPacketizer packets; 221 String packetSelection = getPacketizerOption(s); 222 switch (packetSelection) { 223 case "lnPacketizer": 224 packets = new LnPacketizer(this.getSystemConnectionMemo()); 225 break; 226 case "lnPacketizerStrict": 227 packets = new LnPacketizerStrict(this.getSystemConnectionMemo()); 228 break; 229 default: 230 packets = new LnPacketizer(this.getSystemConnectionMemo()); 231 log.warn("Using Normal do not understand option [{}]", packetSelection); 232 } 233 return packets; 234 } 235 236 private final static Logger log = LoggerFactory.getLogger(LocoBufferAdapter.class); 237 238}