001package jmri.jmrix.ieee802154;
002
003import jmri.jmrix.AbstractMRListener;
004import jmri.jmrix.AbstractMRMessage;
005import jmri.jmrix.AbstractNode;
006import org.slf4j.Logger;
007import org.slf4j.LoggerFactory;
008
009/**
010 * Basic implementation of a node for IEEE 802.15.4 networks.
011 * <p>
012 * Integrated with {@link IEEE802154TrafficController}.
013 * <p>
014 * Each node has 3 addresses associated with it:
015 * <ol>
016 * <li>A 16 bit PAN (Personal Area Network) ID assigned by the user</li>
017 * <li>A 16 bit User Assigned Address</li>
018 * <li>A 64 bit Globally Unique ID assigned by the manufacturer</li>
019 * </ol>
020 * <p>
021 * All nodes in a given network must have the same PAN ID
022 *
023 * @author Paul Bender Copyright 2013
024 */
025public abstract class IEEE802154Node extends AbstractNode {
026
027    /**
028     * Creates a new instance of AbstractNode
029     */
030    public IEEE802154Node() {
031    }
032
033    public IEEE802154Node(byte pan[], byte user[], byte global[]) {
034        panaddress = pan;
035        useraddress = user;
036        globaladdress = global;
037        setNodeAddress((user[0] << 8) + ( user[1] & 0xff) );
038    }
039
040    protected byte panaddress[] = {0, 0}; // default pan address to 0
041    protected byte useraddress[] = {0, 0}; // default user address to 0
042    protected byte globaladdress[] = {0, 0, 0, 0, 0, 0, 0, 0}; // default global address to 0
043
044    /**
045     * Public method to set the node address. Address range is checked in
046     * subclasses.
047     *
048     * @throws IllegalArgumentException if out of range
049     */
050    @Override
051    public void setNodeAddress(int address) {
052        if (checkNodeAddress(address)) {
053            nodeAddress = address;
054        } else {
055            log.error("illegal node address: {}", Integer.toString(address));
056            nodeAddress = 0;
057            throw new IllegalArgumentException("Attempt to set address to invalid value: " + address);
058        }
059    }
060
061    /**
062     * Check for valid address with respect to range, etc.
063     *
064     * @return true if valid
065     */
066    @Override
067    protected boolean checkNodeAddress(int address) {
068        // we're not using this address directly, so ignore.
069        return true;
070    }
071
072    /**
073     * Set PAN address.
074     *
075     * @param addr byte array containing upper and lower bytes of the 16 bit PAN
076     *             address.
077     */
078    public void setPANAddress(byte addr[]) {
079        for (int i = 0; i < panaddress.length; i++) {
080            panaddress[i] = addr[i];
081        }
082    }
083
084    /**
085     * Get the PAN address
086     *
087     * @return byte array containing the upper and lower bytes of the PAN
088     *         address
089     */
090    public byte[] getPANAddress() {
091        return panaddress;
092    }
093
094    /**
095     * Set User address.
096     *
097     * @param addr byte array containing upper and lower bytes of the 16 bit
098     *             user assigned address.
099     */
100    public void setUserAddress(byte addr[]) {
101        for (int i = 0; i < useraddress.length; i++) {
102            useraddress[i] = addr[i];
103        }
104    }
105
106    /**
107     * Get the User address
108     *
109     * @return byte array containing the upper and lower bytes of the User
110     *         assigned address
111     */
112    public byte[] getUserAddress() {
113        return useraddress;
114    }
115
116    /**
117     * Set global address.
118     *
119     * @param addr byte array containing bytes of the 64 bit global address.
120     */
121    public void setGlobalAddress(byte addr[]) {
122        for (int i = 0; i < globaladdress.length; i++) {
123            globaladdress[i] = addr[i];
124        }
125    }
126
127    /**
128     * Get the Global address
129     *
130     * @return byte array containing the 8 bytes of the global address
131     */
132    public byte[] getGlobalAddress() {
133        return globaladdress;
134    }
135
136    /**
137     * Create the needed Initialization packet (AbstractMRMessage) for this
138     * node. Returns null if not needed.
139     */
140    @Override
141    abstract public AbstractMRMessage createInitPacket();
142
143    /**
144     * Create an Transmit packet (AbstractMRMessage) to send current state
145     */
146    @Override
147    abstract public AbstractMRMessage createOutPacket();
148
149    /**
150     * Are there sensors present, and hence this node will need to be polled?
151     * Note: returns 'true' if at least one sensor is active for this node
152     */
153    @Override
154    abstract public boolean getSensorsActive();
155
156    /**
157     * Deal with a timeout in the transmission controller.
158     *
159     * @param m message that didn't receive a reply
160     * @param l listener that sent the message
161     * @return true if initialization required
162     */
163    @Override
164    abstract public boolean handleTimeout(AbstractMRMessage m, AbstractMRListener l);
165
166    /**
167     * A reply was received, so there was not timeout, do any needed processing.
168     */
169    @Override
170    abstract public void resetTimeout(AbstractMRMessage m);
171
172    /**
173     * Return state of needSend flag.
174     */
175    @Override
176    public boolean mustSend() {
177        return needSend;
178    }
179
180    /**
181     * Public to reset state of needSend flag. Subclasses may override to
182     * enforce conditions.
183     */
184    @Override
185    public void resetMustSend() {
186        needSend = false;
187    }
188
189    /**
190     * Public to set state of needSend flag.
191     */
192    @Override
193    public void setMustSend() {
194        needSend = true;
195    }
196
197    boolean needSend = true;          // 'true' if something has changed that requires data to be sent
198
199    private final static Logger log = LoggerFactory.getLogger(IEEE802154Node.class);
200
201}