001package jmri.jmrix.lenz;
002
003import jmri.JmriException;
004import jmri.managers.AbstractPowerManager;
005
006import org.slf4j.Logger;
007import org.slf4j.LoggerFactory;
008
009/**
010 * PowerManager implementation for controlling layout power.
011 *
012 * @author Bob Jacobsen Copyright (C) 2001
013 * @author Paul Bender Copyright (C) 2003-2010
014 */
015public class XNetPowerManager extends AbstractPowerManager<XNetSystemConnectionMemo> implements XNetListener {
016
017    XNetTrafficController tc;
018
019    public XNetPowerManager(XNetSystemConnectionMemo memo) {
020        super(memo);
021        // connect to the TrafficManager
022        tc = memo.getXNetTrafficController();
023        tc.addXNetListener(XNetInterface.CS_INFO, this);
024        // request the current command station status
025        tc.sendXNetMessage(XNetMessage.getCSStatusRequestMessage(), this);
026    }
027
028    @Override
029    public boolean implementsIdle() {
030        // XPressNet implements idle via the broadcast emergency stop commands. 
031        return true;
032    }
033
034    @Override
035    public void setPower(int v) throws JmriException {
036        int old = power;
037        power = UNKNOWN;
038        checkTC();
039        switch (v) {
040            case ON:
041                // send RESUME_OPS
042                tc.sendXNetMessage(XNetMessage.getResumeOperationsMsg(), this);
043                break;
044            case OFF:
045                // send EMERGENCY_OFF
046                tc.sendXNetMessage(XNetMessage.getEmergencyOffMsg(), this);
047                break;
048            case IDLE:
049                // send EMERGENCY_STOP
050                tc.sendXNetMessage(XNetMessage.getEmergencyStopMsg(), this);
051                break;
052            default:
053                break;
054        }
055        firePowerPropertyChange(old, power);
056    }
057
058    // to free resources when no longer used
059    @Override
060    public void dispose() {
061        tc.removeXNetListener(XNetInterface.CS_INFO, this);
062        tc = null;
063    }
064
065    private void checkTC() throws JmriException {
066        if (tc == null) {
067            throw new JmriException("attempt to use PowerManager after dispose");
068        }
069    }
070
071    // to listen for Broadcast messages related to track power.
072    // There are 5 messages to listen for
073    @Override
074    public void message(XNetReply m) {
075        int old = power;
076        log.debug("Message received: {}", m);
077        if (m.getElement(0) == XNetConstants.CS_INFO
078                && m.getElement(1) == XNetConstants.BC_NORMAL_OPERATIONS) {
079            // First, we check for a "normal operations resumed message"
080            // This indicates the power to the track is ON
081            power = ON;
082        } else if (m.getElement(0) == XNetConstants.CS_INFO
083                && m.getElement(1) == XNetConstants.BC_EVERYTHING_OFF) {
084            // Next, we check for a Track Power Off message
085            // This indicates the power to the track is OFF
086            power = OFF;
087        } else if (m.getElement(0) == XNetConstants.BC_EMERGENCY_STOP
088                && m.getElement(1) == XNetConstants.BC_EVERYTHING_OFF) {
089            // Then, we check for an "Emergency Stop" message
090            // This indicates the track power is ON, but all 
091            // locomotives are stopped
092            power = IDLE;
093        } else if (m.getElement(0) == XNetConstants.CS_INFO
094                && m.getElement(1) == XNetConstants.BC_SERVICE_MODE_ENTRY) {
095            // Next we check for a "Service Mode Entry" message
096            // This indicatse track power is off on the mainline.
097            power = OFF;
098        } else if (m.getElement(0) == XNetConstants.CS_REQUEST_RESPONSE
099                && m.getElement(1) == XNetConstants.CS_STATUS_RESPONSE) {
100            // Finally, we look at for the response to a Command 
101            // Station Status Request
102            int statusByte = m.getElement(2);
103            if ((statusByte & 0x01) == 0x01) {
104                // Command station is in Emergency Off Mode
105                power = OFF;
106            } else if ((statusByte & 0x02) == 0x02) {
107                // Command station is in Emergency Stop Mode
108                power = IDLE;
109            } else if ((statusByte & 0x08) == 0x08) {
110                // Command station is in Service Mode, power to the 
111                // track is off
112                power = OFF;
113            } else if ((statusByte & 0x40) == 0x40) {
114                // Command station is in Power Up Mode, and not yet on
115                power = OFF;
116            } else {
117                power = ON;
118            }
119        }
120        firePowerPropertyChange(old, power);
121    }
122
123    /**
124     * Listen for the messages to the LI100/LI101.
125     * 
126     * @param l the message
127     */
128    @Override
129    public void message(XNetMessage l) {
130    }
131
132    /**
133     * Handle a timeout notification.
134     */
135    @Override
136    public void notifyTimeout(XNetMessage msg) {
137        log.debug("Notified of timeout on message{}", msg);
138    }
139
140    // Initialize logging information
141    private static final Logger log = LoggerFactory.getLogger(XNetPowerManager.class);
142
143}