001package jmri.jmrix.maple; 002 003import jmri.jmrix.AbstractMRListener; 004import jmri.jmrix.AbstractMRMessage; 005import jmri.jmrix.AbstractNode; 006import org.slf4j.Logger; 007import org.slf4j.LoggerFactory; 008 009/** 010 * Models a serial node, consisting of one Maple Systems HMI touch screen panel. 011 * <p> 012 * Nodes are numbered ala the Station number, from 1 to 99. 013 * <p> 014 * The array of sensor states is used to update sensor known state only when 015 * there's a change on the serial bus. This allows for the sensor state to be 016 * updated within the program, keeping this updated state until the next change 017 * on the serial bus. E.g. you can manually change a state via an icon, and not 018 * have it change back the next time that node is polled. 019 * 020 * @author Bob Jacobsen Copyright (C) 2003, 2008 021 * @author Bob Jacobsen, Dave Duchamp, multiNode extensions, 2004 022 * @author Bob Jacobsen, Dave Duchamp, revised for Maple, 2009 023 */ 024public class SerialNode extends AbstractNode { 025 026 /** 027 * Maximum number of sensors for Maple. 028 */ 029 static final int MAXSENSORS = 1000; 030 031 // class constants 032 // node definition instance variables (must persist between runs) 033 // protected int pulseWidth = 500; // Pulse width for pulsed turnout control (milliseconds) 034 private int _address = 0; 035 036 // operational instance variables (should not be preserved between runs) 037 038 /** 039 * Assumes a node address of 1, and a node type of 0. 040 * If this constructor is used, actual node address must be set using setNodeAddress. 041 * @param tc serial traffic controller. 042 */ 043 public SerialNode(SerialTrafficController tc) { 044 this(1, 0, tc); 045 } 046 047 /** 048 * Create a new SerialNode and initialize default instance variables. 049 * 050 * @param address Address of node on serial bus (0-99) 051 * @param type 0 (ignored) 052 * @param tc system traffic controller. 053 */ 054 public SerialNode(int address, int type, SerialTrafficController tc) { 055 // set address 056 setNodeAddress(address); 057 _address = address; 058 // register this node 059 tc.registerNode(this); 060 } 061 062 /** 063 * Get state of Sensors. 064 * 065 * @return 'true' since at least one sensor is defined 066 */ 067 @Override 068 public boolean getSensorsActive() { 069 return true; 070 } 071 072 /** 073 * Check valid node address, must match value configured in the Maple HMI. 074 * 075 * @param address node ID, allowed values are 1-99 076 * @return true if in valid range 077 */ 078 @Override 079 protected boolean checkNodeAddress(int address) { 080 return (address > 0) && (address <= 99); 081 } 082 083 /** 084 * Get this node's address. 085 * @return node address. 086 */ 087 public int getAddress() { 088 return _address; 089 } 090 091 /** 092 * Create an Initialization packet (SerialMessage) for this 093 * node. 094 * <p> 095 * Note: Maple Systems devices do not need initialization. This is here 096 * for completion. 097 */ 098 @Override 099 public AbstractMRMessage createInitPacket() { 100 return null; 101 } 102 103 /** 104 * Create a Transmit packet (SerialMessage). Not used in Maple. 105 */ 106 @Override 107 public AbstractMRMessage createOutPacket() { 108 return null; 109 } 110 111 boolean warned = false; 112 113 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( value = "SLF4J_FORMAT_SHOULD_BE_CONST", 114 justification = "only logging 1st warning string passed") 115 void warn(String s) { 116 if (warned) { 117 return; 118 } 119 warned = true; 120 log.warn(s); 121 } 122 123 int timeout = 0; 124 125 /** 126 * {@inheritDoc} 127 * 128 * @return true if initialization required 129 */ 130 @Override 131 public boolean handleTimeout(AbstractMRMessage m, AbstractMRListener l) { 132 // increment timeout count 133 timeout++; 134 log.warn("Poll of node {} timed out. Timeout count = {}", _address, timeout); 135 return false; 136 } 137 138 @Override 139 public void resetTimeout(AbstractMRMessage m) { 140 if (timeout > 0) { 141 log.debug("Reset {} timeout count", timeout); 142 } 143 timeout = 0; 144 } 145 146 public int getTimeoutCount() { 147 return timeout; 148 } 149 150 private final static Logger log = LoggerFactory.getLogger(SerialNode.class); 151 152}