001package jmri.jmrix.dccpp; 002 003import jmri.implementation.AbstractLight; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007/** 008 * Implementation of the Light Object for DCC++ 009 * <p> 010 * NOTE: This is a simplification of the DCCppTurnout class. 011 * <p> 012 * Based in part on SerialLight.java 013 * 014 * @author Paul Bender Copyright (C) 2008-2010 015 * @author Mark Underwood Copyright (C) 2015 016 */ 017public class DCCppLight extends AbstractLight implements DCCppListener { 018 019 private DCCppTrafficController tc = null; 020 private DCCppLightManager lm = null; 021 022 /** 023 * Create a Light object, with only system name. 024 * <p> 025 * 'systemName' was previously validated in DCCppLightManager 026 * 027 * @param tc the traffic controller for the connection 028 * @param lm the managing LightManager for this Light 029 * @param systemName the system name for this Light 030 */ 031 public DCCppLight(DCCppTrafficController tc, DCCppLightManager lm, String systemName) { 032 super(systemName); 033 this.tc = tc; 034 this.lm = lm; 035 // Initialize the Light 036 initializeLight(systemName); 037 } 038 039 /** 040 * Create a Light object, with both system and user names. 041 * <p> 042 * 'systemName' was previously validated in DCCppLightManager 043 * 044 * @param tc the traffic controller for the connection 045 * @param lm the managing LightManager for this Light 046 * @param systemName the system name for this Light 047 * @param userName the user name for this Light 048 */ 049 public DCCppLight(DCCppTrafficController tc, DCCppLightManager lm, String systemName, String userName) { 050 super(systemName, userName); 051 this.tc = tc; 052 this.lm = lm; 053 // Initialize the Light 054 initializeLight(systemName); 055 } 056 057 /** 058 * Dispose of the light object. 059 */ 060 @Override 061 public void dispose() { 062 tc.removeDCCppListener(DCCppInterface.FEEDBACK | DCCppInterface.COMMINFO | DCCppInterface.CS_INFO, this); 063 super.dispose(); 064 } 065 066 /** 067 * Initialize the light object's parameters. 068 */ 069 private synchronized void initializeLight(String systemName) { 070 // Extract the Bit from the name 071 mAddress = lm.getBitFromSystemName(systemName); 072 // Set initial state 073 setState(OFF); 074 // At construction, register for messages 075 tc.addDCCppListener(DCCppInterface.FEEDBACK | DCCppInterface.COMMINFO | DCCppInterface.CS_INFO, this); 076 } 077 078 /** 079 * Sets up system dependent instance variables and set system independent 080 * instance variables to default values. 081 * <p> 082 * Note: most instance variables are in AbstractLight.java 083 */ 084 085 /** 086 * System dependent instance variables 087 */ 088 //protected int mState = OFF; // current state of this light 089 //private int mOldState =mState; // save the old state 090 int mAddress = 0; // accessory output address 091 092 /* Internal State Machine states. */ 093 static final int OFFSENT = 1; 094 static final int COMMANDSENT = 2; 095 static final int IDLE = 0; 096 //private int InternalState = IDLE; 097 098 /** 099 * Set the current state of this Light. 100 * This routine requests the hardware to change. 101 */ 102 @Override 103 synchronized public void setState(int newState) { 104 if (newState != ON && newState != OFF) { 105 // Unsupported state 106 log.warn("Unsupported state {} requested for light {}", newState, getSystemName()); 107 return; 108 } 109 110 log.debug("Light Set State: mstate = {} newstate = {}", mState, newState); 111 112 // get the right packet 113 if (mAddress > 0) { 114 boolean state = (newState == jmri.Light.ON); 115 DCCppMessage msg = DCCppMessage.makeAccessoryDecoderMsg(mAddress, state); 116 //InternalState = COMMANDSENT; 117 tc.sendDCCppMessage(msg, this); 118 119 if (newState != mState) { 120 int oldState = mState; 121 mState = newState; 122 // notify listeners, if any 123 firePropertyChange("KnownState", oldState, newState); 124 } 125 } 126 } 127 128 /** 129 * {@inheritDoc} 130 * Handle an incoming message from the DCC++ Base Station. 131 * <p> 132 * NOTE: We aren't registered as a listener, so this is only triggered 133 * when we send out a message 134 */ 135 @Override 136 synchronized public void message(DCCppReply l) { 137 log.debug("received message: {}", l); 138 // We don't expect a reply, so we don't do anything with replies. 139 } 140 141 /** 142 * {@inheritDoc} 143 * Listen for messages to the DCC++ Base Station. 144 */ 145 @Override 146 public void message(DCCppMessage l) { 147 // messages not handled by DCCpp lights 148 } 149 150 // Handle a timeout notification 151 @Override 152 public void notifyTimeout(DCCppMessage msg) { 153 log.debug("Notified of timeout on message '{}'", msg); 154 } 155 156 private final static Logger log = LoggerFactory.getLogger(DCCppLight.class); 157 158}