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}