001package jmri.jmrix.ieee802154.xbee;
002
003import com.digi.xbee.api.RemoteXBeeDevice;
004import com.digi.xbee.api.XBeeNetwork;
005import com.digi.xbee.api.listeners.IDiscoveryListener;
006import com.digi.xbee.api.models.DiscoveryOptions;
007import java.util.EnumSet;
008import java.util.List;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012
013/*
014 * The Node Manager checks incoming messages for node discovery 
015 * response packets.  If a node is discovered, it is added to the traffic
016 * controller's node list.
017 *
018 * @author Paul Bender Copyright(C) 2012,2016
019 */
020public class XBeeNodeManager implements IDiscoveryListener {
021
022    private final XBeeTrafficController xtc;
023    private XBeeNetwork xbeeNetwork = null;
024
025    public XBeeNodeManager(XBeeTrafficController tc) {
026        xtc = tc;
027        startNodeDiscovery();
028    }
029
030    /*
031     * Send out a node discovery request.
032     */
033    public void startNodeDiscovery() {
034       log.info("Starting XBee Node Discovery Process");
035       xbeeNetwork = xtc.getXBee().getNetwork();
036
037       try {
038          log.debug("configuring discovery timeout");
039          // set the discovery timeout
040          // setting the timeout hangs the network on XBee Series 1
041          xbeeNetwork.setDiscoveryTimeout(2000);
042          
043          log.debug("setting discovery options");
044          // set options
045          // Append the device type identifier and the local device to the
046          // network information.
047          xbeeNetwork.setDiscoveryOptions(EnumSet.of(DiscoveryOptions.APPEND_DD,DiscoveryOptions.DISCOVER_MYSELF));
048       } catch (com.digi.xbee.api.exceptions.TimeoutException te ) {
049         log.debug("timeout during discovery process setup");
050       } catch (com.digi.xbee.api.exceptions.XBeeException xbe) {
051         log.error("exception during discovery process setup");
052       }
053
054       // add this class as a listener for node discovery.
055       log.debug("adding Listener for discovery results");
056       xbeeNetwork.addDiscoveryListener(this);
057
058       // and start the discovery process.
059       xbeeNetwork.startDiscoveryProcess();
060       log.debug("Discovery Process started");
061    }
062
063    /*
064     * @return true if the network discovery process is running
065     */
066    public boolean isDiscoveryRunning(){
067       if (xbeeNetwork == null) {
068          return false;
069       }
070       return xbeeNetwork.isDiscoveryRunning();
071    }
072
073    /*
074     * Stop the discovery process, if it is running.
075     */
076    public void stopNodeDiscovery() {
077      if (isDiscoveryRunning()) {
078         xbeeNetwork.stopDiscoveryProcess();
079      }
080    }
081
082    // IDiscoveryListener interface methods
083    
084    /*
085     * Device discovered callback.
086     */
087    @Override
088    public void deviceDiscovered(RemoteXBeeDevice discoveredDevice){
089        log.debug("New Device discovered {}", discoveredDevice.toString());
090    }
091
092    /*
093     * Discovery error callback.
094     */
095    @Override
096    public void discoveryError(String error){
097        log.error("Error during node discovery process: {}", error);
098    }
099
100    /*
101     * Discovery finished callback.
102     */
103    @Override
104    public void discoveryFinished(String error){
105       if (error != null) {
106         log.error("Node discovery processed finished with error: {}", error);
107       } else {
108         log.info("Node discovery process completed successfully with {} devices discovered", xbeeNetwork.getNumberOfDevices());
109         // retrieve the node list from the network.
110         List<RemoteXBeeDevice> nodeList = xbeeNetwork.getDevices();
111
112         // add the previously unknown nodes to the network.
113
114         for (RemoteXBeeDevice device :nodeList ) {
115             XBeeNode node = (XBeeNode) xtc.getNodeFromXBeeDevice(device);
116
117             if (node == null) {
118                // the node does not exist, we're adding a new one.
119                try {
120                   node = new XBeeNode(device);
121                   // register the node with the traffic controller
122                   xtc.registerNode(node);
123                } catch(com.digi.xbee.api.exceptions.TimeoutException t){
124                  log.error("Timeout registering device {}",device);
125                } catch(com.digi.xbee.api.exceptions.XBeeException e) {
126                  log.error("Exception registering device {}",device);
127                }
128             }
129         }
130
131         // and remove this class from the list of discovery listeners.
132
133         // removing the listener here is causing a 
134         // ConcurrentModificationException on an ArrayList in the library.
135         // xbeeNetwork.removeDiscoveryListener(this);
136       }
137    }
138
139    private static final Logger log = LoggerFactory.getLogger(XBeeNodeManager.class);
140
141}