001package jmri.jmrix.loconet; 002 003import java.util.ArrayList; 004import java.util.Vector; 005import javax.annotation.Nonnull; 006 007import org.slf4j.Logger; 008import org.slf4j.LoggerFactory; 009 010/** 011 * Abstract base class for implementations of LocoNetInterface. 012 * <p> 013 * This provides just the basic interface and some statistics support. 014 * 015 * @author Bob Jacobsen Copyright (C) 2001 016 */ 017public abstract class LnTrafficController implements LocoNetInterface { 018 019 /** 020 * Reference to the system connection memo. 021 */ 022 LocoNetSystemConnectionMemo memo = null; 023 024 /** 025 * Constructor without reference to a LocoNetSystemConnectionMemo. 026 */ 027 public LnTrafficController() { 028 super(); 029 } 030 031 /** 032 * Constructor. Gets a reference to the LocoNetSystemConnectionMemo. 033 * 034 * @param memo connection's memo 035 */ 036 public LnTrafficController(LocoNetSystemConnectionMemo memo) { 037 super(); 038 this.memo = memo; 039 } 040 041 /** 042 * {@inheritDoc} 043 */ 044 @Override 045 public void setSystemConnectionMemo(LocoNetSystemConnectionMemo m) { 046 log.debug("LnTrafficController set memo to {}", m.getUserName()); 047 memo = m; 048 } 049 050 /** 051 * {@inheritDoc} 052 */ 053 @Override 054 public LocoNetSystemConnectionMemo getSystemConnectionMemo() { 055 log.debug("getSystemConnectionMemo {} called in LnTC", memo.getUserName()); 056 return memo; 057 } 058 059 /** 060 * {@inheritDoc} 061 */ 062 @Override 063 abstract public boolean status(); 064 065 /** 066 * Forward a preformatted LocoNetMessage to the actual interface. 067 * <p> 068 * Implementations should update the transmit count statistic. 069 * 070 * @param m message to send; will be updated with CRC 071 */ 072 @Override 073 abstract public void sendLocoNetMessage(LocoNetMessage m); 074 075 // The methods to implement adding and removing listeners 076 077 // relies on Vector being a synchronized class 078 protected Vector<LocoNetListener> listeners = new Vector<LocoNetListener>(); 079 080 @Override 081 public synchronized void addLocoNetListener(int mask, @Nonnull LocoNetListener l) { 082 java.util.Objects.requireNonNull(l); 083 if (!listeners.contains(l)) { 084 listeners.addElement(l); 085 } 086 } 087 088 @Override 089 public synchronized void removeLocoNetListener(int mask, @Nonnull LocoNetListener l) { 090 java.util.Objects.requireNonNull(l); 091 if (listeners.contains(l)) { 092 listeners.removeElement(l); 093 } 094 } 095 096 /** 097 * Forward a LocoNetMessage to all registered listeners. 098 * <p> 099 * Needs to have public access, as 100 * {@link jmri.jmrix.loconet.loconetovertcp.LnOverTcpPacketizer} and 101 * {@link jmri.jmrix.loconet.Intellibox.IBLnPacketizer} invoke it, but don't 102 * inherit from it. 103 * 104 * @param m message to forward. Listeners should not modify it! 105 */ 106 public void notify(LocoNetMessage m) { 107 // record statistics 108 receivedMsgCount++; 109 receivedByteCount += m.getNumDataElements(); 110 111 // make a copy of the listener vector for notifications; synchronized not needed once copied 112 ArrayList<LocoNetListener> v; 113 synchronized (this) { 114 v = new ArrayList<LocoNetListener>(listeners); 115 } 116 117 // forward to all listeners 118 log.debug("notify of incoming LocoNet packet: {}", m); 119 for (LocoNetListener client : v) { 120 log.trace(" notify {} of incoming LocoNet packet: {}", client, m); 121 client.message(m); 122 } 123 } 124 125 /** 126 * Is there a backlog of information for the outbound link? This includes 127 * both in the program (e.g. the outbound queue) and in the Command Station 128 * interface (e.g. flow control from the port). 129 * 130 * @return true if busy, false if nothing waiting to send 131 */ 132 abstract public boolean isXmtBusy(); 133 134 /** 135 * Reset statistics (received message count, transmitted message count, 136 * received byte count). 137 */ 138 public void resetStatistics() { 139 receivedMsgCount = 0; 140 transmittedMsgCount = 0; 141 receivedByteCount = 0; 142 } 143 144 /** 145 * Clean up any resources, particularly threads. 146 * <p> 147 * The object can't be used after this. 148 */ 149 public void dispose() {} 150 151 /** 152 * Monitor the number of LocoNet messages received across the interface. 153 * This includes the messages this client has sent. 154 * 155 * @return the number of messages received 156 */ 157 public int getReceivedMsgCount() { 158 return receivedMsgCount; 159 } 160 protected int receivedMsgCount = 0; 161 162 /** 163 * Monitor the number of bytes in LocoNet messages received across the 164 * interface. This includes the bytes in messages this client has sent. 165 * 166 * @return the number of bytes received 167 */ 168 public int getReceivedByteCount() { 169 return receivedByteCount; 170 } 171 protected int receivedByteCount = 0; 172 173 /** 174 * Monitor the number of LocoNet messages transmitted across the interface. 175 * 176 * @return the number of messages transmitted 177 */ 178 public int getTransmittedMsgCount() { 179 return transmittedMsgCount; 180 } 181 protected int transmittedMsgCount = 0; 182 183 private final static Logger log = LoggerFactory.getLogger(LnTrafficController.class); 184 185}