001package jmri.jmrit.ussctc;
002
003import jmri.*;
004
005/**
006 * Drive a single Track Circuit section on a USS CTC panel.
007 *
008 * @author Bob Jacobsen Copyright (C) 2007, 2017
009 * TODO - add field state diagram
010 */
011
012public class TrackCircuitSection implements Section<CodeGroupNoBits, CodeGroupOneBit> {
013
014    /**
015     *  Anonymous object only for testing
016     */
017    TrackCircuitSection() {}
018
019    /**
020     * Create and configure.
021     *
022     * Accepts user or system names.
023     *
024     * @param inputSensor  Sensor for occupancy on layout
025     * @param panelOutput  Turnout drives lamp on panel
026     * @param station Station to which this Section belongs
027     * @param bell  Bell driver (can be null)
028     */
029    public TrackCircuitSection(String inputSensor, String panelOutput, Station<CodeGroupNoBits, CodeGroupOneBit> station, Bell bell) {
030        NamedBeanHandleManager hm = InstanceManager.getDefault(NamedBeanHandleManager.class);
031        TurnoutManager tm = InstanceManager.getDefault(TurnoutManager.class);
032        SensorManager sm = InstanceManager.getDefault(SensorManager.class);
033
034        hInputSensor = hm.getNamedBeanHandle(inputSensor, sm.provideSensor(inputSensor));
035        hPanelOutput = hm.getNamedBeanHandle(panelOutput, tm.provideTurnout(panelOutput));
036        this.station = station;
037        this.bell = bell;
038
039        // align at start
040        indicationComplete(indicationStart());
041
042        // attach listeners for future changes
043        sm.provideSensor(inputSensor).addPropertyChangeListener((java.beans.PropertyChangeEvent e) -> {layoutTurnoutChanged(e);});
044    }
045
046    /**
047     * Create and configure.
048     * <p>
049     * Accepts user or system names.
050     *
051     * @param inputSensor  Sensor for input from central CTC machine
052     * @param panelOutput  Turnout name for maintainer call on layout
053     * @param station      Station to which this Section belongs
054     */
055    public TrackCircuitSection(String inputSensor, String panelOutput, Station<CodeGroupNoBits, CodeGroupOneBit> station) {
056        this(inputSensor, panelOutput, station, null);
057    }
058
059    NamedBeanHandle<Sensor> hInputSensor;
060    NamedBeanHandle<Turnout> hPanelOutput;
061
062    Bell bell;
063
064    Station<CodeGroupNoBits, CodeGroupOneBit> station;
065    @Override
066    public Station<CodeGroupNoBits, CodeGroupOneBit> getStation() { return station; }
067    @Override
068    public String getName() { return "TC for "+hInputSensor.getBean().getDisplayName(); }
069
070     /**
071     * Start of sending code operation.
072      *
073     * @return code line value to transmit
074     */
075    @Override
076    public CodeGroupNoBits codeSendStart() {
077        return CodeGroupNoBits.None;
078    }
079
080    /**
081     * Process values received from the field unit.
082     */
083    @Override
084    public void indicationComplete(CodeGroupOneBit value) {
085        if ( value == CodeGroupOneBit.Single1 && hPanelOutput.getBean().getCommandedState()!=Turnout.THROWN ) {
086            hPanelOutput.getBean().setCommandedState(Turnout.THROWN);
087            if (bell != null) bell.ring();   // ring on arrival
088        } else if (value == CodeGroupOneBit.Single0 && hPanelOutput.getBean().getCommandedState()!=Turnout.CLOSED ) {
089            hPanelOutput.getBean().setCommandedState(Turnout.CLOSED);
090        }
091    }
092
093    /**
094     * Notification that code has arrived in the field. Sets the turnout on the layout.
095     */
096    @Override
097    public void codeValueDelivered(CodeGroupNoBits value) {
098    }
099
100    /**
101     * Provide state that's returned from field to machine via indication.
102     */
103    @Override
104    public CodeGroupOneBit indicationStart() {
105        // Everything _except_ a clean INACTIVE shows active
106        if (hInputSensor.getBean().getState()!=Sensor.INACTIVE) return CodeGroupOneBit.Single1;
107        return CodeGroupOneBit.Single0;
108    }
109
110    void layoutTurnoutChanged(java.beans.PropertyChangeEvent e) {
111        if (e.getPropertyName().equals("KnownState") && !e.getNewValue().equals(e.getOldValue()) ) {
112            log.debug("Sensor changed from {} to {}, so requestIndicationStart", e.getOldValue(), e.getNewValue());
113            // Always send an indication if there's a change in the turnout
114            station.requestIndicationStart();
115        }
116    }
117
118    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TrackCircuitSection.class);
119
120}