001package jmri.jmrix.dcc4pc;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006/**
007 * Encodes a message to the DCC4PC Interface.
008 * <p>
009 * The {@link Dcc4PcReply} class handles the response from the command station.
010 *
011 * @author Bob Jacobsen Copyright (C) 2001
012 * @author Kevin Dickerson Copyright (C) 2012
013 * 
014 */
015public class Dcc4PcMessage extends jmri.jmrix.AbstractMRMessage {
016
017    public static final int MAXSIZE = 515;
018
019    // create a new one
020    public Dcc4PcMessage(int i) {
021        if (i < 1) {
022            log.error("invalid length in call to ctor");
023        }
024        _nDataChars = i;
025        _dataChars = new int[i];
026        setBinary(true);
027        setRetries(3);
028    }
029
030    /**
031     * Creates a new Dcc4PcMessage containing a byte array to represent a packet
032     * to output
033     *
034     * @param packet The contents of the packet
035     */
036    public Dcc4PcMessage(byte[] packet) {
037        this((packet.length));
038        int i = 0; // counter of byte in output message
039        int j; // counter of byte in input packet
040        setBinary(true);
041        // add each byte of the input message
042        for (j = 0; j < packet.length; j++) {
043            this.setElement(i, packet[i]);
044            i++;
045        }
046        setRetries(1);
047    }
048
049    // from String
050    public Dcc4PcMessage(String s) {
051        _nDataChars = s.length();
052        _dataChars = new int[_nDataChars];
053        for (int i = 0; i < _nDataChars; i++) {
054            _dataChars[i] = s.charAt(i);
055        }
056        setBinary(true);
057        setRetries(3);
058    }
059
060    // copy one
061    public Dcc4PcMessage(Dcc4PcMessage m) {
062        if (m == null) {
063            log.error("copy ctor of null message");
064            return;
065        }
066        _nDataChars = m._nDataChars;
067        _dataChars = new int[_nDataChars];
068        for (int i = 0; i < _nDataChars; i++) {
069            _dataChars[i] = m._dataChars[i];
070        }
071        setBinary(true);
072        setRetries(1);
073    }
074
075    public void setForChildBoard(boolean boo) {
076        childBoard = boo;
077    }
078
079    boolean childBoard = false;
080
081    public boolean isForChildBoard() {
082        return childBoard;
083    }
084
085    /** {@inheritDoc} */
086    @Override
087    public void setElement(int n, int v) {
088        _dataChars[n] = v;
089    }
090
091    /** {@inheritDoc} */
092    @Override
093    public String toString() {
094        StringBuilder buf = new StringBuilder();
095        buf.append("0x");
096        buf.append(Integer.toHexString(0xFF & _dataChars[0]));
097        for (int i = 1; i < _nDataChars; i++) {
098            buf.append(".0x");
099            buf.append(Integer.toHexString(0xff & _dataChars[i]));
100            //buf.append(", 0x" + Integer.toHexString(0xFF & _dataChars[i]));
101        }
102        return buf.toString();
103    }
104
105    /**
106     * Get formatted message for direct output to stream - this is the final
107     * format of the message as a byte array
108     *
109     * @return the formatted message as a byte array
110     */
111    public byte[] getFormattedMessage() {
112        int len = this.getNumDataElements();
113        // space for carriage return if required
114        int cr = 0;
115
116        byte msg[] = new byte[len + cr];
117
118        for (int i = 0; i < len; i++) {
119            msg[i] = (byte) this.getElement(i);
120        }
121        return msg;
122    }
123
124    //Not supported
125    static public Dcc4PcMessage getProgMode() {
126        Dcc4PcMessage m = new Dcc4PcMessage(1);
127        //m.setOpCode('+');
128        return m;
129    }
130
131    //Not supported
132    static public Dcc4PcMessage getExitProgMode() {
133        Dcc4PcMessage m = new Dcc4PcMessage(1);
134        // m.setOpCode(' ');
135        return m;
136    }
137
138    boolean isResponse = false;
139
140    public boolean isGetResponse() {
141        return isResponse;
142    }
143    
144    int board = -1;
145    
146    public int getBoard(){
147        return board;
148    }
149    
150    int messageType = -1;
151    public int getMessageType(){
152        return messageType;
153    }
154    
155    static final int INFO = 0x00;
156    static final int DESC = 0x01;
157    static final int SERIAL = 0x02;
158    static final int CHILDENABLEDINPUTS = 0x07;
159    static final int CHILDRESET = 0x09;
160    static final int CHILDPOLL = 0x0a;
161    static final int RESPONSE = 0x0c;
162    
163    static public Dcc4PcMessage getInfo(int address) {
164        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) 0x0b, (byte) address, (byte) INFO});
165        m.childBoard = true;
166        m.board = address;
167        m.messageType = INFO;
168        m.setRetries(2);
169        return m;
170    }
171
172    static public Dcc4PcMessage getDescription(int address) {
173        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) 0x0b, (byte) address, (byte) DESC});
174        m.childBoard = true;
175        m.board = address;
176        m.messageType = DESC;
177        return m;
178    }
179
180    static public Dcc4PcMessage getSerialNumber(int address) {
181        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) 0x0b, (byte) address, (byte) SERIAL});
182        m.childBoard = true;
183        m.board = address;
184        m.messageType = SERIAL;
185        return m;
186    }
187
188    static public Dcc4PcMessage resetBoardData(int address) {
189        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) 0x0b, (byte) address, (byte) CHILDRESET});
190        m.childBoard = true;
191        m.board = address;
192        m.messageType = CHILDRESET;
193        return m;
194    }
195       
196    static public Dcc4PcMessage pollBoard(int address){
197        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) 0x0b, (byte) address, (byte) CHILDPOLL});
198        m.childBoard = true;
199        m.setTimeout(500);
200        m.board = address;
201        m.messageType = CHILDPOLL;
202        return m;
203    }
204
205    static public Dcc4PcMessage getEnabledInputs(int address) {
206        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) 0x0b, (byte) address, (byte) CHILDENABLEDINPUTS});
207        m.childBoard = true;
208        m.board = address;
209        m.messageType = CHILDENABLEDINPUTS;
210        return m;
211    }
212
213    static public Dcc4PcMessage getInfo() {
214        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) INFO});
215        m.messageType = INFO;
216        return m;
217    }
218
219    static public Dcc4PcMessage getResponse() {
220        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) RESPONSE});
221        m.isResponse = true;
222        m.messageType = RESPONSE;
223        return m;
224    }
225
226    static public Dcc4PcMessage getDescription() {
227        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) DESC});
228        m.messageType = DESC;
229        return m;
230    }
231
232    static public Dcc4PcMessage getSerialNumber() {
233        Dcc4PcMessage m = new Dcc4PcMessage(new byte[]{(byte) SERIAL});
234        m.messageType = SERIAL;
235        return m;
236    }
237    
238    private final static Logger log = LoggerFactory.getLogger(Dcc4PcMessage.class);
239}