001/** 002 * Concrete subclass of TurnoutOperator for a turnout that has sensor feedback. 003 * 004 * @author John Harper Copyright 2005 005 */ 006package jmri.implementation; 007 008import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 009import java.beans.PropertyChangeEvent; 010import java.beans.PropertyChangeListener; 011import jmri.TurnoutOperator; 012import org.slf4j.Logger; 013import org.slf4j.LoggerFactory; 014 015public class SensorTurnoutOperator extends TurnoutOperator { 016 017 long interval; 018 int maxTries; 019 int tries = 0; 020 PropertyChangeListener listener; 021 022 public SensorTurnoutOperator(AbstractTurnout t, long i, int mt) { 023 super(t); 024 interval = i; 025 maxTries = mt; 026 } 027 028 /** 029 * Do the autmation for a turnout with sensor feedback. Keep trying up to 030 * maxTries until the sensor tells us the change has actually happened. Note 031 * the call to operatorCheck each time we're about to actually do something 032 * - if we're no longer the current operator this throws 033 * TurnoutOperatorException which just terminates the thread. 034 */ 035 @Override 036 public void run() { 037 //long startTime = System.currentTimeMillis(); 038 listener = new PropertyChangeListener() { 039 @SuppressFBWarnings(value = "NN_NAKED_NOTIFY", 040 justification = "notify not naked, outside sensor and turnout is shared state") 041 @Override 042 public void propertyChange(PropertyChangeEvent e) { 043 if (e.getPropertyName().equals("KnownState")) { 044 synchronized (this) { 045 this.notify(); 046 } 047 } 048 } 049 }; 050 myTurnout.addPropertyChangeListener(listener); 051 try { 052 operatorCheck(); 053 myTurnout.forwardCommandChangeToLayout(); 054 while (++tries < maxTries) { 055 long nextTry = System.currentTimeMillis() + interval; 056 long remaining; 057 while ((remaining = nextTry - System.currentTimeMillis()) > 0) { 058 try { 059 synchronized (this) { 060 wait(remaining); 061 } 062 } catch (InterruptedException e) { 063 Thread.currentThread().interrupt(); // retain if needed later 064 } 065 } 066 if (myTurnout.isConsistentState()) { 067 break; 068 } 069 operatorCheck(); 070 myTurnout.forwardCommandChangeToLayout(); 071 log.warn("retrying {}, try #{}", myTurnout.getSystemName(), tries + 1); 072 } 073 if (!myTurnout.isConsistentState()) { 074 log.warn("failed to throw {}", myTurnout.getSystemName()); 075 } 076 } catch (TurnoutOperatorException e) { 077 } 078 myTurnout.removePropertyChangeListener(listener); 079 } 080 081 private final static Logger log = LoggerFactory.getLogger(SensorTurnoutOperator.class); 082}