001/** 002 * Consist Manager for use with the NceConsist class for the 003 * consists it builds. 004 * 005 * @author Paul Bender Copyright (C) 2011 006 * @author Daniel Boudreau Copyright (C) 2012 007 */ 008package jmri.jmrix.nce; 009 010import jmri.Consist; 011import jmri.LocoAddress; 012import jmri.DccLocoAddress; 013import jmri.implementation.AbstractConsistManager; 014import jmri.jmrix.ConnectionStatus; 015import jmri.jmrix.JmrixConfigPane; 016import org.slf4j.Logger; 017import org.slf4j.LoggerFactory; 018 019public class NceConsistManager extends AbstractConsistManager { 020 021 private NceSystemConnectionMemo memo = null; 022 023 public NceConsistManager(NceSystemConnectionMemo m) { 024 super(); 025 memo = m; 026 } 027 028 /** 029 * Request an update from the layout, loading 030 * Consists from the command station. 031 */ 032 @Override 033 public void requestUpdateFromLayout() { 034 if (shouldRequestUpdateFromLayout()) { 035 startConsistReader(); 036 } 037 } 038 039 /** 040 * This implementation does not support command station assisted consists, 041 * so return false. 042 * 043 */ 044 @Override 045 public boolean isCommandStationConsistPossible() { 046 return false; 047 } 048 049 /** 050 * Does a CS consist require a separate consist address? 051 * 052 */ 053 @Override 054 public boolean csConsistNeedsSeperateAddress() { 055 return false; 056 } 057 058 /** 059 * Add a new NceConsist with the given address to consistTable/consistList 060 */ 061 @Override 062 public Consist addConsist(LocoAddress locoAddress) { 063 if (! (locoAddress instanceof DccLocoAddress)) { 064 throw new IllegalArgumentException("locoAddress is not a DccLocoAddress object"); 065 } 066 if (consistTable.containsKey(locoAddress)) // no duplicates allowed. 067 { 068 return consistTable.get(locoAddress); 069 } 070 log.debug("Add consist, address {}", locoAddress); 071 NceConsist consist = new NceConsist((DccLocoAddress) locoAddress, memo); 072 consistTable.put(locoAddress, consist); 073 notifyConsistListChanged(); 074 return consist; 075 } 076 077 private void addConsist(NceConsist consist) { 078 log.debug("Add consist {}", consist.getConsistAddress()); 079 //delConsist(consist.getConsistAddress()); // remove consist if one exists 080 consistTable.put(consist.getConsistAddress(), consist); 081 notifyConsistListChanged(); 082 } 083 084 @Override 085 public Consist getConsist(LocoAddress locoAddress) { 086 log.debug("Requesting NCE consist {}", locoAddress); 087 NceConsist consist = (NceConsist) super.getConsist(locoAddress); 088 // Checking the CS memory each time a consist is requested creates lots of NCE messages! 089 //consist.checkConsist(); 090 return consist; 091 } 092 093 // remove the old Consist 094 @Override 095 public void delConsist(LocoAddress locoAddress) { 096 NceConsist consist = (NceConsist) getConsist(locoAddress); 097 // kill this consist 098 consist.dispose(); 099 super.delConsist(locoAddress); 100 } 101 102 public void startConsistReader() { 103 // read command station memory (not USB and not simulator) Can't determine if simulator selected, but can determine if port name is the default 104 if (memo.getNceUsbSystem() == NceTrafficController.USB_SYSTEM_NONE && !memo.getNceTrafficController().getPortName().equals(JmrixConfigPane.NONE_SELECTED) 105 && memo.getNceTrafficController().getCommandOptions() > NceTrafficController.OPTION_1999) { 106 new NceConsistReader().start(); 107 } 108 } 109 110 public class NceConsistReader extends Thread { 111 112 int _consistNum = NceConsist.CONSIST_MAX; 113 114 NceConsistReader() { 115 setName("Initialize NCE consists"); 116 } 117 118 @Override 119 public void run() { 120 searchNext(); 121 } 122 123 // NCE allocates consist numbers starting at 127, so we do the same 124 private void searchNext() { 125 synchronized (this) { 126 // we need to wait for the connection to be up and running 127 while (!ConnectionStatus.instance() 128 .getConnectionState(memo.getUserName(), memo.getNceTrafficController().getPortName()) 129 .equals(ConnectionStatus.CONNECTION_UP)) { 130 log.debug("Waiting for NCE connected"); 131 try { 132 wait(2000); // wait 2 seconds and try again 133 } catch (InterruptedException e) { 134 Thread.currentThread().interrupt(); // retain if needed later 135 } 136 } 137 } 138 while (_consistNum >= NceConsist.CONSIST_MIN) { 139 if (log.isDebugEnabled()) { 140 log.debug("Reading consist from command station: {}", _consistNum); 141 } 142 NceConsist consist = new NceConsist(_consistNum, memo); 143 // wait until consist finishes CS read 144 while (!consist.isValid()) { 145 synchronized (this) { 146 try { 147 //log.debug("Waiting for consist "+_consistNum+" to be valid"); 148 wait(100); // wait 100 milliseconds and check again 149 } catch (InterruptedException e) { 150 Thread.currentThread().interrupt(); // retain if needed later 151 } 152 } 153 } 154 if (consist.getConsistList().size() > 0) { 155 addConsist(consist); 156 } 157 _consistNum--; 158 } 159 // when we finish reading, notify any listeners. 160 notifyConsistListChanged(); 161 } 162 } 163 164 private final static Logger log = LoggerFactory.getLogger(NceConsistManager.class); 165 166}