001package jmri.jmrix.can.cbus; 002 003import javax.annotation.Nonnull; 004 005import jmri.jmrix.can.CanSystemConnectionMemo; 006 007public class CbusEvent extends CbusEventDataElements { 008 009 private int _nn; 010 private int _en; 011 protected EvState _state; 012 protected String _name; 013 private final CanSystemConnectionMemo _memo; 014 015 /** 016 * Create a new event 017 * <p> 018 * New events have an unknown on or off status 019 * 020 * @param nn Node Number 021 * @param en Event Number 022 */ 023 public CbusEvent( int nn, int en){ 024 super(); 025 this._nn = nn; 026 this._en = en; 027 this._state = EvState.UNKNOWN; 028 this._name = ""; 029 this._memo = null; 030 } 031 032 /** 033 * Create a new event by Connection 034 * <p> 035 * New events have an unknown on or off status 036 * 037 * @param memo System Connection 038 * @param nn Node Number 039 * @param en Event Number 040 */ 041 public CbusEvent( CanSystemConnectionMemo memo, int nn, int en){ 042 super(); 043 this._nn = nn; 044 this._en = en; 045 this._state = EvState.UNKNOWN; 046 this._name = ""; 047 this._memo = memo; 048 } 049 050 /** 051 * Get state of the event 052 * 053 * @return the enum event state, on off or unknown. 054 * 055 */ 056 public EvState getState() { 057 return _state; 058 } 059 060 /** 061 * Set current state of the event. 062 * <p> 063 * Does NOT send update to layout. 064 * 065 * @param newval the enum event state ie ON, OFF, UNKNOWN 066 */ 067 public void setState( EvState newval ) { 068 _state = newval; 069 } 070 071 /** 072 * Get event event number 073 * 074 * @return event Number 075 * 076 */ 077 public int getEn() { 078 return _en; 079 } 080 081 /** 082 * Get event node number. 083 * 084 * @return node Number 085 */ 086 public int getNn(){ 087 return _nn; 088 } 089 090 /** 091 * Set event event number. 092 * 093 * @param en Event Number, not restricted so can be -1 for unknown 094 */ 095 public void setEn ( int en ) { 096 _en = en; 097 } 098 099 /** 100 * Set event node number. 101 * 102 * @param nn Node Number, not restricted so can be -1 for unknown 103 */ 104 public void setNn ( int nn ) { 105 _nn = nn; 106 } 107 108 /** 109 * Set event name. 110 * 111 * @param name new Event Name 112 */ 113 public void setName( String name ) { 114 _name = name; 115 } 116 117 /** 118 * Set event name only if there is no existing name. 119 * 120 * @param name Event Name 121 */ 122 public void setNameIfNoName (@Nonnull String name){ 123 if (_name.isEmpty()) { 124 _name = name; 125 } 126 } 127 128 /** 129 * Get event name. 130 * 131 * @return the Event Name 132 */ 133 @Nonnull 134 public String getName() { 135 return _name; 136 } 137 138 /** 139 * Get Node name. 140 * <p> 141 * Helper method, node name not stored in event, retrieved via @CbusNameService 142 * 143 * @return Node Name 144 */ 145 public String getNodeName() { 146 return new CbusNameService(_memo).getNodeName( getNn() ); 147 } 148 149 /** 150 * Test if a node and event number combination matches this event. 151 * 152 * @param nn Node Number 153 * @param en Event Number 154 * 155 * @return true on match, else false 156 */ 157 public boolean matches(int nn, int en) { 158 return (nn == _nn) && (en == _en); 159 } 160 161 /** 162 * {@inheritDoc} 163 * <p> 164 * Custom method to compare Node Number and Event Number. 165 */ 166 @Override 167 public boolean equals(Object o) { 168 return ((o instanceof CbusEvent) && matches(((CbusEvent) o).getNn(),((CbusEvent) o).getEn())); 169 } 170 171 /** {@inheritDoc} */ 172 @Override 173 public int hashCode() { 174 return java.util.Objects.hash(getEn(), getNn()); 175 } 176 177 /** 178 * Send ON event CAN frame. 179 * <p> 180 * Long event if Node num greater than 0, else short. 181 */ 182 public void sendOn(){ 183 sendEvent(EvState.ON); 184 } 185 186 /** 187 * Send OFF event CAN frame. 188 * <p> 189 * Long event if Node num greater than 0, else short. 190 */ 191 public void sendOff(){ 192 sendEvent(EvState.OFF); 193 } 194 195 /** 196 * Send event status request CAN frame. 197 * <p> 198 * Long request if Node num greater than 0, else short. 199 */ 200 public void sendRequest(){ 201 sendEvent(EvState.REQUEST); 202 } 203 204 /** 205 * Send event CAN frame via ENUM. 206 * <p> 207 * Also updates the event status as per the enum value. 208 * <p> 209 * If current state unknown, toggle sends event off. 210 * <p> 211 * Long event if Node num greater than 0, else short. 212 * 213 * @param state The enum state requested to be sent, ie ON, OFF, REQUEST, TOGGLE 214 */ 215 public void sendEvent(EvState state) { 216 CanSystemConnectionMemo memo; 217 if (_memo==null) { 218 memo = jmri.InstanceManager.getDefault(CanSystemConnectionMemo.class); 219 } else { 220 memo = _memo; 221 } 222 if ( state == EvState.TOGGLE ) { 223 if ( _state == EvState.OFF ) { 224 state =EvState.ON; 225 } 226 else { 227 state =EvState.OFF; 228 } 229 } 230 _state = state; 231 232 jmri.util.ThreadingUtil.runOnLayout( () -> { 233 memo.getTrafficController().sendCanMessage(getCanMessage(memo.getTrafficController().getCanid(),_nn,_en,_state), null); 234 } ); 235 } 236 237 /** 238 * Get a String with event overview. 239 * 240 * @return includes event name and node name if known 241 */ 242 @Override 243 public String toString() { 244 StringBuilder addevbuf = new StringBuilder(50); 245 if ( _nn > 0 ) { 246 addevbuf.append (Bundle.getMessage("OPC_NN")).append (":"); 247 addevbuf.append (_nn).append (" "); 248 if ( !getNodeName().isEmpty() ) { 249 addevbuf.append (getNodeName()).append (" "); 250 } 251 } 252 addevbuf.append (Bundle.getMessage("OPC_EN")).append (":"); 253 addevbuf.append (_en).append (" "); 254 if ( !getName().isEmpty() ) { 255 addevbuf.append ( getName() ).append (" "); 256 } 257 return addevbuf.toString(); 258 } 259 260 // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusEvent.class); 261 262}