001package jmri.jmrix.ieee802154;
002
003import jmri.util.StringUtil;
004
005/**
006 * Contains the data payload of an IEEE 802.15.4 packet.
007 *
008 * @author Bob Jacobsen Copyright (C) 2001,2003, 2006, 2007, 2008 Converted to
009 * multiple connection
010 * @author kcameron Copyright (C) 2011 Modified for IEEE 802.15.4 connection
011 * @author Paul Bender Copyright (C) 2013
012 */
013public class IEEE802154Message extends jmri.jmrix.AbstractMRMessage {
014
015    /**
016     * Suppress the default ctor, as the length must always be specified
017     */
018    protected IEEE802154Message() {
019    }
020
021    public IEEE802154Message(int l) {
022        super(l);
023        setResponseLength(0);  // only polls require a response
024        setBinary(true);
025        setTimeout(5000);
026    }
027
028    /**
029     * This ctor interprets the String as the exact sequence to send,
030     * byte-for-byte.
031     * @param m msg to send
032     * @param l length of expected response (not used)
033     *
034     */
035    public IEEE802154Message(String m, int l) {
036        super(m);
037        //setResponseLength(l);
038        setBinary(true);
039        setTimeout(5000);
040        // gather bytes in result
041        byte b[] = jmri.util.StringUtil.bytesFromHexString(m);
042        if (b.length == 0) {
043            // no such thing as a zero-length message
044            _nDataChars = 0;
045            _dataChars = null;
046            return;
047        }
048        _nDataChars = b.length;
049        _dataChars = new int[_nDataChars];
050        for (int i = 0; i < b.length; i++) {
051            setElement(i, b[i]);
052        }
053    }
054
055    /**
056     * This ctor interprets the byte array as a sequence of characters to send.
057     * @deprecated 5.13.5, unused, requires further development.
058     * @param a Array of bytes to send
059     * @param l length of expected response
060     */
061    @Deprecated( since="5.13.5", forRemoval=true)
062    public IEEE802154Message(byte[] a, int l) {
063        // super(String.valueOf(a)); // Spotbug toString on array
064        // requires further development to produce correct values for hardware type.
065        super(StringUtil.hexStringFromBytes(a).replaceAll("\\s", ""));
066        setResponseLength(l);
067        setBinary(true);
068        setTimeout(5000);
069    }
070
071    /**
072     * Check whether the message has a valid parity IEEE 802.15.4 messages have
073     * a two byte parity.
074     * @return true if parity is valid
075     */
076    public boolean checkParity() {
077        int len = getNumDataElements();
078        int chksum = 0x0000;  /* the seed */
079
080        int loop;
081
082        for (loop = 0; loop < len - 1; loop = loop + 2) {  // calculate contents for data part
083            chksum ^= (getElement(loop) << 8);
084            chksum ^= getElement(loop + 1);
085        }
086        return ((chksum & 0xFFFF) == ((getElement(len - 2) << 8) + getElement(len - 1)));
087    }
088
089    public void setParity() {
090        int len = getNumDataElements();
091        int chksum = 0x00;  /* the seed */
092
093        int loop;
094
095        for (loop = 0; loop < len - 1; loop++) {  // calculate contents for data part
096            chksum ^= (getElement(loop) << 8);
097            chksum ^= getElement(loop + 1);
098        }
099        setElement(len - 1, chksum & 0xFF);
100        setElement(len - 2, ((chksum & 0xFF00) >> 8));
101    }
102
103    int responseLength = -1;  // -1 is an invalid value, indicating it hasn't been set
104
105    public void setResponseLength(int l) {
106        responseLength = l;
107    }
108
109    public int getResponseLength() {
110        return responseLength;
111    }
112
113}
114