001package jmri.jmrix.oaktree;
002
003import jmri.util.StringUtil;
004
005/**
006 * Contains the data payload of a serial packet.
007 * <p>
008 * Note that <i>only</i> the payload, not the header or trailer, nor the padding
009 * DLE characters are included. These are added during transmission.
010 *
011 * @author Bob Jacobsen Copyright (C) 2001,2003, 2006
012 */
013public class SerialMessage extends jmri.jmrix.AbstractMRMessage {
014    // is this logically an abstract class?
015
016    public SerialMessage(int l) {
017        super(5);  // all OakTree messages are five bytes
018        setResponseLength(l);
019        setBinary(true);
020    }
021
022    // copy one
023    public SerialMessage(SerialMessage m, int l) {
024        super(m);
025        setResponseLength(l);
026        setBinary(true);
027    }
028
029    /**
030     * Interpret the String as the exact sequence to send,
031     * byte-for-byte.
032     * @param m message string.
033     * @param l response length.
034     */
035    public SerialMessage(String m, int l) {
036        super(m);
037        setResponseLength(l);
038        setBinary(true);
039    }
040
041    /**
042     * Interpret the byte array as a sequence of characters to send.
043     * @deprecated 5.13.5, unused, requires further development.
044     * @param a Array of bytes to send
045     * @param l response length.
046     */
047    @Deprecated( since="5.13.5", forRemoval=true)
048    public SerialMessage(byte[] a, int l) {
049        // super(String.valueOf(a)); // Spotbug toString on array
050        // requires further development to produce correct values for hardware type.
051        super(StringUtil.hexStringFromBytes(a).replaceAll("\\s", ""));
052        setResponseLength(l);
053        setBinary(true);
054    }
055
056    int responseLength = -1;  // -1 is an invalid value, indicating it hasn't been set
057
058    public void setResponseLength(int l) {
059        responseLength = l;
060    }
061
062    public int getResponseLength() {
063        return responseLength;
064    }
065
066    /**
067     * Override parent method to ensure that message always has valid error
068     * check byte.
069     */
070    @Override
071    public void setElement(int element, int value) {
072        super.setElement(element, value);
073        int ecb = getElement(0) ^ getElement(1) ^ getElement(2) ^ getElement(3);
074        super.setElement(4, ecb);
075    }
076
077    // static methods to recognize a message
078    public boolean isPoll() {
079        return getElement(1) == 48;
080    }
081
082    public boolean isXmt() {
083        return getElement(1) == 17;
084    }
085
086    public int getAddr() {
087        return getElement(0);
088    }
089
090    // static methods to return a formatted message
091    static public SerialMessage getPoll(int addr) {
092        // eventually this will have to include logic for reading
093        // various bytes on the card, but our supported
094        // cards don't require that yet
095        SerialMessage m = new SerialMessage(5);
096        m.setElement(0, addr);
097        m.setElement(1, 48);  // read processed data
098        m.setElement(2, 0);  // read first two bytes
099        m.setElement(3, 0);
100        m.setTimeout(SHORT_TIMEOUT);    // minumum reasonable timeout
101        return m;
102    }
103
104}