001package jmri.jmrix.ieee802154.xbee;
002
003import com.digi.xbee.api.exceptions.InterfaceNotOpenException;
004import com.digi.xbee.api.exceptions.TimeoutException;
005import com.digi.xbee.api.exceptions.XBeeException;
006import com.digi.xbee.api.io.IOLine;
007import com.digi.xbee.api.io.IOValue;
008import jmri.Light;
009import jmri.implementation.AbstractLight;
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013/**
014 * Light implementation for XBee systems.
015 *
016 * @author Paul Bender Copyright (C) 2014
017 */
018public class XBeeLight extends AbstractLight {
019
020    private String nodeIdentifier; /* This is a string representation of
021     the XBee address in the system name
022     It may be an address or it may be
023     the NodeIdentifier string stored in
024     the NI parameter on the node.*/
025
026    private XBeeNode node = null; // Which node does this belong too.
027
028    private int address;
029    private int pin;         /* Which DIO pin does this light represent. */
030
031    private String systemName;
032
033    protected XBeeTrafficController tc = null;
034
035    /**
036     * Create a Light object, with system and user names and a reference to the
037     * traffic controller.
038     * @param systemName Xbee system id : pin id
039     * @param userName User friendly name
040     * @param controller tc for connection for this node
041     */
042    public XBeeLight(String systemName, String userName, XBeeTrafficController controller) {
043        super(systemName, userName);
044        tc = controller;
045        init(systemName);
046    }
047
048    public XBeeLight(String systemName, XBeeTrafficController controller) {
049        super(systemName);
050        tc = controller;
051        init(systemName);
052    }
053
054    /**
055     * Common initialization for both constructors
056     */
057    private void init(String id) {
058        // store address
059        systemName = id;
060        jmri.jmrix.ieee802154.IEEE802154SystemConnectionMemo m = tc.getAdapterMemo();
061        if( !(m instanceof XBeeConnectionMemo))
062        {
063           log.error("Memo associated with the traffic controller is not the right type");
064           throw new IllegalArgumentException("Memo associated with the traffic controller is not the right type");
065        } else {
066           XBeeConnectionMemo memo = (XBeeConnectionMemo) m;
067           String prefix = memo.getLightManager().getSystemPrefix();
068           if (systemName.contains(":")) {
069               //Address format passed is in the form of encoderAddress:input or L:light address
070               int seperator = systemName.indexOf(":");
071               try {
072                   nodeIdentifier = systemName.substring(prefix.length() + 1, seperator);
073                   if ((node = (XBeeNode) tc.getNodeFromName(nodeIdentifier)) == null) {
074                       if ((node = (XBeeNode) tc.getNodeFromAddress(nodeIdentifier)) == null) {
075                           try {
076                               node = (XBeeNode) tc.getNodeFromAddress(Integer.parseInt(nodeIdentifier));
077                           } catch (java.lang.NumberFormatException nfe) {
078                               // if there was a number format exception, we couldn't
079                              // find the node.
080                              node = null;
081                          }
082                       }
083                   }
084                   pin = Integer.parseInt(systemName.substring(seperator + 1));
085               } catch (NumberFormatException ex) {
086                   log.debug("Unable to convert {} into the cab and input format of nn:xx", systemName);
087              }
088           } else {
089               try {
090                   nodeIdentifier = systemName.substring(prefix.length() + 1, id.length() - 1);
091                   address = Integer.parseInt(systemName.substring(prefix.length() + 1));
092                   node = (XBeeNode) tc.getNodeFromAddress(address / 10);
093                   // calculate the pin to use.
094                   pin = ((address) % 10);
095               } catch (NumberFormatException ex) {
096                   log.debug("Unable to convert {} Hardware Address to a number", systemName);
097               }
098           }
099           if (log.isDebugEnabled()) {
100               log.debug("Created Light {} (NodeIdentifier {} D{})", systemName, nodeIdentifier, pin);
101           }
102        }
103    }
104
105    @Override
106    protected void doNewState(int oldState, int newState) {
107        try  {
108            if((newState == Light.ON) ) {
109              node.getXBee().setDIOValue(IOLine.getDIO(pin),IOValue.HIGH);
110            } else {
111              node.getXBee().setDIOValue(IOLine.getDIO(pin),IOValue.LOW);
112            }
113        } catch (TimeoutException toe) {
114           log.error("Timeout setting IO line value for light {} on {}",getUserName(),node.getXBee());
115        } catch (InterfaceNotOpenException ino) {
116           log.error("Interface Not Open setting IO line value for light {} on {}",getUserName(),node.getXBee());
117        } catch (XBeeException xbe) {
118           log.error("Error setting IO line value for light {} on {}",getUserName(),node.getXBee());
119        }
120    }
121
122    private final static Logger log = LoggerFactory.getLogger(XBeeLight.class);
123}