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 pin;         /* Which DIO pin does this light represent. */
029
030    protected XBeeTrafficController tc = null;
031
032    /**
033     * Create a Light object, with system and user names and a reference to the
034     * traffic controller.
035     * @param systemName Xbee system id : pin id
036     * @param userName User friendly name
037     * @param controller tc for connection for this node
038     */
039    public XBeeLight(String systemName, String userName, XBeeTrafficController controller) {
040        super(systemName, userName);
041        tc = controller;
042        init(systemName);
043    }
044
045    public XBeeLight(String systemName, XBeeTrafficController controller) {
046        super(systemName);
047        tc = controller;
048        init(systemName);
049    }
050
051    /**
052     * Common initialization for both constructors
053     */
054    private void init(String id) {
055        // store address
056        jmri.jmrix.ieee802154.IEEE802154SystemConnectionMemo m = tc.getAdapterMemo();
057        if( !(m instanceof XBeeConnectionMemo))
058        {
059           log.error("Memo associated with the traffic controller is not the right type");
060           throw new IllegalArgumentException("Memo associated with the traffic controller is not the right type");
061        } else {
062           XBeeConnectionMemo memo = (XBeeConnectionMemo) m;
063           String prefix = memo.getLightManager().getSystemPrefix();
064           if (id.contains(":")) {
065               //Address format passed is in the form of encoderAddress:input or L:light address
066               int seperator = id.indexOf(":");
067               try {
068                   nodeIdentifier = id.substring(prefix.length() + 1, seperator);
069                   if ((node = (XBeeNode) tc.getNodeFromName(nodeIdentifier)) == null) {
070                       if ((node = (XBeeNode) tc.getNodeFromAddress(nodeIdentifier)) == null) {
071                           try {
072                               node = (XBeeNode) tc.getNodeFromAddress(Integer.parseInt(nodeIdentifier));
073                           } catch (java.lang.NumberFormatException nfe) {
074                               // if there was a number format exception, we couldn't
075                              // find the node.
076                              node = null;
077                          }
078                       }
079                   }
080                   pin = Integer.parseInt(id.substring(seperator + 1));
081               } catch (NumberFormatException ex) {
082                   log.debug("Unable to convert {} into the cab and input format of nn:xx", id);
083              }
084           } else {
085               try {
086                   nodeIdentifier = id.substring(prefix.length() + 1, id.length() - 1);
087                   int address = Integer.parseInt(id.substring(prefix.length() + 1));
088                   node = (XBeeNode) tc.getNodeFromAddress(address / 10);
089                   // calculate the pin to use.
090                   pin = ((address) % 10);
091               } catch (NumberFormatException ex) {
092                   log.debug("Unable to convert {} Hardware Address to a number", id);
093               }
094           }
095           if (log.isDebugEnabled()) {
096               log.debug("Created Light {} (NodeIdentifier {} D{})", id, nodeIdentifier, pin);
097           }
098        }
099    }
100
101    @Override
102    protected void doNewState(int oldState, int newState) {
103        try  {
104            if((newState == Light.ON) ) {
105              node.getXBee().setDIOValue(IOLine.getDIO(pin),IOValue.HIGH);
106            } else {
107              node.getXBee().setDIOValue(IOLine.getDIO(pin),IOValue.LOW);
108            }
109        } catch (TimeoutException toe) {
110           log.error("Timeout setting IO line value for light {} on {}",getUserName(),node.getXBee());
111        } catch (InterfaceNotOpenException ino) {
112           log.error("Interface Not Open setting IO line value for light {} on {}",getUserName(),node.getXBee());
113        } catch (XBeeException xbe) {
114           log.error("Error setting IO line value for light {} on {}",getUserName(),node.getXBee());
115        }
116    }
117
118    private final static Logger log = LoggerFactory.getLogger(XBeeLight.class);
119}