001package jmri.jmrix.mrc; 002 003import java.util.Date; 004import jmri.NmraPacket; 005import jmri.Turnout; 006import jmri.implementation.AbstractTurnout; 007import org.slf4j.Logger; 008import org.slf4j.LoggerFactory; 009 010/** 011 * New MRC implementation of the Turnout interface From Xpa+Modem implementation 012 * of the Turnout interface. 013 * 014 * @author Paul Bender Copyright (C) 2004 015 * @author Martin Wade Copyright (C) 2014 016 * 017 */ 018public class MrcTurnout extends AbstractTurnout implements MrcTrafficListener { 019 020 // Private data member to keep track of what turnout we control. 021 int _number; 022 MrcTrafficController tc = null; 023 String prefix = ""; 024 025 /** 026 * Mrc turnouts use any address allowed as an accessory decoder address on 027 * the particular command station. 028 * @param number turnout address value 029 * @param tc traffic controller for connection 030 * @param p system prefix for connection 031 */ 032 public MrcTurnout(int number, MrcTrafficController tc, String p) { 033 super(p + "T" + number); 034 _number = number; 035 if (_number < NmraPacket.accIdLowLimit || _number > NmraPacket.accIdHighLimit) { 036 throw new IllegalArgumentException("Turnout value: " + _number 037 + " not in the range " + NmraPacket.accIdLowLimit + " to " 038 + NmraPacket.accIdHighLimit); 039 } 040 this.tc = tc; 041 this.prefix = p + "T"; 042 tc.addTrafficListener(MrcInterface.TURNOUTS, this); 043 } 044 045 public int getNumber() { 046 return _number; 047 } 048 049 /** 050 * MRC turnouts can be inverted 051 */ 052 @Override 053 public boolean canInvert() { 054 return true; 055 } 056 057 /** 058 * {@inheritDoc} 059 */ 060 @Override 061 protected void forwardCommandChangeToLayout(int newState) { 062 // sort out states 063 if ((newState & Turnout.CLOSED) != 0) { 064 // first look for the double case, which we can't handle 065 if ((newState & Turnout.THROWN) != 0) { 066 // this is the disaster case! 067 log.error("Cannot command both CLOSED and THROWN {}", newState); // NOI18N 068 return; 069 } else { 070 // send a CLOSED command 071 forwardToCommandStation(!getInverted()); 072 } 073 } else { 074 // send a THROWN command 075 forwardToCommandStation(getInverted()); 076 } 077 } 078 079 void forwardToCommandStation(boolean state) { 080 MrcMessage m = null; 081 if (_number < 1000) { 082 m = MrcMessage.getSwitchMsg(_number, state); 083 } else { 084 m = MrcMessage.getRouteMsg((_number - 1000), state); 085 } 086 tc.sendMrcMessage(m); 087 } 088 089 @Override 090 public void notifyRcv(Date timestamp, MrcMessage m) { 091 if (m.getMessageClass() != MrcInterface.TURNOUTS) { 092 return; 093 } 094 if (m.getAccAddress() != getNumber()) { 095 if (m.getElement(0) == MrcPackets.ROUTECONTROLPACKETCMD) { 096 if ((m.getElement(4) + 1000) == getNumber()) { 097 if (m.getElement(6) == 0x00) { 098 newKnownState(jmri.Turnout.THROWN); 099 } else if (m.getElement(6) == 0x80) { 100 newKnownState(jmri.Turnout.CLOSED); 101 } else { 102 newKnownState(jmri.Turnout.UNKNOWN); 103 } 104 } 105 } 106 return; 107 } 108 newKnownState(m.getAccState()); 109 } 110 111 @Override 112 public void notifyXmit(Date timestamp, MrcMessage m) {/* message(m); */ 113 114 } 115 116 @Override 117 public void notifyFailedXmit(Date timestamp, MrcMessage m) { /*message(m);*/ } 118 119 @Override 120 protected void turnoutPushbuttonLockout(boolean pushButtonLockout) { 121 } 122 123 private final static Logger log = LoggerFactory.getLogger(MrcTurnout.class); 124 125}