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