001package jmri.jmrix.powerline.simulator;
002
003import java.io.DataInputStream;
004import java.io.DataOutputStream;
005import java.io.PipedInputStream;
006import java.io.PipedOutputStream;
007
008import jmri.jmrix.powerline.SerialPortController;
009import jmri.util.ImmediatePipedOutputStream;
010
011/**
012 * Implement simulator for Powerline serial systems.
013 * <p>
014 * System names are "PLnnn", where P is the user-configurable system prefix,
015 * nnn is the bit number without padding.
016 * <p>
017 * Based on the NCE simulator.
018 *
019 * @author Dave Duchamp Copyright (C) 2004
020 * @author Bob Jacobsen Copyright (C) 2006, 2007, 2008 Converted to multiple connection
021 * @author kcameron Copyright (C) 2011
022 */
023public class SimulatorAdapter extends SerialPortController implements Runnable {
024
025    // private control members
026    private Thread sourceThread;
027
028    // streams to share with user class
029    private DataOutputStream pout = null; // this is provided to classes who want to write to us
030    private DataInputStream pin = null; // this is provided to classes who want data from us
031
032    // internal ends of the pipes
033
034    //private DataOutputStream outpipe = null; // feed pin
035
036    //private DataInputStream inpipe = null; // feed pout
037
038    public SimulatorAdapter() {
039        super(new SpecificSystemConnectionMemo());
040    }
041
042    @Override
043    public String openPort(String portName, String appName) {
044        try (PipedOutputStream tempPipeI = new ImmediatePipedOutputStream();
045            PipedOutputStream tempPipeO = new ImmediatePipedOutputStream()) {
046
047            pout = new DataOutputStream(tempPipeI);
048            pin = new DataInputStream(new PipedInputStream(tempPipeO));
049            opened = true;
050            return null; // indicates OK return
051        } catch (java.io.IOException e) {
052            log.error("init (pipe): Exception: ", e);
053            opened = false;
054            return e.toString();
055        }
056    }
057
058    /**
059     * Set up all of the other objects to simulate operation with an command
060     * station.
061     */
062    @Override
063    public void configure() {
064        SpecificTrafficController tc = new SpecificTrafficController(this.getSystemConnectionMemo());
065
066        // connect to the traffic controller
067        this.getSystemConnectionMemo().setTrafficController(tc);
068        tc.setAdapterMemo(this.getSystemConnectionMemo());
069        this.getSystemConnectionMemo().configureManagers();
070        tc.connectPort(this);
071
072        // Configure the form of serial address validation for this connection
073        this.getSystemConnectionMemo().setSerialAddress(new jmri.jmrix.powerline.SerialAddress(this.getSystemConnectionMemo()));
074
075        // start the simulator
076        sourceThread = new Thread(this);
077        sourceThread.setName("Powerline Simulator");
078        sourceThread.setPriority(Thread.MIN_PRIORITY);
079        sourceThread.start();
080    }
081
082    // base class methods for the PortController interface
083    @Override
084    public DataInputStream getInputStream() {
085        if (!opened || pin == null) {
086            log.error("getInputStream called before load(), stream not available");
087        }
088        return pin;
089    }
090
091    @Override
092    public DataOutputStream getOutputStream() {
093        if (!opened || pout == null) {
094            log.error("getOutputStream called before load(), stream not available");
095        }
096        return pout;
097    }
098
099    @Override
100    public boolean status() {
101        return opened;
102    }
103
104    /**
105     * {@inheritDoc}
106     */
107    @Override
108    public String[] validBaudRates() {
109        log.debug("validBaudRates should not have been invoked");
110        return new String[]{};
111    }
112
113    /**
114     * {@inheritDoc}
115     */
116    @Override
117    public int[] validBaudNumbers() {
118        return new int[]{};
119    }
120
121    @Override
122    public String getCurrentBaudRate() {
123        return "";
124    }
125
126    @Override
127    public String getCurrentPortName(){
128        return "";
129    }
130
131    @Override
132    public void run() { // start a new thread
133        // Simulator thread just reports start and ends
134        log.info("Powerline Simulator Started");
135    }
136
137    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SimulatorAdapter.class);
138
139}