001package jmri.jmrix.loconet; 002 003import java.util.Comparator; 004import java.util.ResourceBundle; 005import javax.annotation.Nonnull; 006 007import jmri.*; 008import jmri.jmrix.ConfiguringSystemConnectionMemo; 009import jmri.jmrix.DefaultSystemConnectionMemo; 010import jmri.jmrix.debugthrottle.DebugThrottleManager; 011import jmri.jmrix.loconet.swing.LnComponentFactory; 012import jmri.jmrix.swing.ComponentFactory; 013import jmri.managers.DefaultProgrammerManager; 014import jmri.util.NamedBeanComparator; 015 016import org.slf4j.Logger; 017import org.slf4j.LoggerFactory; 018 019/** 020 * Lightweight class to denote that a system is active, and provide general 021 * information. 022 * <p> 023 * Objects of specific subtypes are registered in the instance manager to 024 * activate their particular system. 025 * 026 * @author Bob Jacobsen Copyright (C) 2010 027 */ 028public class LocoNetSystemConnectionMemo extends DefaultSystemConnectionMemo implements ConfiguringSystemConnectionMemo { 029 030 /** 031 * Must manually register() after construction is complete. 032 * @param lt Traffic controller to be used 033 * @param sm Slot Manager to be used 034 */ 035 public LocoNetSystemConnectionMemo(LnTrafficController lt, SlotManager sm) { 036 super("L", "LocoNet"); // NOI18N 037 this.lt = lt; 038 039 this.sm = sm; // doesn't full register, but fine for this purpose. 040 041 // self-registration is deferred until the command station type is set below 042 043 // create and register the ComponentFactory for the GUI 044 InstanceManager.store(cf = new LnComponentFactory(this), 045 ComponentFactory.class); 046 } 047 048 /** 049 * Must manually register() after construction is complete. 050 */ 051 public LocoNetSystemConnectionMemo() { 052 this("L", "LocoNet"); // NOI18N 053 } 054 055 public LocoNetSystemConnectionMemo(@Nonnull String prefix, @Nonnull String name) { 056 super(prefix, name); // NOI18N 057 058 // create and register the ComponentFactory for the GUI 059 InstanceManager.store(cf = new LnComponentFactory(this), 060 ComponentFactory.class); 061 } 062 063 /** 064 * Do both the default parent 065 * {@link jmri.SystemConnectionMemo} registration, 066 * and register this specific type. 067 */ 068 @Override 069 public void register() { 070 super.register(); // registers general type 071 InstanceManager.store(this, LocoNetSystemConnectionMemo.class); // also register as specific type 072 } 073 074 ComponentFactory cf = null; 075 private LnTrafficController lt; 076 protected LocoNetThrottledTransmitter tm; 077 private SlotManager sm; 078 private LncvDevicesManager lncvdm = null; 079 private LnMessageManager lnm = null; 080 private Ln7gAccyRoutesManager ln7gAcRtm; 081 082 /** 083 * Provide access to the SlotManager for this particular connection. 084 * 085 * @return the slot manager or null if no valid slot manager is available 086 */ 087 public SlotManager getSlotManager() { 088 if (sm == null) { 089 log.debug("slot manager is null, but there should always be a valid SlotManager", new Exception("Traceback")); 090 } 091 return sm; 092 } 093 094 /** 095 * Provide access to the TrafficController for this particular connection. 096 * 097 * @return the LocoNet-specific TrafficController 098 */ 099 public LnTrafficController getLnTrafficController() { 100 if (lt == null) { 101 setLnTrafficController(new LnPacketizer(this)); // default to Packetizer TrafficController 102 log.debug("Auto create of LnTrafficController for initial configuration"); 103 } 104 return lt; 105 } 106 107 public void setLnTrafficController(LnTrafficController lt) { 108 this.lt = lt; 109 } 110 111 public LnMessageManager getLnMessageManager() { 112 // create when needed 113 if (lnm == null) { 114 lnm = new LnMessageManager(getLnTrafficController()); 115 } 116 return lnm; 117 } 118 119 public DefaultProgrammerManager getProgrammerManager() { 120 return (DefaultProgrammerManager) classObjectMap.computeIfAbsent(DefaultProgrammerManager.class,(Class<?> c) -> new LnProgrammerManager(this)); 121 } 122 123 public void setProgrammerManager(DefaultProgrammerManager p) { 124 store(p,DefaultProgrammerManager.class); 125 } 126 127 public void setLncvDevicesManager(LncvDevicesManager lncvdm) { 128 this.lncvdm = lncvdm; 129 } 130 131 protected boolean mTurnoutNoRetry = false; 132 protected boolean mTurnoutExtraSpace = false; 133 protected boolean mInterrogateAtStart = true; 134 135 /** 136 * Configure the programming manager and "command station" objects. 137 * 138 * @param type Command station type, used to configure various 139 * operations 140 * @param mTurnoutNoRetry Is the user configuration set for no turnout 141 * operation retries? 142 * @param mTurnoutExtraSpace Is the user configuration set for extra time 143 * between turnout operations? 144 * @param mTranspondingAvailable Is the layout configured to provide 145 * transopnding reports 146 * @param mInterrogate Send interrogate messages at start up 147 * @param mLoconetProtocolAutoDetect Do we automatically detect the protocol to use or force LocoNet 1.1 148 */ 149 public void configureCommandStation(LnCommandStationType type, boolean mTurnoutNoRetry, 150 boolean mTurnoutExtraSpace, boolean mTranspondingAvailable, 151 boolean mInterrogate, boolean mLoconetProtocolAutoDetect) { 152 153 // store arguments 154 this.mTurnoutNoRetry = mTurnoutNoRetry; 155 this.mTurnoutExtraSpace = mTurnoutExtraSpace; 156 this.mInterrogateAtStart = mInterrogate; 157 158 // create and install SlotManager 159 if (sm != null) { 160 log.error("Installing SlotManager twice", new Exception("TraceBack")); 161 } 162 sm = type.getSlotManager(lt); 163 if (sm != null) { 164 sm.setThrottledTransmitter(tm, mTurnoutNoRetry); 165 166 sm.setCommandStationType(type); 167 sm.setSystemConnectionMemo(this); 168 sm.setTranspondingAvailable(mTranspondingAvailable); 169 sm.setLoconetProtocolAutoDetect(mLoconetProtocolAutoDetect); 170 171 // store as CommandStation object 172 InstanceManager.store(sm, jmri.CommandStation.class); 173 store(sm, jmri.CommandStation.class); 174 } 175 176 } 177 178 /** 179 * Configure the common managers for LocoNet connections. This puts the 180 * common manager config in one place. 181 */ 182 @Override 183 public void configureManagers() { 184 185 tm = new LocoNetThrottledTransmitter(getLnTrafficController(), mTurnoutExtraSpace); 186 log.debug("ThrottleTransmitted configured with: {}", mTurnoutExtraSpace); 187 if (sm != null) { 188 sm.setThrottledTransmitter(tm, mTurnoutNoRetry); 189 log.debug("set turnout retry: {}", mTurnoutNoRetry); 190 } 191 192 InstanceManager.store(getPowerManager(), PowerManager.class); 193 194 InstanceManager.setSensorManager( 195 getSensorManager()); 196 197 InstanceManager.setTurnoutManager( 198 getTurnoutManager()); 199 200 InstanceManager.setLightManager( 201 getLightManager()); 202 203 InstanceManager.setDefault(StringIOManager.class, getStringIOManager()); 204 205 InstanceManager.setThrottleManager( 206 getThrottleManager()); 207 208 DefaultProgrammerManager programmerManager = getProgrammerManager(); 209 210 if (programmerManager.isAddressedModePossible()) { 211 store(programmerManager, AddressedProgrammerManager.class); 212 InstanceManager.store(programmerManager, AddressedProgrammerManager.class); 213 } 214 if (programmerManager.isGlobalProgrammerAvailable()) { 215 store(getProgrammerManager(), GlobalProgrammerManager.class); 216 InstanceManager.store(getProgrammerManager(), GlobalProgrammerManager.class); 217 } 218 219 InstanceManager.setReporterManager(getReporterManager()); 220 221 InstanceManager.setDefault(CabSignalManager.class,getCabSignalManager()); 222 223 setConsistManager(new LocoNetConsistManager(this)); 224 225 setLncvDevicesManager(new jmri.jmrix.loconet.LncvDevicesManager(this)); 226 227 ClockControl cc = getClockControl(); 228 229 InstanceManager.setDefault(ClockControl.class, cc); 230 231 getIdTagManager(); 232 233 // register this SystemConnectionMemo to connect to rest of system 234 register(); 235 236 // This must be done after the memo is registered 237 getPredefinedMeters(); 238 239 // This must be done after the memo is registered 240 getThrottleStringIO(); 241 242 ln7gAcRtm = 243 setLn7gAccyRoutesManager( 244 getLn7gAccyRoutesManager()); 245 log.debug("Established Ln Accy Rt Mgr with memo {}",ln7gAcRtm.getMemo()); 246 247 } 248 249 public LnPowerManager getPowerManager() { 250 if (getDisabled()) { 251 return null; 252 } 253 return (LnPowerManager) classObjectMap.computeIfAbsent(PowerManager.class,(Class<?> c) -> new LnPowerManager(this)); 254 } 255 256 public ThrottleManager getThrottleManager() { 257 if (getSlotManager() != null) { 258 log.debug("GetThrottleManager for {}", getSlotManager().getCommandStationType()); 259 } 260 if (getDisabled()) { 261 return null; 262 } 263 ThrottleManager throttleManager = get(ThrottleManager.class); 264 if (throttleManager == null && getSlotManager() != null) { 265 // ask command station type for specific throttle manager 266 LnCommandStationType cmdstation = getSlotManager().getCommandStationType(); 267 log.debug("getThrottleManager constructs for {}", cmdstation.getName()); 268 throttleManager = cmdstation.getThrottleManager(this); 269 log.debug("result was type {}", throttleManager.getClass()); 270 store(throttleManager,ThrottleManager.class); 271 } 272 return throttleManager; 273 } 274 275 public void setThrottleManager(ThrottleManager t) { 276 store(t,ThrottleManager.class); 277 } 278 279 public LnTurnoutManager getTurnoutManager() { 280 if (getDisabled()) { 281 return null; 282 } 283 return (LnTurnoutManager) classObjectMap.computeIfAbsent(TurnoutManager.class,(Class<?> c) -> new LnTurnoutManager(this, tm, mTurnoutNoRetry)); 284 } 285 286 public LnClockControl getClockControl() { 287 if (getDisabled()) { 288 return null; 289 } 290 return (LnClockControl) classObjectMap.computeIfAbsent(ClockControl.class,(Class<?> c) -> new LnClockControl(this)); 291 } 292 293 public LnReporterManager getReporterManager() { 294 if (getDisabled()) { 295 return null; 296 } 297 return (LnReporterManager) classObjectMap.computeIfAbsent(ReporterManager.class, (Class<?> c) -> new LnReporterManager(this)); 298 } 299 300 public LnSensorManager getSensorManager() { 301 if (getDisabled()) { 302 return null; 303 } 304 return (LnSensorManager) classObjectMap.computeIfAbsent(SensorManager.class, (Class<?> c) -> new LnSensorManager(this, mInterrogateAtStart)); 305 } 306 307 public LnLightManager getLightManager() { 308 if (getDisabled()) { 309 return null; 310 } 311 return (LnLightManager) classObjectMap.computeIfAbsent(LightManager.class, (Class<?> c) -> new LnLightManager(this)); 312 } 313 314 public LncvDevicesManager getLncvDevicesManager() { 315 if (getDisabled()) { 316 return null; 317 } 318 if (lncvdm == null) { 319 setLncvDevicesManager(new LncvDevicesManager(this)); 320 log.debug("Auto create of LncvDevicesManager for initial configuration"); 321 } 322 return lncvdm; 323 } 324 325 public LnStringIOManager getStringIOManager() { 326 if (getDisabled()) { 327 return null; 328 } 329 return (LnStringIOManager) classObjectMap.computeIfAbsent(StringIOManager.class, (Class<?> c) -> new LnStringIOManager(this)); 330 } 331 332 public Ln7gAccyRoutesManager setLn7gAccyRoutesManager(Ln7gAccyRoutesManager ln7gaccyrm) { 333 this.ln7gAcRtm = ln7gaccyrm; 334 if (this.ln7gAcRtm != null) { 335 // this can only be true when getDisabled() == false 336 this.ln7gAcRtm.initContext(this); 337 } 338 return this.ln7gAcRtm; 339 } 340 341 public Ln7gAccyRoutesManager getLn7gAccyRoutesManager() { 342 if (getDisabled()) { 343 return null; 344 } 345 return (Ln7gAccyRoutesManager) classObjectMap.computeIfAbsent(Ln7gAccyRoutesManager.class, 346 (Class<?> c) -> new Ln7gAccyRoutesManager()); 347 } 348 349 protected LnPredefinedMeters predefinedMeters; 350 351 public LnPredefinedMeters getPredefinedMeters() { 352 if (getDisabled()) { 353 log.warn("Aborting getPredefinedMeters account is disabled!"); 354 return null; 355 } 356// switch (getSlotManager().commandStationType) { 357// case COMMAND_STATION_USB_DCS240_ALONE: 358// case COMMAND_STATION_DCS240: 359// case COMMAND_STATION_DCS210: 360// case COMMAND_STATION_USB_DCS52_ALONE: 361// case COMMAND_STATION_DCS052: 362// break; 363// default: 364// // The command station does not support these meters 365// return null; 366// } 367 if (predefinedMeters == null) { 368 predefinedMeters = new LnPredefinedMeters(this); 369 } 370 return predefinedMeters; 371 } 372 373 LnThrottleStringIO throttleStringIO; 374 375 public void getThrottleStringIO() { 376 if (getDisabled()) { 377 log.warn("Aborting getThrottleStringIO account is disabled!"); 378 return; 379 } 380 if (throttleStringIO == null) { 381 throttleStringIO = new LnThrottleStringIO(this); 382 InstanceManager.getDefault(jmri.StringIOManager.class) 383 .register(throttleStringIO); 384 } 385 } 386 387 @Override 388 protected ResourceBundle getActionModelResourceBundle() { 389 return ResourceBundle.getBundle("jmri.jmrix.loconet.LocoNetActionListBundle"); 390 } 391 392 @Override 393 public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) { 394 return new NamedBeanComparator<>(); 395 } 396 397 // yes, tagManager is static. Tags can move between system connections. 398 // when readers are not all on the same LocoNet 399 // this manager is loaded on demand. 400 static TranspondingTagManager tagManager; 401 402 static public TranspondingTagManager getIdTagManager() { 403 synchronized (LocoNetSystemConnectionMemo.class) { // since tagManager can be null, can't synch on that 404 if (tagManager == null) { 405 tagManager = new TranspondingTagManager(); 406 InstanceManager.setIdTagManager(tagManager); 407 } 408 return tagManager; 409 } 410 } 411 412 public LnCabSignalManager getCabSignalManager() { 413 return (LnCabSignalManager) classObjectMap.computeIfAbsent(CabSignalManager.class,(Class<?> c) -> new LnCabSignalManager(this)); 414 } 415 416 @Override 417 public void dispose() { 418 if (throttleStringIO != null) { 419 throttleStringIO = null; 420 } 421 if (predefinedMeters != null) { 422 predefinedMeters.dispose(); 423 } 424 LnPowerManager pm = (LnPowerManager) classObjectMap.get(PowerManager.class); 425 InstanceManager.deregister(this, LocoNetSystemConnectionMemo.class); 426 if (cf != null) { 427 InstanceManager.deregister(cf, ComponentFactory.class); 428 cf = null; 429 } 430 ThrottleManager throttleManager = get(ThrottleManager.class); 431 if (throttleManager != null) { 432 if (throttleManager instanceof LnThrottleManager) { 433 InstanceManager.deregister(((LnThrottleManager) throttleManager), LnThrottleManager.class); 434 } else if (throttleManager instanceof DebugThrottleManager) { 435 InstanceManager.deregister(((DebugThrottleManager) throttleManager), DebugThrottleManager.class); 436 } 437 deregister(throttleManager,ThrottleManager.class); 438 } 439 440 if (tm != null){ 441 tm.dispose(); 442 tm = null; 443 } 444 if (sm != null){ 445 sm.dispose(); 446 sm = null; 447 } 448 if (lt != null){ 449 lt.dispose(); 450 lt = null; 451 } 452 if (pm != null){ 453 pm.dispose(); 454 } 455 super.dispose(); 456 } 457 458 private final static Logger log = LoggerFactory.getLogger(LocoNetSystemConnectionMemo.class); 459 460}