001package jmri.jmrit.ussctc; 002 003 004import java.util.*; 005 006/** 007 * A Station represents a specific codeline field station. 008 * It defines the bits in the code message and holds references to the 009 * hardware at both ends that is controlled by those bits. For example: 010 * <ul> 011 * <li>Two bits for Turnouts, see {@link CodeGroupTwoBits} 012 * <li>Three bits for Signals, see {@link CodeGroupThreeBits} 013 * <li>One bit for maintainer call, track circuits, etc, see {@link CodeGroupOneBit} 014 * </ul> 015 * The basic structure is to mate two objects that interact via a 016 * shared enum. Alternately, this can be a single object: e.g. a 017 * {@link TurnoutSection} that functions in both the central CTC machine and field hardware roles. 018 * <ul> 019 * <li>The field object listens to the status of the layout and sends indications on changes. 020 * <p>The central (CTC machine) object responds to those indications. 021 * <li>The central (CTC machine) object sends when Code is pressed. 022 * <p>The field object responds to those when received. 023 * </ul> 024 * 025 * @author Bob Jacobsen Copyright (C) 2007, 2017 026 */ 027public class Station<To extends Enum<To>, From extends Enum<From>> { 028 029 public Station(String name, CodeLine codeline, CodeButton button) { 030 this.name = name; 031 this.codeline = codeline; 032 this.button = button; 033 034 button.addStation(this); // register with Codebutton 035 } 036 037 String name; 038 CodeLine codeline; 039 CodeButton button; 040 041 /** 042 * @param section next Section subclass that makes up part of this Station 043 * @return this Station to allow chaining 044 */ 045 public Station<To, From> add(Section<To, From> section) { 046 sections.add(section); 047 return this; 048 } 049 050 /** 051 * Provide access to CodeLine to which this Station is attached. 052 * @return Codeline reference for this Station 053 */ 054 CodeLine getCodeLine() { return codeline; } 055 056 /** 057 * Provide access this Station's name 058 * @return Human-readable name 059 */ 060 String getName() { return name; } 061 062 @Override 063 public String toString() { 064 StringBuffer retval = new StringBuffer("Station "+name+"\n sentValues:"); 065 066 if (sentValues == null) retval.append(" (null)"); 067 else { 068 for (Enum<?> e : sentValues) { 069 retval.append(" "); 070 retval.append(e); 071 } 072 } 073 074 retval.append("\n indicationValues:"); 075 if (indicationValues == null) retval = retval.append(" (null)"); 076 else { 077 for (Enum<?> e : sentValues) { 078 retval.append(" "); 079 retval.append(e); 080 } 081 } 082 083 return new String(retval); 084 } 085 086 /** 087 * Tell the Sections to start a code-send operation (from machine to field). 088 * Usually comes from a {@link CodeButton} 089 */ 090 public void codeSendRequest() { 091 log.debug("Station - start codeSendRequest"); 092 sentValues = new ArrayList<>(); 093 sections.forEach((section) -> { 094 // accumulate send values, which also sets indicators 095 sentValues.add(section.codeSendStart()); 096 } ); 097 098 codeline.requestSendCode(this); 099 log.debug("Station - end codeSendRequest"); 100 101 } 102 103 public void codeSendComplete() { 104 log.debug("Station - start codeSendComplete"); 105 106 // notify 107 sections.forEach((section) -> { 108 // accumulate send values, which also sets indicators 109 sentValues.add(section.codeSendStart()); 110 } ); 111 112 log.debug("Station - end codeSendComplete"); 113 } 114 115 /** 116 * Tell the sections that code information has arrived in the field 117 */ 118 public void codeValueDelivered() { 119 log.debug("Station - start codeValueDelivered"); 120 // clear the code light 121 button.codeValueDelivered(); 122 123 // tell each section 124 for (int i = 0; i < sections.size(); i++) { 125 sections.get(i).codeValueDelivered(sentValues.get(i)); 126 } 127 log.debug("Station - end codeValueDelivered"); 128 } 129 130 131 public void requestIndicationStart() { 132 log.debug("Station - start requestIndicationStart"); 133 codeline.requestIndicationStart(this); 134 log.debug("Station - end requestIndicationStart"); 135 } 136 137 /** 138 * Gather layout status and turn on code lamp. 139 * Rest of action is on indicationComplete 140 */ 141 public void indicationStart() { 142 log.debug("Station - start indicationStart"); 143 144 button.indicationStart(); 145 146 indicationValues = new ArrayList<>(); 147 sections.forEach((section) -> { 148 // accumulate send values, which also sets indicators 149 indicationValues.add(section.indicationStart()); 150 } ); 151 log.debug("Station - end indicationStart"); 152 } 153 154 /** 155 * Gather layout status and turn on code lamp. 156 * Rest of action is on indicationComplete 157 */ 158 public void indicationComplete() { 159 log.debug("Station - start indicationComplete"); 160 161 // tell each section 162 for (int i = 0; i < sections.size(); i++) { 163 sections.get(i).indicationComplete(indicationValues.get(i)); 164 } 165 // clear the code light 166 button.indicationComplete(); 167 168 log.debug("Station - end indicationComplete"); 169 } 170 171 ArrayList<Section<To, From>> sections = new ArrayList<>(); 172 ArrayList<To> sentValues; 173 ArrayList<From> indicationValues; 174 175 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Station.class); 176}