001package jmri.jmrix.powerline;
002
003import jmri.jmrix.AbstractMRListener;
004import jmri.jmrix.AbstractMRMessage;
005import jmri.jmrix.AbstractMRReply;
006import jmri.jmrix.AbstractMRTrafficController;
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010/**
011 * Converts Stream-based I/O to/from messages. The "SerialInterface" side
012 * sends/receives message objects.
013 * <p>
014 * The connection to a SerialPortController is via a pair of *Streams, which
015 * then carry sequences of characters for transmission. Note that this
016 * processing is handled in an independent thread.
017 * <p>
018 * This maintains a list of nodes, but doesn't currently do anything with it.
019 * <p>
020 * This implementation is complete and can be instantiated, but is not
021 * functional. It will be created e.g. when a default object is needed for
022 * configuring nodes, etc, during the initial configuration. A subclass must be
023 * instantiated to actually communicate with an adapter.
024 *
025 * @author Bob Jacobsen Copyright (C) 2001, 2003, 2005, 2006, 2008 Converted to
026 * multiple connection
027 * @author kcameron Copyright (C) 2011
028 */
029abstract public class SerialTrafficController extends AbstractMRTrafficController implements SerialInterface {
030
031    /**
032     * Create a new TrafficController instance. Simple implementation.
033     */
034    public SerialTrafficController() {
035        super();
036        logDebug = log.isDebugEnabled();
037
038        // not polled at all, so allow unexpected messages, and
039        // use poll delay just to spread out startup
040        setAllowUnexpectedReply(true);
041        mWaitBeforePoll = 1000;  // can take a long time to send
042    }
043
044    /**
045     * Send a sequence of X10 messages to an adapter.
046     * <p>
047     * Makes them into the local messages and then queues in order.
048     * <p>
049     * This is a default, null implementation, which must be overridden in an
050     * adapter-specific subclass.
051     *
052     * @param s sequence to send
053     * @param l listener for reply
054     */
055    public void sendX10Sequence(X10Sequence s, SerialListener l) {
056    }
057
058    /**
059     * Send a sequence of Insteon messages to an adapter.
060     * <p>
061     * Makes them into the local messages and then queues in order.
062     * <p>
063     * This is a default, null implementation, which must be overridden in an
064     * adapter-specific subclass.
065     *
066     * @param s sequence to send
067     * @param l listener for reply
068     */
069    public void sendInsteonSequence(InsteonSequence s, SerialListener l) {
070    }
071    
072    /**
073     * Send a sequence of DMX messages to an adapter.
074     * <p>
075     * Makes them into the local messages and then queues in order.
076     * <p>
077     * This is a default, null implementation, which must be overridden in an
078     * adapter-specific subclass.
079     *
080     * DMX does work with a sequence, it directly updates the data array
081     * @param unitid which light
082     * @param newStep new intesity value
083     * 
084     * @return true on success
085     */
086    public boolean sendDmxSequence(int unitid, byte newStep) {
087        return false;
088    }
089
090    /**
091     * Provide the maximum number of dimming steps available.
092     *
093     * @return By default, dimming not available.
094     */
095    public int getNumberOfIntensitySteps() {
096        return 0;
097    }
098
099    /**
100     * Get a message of a specific length for filling in.
101     * <p>
102     * This is a default, null implementation, which must be overridden in an
103     * adapter-specific subclass.
104     *
105     * @param length message size
106     * @return null
107     */
108    public SerialMessage getSerialMessage(int length) {
109        return null;
110    }
111
112    // have several debug statements in tight loops, e.g. every character;
113    // only want to check once
114    protected boolean logDebug = false;
115
116    // The methods to implement the SerialInterface
117    @Override
118    public synchronized void addSerialListener(SerialListener l) {
119        this.addListener(l);
120    }
121
122    @Override
123    public synchronized void removeSerialListener(SerialListener l) {
124        this.removeListener(l);
125    }
126
127    @Override
128    protected int enterProgModeDelayTime() {
129        // we should to wait at least a second after enabling the programming track
130        return 1000;
131    }
132
133    /**
134     * Forward a SerialMessage to all registered SerialInterface listeners.
135     */
136    @Override
137    protected void forwardMessage(AbstractMRListener client, AbstractMRMessage m) {
138        ((SerialListener) client).message((SerialMessage) m);
139    }
140
141    /**
142     * Forward a reply to all registered SerialInterface listeners.
143     */
144    @Override
145    protected void forwardReply(AbstractMRListener client, AbstractMRReply r) {
146        ((SerialListener) client).reply((SerialReply) r);
147    }
148
149    SerialSensorManager mSensorManager = null;
150
151    public void setSensorManager(SerialSensorManager m) {
152        mSensorManager = m;
153    }
154
155    public SerialSensorManager getSensorManager() {
156        return mSensorManager;
157    }
158
159    /**
160     * Eventually, do initialization if needed
161     */
162    @Override
163    protected AbstractMRMessage pollMessage() {
164        return null;
165    }
166
167    @Override
168    protected AbstractMRListener pollReplyHandler() {
169        return null;
170    }
171
172    /**
173     * Forward a preformatted message to the actual interface.
174     */
175    @Override
176    public void sendSerialMessage(SerialMessage m, SerialListener reply) {
177        sendMessage(m, reply);
178    }
179
180    @Override
181    protected void forwardToPort(AbstractMRMessage m, AbstractMRListener reply) {
182        if (logDebug) {
183            log.debug("forward {}", m);
184        }
185        sendInterlock = ((SerialMessage) m).getInterlocked();
186        super.forwardToPort(m, reply);
187    }
188
189    @Override
190    protected AbstractMRMessage enterProgMode() {
191        return null;
192    }
193
194    @Override
195    protected AbstractMRMessage enterNormalMode() {
196        return null;
197    }
198
199    public void setAdapterMemo(SerialSystemConnectionMemo adaptermemo) {
200        memo = adaptermemo;
201    }
202
203    public SerialSystemConnectionMemo getAdapterMemo() {
204        return memo;
205    }
206
207    protected SerialSystemConnectionMemo memo = null;
208    SerialTrafficController self = null;
209
210    boolean sendInterlock = false; // send the 00 interlock when CRC received
211    boolean expectLength = false;  // next byte is length of read
212    boolean countingBytes = false; // counting remainingBytes into reply buffer
213    int remainingBytes = 0;        // count of bytes _left_
214
215    /**
216     * This is a default, null implementation, which must be overridden in an
217     * adapter-specific subclass.
218     */
219    @Override
220    protected boolean endOfMessage(AbstractMRReply msg) {
221        return true;
222    }
223
224    /**
225     * This is a default, null implementation, which must be overridden in an
226     * adapter-specific subclass.
227     */
228    @Override
229    protected AbstractMRReply newReply() {
230        return null;
231    }
232
233    private final static Logger log = LoggerFactory.getLogger(SerialTrafficController.class);
234
235}