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