001package jmri.jmrix.srcp;
002
003import jmri.Sensor;
004import jmri.implementation.AbstractSensor;
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007
008/**
009 * SRCPSensor implementation of the Sensor interface.
010 *
011 * @author Bob Jacobsen Copyright (C) 2001, 2008
012 * @author Paul Bender Copyright (C) 2010
013 */
014public class SRCPSensor extends AbstractSensor implements SRCPListener {
015
016    // data members
017    private final int _number;   // sensor number
018    private final int _bus;      // bus number
019    private SRCPTrafficController tc = null;
020
021    /**
022     * SRCP sensors use the sensor number on the remote host.
023     *
024     * @param number sensor number on remote host
025     * @param memo   associated connection memo
026     */
027    public SRCPSensor(int number, SRCPBusConnectionMemo memo) {
028        super(memo.getSystemPrefix() + "S" + number);
029        _number = number;
030        _bus = memo.getBus();
031        tc = memo.getTrafficController();
032        // At construction, register for messages
033        tc.addSRCPListener(this);
034        // Then request status.
035        requestUpdateFromLayout();
036    }
037
038    public int getNumber() {
039        return _number;
040    }
041
042    /** Handle a request to change state by sending a formatted packet
043     * to the server.
044     */
045    @Override
046    public void setKnownState(int newState) throws jmri.JmriException {
047        // sort out states
048        if ((newState & Sensor.ACTIVE) != 0) {
049            // first look for the double case, which we can't handle
050            if ((newState & Sensor.INACTIVE) != 0) {
051                // this is the disaster case!
052                log.error("Cannot command both ACTIVE and INACTIVE {}", newState);
053                return;
054            } else {
055                // send an ACTIVE command
056                sendMessage(!getInverted());
057            }
058        } else {
059            // send a INACTIVE command
060            sendMessage(getInverted());
061        }
062        if (_knownState != newState) {
063            int oldState = _knownState;
064            _knownState = newState;
065            firePropertyChange("KnownState", oldState, _knownState);
066        }
067    }
068
069    @Override
070    public void requestUpdateFromLayout() {
071        // get the message text
072        String text = "GET " + _bus + " FB " + _number + "\n";
073
074        // create and send the message itself
075        tc.sendSRCPMessage(new SRCPMessage(text), this);
076    }
077
078    protected void sendMessage(boolean active) {
079        // get the message text
080        String text;
081        if (active) {
082            text = "SET " + _bus + " FB " + _number + " 1\n";
083        } else // thrown
084        {
085            text = "SET " + _bus + " FB " + _number + " 0\n";
086        }
087
088        // create and send the message itself
089        tc.sendSRCPMessage(new SRCPMessage(text), this);
090    }
091
092    // to listen for status changes from SRCP system
093    @Override
094    public void reply(SRCPReply m) {
095        String message = m.toString();
096        log.debug("Message Received: {}", m);
097        if (!message.contains(_bus + " FB " + _number)) {
098            return; // not for us
099        }
100        if (m.toString().contains(_bus + " FB " + _number + " 0")) {
101            setOwnState(!getInverted() ? jmri.Sensor.INACTIVE : jmri.Sensor.ACTIVE);
102        } else if (m.toString().contains(_bus + " FB " + _number + " 1")) {
103            setOwnState(!getInverted() ? jmri.Sensor.ACTIVE : jmri.Sensor.INACTIVE);
104        } else {
105            setOwnState(jmri.Sensor.UNKNOWN);
106        }
107    }
108
109    @Override
110    public void reply(jmri.jmrix.srcp.parser.SimpleNode n) {
111        if (log.isDebugEnabled()) {
112            log.debug("reply called with simpleNode {}", n.jjtGetValue());
113        }
114        //if( n.jjtGetChild(3) instanceof jmri.jmrix.srcp.parser.ASTfb )
115        reply(new SRCPReply(n));
116    }
117
118    @Override
119    public void message(SRCPMessage m) {
120    }
121
122    private final static Logger log = LoggerFactory.getLogger(SRCPSensor.class);
123
124}