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