001package jmri.jmrix.can.cbus; 002 003import jmri.implementation.AbstractLight; 004import jmri.jmrix.can.CanListener; 005import jmri.jmrix.can.CanMessage; 006import jmri.jmrix.can.CanReply; 007import jmri.jmrix.can.TrafficController; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011/** 012 * Light implementation for CBUS connections. 013 * 014 * @author Matthew Harris Copyright (C) 2015 015 */ 016public class CbusLight extends AbstractLight implements CanListener, CbusEventInterface { 017 018 private CbusAddress addrOn; // go to on state 019 private CbusAddress addrOff; // go to off state 020 021 protected CbusLight(String prefix, String address, TrafficController tc) { 022 super(prefix + "L" + address); 023 this.tc = tc; 024 init(address); 025 } 026 027 private final TrafficController tc; 028 029 /** 030 * Common initialization for both constructors. 031 * <p> 032 * 033 */ 034 private void init(String address) { 035 // build local addresses 036 CbusAddress a = new CbusAddress(address); 037 CbusAddress[] v = a.split(); 038 switch (v.length) { 039 case 0: 040 log.error("Did not find usable system name: {}", address); 041 return; 042 case 1: 043 addrOn = v[0]; 044 // need to complement here for addr 1 045 // so address _must_ start with address + or - 046 if (address.startsWith("+")) { 047 addrOff = new CbusAddress("-" + address.substring(1)); 048 } else if (address.startsWith("-")) { 049 addrOff = new CbusAddress("+" + address.substring(1)); 050 } else { 051 log.error("can't make 2nd event from systemname {}", address); 052 return; 053 } 054 break; 055 case 2: 056 addrOn = v[0]; 057 addrOff = v[1]; 058 break; 059 default: 060 log.error("Can't parse CbusLight system name: {}", address); 061 return; 062 } 063 // connect 064 addTc(tc); 065 } 066 067 /** 068 * Handle a request to change state by sending CBUS events. 069 * 070 */ 071 @Override 072 protected void doNewState(int oldState, int newState) { 073 CanMessage m; 074 switch (newState) { 075 case ON: 076 m = addrOn.makeMessage(tc.getCanid()); 077 CbusMessage.setPri(m, CbusConstants.DEFAULT_DYNAMIC_PRIORITY * 4 + CbusConstants.DEFAULT_MINOR_PRIORITY); 078 tc.sendCanMessage(m, this); 079 break; 080 case OFF: 081 m = addrOff.makeMessage(tc.getCanid()); 082 CbusMessage.setPri(m, CbusConstants.DEFAULT_DYNAMIC_PRIORITY * 4 + CbusConstants.DEFAULT_MINOR_PRIORITY); 083 tc.sendCanMessage(m, this); 084 break; 085 default: 086 log.warn("illegal state requested for Light: {}", getSystemName()); 087 break; 088 } 089 } 090 091 /** {@inheritDoc} */ 092 @Override 093 public void requestUpdateFromLayout() { 094 CanMessage m = addrOn.makeMessage(tc.getCanid()); 095 m.setOpCode( CbusOpCodes.isShortEvent(CbusMessage.getOpcode(m)) ? CbusConstants.CBUS_ASRQ : CbusConstants.CBUS_AREQ); 096 CbusMessage.setPri(m, CbusConstants.DEFAULT_DYNAMIC_PRIORITY * 4 + CbusConstants.DEFAULT_MINOR_PRIORITY); 097 tc.sendCanMessage(m, this); 098 } 099 100 /** {@inheritDoc} */ 101 @Override 102 public void message(CanMessage f) { 103 if ( f.extendedOrRtr() ) { 104 return; 105 } 106 if (addrOn.match(f)) { 107 notifyStateChange(getState(), ON); 108 } else if (addrOff.match(f)) { 109 notifyStateChange(getState(), OFF); 110 } 111 } 112 113 /** {@inheritDoc} */ 114 @Override 115 public void reply(CanReply origf) { 116 if ( origf.extendedOrRtr() ) { 117 return; 118 } 119 // convert response events to normal 120 CanReply f = CbusMessage.opcRangeToStl(origf); 121 if (addrOn.match(f)) { 122 notifyStateChange(getState(), ON); 123 } else if (addrOff.match(f)) { 124 notifyStateChange(getState(), OFF); 125 } 126 } 127 128 /** 129 * Get a CanMessage for the On Light Address. 130 * @return CanMessage for Light ON 131 */ 132 public CanMessage getAddrOn(){ 133 return addrOn.makeMessage(tc.getCanid()); 134 } 135 136 /** 137 * Get a CanMessage for the Off Light Address. 138 * @return CanMessage for Light OFF 139 */ 140 public CanMessage getAddrOff(){ 141 return addrOff.makeMessage(tc.getCanid()); 142 } 143 144 /** 145 * {@inheritDoc} 146 */ 147 @Override 148 public CanMessage getBeanOnMessage(){ 149 return checkEvent(getAddrOn()); 150 } 151 152 /** 153 * {@inheritDoc} 154 */ 155 @Override 156 public CanMessage getBeanOffMessage(){ 157 return checkEvent(getAddrOff()); 158 } 159 160 /** 161 * {@inheritDoc} 162 */ 163 @Override 164 public void dispose() { 165 tc.removeCanListener(this); 166 super.dispose(); 167 } 168 169 private static final Logger log = LoggerFactory.getLogger(CbusLight.class); 170}