001/**
002 * DCCppPowerManager.java
003 *
004 * PowerManager implementation for controlling layout power
005 *
006 * @author Bob Jacobsen Copyright (C) 2001
007 * @author Paul Bender Copyright (C) 2003-2010
008 * @author Mark Underwood Copyright (C) 2015
009  *
010 * Based on XNetPowerManager by Bob Jacobsen and Paul Bender
011 */
012package jmri.jmrix.dccpp;
013
014import jmri.JmriException;
015import jmri.managers.AbstractPowerManager;
016
017import org.slf4j.Logger;
018import org.slf4j.LoggerFactory;
019
020public class DCCppPowerManager extends AbstractPowerManager<DCCppSystemConnectionMemo> implements DCCppListener {
021
022    DCCppTrafficController tc = null;
023
024    public DCCppPowerManager(DCCppSystemConnectionMemo memo) {
025        super(memo);
026        // connect to the TrafficManager
027        tc = memo.getDCCppTrafficController();
028        tc.addDCCppListener(DCCppInterface.CS_INFO, this);
029        // request the current command station status
030        tc.sendDCCppMessage(DCCppMessage.makeCSStatusMsg(), this);
031        // request the trackmanager configuration
032        tc.sendDCCppMessage(DCCppMessage.makeTrackManagerRequestMsg(), this);
033    }
034
035    @Override
036    public void setPower(int v) throws JmriException {
037        int old = power;
038        power = UNKNOWN;
039        checkTC();
040        if (v == ON) {
041            // send TRACK_POWER_ON
042            tc.sendDCCppMessage(DCCppMessage.makeTrackPowerOnMsg(), this);
043        } else if (v == OFF) {
044            // send TRACK_POWER_OFF
045            tc.sendDCCppMessage(DCCppMessage.makeTrackPowerOffMsg(), this);
046        }
047        firePowerPropertyChange(old, power);
048    }
049
050    // to free resources when no longer used
051    @Override
052    public void dispose() throws JmriException {
053        tc.removeDCCppListener(DCCppInterface.CS_INFO, this);
054        tc = null;
055    }
056
057    private void checkTC() throws JmriException {
058        if (tc == null) {
059            throw new JmriException("attempt to use PowerManager after dispose");
060        }
061    }
062
063    // listen for power and status messages
064    @Override
065    public void message(DCCppReply m) {
066        if (m.isPowerReply()) {
067            log.debug("Power Reply message received: {}", m);
068            int old = power;
069            if (m.getPowerBool()) {
070                power = ON;
071            } else {
072                power = OFF;
073            }
074            firePowerPropertyChange(old, power);
075
076        // if status reply 's', then update the command station info (version, etc.)
077        } else if (m.isStatusReply()) {
078            log.debug("Version Info Received: {}", m);
079            tc.getCommandStation().setCommandStationInfo(m);
080        
081        // store trackmanager mode by index (0-7 for A-H) 
082        } else if (m.isTrackManagerReply()) {
083            log.debug("Track Manager Reply Received: {}", m);
084            int trackNum = m.getTrackManagerLetter() - 'A'; //get track number from track letter
085            tc.getCommandStation().setTrackMode(trackNum, m.getTrackManagerMode());
086        }
087    }
088
089    // listen for the messages to the CommandStation
090    @Override
091    public void message(DCCppMessage l) {
092    }
093
094    // Handle message timeout notification
095    // If the message still has retries available, reduce retries and send it back to the traffic controller.
096    @Override
097    public void notifyTimeout(DCCppMessage msg) {
098        log.debug("Notified of timeout on message '{}' , {} retries available.", msg, msg.getRetries());
099        if (msg.getRetries() > 0) {
100            msg.setRetries(msg.getRetries() - 1);
101            tc.sendDCCppMessage(msg, this);
102        }        
103    }
104
105    // Initialize logging information
106    private final static Logger log = LoggerFactory.getLogger(DCCppPowerManager.class);
107
108}
109
110
111