001package jmri.jmrix.loconet;
002
003import jmri.implementation.DefaultCabSignal;
004import jmri.LocoAddress;
005import jmri.SignalMast;
006import org.slf4j.Logger;
007import org.slf4j.LoggerFactory;
008
009/**
010 * Ln implementation of a Cab Signal Object, describing the state of the 
011 * track ahead relative to a locomotive with a given address.  This is 
012 * effectively a mobile signal mast.
013 *
014 * @author Steve Young Copyright (C) 2018
015 * @author Paul Bender Copyright (C) 2019
016 */
017public class LnCabSignal extends DefaultCabSignal {
018
019    private LocoNetSystemConnectionMemo _memo = null;
020
021    public LnCabSignal(LocoNetSystemConnectionMemo memo,LocoAddress address){
022       super(address);
023       _memo = memo;
024       log.debug("created cab signal for {}",address);
025    }
026
027    /**
028     * A method for cleaning up the cab signal 
029     */
030    @Override
031    public void dispose(){
032        super.dispose();
033        _memo=null;
034    }
035
036    /**
037     * Forward the command to the layout that sets the displayed signal
038     * aspect for this address
039     */
040    @Override
041    protected void forwardAspectToLayout(){
042        LocoAddress locoaddr = getCabSignalAddress();
043        SignalMast mast = getNextMast();
044        // adapted from cabsignaller.py by Nigel Cliffe
045        // Message variables are Loco = Decimal loco address,
046
047        // Calculate the two byte loco address value
048        int locoD1 = locoaddr.getNumber() / 128;  //integer division, automatically rounds
049        int locoD2 = locoaddr.getNumber() % 128;  //modulo division, gets the remainder.
050        // determine the mast
051        //  others are binary 1 or 0
052        //  bit 4 = 1 show mast,  bit 4 = 0 hide mast.
053        //  bit 3 = 1 show vertical, bit 3 = 0 hide vertical
054        //  bit 2 = 1 show diagonal, bit 2 = 0 hide diagonal
055        //  bit 1 = 1 show horizontal, bit 1 = 0 hide horizontal
056        //  bit 0 = 1 blink, bit 0 = 0 no blink
057        int signalD3=0; // default case, off.
058
059        if(mast!=null){
060           String speed = (String) mast.getSignalSystem().getProperty(mast.getAspect(), "speed");
061           // set aspect based on signal "speed" first.
062           switch(speed) {
063              case "Normal":
064              case "Clear":
065                    signalD3 = 0x18; // show vertical;
066                    break;
067              case "Limited":
068                    signalD3 = 0x19; // show vertical blinking;
069                    break;
070              case "Medium":
071                    signalD3 = 0x14; // show diagonal;
072                    break;
073              case "Stop":
074                    signalD3 = 0x12; // show horizontal (stop);
075                    break;
076              case "Restricting":
077              case "RestrictedSlow":
078              case "Restricted":
079              case "Slow":
080                    signalD3 = 0x13; // blink horizontal
081                    break;
082              default: {
083                   // if no matching speed in the list above, check for
084                   // the constant values in the SignalAppearanceMap.
085                   if(mast.getAspect().equals(mast.getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.PERMISSIVE))){
086                      signalD3 = 0x18; // show vertical;
087                   } else if(mast.getAspect().equals(mast.getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.DANGER))){
088                      signalD3 = 0x12; // show horizontal (stop);
089                   } else if(mast.getAspect().equals(mast.getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.HELD))){
090                      signalD3 = 0x12; // show horizontal (stop);
091                   } else if(mast.getAspect().equals(mast.getAppearanceMap().getSpecificAppearance(jmri.SignalAppearanceMap.DARK))){
092                      signalD3 = 0x00; // show nothing;
093                   } else {
094                      signalD3 = 0x14; // show diagonal;*/
095                   }
096               }
097           }
098        }
099        // this is a litteral translation from the script.  it should be
100        // created from a method in LocoNetMessage.
101        LocoNetMessage peerXFerMessage = new LocoNetMessage(16);
102        peerXFerMessage.setOpCode(229);
103        peerXFerMessage.setElement(1,16);
104        peerXFerMessage.setElement(2,127);
105        peerXFerMessage.setElement(3,0);
106        peerXFerMessage.setElement(4,0);
107        peerXFerMessage.setElement(5,0);
108        peerXFerMessage.setElement(6,locoD1);
109        peerXFerMessage.setElement(7,locoD2);
110        peerXFerMessage.setElement(8,signalD3);
111        peerXFerMessage.setElement(9,0);
112        peerXFerMessage.setElement(10,112);
113        peerXFerMessage.setElement(11,0);
114        peerXFerMessage.setElement(12,0);
115        peerXFerMessage.setElement(13,0);
116        peerXFerMessage.setElement(14,0);
117        peerXFerMessage.setElement(15,0);
118
119        _memo.getLnTrafficController().sendLocoNetMessage(peerXFerMessage);
120    }
121
122    /**
123     * Forward the command to the layout that clears any displayed signal
124     * for this address
125     */
126    @Override
127    protected void resetLayoutCabSignal(){
128        LocoAddress locoaddr = getCabSignalAddress();
129        // Calculate the two byte loco address value
130        int locoD1 = locoaddr.getNumber() / 128;  //integer division, automatically rounds
131        int locoD2 = locoaddr.getNumber() % 128;  //modulo division, gets the remainder.
132        int signalD3=0; // off.
133
134        LocoNetMessage peerXFerMessage = new LocoNetMessage(16);
135        peerXFerMessage.setOpCode(229);
136        peerXFerMessage.setElement(1,16);
137        peerXFerMessage.setElement(2,127);
138        peerXFerMessage.setElement(3,0);
139        peerXFerMessage.setElement(4,0);
140        peerXFerMessage.setElement(5,0);
141        peerXFerMessage.setElement(6,locoD1);
142        peerXFerMessage.setElement(7,locoD2);
143        peerXFerMessage.setElement(8,signalD3);
144        peerXFerMessage.setElement(9,0);
145        peerXFerMessage.setElement(10,112);
146        peerXFerMessage.setElement(11,0);
147        peerXFerMessage.setElement(12,0);
148        peerXFerMessage.setElement(13,0);
149        peerXFerMessage.setElement(14,0);
150        peerXFerMessage.setElement(15,0);
151        _memo.getLnTrafficController().sendLocoNetMessage(peerXFerMessage);
152    }
153
154    private final static Logger log = LoggerFactory.getLogger(LnCabSignal.class);
155
156
157}