001package jmri.jmrix.secsi; 002 003import jmri.Turnout; 004import jmri.implementation.AbstractTurnout; 005import org.slf4j.Logger; 006import org.slf4j.LoggerFactory; 007 008/** 009 * Extend jmri.AbstractTurnout for SECSI serial layouts. 010 * 011 * This object doesn't listen to the SECSI serial communications. This is 012 * because it should be the only object that is sending messages for this 013 * turnout; more than one Turnout object pointing to a single device is not 014 * allowed. 015 * 016 * @author Bob Jacobsen Copyright (C) 2003, 2006, 2007 017 */ 018public class SerialTurnout extends AbstractTurnout { 019 020 private SecsiSystemConnectionMemo memo = null; 021 022 /** 023 * Create a Turnout object, with both system and user names. 024 * <p> 025 * 'systemName' was previously validated in SerialTurnoutManager. 026 * @param systemName turnout system name 027 * @param userName turnout user name 028 * @param _memo system connection 029 */ 030 public SerialTurnout(String systemName, String userName, SecsiSystemConnectionMemo _memo) { 031 super(systemName, userName); 032 memo = _memo; 033 // Save system Name 034 tSystemName = systemName; 035 // Extract the Bit from the name 036 tBit = SerialAddress.getBitFromSystemName(systemName, memo.getSystemPrefix()); 037 } 038 039 /** 040 * {@inheritDoc} 041 * Sends a Secsi command 042 */ 043 @Override 044 protected void forwardCommandChangeToLayout(int newState) { 045 // implementing classes will typically have a function/listener to get 046 // updates from the layout, which will then call 047 // public void firePropertyChange(String propertyName, 048 // Object oldValue, Object newValue) 049 // _once_ if anything has changed state (or set the commanded state directly) 050 051 // sort out states 052 if ((newState & Turnout.CLOSED) != 0) { 053 // first look for the double case, which we can't handle 054 if ((newState & Turnout.THROWN) != 0) { 055 // this is the disaster case! 056 log.error("Cannot command both CLOSED and THROWN {}", newState); 057 return; 058 } else { 059 // send a CLOSED command 060 sendMessage(getInverted()); 061 } 062 } else { 063 // send a THROWN command 064 sendMessage(!getInverted()); 065 } 066 } 067 068 @Override 069 protected void turnoutPushbuttonLockout(boolean _pushButtonLockout) { 070 log.debug("Send command to {} Pushbutton", (_pushButtonLockout ? "Lock" : "Unlock")); 071 } 072 073 @Override 074 public void dispose() { 075 // no connections need to be broken 076 super.dispose(); 077 } 078 079 // data members 080 String tSystemName; // System Name of this turnout 081 int tBit; // bit number of turnout control in Serial node 082 083 protected void sendMessage(boolean closed) { 084 SerialNode tNode = SerialAddress.getNodeFromSystemName(tSystemName, memo.getTrafficController()); 085 if (tNode == null) { 086 // node does not exist, ignore call 087 return; 088 } 089 tNode.setOutputBit(tBit, closed); 090 } 091 092 private final static Logger log = LoggerFactory.getLogger(SerialTurnout.class); 093 094}