001package jmri.jmrix.lenz.liusbethernet;
002
003import jmri.jmrix.lenz.LenzCommandStation;
004import jmri.jmrix.lenz.XNetInitializationManager;
005import jmri.jmrix.lenz.XNetNetworkPortController;
006import jmri.jmrix.lenz.XNetTrafficController;
007import jmri.util.zeroconf.ZeroConfClient;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011/**
012 * Provide access to XpressNet via a the Lenz LIUSBEthernet.
013 * <p>
014 * NOTES: By default, the LIUSBEthernet has an IP address of 192.168.0.200
015 * and listens to port 5550. The LIUSBEtherenet disconnects both ports if
016 * there is 60 seconds of inactivity on the port.
017 *
018 * @author Paul Bender (C) 2011-2013
019 */
020public class LIUSBEthernetAdapter extends XNetNetworkPortController {
021
022    static final int COMMUNICATION_TCP_PORT = 5550;
023    static final String DEFAULT_IP_ADDRESS = "192.168.0.200";
024
025    public LIUSBEthernetAdapter() {
026        super();
027        log.debug("Constructor Called");
028        setHostName(DEFAULT_IP_ADDRESS);
029        setPort(COMMUNICATION_TCP_PORT);
030        this.manufacturerName = jmri.jmrix.lenz.LenzConnectionTypeList.LENZ;
031    }
032
033    @Override
034    public void connect() throws java.io.IOException {
035        super.connect();
036        log.debug("openPort called");
037    }
038
039    /**
040     * Can the port accept additional characters?
041     *
042     * @return true if the port is opened
043     */
044    @Override
045    public boolean okToSend() {
046        return ( status() && super.okToSend());
047    }
048
049    @Override
050    public boolean status() {
051        return (opened);
052    }
053
054    /**
055     * Set up all of the other objects to operate with a LIUSB Ethernet
056     * interface.
057     */
058    @Override
059    public void configure() {
060        log.debug("configure called");
061        // connect to a packetizing traffic controller
062        XNetTrafficController packets = (new LIUSBEthernetXNetPacketizer(new LenzCommandStation()));
063        packets.connectPort(this);
064
065        // start operation
066        // packets.startThreads();
067        this.getSystemConnectionMemo().setXNetTrafficController(packets);
068
069        new XNetInitializationManager()
070                .memo(this.getSystemConnectionMemo())
071                .setDefaults()
072                .versionCheck()
073                .setTimeout(30000)
074                .init();
075        new jmri.jmrix.lenz.XNetHeartBeat(this.getSystemConnectionMemo());
076    }
077
078    private boolean mDNSConfigure = false;
079
080    /**
081     * Set whether or not this adapter should be
082     * configured automatically via MDNS.
083     *
084     * @param autoconfig boolean value
085     */
086    @Override
087    public void setMdnsConfigure(boolean autoconfig) {
088        log.debug("Setting LIUSB Ethernet adapter autoconfiguration to: {}", autoconfig);
089        mDNSConfigure = autoconfig;
090    }
091
092    /**
093     * Get whether or not this adapter is configured
094     * to use autoconfiguration via MDNS.
095     *
096     * @return true if configured using MDNS
097     */
098    @Override
099    public boolean getMdnsConfigure() {
100        return mDNSConfigure;
101    }
102
103    /**
104     * Set the server's host name and port
105     * using mdns autoconfiguration.
106     */
107    @Override
108    public void autoConfigure() {
109        log.info("Configuring XpressNet interface via JmDNS");
110        if (getHostName().equals(DEFAULT_IP_ADDRESS)) {
111            setHostName(""); // reset the hostname to none.
112        }
113        String serviceType = Bundle.getMessage("defaultMDNSServiceType");
114        log.debug("Listening for service: {}", serviceType);
115
116        if (mdnsClient == null) {
117            mdnsClient = new ZeroConfClient();
118            mdnsClient.startServiceListener(serviceType);
119        }
120        // leave the wait code below commented out for now.  It
121        // does not appear to be needed for proper ZeroConf discovery.
122        //try {
123        //  synchronized(mdnsClient){
124        //  // we may need to add a timeout here.
125        //  mdnsClient.wait(keepAliveTimeoutValue);
126        //  if(log.isDebugEnabled()) mdnsClient.listService(serviceType);
127        //  }
128        //} catch(java.lang.InterruptedException ie){
129        //  log.error("MDNS auto Configuration failed.");
130        //  return;
131        //}
132        try {
133            // if there is a hostname set, use the host name (which can
134            // be changed) to find the service.
135            String qualifiedHostName = m_HostName
136                    + "." + Bundle.getMessage("defaultMDNSDomainName");
137            setHostAddress(mdnsClient.getServiceOnHost(serviceType,
138                    qualifiedHostName).getHostAddresses()[0]);
139        } catch (java.lang.NullPointerException npe) {
140            // if there is no hostname set, use the service name (which can't
141            // be changed) to find the service.
142            String qualifiedServiceName = Bundle.getMessage("defaultMDNSServiceName")
143                    + "." + serviceType;
144            setHostAddress(mdnsClient.getServicebyAdName(serviceType,
145                    qualifiedServiceName).getHostAddresses()[0]);
146        }
147    }
148
149    ZeroConfClient mdnsClient = null;
150
151    /**
152     * Get the ZeroConf/mDNS advertisement name.
153     * <p>
154     * This value is fixed on the LIUSB-Ethernet, so return the default
155     * value.
156     */
157    @Override
158    public String getAdvertisementName() {
159        return Bundle.getMessage("defaultMDNSServiceName");
160    }
161
162    /**
163     * Get the ZeroConf/mDNS service type.
164     * <p>
165     * This value is fixed on the LIUSB-Ethernet, so return the default
166     * value.
167     */
168    @Override
169    public String getServiceType() {
170        return Bundle.getMessage("defaultMDNSServiceType");
171    }
172
173    private static final Logger log = LoggerFactory.getLogger(LIUSBEthernetAdapter.class);
174
175}