001package jmri.jmrix.rps; 002 003import java.util.List; 004import jmri.LocoAddress; 005import jmri.DccLocoAddress; 006import jmri.DccThrottle; 007import jmri.SignalHead; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011/** 012 * Create a Block that can control a locomotive within a specific Block based on 013 * an RpsSensor. It sets speed based on aspect of a specific signal. 014 * 015 * @author Bob Jacobsen Copyright (C) 2007 016 */ 017public class RpsBlock implements java.beans.PropertyChangeListener, jmri.ThrottleListener { 018 019 public RpsBlock(RpsSensor sensor, SignalHead signal, float slow, float fast) { 020 this.sensor = sensor; 021 this.signal = signal; 022 this.slow = slow; 023 this.fast = fast; 024 025 this.sensor.addPropertyChangeListener(this); 026 this.signal.addPropertyChangeListener(this); 027 } 028 029 public RpsBlock(String sensorname, String signalname, float slow, float fast) { 030 this((RpsSensor) jmri.InstanceManager.sensorManagerInstance().getSensor(sensorname), 031 jmri.InstanceManager.getDefault(jmri.SignalHeadManager.class).getSignalHead(signalname), 032 slow, fast); 033 } 034 035 float slow, fast; 036 SignalHead signal = null; 037 RpsSensor sensor = null; 038 039 @Override 040 public void propertyChange(java.beans.PropertyChangeEvent e) { 041 handleParameterChange(e.getPropertyName(), 042 e.getOldValue(), e.getNewValue(), 043 e.getSource()); 044 } 045 046 void handleParameterChange(String property, 047 Object oldState, Object newState, 048 Object source) { 049 log.debug("Change {} from {}", property, source); 050 if (property.equals("Arriving")) { 051 arriving((Integer) newState); 052 } else if (property.equals("Leaving")) { 053 leaving((Integer) newState); 054 } else if (property.equals("Appearance")) { 055 appearance(); 056 } else { 057 log.debug("Parameter ignored"); 058 } 059 } 060 061 // arriving and departing just checks who's here 062 void arriving(Integer number) { 063 acquireThrottle(number); 064 updateCurrentThrottles(); 065 } 066 067 void leaving(Integer number) { 068 acquireThrottle(number); 069 } 070 071 void appearance() { 072 updateCurrentThrottles(); 073 } 074 075 void acquireThrottle(Integer num) { 076 Object o = throttleTable.get(num); 077 if (o != null) { 078 return; // already present 079 } 080 } 081 082 @Override 083 public void notifyThrottleFound(DccThrottle t) { 084 // put in map 085 Integer num = Integer.valueOf(((DccLocoAddress) t.getLocoAddress()).getNumber()); 086 throttleTable.put(num, t); 087 } 088 089 @Override 090 public void notifyFailedThrottleRequest(LocoAddress address, String reason) { 091 } 092 093 /** 094 * No steal or share decisions made locally 095 * <p> 096 * {@inheritDoc} 097 */ 098 @Override 099 public void notifyDecisionRequired(jmri.LocoAddress address, DecisionType question) { 100 } 101 102 void updateCurrentThrottles() { 103 List<Integer> l = sensor.getContents(); 104 if (l.size() == 0) { 105 return; 106 } 107 if (l.size() > 1) { 108 log.warn("More than one address present!"); 109 } 110 for (int i = 0; i < l.size(); i++) { 111 Integer num = l.get(i); 112 DccThrottle t = throttleTable.get(num); 113 if (t != null) { 114 updateOneThrottle(t); 115 } else { 116 log.warn("Throttle not yet available for: {}", num); 117 } 118 } 119 } 120 121 void updateOneThrottle(DccThrottle t) { 122 // get proper speed 123 int app = signal.getAppearance(); 124 switch (app) { 125 case SignalHead.RED: 126 t.setSpeedSetting(0.f); 127 break; 128 case SignalHead.GREEN: 129 t.setSpeedSetting(fast); 130 break; 131 default: 132 t.setSpeedSetting(slow); 133 break; 134 } 135 } 136 137 public void dispose() { 138 sensor.removePropertyChangeListener(this); 139 } 140 141 static java.util.Hashtable<Integer, DccThrottle> throttleTable = new java.util.Hashtable<Integer, DccThrottle>(); 142 143 private final static Logger log = LoggerFactory.getLogger(RpsBlock.class); 144 145}