001package jmri.jmrix.bidib; 002 003import java.util.Comparator; 004import java.util.ResourceBundle; 005import javax.annotation.Nonnull; 006import jmri.GlobalProgrammerManager; 007 008import jmri.InstanceManager; 009import jmri.LightManager; 010//import jmri.MultiMeter; 011import jmri.PowerManager; 012import jmri.SensorManager; 013import jmri.ThrottleManager; 014import jmri.TurnoutManager; 015import jmri.CommandStation; 016import jmri.NamedBean; 017import jmri.ReporterManager; 018//import jmri.jmrix.ConfiguringSystemConnectionMemo; 019import jmri.jmrix.DefaultSystemConnectionMemo; 020//import jmri.ConsistManager; 021import jmri.util.NamedBeanComparator; 022import org.slf4j.Logger; 023import org.slf4j.LoggerFactory; 024 025/** 026 * Lightweight class to denote that a system is active and provide general 027 * information. 028 * <p> 029 * Objects of specific subtypes are registered in the instance manager to 030 * activate their particular system. 031 * 032 * @author Paul Bender Copyright (C) 2010 033 * @author Mark Underwood Copyright (C) 2015 034 * @author Eckart Meyer Copyright (C) 2019-2023 035 * 036 * Based on DCCppSystemConnectionMemo by Paul Bender and Mark Underwood. 037 */ 038public class BiDiBSystemConnectionMemo extends DefaultSystemConnectionMemo /* implements ConfiguringSystemConnectionMemo */ { 039 040// @SuppressWarnings("OverridableMethodCallInConstructor") 041 public BiDiBSystemConnectionMemo(@Nonnull BiDiBTrafficController tc) { 042 super("B", "BiDiB"); 043 log.trace("**** ctor 1 BiDiBSystemConnectionMemo"); 044 this.tc = tc; 045 tc.setSystemConnectionMemo(this); 046 register(); // registers general type 047 InstanceManager.store(this, BiDiBSystemConnectionMemo.class); // also register as specific type 048 049 // create and register the BiDiBComponentFactory 050 InstanceManager.store(cf = new jmri.jmrix.bidib.swing.BiDiBComponentFactory(this), 051 jmri.jmrix.swing.ComponentFactory.class); 052 053 log.debug("Created BiDiBSystemConnectionMemo"); 054 } 055 056// @SuppressWarnings("OverridableMethodCallInConstructor") 057 public BiDiBSystemConnectionMemo() { 058 super("B", "BiDiB"); 059 log.trace("**** ctor 2 BiDiBSystemConnectionMemo"); 060 register(); // registers general type 061 InstanceManager.store(this, BiDiBSystemConnectionMemo.class); // also register as specific type 062 063 // create and register the BiDiBComponentFactory 064 InstanceManager.store(cf = new jmri.jmrix.bidib.swing.BiDiBComponentFactory(this), 065 jmri.jmrix.swing.ComponentFactory.class); 066 067 log.debug("Created BiDiBSystemConnectionMemo"); 068 } 069 070 jmri.jmrix.swing.ComponentFactory cf = null; 071 072 /** 073 * Provide access to the TrafficController for this particular connection. 074 * 075 * @return BiDiB Traffic Controller 076 */ 077 public BiDiBTrafficController getBiDiBTrafficController() { 078 log.trace("getBiDiBTrafficController"); 079 if (tc == null) { 080 setBiDiBTrafficController(new BiDiBTrafficController(null)); 081 log.debug("Auto create of BiDiBTrafficController for initial configuration"); 082 } 083 return tc; 084 } 085 086 private BiDiBTrafficController tc; 087 088 /** 089 * Set the traffic controller instance associated with this connection memo. 090 * 091 * @param tc the {@link jmri.jmrix.bidib.BiDiBTrafficController} object to use. 092 */ 093 public void setBiDiBTrafficController(@Nonnull BiDiBTrafficController tc) { 094 this.tc = tc; 095 // in addition to setting the traffic controller in this object, 096 // set the systemConnectionMemo in the traffic controller 097 tc.setSystemConnectionMemo(this); 098 } 099 100 /** 101 * Configure the common managers for BiDiB connections. This puts the 102 * common manager config in one place. This method is static so that it can 103 * be referenced from classes that don't inherit. 104 */ 105 public void configureManagers() { 106 if (tc.getCurrentGlobalProgrammerNode() != null) { 107 InstanceManager.store(getProgrammerManager(), GlobalProgrammerManager.class); 108 } 109 if (tc.getFirstCommandStationNode() != null) { 110 InstanceManager.store(getProgrammerManager(), jmri.AddressedProgrammerManager.class); 111 InstanceManager.setThrottleManager(getThrottleManager()); 112 InstanceManager.store(getCommandStation(), jmri.CommandStation.class); //unsed?? 113 } 114 if (tc.getFirstBoosterNode()!= null) { 115 InstanceManager.store(getPowerManager(), jmri.PowerManager.class); 116 // setup the PredefinedMeters 117 createPredefinedMeters(); 118 } 119// if (tc.getFirstOutputNode() != null || tc.getFirstCommandStationNode() != null) { 120// } 121 122 // always 123 InstanceManager.setTurnoutManager(getTurnoutManager()); 124 InstanceManager.setSensorManager(getSensorManager()); 125 InstanceManager.setReporterManager(getReporterManager()); 126 InstanceManager.setLightManager(getLightManager()); 127 128// InstanceManager.store(getConsistManager(), ConsistManager.class); 129 130 131 } 132 133 /** 134 * Called after all components (Sensors, Lights, ...) have been loaded 135 * Used to get some data from the device in one run 136 * 137 * NOT USED ANYMORE 138 */ 139 public void postConfigure() { 140// log.info("+++++++++ {}: post configure starts ++++++++++++", tc.getSystemConnectionMemo().getUserName()); 141// log.debug("memo: {}, bidib: {}", this, tc.getBidib()); 142// // get all BiDiB Port Configuration data 143// tc.allPortConfigX(); 144// // and then the status of all ports 145// tc.allPortLcStat(); 146// // then the status of all accessories 147// tc.allAccessoryState(); 148// // finally all feedback channels 149// tc.allFeedback(); 150// log.info("--------- {}: post configure ends -------------", tc.getSystemConnectionMemo().getUserName()); 151// try { 152// tc.getBidib().getRootNode().getMagic(1000); 153// log.info("MAGIC received from root node: {}", tc.getBidib().getRootNode()); 154// } 155// catch (ProtocolException ex) { 156// log.error("post configure - no answer from root node: " + tc.getBidib().getRootNode()); // NOSONAR 157// } 158 } 159 160 161 /** 162 * Provides access to the Programmer for this particular connection. 163 * 164 * @return programmer manager 165 */ 166 public BiDiBProgrammerManager getProgrammerManager() { 167 log.trace("getProgrammerManager"); 168 //Do not want to return a programmer if the system is disabled 169 if (getDisabled()) { 170 return null; 171 } 172 return (BiDiBProgrammerManager) classObjectMap.computeIfAbsent(BiDiBProgrammerManager.class,(Class<?> c) -> { 173 BiDiBProgrammerManager programmerManager = new BiDiBProgrammerManager(this); 174 log.debug("programmer manager created: {}", programmerManager); 175 return programmerManager; 176 }); 177 } 178 179 public void setProgrammerManager(BiDiBProgrammerManager p) { 180 store(p,BiDiBProgrammerManager.class); 181 } 182 183 /* 184 * Provides access to the Throttle Manager for this particular connection. 185 */ 186 public ThrottleManager getThrottleManager() { 187 log.trace("getThrottleManager"); 188 if (getDisabled()) { 189 return null; 190 } 191 return (ThrottleManager) classObjectMap.computeIfAbsent(ThrottleManager.class, (Class<?> c) -> { 192 ThrottleManager throttleManager = new BiDiBThrottleManager(this); 193 log.debug("throttle manager created: {}", throttleManager); 194 return throttleManager; 195 }); 196 } 197 198 public void setThrottleManager(ThrottleManager t) { 199 store(t,ThrottleManager.class); 200 } 201 202 /* 203 * Provides access to the Power Manager for this particular connection. 204 */ 205// @Nonnull 206 public PowerManager getPowerManager() { 207 log.trace("getPowerManager"); 208 if (getDisabled()) { 209 return null; 210 } 211 return (PowerManager) classObjectMap.computeIfAbsent(PowerManager.class, (Class<?> c) -> { 212 PowerManager powerManager = new BiDiBPowerManager(this); 213 log.debug("power manager created: {}", powerManager); 214 return powerManager; 215 }); 216 } 217 218 public void setPowerManager(@Nonnull PowerManager p) { 219 store(p,PowerManager.class); 220 } 221 222 223 224 /* 225 * Provides access to the Sensor Manager for this particular connection. 226 */ 227 public SensorManager getSensorManager() { 228 log.trace("getSensorManager"); 229 if (getDisabled()) { 230 return null; 231 } 232 return (SensorManager) classObjectMap.computeIfAbsent(SensorManager.class, (Class<?> c) -> { 233 SensorManager sensorManager = new BiDiBSensorManager(this); 234 log.debug("sensor manager created: {}", sensorManager); 235 return sensorManager; 236 }); 237 } 238 239 public void setSensorManager(@Nonnull SensorManager s) { 240 store(s,SensorManager.class); 241 } 242 243 /* 244 * Provides access to the Reporter Manager for this particular connection. 245 * BiDiB uses the reporter for RailCom 246 */ 247 public ReporterManager getReporterManager() { 248 log.trace("getReporterManager"); 249 if (getDisabled()) { 250 return null; 251 } 252 return (ReporterManager) classObjectMap.computeIfAbsent(ReporterManager.class, (Class<?> c) -> { 253 ReporterManager reporterManager = new BiDiBReporterManager(this); 254 log.debug("reporter manager created: {}", reporterManager); 255 return reporterManager; 256 }); 257 } 258 259 public void setReporterManager(@Nonnull ReporterManager s) { 260 store(s,ReporterManager.class); 261 } 262 263 /* 264 * Provides access to the Turnout Manager for this particular connection. 265 */ 266 public TurnoutManager getTurnoutManager() { 267 log.trace("getTurnoutManager"); 268 if (getDisabled()) { 269 return null; 270 } 271 return (TurnoutManager) classObjectMap.computeIfAbsent(TurnoutManager.class, (Class<?> c) -> { 272 TurnoutManager turnoutManager = new BiDiBTurnoutManager(this); 273 log.debug("turnout manager created: {}", turnoutManager); 274 return turnoutManager; 275 }); 276 } 277 278 public void setTurnoutManager(@Nonnull TurnoutManager t) { 279 store(t,TurnoutManager.class); 280 } 281 282 /* 283 * Provides access to the Light Manager for this particular connection. 284 */ 285 public LightManager getLightManager() { 286 log.trace("getLightManager"); 287 if (getDisabled()) { 288 return null; 289 } 290 return (LightManager) classObjectMap.computeIfAbsent(LightManager.class, (Class<?> c) -> { 291 LightManager lightManager = new BiDiBLightManager(this); 292 log.debug("light manager created: {}", lightManager); 293 return lightManager; 294 }); 295 } 296 297 public void setLightManager(@Nonnull LightManager l) { 298 store(l,LightManager.class); 299 } 300 301 /* 302 * Provides access to the mulit meter for this particular connection. 303 */ 304// public void enableMultiMeter(){ 305// jmri.InstanceManager.store( getMultiMeter(), jmri.MultiMeter.class ); 306// } 307 308 protected BiDiBPredefinedMeters predefinedMeters; 309 310 public BiDiBPredefinedMeters createPredefinedMeters() { 311 if (getDisabled()) { 312 return null; 313 } 314 if (predefinedMeters == null) { 315 InstanceManager.setMeterManager(new jmri.managers.AbstractMeterManager(this)); 316 predefinedMeters = new BiDiBPredefinedMeters(this); 317 } 318 return predefinedMeters; 319 } 320 321 /* 322 * Provides access to the Command Station for this particular connection. 323 * NOTE: Command Station defaults to NULL 324 */ 325 public CommandStation getCommandStation() { 326 log.trace("getCommandStation"); 327 if (getDisabled() || tc.getFirstCommandStationNode()== null) { 328 return null; 329 } 330 return (CommandStation) classObjectMap.computeIfAbsent(CommandStation.class, (Class<?> c) -> { 331 return tc; 332 }); 333 } 334 335 336 /** 337 * {@inheritDoc} 338 */ 339 @Override 340 public boolean provides(Class<?> type) { 341 log.trace("check for {}", type); 342 //log.trace(" this: {}, tc: {}", this, tc); 343//return (get(type) != null); 344//TODO: what if we finally support "lost node" and "new node"? 345 if (getDisabled() || tc == null) { 346 return false; 347 } else if (type.equals(jmri.GlobalProgrammerManager.class)) { 348 BiDiBProgrammerManager p = getProgrammerManager(); 349 if (p == null) { 350 return false; 351 } 352 return p.isGlobalProgrammerAvailable(); 353 } else if (type.equals(jmri.AddressedProgrammerManager.class)) { 354 BiDiBProgrammerManager p = getProgrammerManager(); 355 if (p == null) { 356 return false; 357 } 358 return p.isAddressedModePossible(); 359 //TODO: Update return value of the following as Managers are brought online. 360 } else if (type.equals(jmri.ThrottleManager.class)) { 361// return true; 362 return (tc.getFirstCommandStationNode() != null); 363 } else if (type.equals(jmri.PowerManager.class)) { 364// return true; 365 return (tc.getFirstBoosterNode() != null); 366 } else if (type.equals(jmri.ReporterManager.class)) { 367 return true; 368// return (tc.getFirstCommandStationNode() != null); 369 } else if (type.equals(jmri.SensorManager.class)) { 370 return true; 371// return (tc.getFirstOutputNode() != null || tc.getFirstCommandStationNode() != null); 372 } else if (type.equals(jmri.TurnoutManager.class)) { 373 return true; 374// return (tc.getFirstOutputNode() != null || tc.getFirstCommandStationNode() != null); 375 } else if (type.equals(jmri.LightManager.class)) { 376 return true; 377 } else if (type.equals(jmri.ConsistManager.class)) { 378 return false; //for now, we do not provide a consist manager - TODO! 379 } else if (type.equals(jmri.CommandStation.class)) { 380// return true; 381// return false; 382 return (tc.getFirstCommandStationNode() != null); 383// } else if (type.equals(jmri.MultiMeter.class)) { 384//// return true; 385// return (tc.getFirstBoosterNode() != null); 386 } else { 387 return super.provides(type); 388 } 389 } 390 391 /** 392 * {@inheritDoc} 393 */ 394 @SuppressWarnings("unchecked") 395 @Override 396// public <T> T get(Class<?> T) { //v5.2 397 public <T> T get(Class<T> T) { 398 if (getDisabled()) { 399 return null; 400 } 401 log.trace("get {}", T); 402 if (T.equals(jmri.GlobalProgrammerManager.class)) { 403 return (T) getProgrammerManager(); 404 } 405 if (T.equals(jmri.AddressedProgrammerManager.class)) { 406 return (T) getProgrammerManager(); 407 } 408 if (T.equals(jmri.ThrottleManager.class)) { 409 return (T) getThrottleManager(); 410 } 411 if (T.equals(jmri.PowerManager.class)) { 412 return (T) getPowerManager(); 413 } 414 if (T.equals(jmri.SensorManager.class)) { 415 return (T) getSensorManager(); 416 } 417 if (T.equals(jmri.ReporterManager.class)) { 418 return (T) getReporterManager(); 419 } 420 if (T.equals(jmri.TurnoutManager.class)) { 421 return (T) getTurnoutManager(); 422 } 423 if (T.equals(jmri.LightManager.class)) { 424 return (T) getLightManager(); 425 } 426 if (T.equals(jmri.ConsistManager.class)) { 427 return null;//for now, we do not provide a consist manager - TODO! 428 } 429 if (T.equals(jmri.CommandStation.class)) { 430 return (T) getCommandStation(); 431 } 432// if (T.equals(jmri.MultiMeter.class)) { 433// return (T) getMultiMeter(); 434// } 435 return super.get(T); 436 } 437 438 /** 439 * {@inheritDoc} 440 */ 441 @Override 442 @Nonnull 443 protected ResourceBundle getActionModelResourceBundle() { 444 log.debug("getActionModelResourceBundle"); 445 return ResourceBundle.getBundle("jmri.jmrix.bidib.BiDiBActionListBundle"); 446 } 447 448 /** 449 * {@inheritDoc} 450 */ 451 @Override 452 public <B extends NamedBean> Comparator<B> getNamedBeanComparator(Class<B> type) { 453 return new NamedBeanComparator<>(); 454 } 455 456 /** 457 * {@inheritDoc} 458 */ 459 @Override 460 public void dispose() { 461 log.info("---- dispose -----"); 462 InstanceManager.deregister(this, BiDiBSystemConnectionMemo.class); 463 if (predefinedMeters != null) { 464 predefinedMeters.dispose(); 465 } 466 if (cf != null) { 467 InstanceManager.deregister(cf, jmri.jmrix.swing.ComponentFactory.class); 468 } 469 super.dispose(); 470 tc = null; 471 } 472 473 private final static Logger log = LoggerFactory.getLogger(BiDiBSystemConnectionMemo.class); 474 475} 476