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