001package jmri.jmrix.lenz;
002
003import jmri.Programmer;
004import jmri.jmrix.lenz.XNetProgrammer.XNetConfigurator;
005
006/**
007 * XNet specific class to send heartbeat messages to
008 * the XNet.  Heartbeat messages are only required if
009 * no other messages are sent for a specific period
010 * of time, so any outgoing message should restart
011 * the timer.
012 *
013 * @author Paul Bender Copyright (C) 2019
014 */
015public class XNetHeartBeat implements XNetListener {
016
017    private javax.swing.Timer keepAliveTimer; // Timer used to periodically
018    // send a message to both
019    // ports to keep the ports
020    // open
021    private static final int keepAliveTimeoutValue = 30000; // Interval
022    // to send a message
023    // Must be < 60s.
024    private final XNetTrafficController tc;
025    private final XNetSystemConnectionMemo memo;
026
027    public XNetHeartBeat(XNetSystemConnectionMemo memo) {
028        this.memo = memo;
029        tc = memo.getXNetTrafficController();
030        tc.addXNetListener(~0,this);
031        keepAliveTimer();
032    }
033
034    /*
035     * Set up the keepAliveTimer, and start it.
036     */
037    private void keepAliveTimer() {
038        if (keepAliveTimer == null) {
039            keepAliveTimer = new javax.swing.Timer(keepAliveTimeoutValue, e -> {
040                // If the timer times out, and we are not currently
041                // programming, send a request for status
042                XNetConfigurator p = null;
043                if(memo.provides(jmri.GlobalProgrammerManager.class)){
044                    Programmer prog = memo.getProgrammerManager().getGlobalProgrammer();
045                    if (prog != null) {
046                        p = (XNetConfigurator) prog.getConfigurator();
047                    }
048                }
049                if (p == null || !(p.programmerBusy())) {
050                   tc.sendXNetMessage(
051                    XNetMessage.getCSStatusRequestMessage(),
052                    null);
053                }
054            });
055        }
056        keepAliveTimer.stop();
057        keepAliveTimer.setInitialDelay(keepAliveTimeoutValue);
058        keepAliveTimer.setRepeats(true);
059        keepAliveTimer.start();
060    }
061
062    public void dispose(){
063       keepAliveTimer.stop();
064       keepAliveTimer = null;
065    }
066
067    // XNetListener methods.
068
069    /**
070     * {@inheritDoc}
071     */
072    @Override
073    public void message(XNetReply msg){
074        // this class doesn't care about incoming messages.
075    }
076
077    /**
078     * {@inheritDoc}
079     */
080    @Override
081    public void message(XNetMessage msg){
082       // if we see any outgoing message, restart the timer
083       keepAliveTimer.restart();
084    }
085
086    /**
087     * {@inheritDoc}
088     */
089    @Override
090    public void notifyTimeout(XNetMessage msg){
091        // this class doesn't care about timeouts.
092    }
093
094}