001package jmri.jmrix.loconet.uhlenbrock; 002 003import java.util.Hashtable; 004import jmri.DccLocoAddress; 005import jmri.DccThrottle; 006import jmri.LocoAddress; 007import jmri.ThrottleListener; 008import jmri.jmrix.loconet.LnThrottleManager; 009import jmri.jmrix.loconet.LocoNetSlot; 010import jmri.jmrix.loconet.LocoNetSystemConnectionMemo; 011import jmri.jmrix.loconet.LocoNetThrottle; 012import jmri.jmrix.loconet.SlotListener; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016/** 017 * LocoNet implementation of a ThrottleManager for Uhlenbrock. 018 * <p> 019 * Works in cooperation with the SlotManager, which actually handles the 020 * communications. 021 * 022 * @see jmri.jmrix.loconet.SlotManager 023 * @author Bob Jacobsen Copyright (C) 2001 024 */ 025public class UhlenbrockLnThrottleManager extends LnThrottleManager { 026 027 public UhlenbrockLnThrottleManager(UhlenbrockSystemConnectionMemo memo) { 028 super(memo); 029 } 030 031 /** 032 * The Intellibox-II doesn't always respond to a request loco message, 033 * therefore the system will not allow further requests to create a throttle 034 * to that address as one is already in process. 035 * 036 * With the Intellibox throttle, it will make three attempts to connect if 037 * no response is received from the command station after 2 seconds. 038 * Otherwise it will send a failthrottlerequest message out. 039 */ 040 @Override 041 public void requestThrottleSetup(LocoAddress address, boolean control) { 042 if (!(address instanceof DccLocoAddress)){ 043 log.error("{} is not a DCCLocoAddress",address); 044 failedThrottleRequest(address, "Address" + address + " is not a DccLocoAddress"); 045 return; 046 } 047 slotManager.slotFromLocoAddress(((DccLocoAddress) address).getNumber(), this); 048 049 class RetrySetup implements Runnable { 050 051 DccLocoAddress address; 052 SlotListener list; 053 054 RetrySetup(DccLocoAddress address, SlotListener list) { 055 this.address = address; 056 this.list = list; 057 } 058 059 @Override 060 public void run() { 061 int count = 0; 062 while (count < 3) { 063 try { 064 Thread.sleep(2000); 065 } catch (InterruptedException ex) { 066 return; 067 } 068 slotManager.slotFromLocoAddress(address.getNumber(), list); 069 log.warn("No response to requesting loco {}, will try again {}", address, count); 070 count++; 071 } 072 log.error("No response to requesting loco {} after {} attempts; will cancel the request", address, count); 073 failedThrottleRequest(address, "Failed to get response from command station"); 074 } 075 } 076 Thread thr = new Thread(new RetrySetup((DccLocoAddress) address, this)); 077 thr.start(); 078 waitingForNotification.put(((DccLocoAddress) address).getNumber(), thr); 079 } 080 081 Hashtable<Integer, Thread> waitingForNotification = new Hashtable<Integer, Thread>(5); 082 083 /** 084 * SlotListener contract. Get notification that an address has changed slot. 085 * This method creates a throttle for all ThrottleListeners of that address 086 * and notifies them via the ThrottleListener.notifyThrottleFound method. 087 */ 088 @Override 089 public void notifyChangedSlot(LocoNetSlot s) { 090 DccThrottle throttle = new LocoNetThrottle((LocoNetSystemConnectionMemo) adapterMemo, s); 091 notifyThrottleKnown(throttle, new DccLocoAddress(s.locoAddr(), isLongAddress(s.locoAddr()))); 092 if (waitingForNotification.containsKey(s.locoAddr())) { 093 Thread r = waitingForNotification.get(s.locoAddr()); 094 synchronized (r) { 095 r.interrupt(); 096 } 097 waitingForNotification.remove(s.locoAddr()); 098 } 099 } 100 101 @Override 102 public void failedThrottleRequest(LocoAddress address, String reason) { 103 if (waitingForNotification.containsKey(address.getNumber())) { 104 waitingForNotification.get(address.getNumber()).interrupt(); 105 waitingForNotification.remove(address.getNumber()); 106 } 107 super.failedThrottleRequest(address, reason); 108 } 109 110 /** 111 * Cancel a request for a throttle. 112 * 113 * @param address The decoder address desired. 114 * @param l The ThrottleListener cancelling request for a throttle. 115 */ 116 @Override 117 public void cancelThrottleRequest(LocoAddress address, ThrottleListener l) { 118 int loconumber = address.getNumber(); 119 if (waitingForNotification.containsKey(loconumber)) { 120 waitingForNotification.get(loconumber).interrupt(); 121 waitingForNotification.remove(loconumber); 122 } 123 super.cancelThrottleRequest(address, l); 124 } 125 126 private final static Logger log = LoggerFactory.getLogger(UhlenbrockLnThrottleManager.class); 127 128}