001package jmri.jmrix.rfid.serialdriver;
002
003import java.util.Arrays;
004import jmri.jmrix.rfid.RfidPortController;
005import jmri.jmrix.rfid.RfidProtocol;
006import jmri.jmrix.rfid.RfidSystemConnectionMemo;
007import jmri.jmrix.rfid.RfidTrafficController;
008import jmri.jmrix.rfid.generic.standalone.StandaloneReporterManager;
009import jmri.jmrix.rfid.generic.standalone.StandaloneSensorManager;
010import jmri.jmrix.rfid.generic.standalone.StandaloneTrafficController;
011import jmri.jmrix.rfid.merg.concentrator.ConcentratorReporterManager;
012import jmri.jmrix.rfid.merg.concentrator.ConcentratorSensorManager;
013import jmri.jmrix.rfid.merg.concentrator.ConcentratorTrafficController;
014import jmri.jmrix.rfid.protocol.coreid.CoreIdRfidProtocol;
015import jmri.jmrix.rfid.protocol.em18.Em18RfidProtocol;
016import jmri.jmrix.rfid.protocol.olimex.OlimexRfid1356mifareProtocol;
017import jmri.jmrix.rfid.protocol.olimex.OlimexRfidProtocol;
018import jmri.jmrix.rfid.protocol.parallax.ParallaxRfidProtocol;
019import jmri.jmrix.rfid.protocol.seeedstudio.SeeedStudioRfidProtocol;
020import org.slf4j.Logger;
021import org.slf4j.LoggerFactory;
022
023/**
024 * Provide access to RFID devices via a serial com port.
025 * Derived from the Oaktree code.
026 *
027 * @author Bob Jacobsen Copyright (C) 2006, 2007, 2008
028 * @author Matthew Harris Copyright (C) 2011
029 * @author Oscar A. Pruitt Copyright (C) 2015
030 * @author B. Milhaupt Copyright (C) 2017
031 * @since 2.11.4
032 */
033public class SerialDriverAdapter extends RfidPortController {
034
035    public SerialDriverAdapter() {
036        super(new RfidSystemConnectionMemo());
037        option1Name = "Adapter"; // NOI18N
038        option2Name = "Concentrator-Range"; // NOI18N
039        option3Name = "Protocol"; // NOI18N
040        option4Name = "Device"; // NOI18N
041        options.put(option1Name, new Option(Bundle.getMessage("ConnectionAdapter"), new String[]{"Generic Stand-alone", "MERG Concentrator"}, false)); // NOI18N
042        options.put(option2Name, new Option(Bundle.getMessage("ConnectionConcentratorRange"), new String[]{"A-H", "I-P"}, false)); // NOI18N
043        options.put(option3Name, new Option(Bundle.getMessage("ConnectionProtocol"), new String[]{"CORE-ID", "Olimex", "Parallax", "SeeedStudio", "EM-18"}, false)); // NOI18N
044        options.put(option4Name, new Option(Bundle.getMessage("ConnectionDeviceType"), new String[]{"MOD-RFID125", "MOD-RFID1356MIFARE"}, false)); // NOI18N
045        this.manufacturerName = jmri.jmrix.rfid.RfidConnectionTypeList.RFID;
046    }
047
048    @Override
049    public String openPort(String portName, String appName) {
050        // get and open the primary port
051        currentSerialPort = activatePort(portName, log);
052        if (currentSerialPort == null) {
053            log.error("failed to connect RFID to {}", portName);
054            return Bundle.getMessage("SerialPortNotFound", portName);
055        }
056        log.info("Connecting RFID to {} {}", portName, currentSerialPort);
057        
058        // try to set it for communication via SerialDriver
059        // find the baud rate value, configure comm options
060        int baud = currentBaudNumber(mBaudRate);
061
062        // the Parallax reader uses 2400 baud, so set that here
063        if (getOptionState(option3Name).equals("Parallax")) {
064            log.debug("Set baud rate to 2400 for Parallax reader");
065            baud = 2400;
066        }
067        setBaudRate(currentSerialPort, baud);
068        configureLeads(currentSerialPort, true, true);
069        // find and configure flow control
070        FlowControl flow = FlowControl.NONE; // default
071        if (getOptionState(option1Name).equals("MERG Concentrator")) {
072            // Set Hardware Flow Control for Concentrator
073            log.debug("Set hardware flow control for Concentrator");
074            flow = FlowControl.RTSCTS;
075        }
076        setFlowControl(currentSerialPort, flow);
077
078        // report status
079        reportPortStatus(log, portName);
080
081        opened = true;
082
083        return null; // indicates OK return
084    }
085
086    /**
087     * Can the port accept additional characters?
088     *
089     * @return always true
090     */
091    public boolean okToSend() {
092        return true;
093    }
094
095    /**
096     * Set up all of the other objects to operate connected to this port
097     */
098    @Override
099    public void configure() {
100        RfidTrafficController control;
101        RfidProtocol protocol;
102
103        // set up the system connection first
104        String opt1 = getOptionState(option1Name);
105        switch (opt1) {
106            case "Generic Stand-alone": // NOI18N
107                // create a Generic Stand-alone port controller
108                log.debug("Create Generic Standalone SpecificTrafficController"); // NOI18N
109                control = new StandaloneTrafficController(this.getSystemConnectionMemo());
110                this.getSystemConnectionMemo().setRfidTrafficController(control);
111                this.getSystemConnectionMemo().configureManagers(
112                        new StandaloneSensorManager(this.getSystemConnectionMemo()),
113                        new StandaloneReporterManager(this.getSystemConnectionMemo()));
114                break;
115            case "MERG Concentrator": // NOI18N
116                // create a MERG Concentrator port controller
117                log.debug("Create MERG Concentrator SpecificTrafficController"); // NOI18N
118                control = new ConcentratorTrafficController(this.getSystemConnectionMemo(), getOptionState(option2Name));
119                this.getSystemConnectionMemo().setRfidTrafficController(control);
120                this.getSystemConnectionMemo().configureManagers(
121                        new ConcentratorSensorManager(this.getSystemConnectionMemo()),
122                        new ConcentratorReporterManager(this.getSystemConnectionMemo()));
123                break;
124            default:
125                // no connection at all - warn
126                log.warn("adapter option {} defaults to Generic Stand-alone", opt1); // NOI18N
127                // create a Generic Stand-alone port controller
128                control = new StandaloneTrafficController(this.getSystemConnectionMemo());
129                this.getSystemConnectionMemo().setRfidTrafficController(control);
130                this.getSystemConnectionMemo().configureManagers(
131                        new StandaloneSensorManager(this.getSystemConnectionMemo()),
132                        new StandaloneReporterManager(this.getSystemConnectionMemo()));
133                break;
134        }
135
136        // Now do the protocol
137        String opt3 = getOptionState(option3Name);
138        String opt4 = getOptionState(option4Name);
139        if (opt1.equals("MERG Concentrator")) { // NOI18N
140            // MERG Concentrator only supports CORE-ID
141            log.info("set protocol to CORE-ID"); // NOI18N
142            String opt2 = getOptionState(option2Name);
143            switch (opt2) {
144                case "A-H": // NOI18N
145                    log.info("set concentrator range to 'A-H' at position 1"); // NOI18N
146                    protocol = new CoreIdRfidProtocol('A', 'H', 1);
147                    break;
148                case "I-P": // NOI18N
149                    log.info("set concentrator range to 'I-P' at position 1"); // NOI18N
150                    protocol = new CoreIdRfidProtocol('I', 'P', 1);
151                    break;
152                default:
153                    // unrecognised concentrator range - warn
154                    log.warn("concentrator range '{}' not supported - default to no concentrator", opt2); // NOI18N
155                    protocol = new CoreIdRfidProtocol();
156                    break;
157            }
158        } else {
159            switch (opt3) {
160                case "CORE-ID": // NOI18N
161                    log.info("set protocol to CORE-ID"); // NOI18N
162                    protocol = new CoreIdRfidProtocol();
163                    break;
164                case "Olimex": // NOI18N
165                    if (opt4.equals("MOD-RFID1356MIFARE")) { // NOI18N
166                        log.info("set protocol for Olimex MOD-RFID1356MIFARE"); // NOI18N
167                        protocol = new OlimexRfid1356mifareProtocol();
168                    } else {
169                        log.info("set protocol for Olimex MOD-RFID125"); // NOI18N
170                        protocol = new OlimexRfidProtocol();
171                    }
172                    break;
173                case "Parallax": // NOI18N
174                    log.info("set protocol to Parallax"); // NOI18N
175                    protocol = new ParallaxRfidProtocol();
176                    break;
177                case "SeeedStudio": // NOI18N
178                    log.info("set protocol to SeeedStudio"); // NOI18N
179                    protocol = new SeeedStudioRfidProtocol();
180                    break;
181                case "EM-18": // NOI18N
182                    log.info("set protocol to EM-18"); // NOI18N
183                    protocol = new Em18RfidProtocol();
184                    break;
185                default:
186                    // no protocol at all - warn
187                    log.warn("protocol option {} defaults to CORE-ID", opt3);
188                    // create a coreid protocol
189                    protocol = new CoreIdRfidProtocol();
190                    break;
191            }
192        }
193        this.getSystemConnectionMemo().setProtocol(protocol);
194
195        // connect to the traffic controller
196        this.getSystemConnectionMemo().setRfidTrafficController(control);
197        control.setAdapterMemo(this.getSystemConnectionMemo());
198        control.connectPort(this);
199        control.sendInitString();
200    }
201
202    // base class methods for the RfidPortController interface
203    
204    @Override
205    public boolean status() {
206        return opened;
207    }
208
209    /**
210     * {@inheritDoc}
211     */
212    @Override
213    public String[] validBaudRates() {
214        return Arrays.copyOf(validSpeeds, validSpeeds.length);
215    }
216
217    /**
218     * {@inheritDoc}
219     */
220    @Override
221    public int[] validBaudNumbers() {
222        return Arrays.copyOf(validSpeedValues, validSpeedValues.length);
223    }
224
225    protected String[] validSpeeds = new String[]{Bundle.getMessage("BaudAutomatic")};
226    protected int[] validSpeedValues = new int[]{9600};
227
228    @Override
229    public int defaultBaudIndex() {
230        return 0;
231    }
232
233    // private control members
234
235    private static final Logger log = LoggerFactory.getLogger(SerialDriverAdapter.class);
236
237}