001package jmri.jmrix.lenz; 002 003import java.util.EnumSet; 004import java.util.HashMap; 005import jmri.LocoAddress; 006import jmri.SpeedStepMode; 007import jmri.jmrix.AbstractThrottleManager; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011/** 012 * XNet implementation of a ThrottleManager based on the 013 * AbstractThrottleManager. 014 * 015 * @author Paul Bender Copyright (C) 2002-2004 016 * @navassoc 1 - * jmri.jmrix.lenz.XNetThrottle 017 */ 018public class XNetThrottleManager extends AbstractThrottleManager implements XNetListener { 019 020 protected final HashMap<LocoAddress, XNetThrottle> throttles = new HashMap<>(5); 021 022 protected XNetTrafficController tc; 023 024 /** 025 * Constructor. 026 * @param memo system connection. 027 */ 028 public XNetThrottleManager(XNetSystemConnectionMemo memo) { 029 super(memo); 030 // connect to the TrafficManager 031 tc = memo.getXNetTrafficController(); 032 033 // Register to listen for throttle messages 034 tc.addXNetListener(XNetInterface.THROTTLE, this); 035 } 036 037 /** 038 * Request a new throttle object be creaetd for the address, and let the 039 * throttle listeners know about it. 040 */ 041 @Override 042 public void requestThrottleSetup(LocoAddress address, boolean control) { 043 XNetThrottle throttle; 044 if (log.isDebugEnabled()) { 045 log.debug("Requesting Throttle: {}", address); 046 } 047 // range check for LH200 and Compact/Commander 048 if (tc.getCommandStation().getCommandStationType() == 0x01 || 049 tc.getCommandStation().getCommandStationType() == 0x02 ) { 050 if(address.getNumber()>=100) { 051 String typeString = Bundle.getMessage(tc.getCommandStation().getCommandStationType() == 0x01?"CSTypeLH200":"CSTypeCompact"); 052 failedThrottleRequest(address,Bundle.getMessage("ThrottleErrorCSTwoDigit",typeString)); 053 return; 054 } 055 } 056 if (throttles.containsKey(address)) { 057 notifyThrottleKnown(throttles.get(address), address); 058 } else { 059 throttle = new XNetThrottle((XNetSystemConnectionMemo) adapterMemo, address, tc); 060 throttles.put(address, throttle); 061 notifyThrottleKnown(throttle, address); 062 } 063 } 064 065 /** 066 * XpressNet based systems DO NOT use the Dispatch Function. 067 */ 068 @Override 069 public boolean hasDispatchFunction() { 070 return false; 071 } 072 073 /** 074 * XpressNet based systems can have multiple throttles for the same 075 * device. 076 * <p> 077 * {@inheritDoc} 078 */ 079 @Override 080 protected boolean singleUse() { 081 return false; 082 } 083 084 /** 085 * Address 100 and above is a long address. 086 */ 087 @Override 088 public boolean canBeLongAddress(int address) { 089 return isLongAddress(address); 090 } 091 092 /** 093 * Address 99 and below is a short address. 094 */ 095 @Override 096 public boolean canBeShortAddress(int address) { 097 return !isLongAddress(address); 098 } 099 100 /** 101 * Are there any ambiguous addresses (short vs long) on this system? 102 */ 103 @Override 104 public boolean addressTypeUnique() { 105 return true; 106 } 107 108 /** 109 * Local method for deciding short/long address 110 * @param num address to examine 111 * @return true if can be long address 112 */ 113 static protected boolean isLongAddress(int num) { 114 return (num >= 100); 115 } 116 117 /** 118 * What speed modes are supported by this system? value should be xor of 119 * possible modes specifed by the DccThrottle interface XpressNet supports 120 * 14,27,28 and 128 speed step modes 121 */ 122 @Override 123 public EnumSet<SpeedStepMode> supportedSpeedModes() { 124 return EnumSet.of(SpeedStepMode.NMRA_DCC_128 125 , SpeedStepMode.NMRA_DCC_28 126 , SpeedStepMode.NMRA_DCC_27 127 , SpeedStepMode.NMRA_DCC_14); 128 } 129 130 /** 131 * Handle incoming messages for throttles. 132 */ 133 @Override 134 public void message(XNetReply r) { 135 // We want to check to see if a throttle has taken over an address 136 if (r.getElement(0) == XNetConstants.LOCO_INFO_RESPONSE) { 137 if (r.getElement(1) == XNetConstants.LOCO_NOT_AVAILABLE) { 138 // This is a take over message. If we know about this throttle, 139 // send the message on. 140 LocoAddress address = new jmri.DccLocoAddress(r.getThrottleMsgAddr(), 141 isLongAddress(r.getThrottleMsgAddr())); 142 if (throttles.containsKey(address)) { 143 throttles.get(address).message(r); 144 } 145 } 146 } 147 148 } 149 150 /** 151 * Listen for the messages to the LI100/LI101. 152 */ 153 @Override 154 public void message(XNetMessage l) { 155 } 156 157 /** 158 * Handle a timeout notification. 159 */ 160 @Override 161 public void notifyTimeout(XNetMessage msg) { 162 } 163 164 @Override 165 public void releaseThrottle(jmri.DccThrottle t, jmri.ThrottleListener l) { 166 } 167 168 @Override 169 public boolean disposeThrottle(jmri.DccThrottle t, jmri.ThrottleListener l) { 170 if (super.disposeThrottle(t, l)) { 171 if(!(t instanceof XNetThrottle)) { 172 throw new IllegalArgumentException("Attempt to dispose non-XpressNet Throttle"); 173 } 174 XNetThrottle lnt = (XNetThrottle) t; 175 lnt.throttleDispose(); 176 return true; 177 } 178 return false; 179 } 180 181 private static final Logger log = LoggerFactory.getLogger(XNetThrottleManager.class); 182 183}