001package jmri.jmrix.can.cbus; 002 003import jmri.implementation.DefaultCabSignal; 004import jmri.jmrix.can.CanSystemConnectionMemo; 005import jmri.jmrix.can.CanMessage; 006import jmri.jmrix.can.TrafficController; 007import jmri.LocoAddress; 008import jmri.SignalAppearanceMap; 009import jmri.SignalMast; 010 011/** 012 * CBUS implementation of a Cab Signal Object, describing the state of the 013 * track ahead relative to a locomotive with a given address. This is 014 * effectively a mobile signal mast. 015 * <p> 016 * Uses an experimental MERG CBUS OPC 017 * todo - add semaphore flags 018 * todo - add loco speed / block speed 019 * 020 * @author Steve Young Copyright (C) 2018 021 * @author Paul Bender Copyright (C) 2019 022 */ 023public class CbusCabSignal extends DefaultCabSignal { 024 025 private TrafficController tc; 026 027 public CbusCabSignal(CanSystemConnectionMemo memo,LocoAddress address){ 028 super(address); 029 tc = memo.getTrafficController(); 030 log.debug("created cab signal for {}",address); 031 } 032 033 /** 034 * A method for cleaning up the cab signal 035 */ 036 @Override 037 public void dispose(){ 038 super.dispose(); 039 tc=null; 040 } 041 042 /** 043 * Forward the command to the layout that sets the displayed signal 044 * aspect for this address 045 */ 046 @Override 047 protected void forwardAspectToLayout(){ 048 LocoAddress locoaddr = getCabSignalAddress(); 049 SignalMast mast = getNextMast(); 050 051 int locoAddr = locoaddr.getNumber(); 052 if (locoaddr.getProtocol() == (LocoAddress.Protocol.DCC_LONG)) { 053 locoAddr |= 0xC000; 054 } 055 // Calculate the two byte loco address value 056 int locoD1 = locoAddr / 256; 057 int locoD2 = locoAddr & 0xff; 058 059 int sendAspect1 = 0xff; // default case, unknown. 060 int sendAspect2 = 0x00; 061 int sendSpeed = 0xff; // default case, unknown. 062 063 if ( mast != null ) { 064 // String speed = (String) mast.getSignalSystem().getProperty(mast.getAspect(), "speed"); 065 String aspect = mast.getAspect(); 066 if ( aspect != null ) { 067 switch( aspect ) { // in a future java, add null to switch case 068 case "Danger": // NOI18N 069 case "On": // NOI18N 070 sendAspect1 = 0; 071 break; 072 case "Caution": // NOI18N 073 sendAspect1 = 1; 074 break; 075 case "Preliminary Caution": // NOI18N 076 sendAspect1 = 2; 077 break; 078 case "Proceed": // NOI18N 079 sendAspect1 = 3; 080 break; 081 case "Off": // NOI18N 082 sendAspect1 = 4; 083 break; 084 case "Flash Caution": // NOI18N 085 sendAspect1 = 1; 086 sendAspect2 = 1; 087 break; 088 case "Flash Preliminary Caution": // NOI18N 089 sendAspect1 = 2; 090 sendAspect2 = 1; 091 break; 092 default: { 093 // if no matching speed in the list above, check for 094 // the constant values in the SignalAppearanceMap. 095 if(aspect.equals(mast.getAppearanceMap().getSpecificAppearance(SignalAppearanceMap.PERMISSIVE))){ 096 sendAspect1 = 0x04; 097 } else if(aspect.equals(mast.getAppearanceMap().getSpecificAppearance(SignalAppearanceMap.DANGER))){ 098 sendAspect1 = 0x00; 099 } else if(aspect.equals(mast.getAppearanceMap().getSpecificAppearance(SignalAppearanceMap.HELD))){ 100 sendAspect1 = 0x00; 101 } else if(aspect.equals(mast.getAppearanceMap().getSpecificAppearance(SignalAppearanceMap.DARK))){ 102 sendAspect1 = 0x00; // show nothing; 103 } 104 } 105 } 106 } 107 } 108 109 CanMessage m = new CanMessage(7,tc.getCanid()); 110 CbusMessage.setPri(m, CbusConstants.DEFAULT_DYNAMIC_PRIORITY * 4 + CbusConstants.DEFAULT_MINOR_PRIORITY); 111 m.setElement(0, CbusConstants.CBUS_CABDAT); 112 m.setElement(1, locoD1); // addr hi 113 m.setElement(2, locoD2); // addr low 114 m.setElement(3, 1); // datcode type 115 m.setElement(4, ( sendAspect1 )); // aspect 1 116 m.setElement(5, ( sendAspect2 )); // aspect 2 117 m.setElement(6, ( sendSpeed ) ); // speed 118 tc.sendCanMessage(m, null); 119 } 120 121 /** 122 * Forward the command to the layout that clears any displayed signal 123 * for this address 124 */ 125 @Override 126 protected void resetLayoutCabSignal(){ 127 LocoAddress locoaddr = getCabSignalAddress(); 128 int locoAddr = locoaddr.getNumber(); 129 if (locoaddr.getProtocol()==(LocoAddress.Protocol.DCC_LONG)) { 130 locoAddr |= 0xC000; 131 } 132 // Calculate the two byte loco address value 133 int locoD1 = locoAddr / 256; 134 int locoD2 = locoAddr & 0xff; 135 136 CanMessage m = new CanMessage(7,tc.getCanid()); 137 CbusMessage.setPri(m, CbusConstants.DEFAULT_DYNAMIC_PRIORITY * 4 + CbusConstants.DEFAULT_MINOR_PRIORITY); 138 m.setElement(0, CbusConstants.CBUS_CABDAT); // experimental cabdata opc 139 m.setElement(1, locoD1); // addr hi 140 m.setElement(2, locoD2); // addr low 141 m.setElement(3, 1); // datcode type 142 m.setElement(4, ( 0xff )); // aspect 1 143 m.setElement(5, ( 0 )); // aspect 2 144 m.setElement(6, ( 0xff )); // speed 145 tc.sendCanMessage(m, null); 146 } 147 148 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusCabSignal.class); 149 150}