001package jmri.jmrix.roco.z21;
002
003import java.net.DatagramSocket;
004import java.util.ResourceBundle;
005import jmri.jmrix.ConnectionStatus;
006import org.slf4j.Logger;
007import org.slf4j.LoggerFactory;
008
009/**
010 * Adapter representing a Z21 communication port.
011 * <p>
012 * Note: This connection uses UDP for communication.
013 *
014 * @author Bob Jacobsen Copyright (C) 2001, 2008
015 * @author Paul Bender Copyright (C) 2004,2010,2011,2014
016 */
017public class Z21Adapter extends jmri.jmrix.AbstractNetworkPortController {
018
019    protected static ResourceBundle rb =  ResourceBundle.getBundle("jmri.jmrix.roco.z21.z21AdapterConfigurationBundle");
020    protected static int COMMUNICATION_UDP_PORT = java.lang.Integer.parseInt(rb.getString("z21UDPPort1"));
021    protected static String DEFAULT_IP_ADDRESS = rb.getString("defaultZ21IPAddress");
022
023    private DatagramSocket socket = null;
024
025    public Z21Adapter() {
026        super(new Z21SystemConnectionMemo());
027        setHostName(DEFAULT_IP_ADDRESS);
028        setPort(COMMUNICATION_UDP_PORT);
029        allowConnectionRecovery = true; // all classes derived from this class
030        // can recover from a connection failure
031
032    }
033
034    /**
035     * Configure all of the other jmrix widgets needed to work with this adapter
036     */
037    @Override
038    public void configure() {
039        if (log.isDebugEnabled()) {
040            log.debug("configure called");
041        }
042        // connect to a packetizing traffic controller
043        Z21TrafficController packets = new Z21TrafficController();
044        packets.connectPort(this);
045
046        // start operation
047        this.getSystemConnectionMemo().setTrafficController(packets);
048        this.getSystemConnectionMemo().configureManagers();
049    }
050
051    @Override
052    public void connect() throws java.io.IOException {
053        opened = false;
054        if (getHostAddress() == null || m_port == 0) {
055            log.error("No host name or port set : {}:{}", m_HostName, m_port);
056            return;
057        }
058        try {
059            socket = new DatagramSocket();
060            opened = true;
061        } catch (java.net.SocketException se) {
062            log.error("Socket Exception creating connection.");
063            ConnectionStatus.instance().setConnectionState(
064                    this.getSystemConnectionMemo(),
065                    ConnectionStatus.CONNECTION_DOWN);
066            throw (se);
067        }
068        if (opened) {
069            ConnectionStatus.instance().setConnectionState(
070                    this.getSystemConnectionMemo(),
071                    ConnectionStatus.CONNECTION_UP);
072        }
073
074    }
075
076    /**
077     * @return the DatagramSocket of this connection.  Returns null
078     *         if not connected.
079     */
080    public DatagramSocket getSocket() {
081        return socket;
082    }
083
084    /**
085     * Check that this object is ready to operate. This is a question of
086     * configuration, not transient hardware status.
087     */
088    @Override
089    public boolean status() {
090        return opened;
091    }
092
093    @Override
094    public Z21SystemConnectionMemo getSystemConnectionMemo() {
095        return (Z21SystemConnectionMemo) super.getSystemConnectionMemo();
096    }
097
098    /**
099     * Customizable method to deal with resetting a system connection after a
100     * successful recovery of a connection.
101     */
102    @Override
103    protected void resetupConnection() {
104        // UDP connection is re-established for each message.
105    }
106
107    @Override
108    public void dispose(){
109       super.dispose();
110       if (opened) {
111          socket.close();
112       }
113       opened = false;
114       allowConnectionRecovery = false; // disposing of the object should
115                                        // result in not allowing reconnection.
116    }
117
118    private static final Logger log = LoggerFactory.getLogger(Z21Adapter.class);
119
120}