001package jmri.jmrix.cmri.serial.serialmon; 002 003import jmri.jmrix.cmri.CMRISystemConnectionMemo; 004import jmri.jmrix.cmri.serial.SerialListener; 005import jmri.jmrix.cmri.serial.SerialMessage; 006import jmri.jmrix.cmri.serial.SerialReply; 007import jmri.jmrix.cmri.serial.SerialNode; 008 009import java.awt.event.ActionEvent; 010 011import javax.swing.BoxLayout; 012import javax.swing.JButton; 013import javax.swing.JPanel; 014 015/** 016 * Frame displaying (and logging) CMRI serial command messages. 017 * 018 * @author Bob Jacobsen Copyright (C) 2001 019 * @author Chuck Catania Copyright (C) 2014, 2016, 2017 020 */ 021public class SerialMonFrame extends jmri.jmrix.AbstractMonFrame implements SerialListener { 022 // member declarations 023 // String deltaTCheck = this.getClass().getName()+".DeltaT"; // NOI18N 024 025 protected JButton packetfilterButton = new JButton(Bundle.getMessage("FilterPacketsText") ); // NOI18N 026 protected static int _DLE = 0x10; 027 028 private CMRISystemConnectionMemo _memo = null; 029 030 public SerialMonFrame(CMRISystemConnectionMemo memo) { 031 super(); 032 _memo = memo; 033 } 034 035 @Override 036 public void dispose() { 037 super.dispose(); 038 } 039 040 @Override 041 protected String title() { 042 return Bundle.getMessage("SerialCommandMonTitle")+" "+Bundle.getMessage("Connection")+_memo.getUserName(); // NOI18N 043 } 044 045 @Override 046 protected void init() { 047 // connect to TrafficController 048 _memo.getTrafficController().addSerialListener(this); 049 // Load the packet filter bits 050 initializePacketFilters(); 051 052 // Add additional controls to the super class window 053 JPanel paneA = new JPanel(); 054 paneA.setLayout(new BoxLayout(paneA, BoxLayout.Y_AXIS)); 055 056 JPanel pane1 = new JPanel(); 057 pane1.setLayout(new BoxLayout(pane1, BoxLayout.X_AXIS)); 058 059 packetfilterButton.setText(Bundle.getMessage("FilterPacketsText")); // NOI18N 060 packetfilterButton.setVisible(true); 061 packetfilterButton.setToolTipText(Bundle.getMessage("FilterPacketTip")); // NOI18N 062 pane1.add(packetfilterButton); 063 packetfilterButton.addActionListener(this::openPacketFilterPerformed); 064 065 paneA.add(pane1); 066 getContentPane().add(paneA); 067 pack(); 068 paneA.setMaximumSize(paneA.getSize()); 069 pack(); 070 071 // Move the filter packets button to the middle 072 getContentPane().setComponentZOrder(paneA,1); 073 } 074 075 /** 076 * Define system-specific help item. 077 */ 078 @Override 079 protected void setHelp() { 080 addHelpMenu("package.jmri.jmrix.cmri.serial.serialmon.SerialMonFrame", true); // NOI18N 081 } 082 083 /** 084 * Initialize packet type filters. 085 */ 086 public void initializePacketFilters() { 087 // get all configured nodes 088 SerialNode node = (SerialNode) _memo.getTrafficController().getNode(0); 089 int index = 1, 090 pktTypeIndex = 0; 091 092 while (node != null) { 093 // Set all nodes and packet types to be monitored 094 //----------------------------------------------- 095 do { 096 node.setMonitorPacketBit(pktTypeIndex, true); 097 pktTypeIndex++; 098 } while (pktTypeIndex < SerialFilterFrame.numMonPkts); 099 100 node = (SerialNode) _memo.getTrafficController().getNode(index); 101 index++; 102 pktTypeIndex = 0; 103 } 104 } 105 106 /** 107 * Open the node/packet filter window. 108 * @param e unused. 109 */ 110 public void openPacketFilterPerformed(ActionEvent e) { 111 // create a SerialFilterFrame 112 SerialFilterFrame f = new SerialFilterFrame(_memo); 113 try { 114 f.initComponents(); 115 } 116 catch (Exception ex) { 117 log.warn("SerialMonFrame starting SerialFilterFrame: Exception: {}", ex.toString()); 118 } 119 f.setVisible(true); 120 } 121 122 //------------------- 123 // Transmit Packets 124 //------------------- 125 @Override 126 public synchronized void message(SerialMessage l) { 127 128 SerialNode monitorNode = (SerialNode) _memo.getTrafficController().getNodeFromAddress(l.getUA()); 129 130 // Test for node and packets being monitored 131 //------------------------------------------ 132 if (monitorNode == null) return; 133 if (!monitorNode.getMonitorNodePackets()) return; 134 135 int aPacketTypeID = l.getElement(1); 136 137 // check for valid length 138 if (l.getNumDataElements() < 2) { 139 nextLine("Truncated message of length "+l.getNumDataElements()+"\n",l.toString()); 140 return; 141 } 142 143 switch(aPacketTypeID) { 144 case 0x50: // (P) Poll 145 if(monitorNode.getMonitorPacketBit(SerialFilterFrame.monPktPoll)) 146 { 147 nextLine("Poll ua="+l.getUA()+"\n", l.toString()); 148 } 149 break; 150 151 case 0x54: // (T) Transmit 152 if (monitorNode.getMonitorPacketBit(SerialFilterFrame.monPktTransmit)) 153 { 154 StringBuilder sb = new StringBuilder("Transmit ua="); 155 sb.append(l.getUA()); 156 sb.append(" OB="); 157 for (int i=2; i<l.getNumDataElements(); i++) 158 { 159 if ((rawCheckBox.isSelected()) && ( l.getElement(i) == _DLE )) //c2 160 { 161 sb.append("<dle>"); // Convert DLE (0x10) to text 162 i++; 163 } 164 165 sb.append(Integer.toHexString(l.getElement(i)&0x000000ff).toUpperCase()); //c2 166 sb.append(" "); 167 } 168 sb.append("\n"); 169 nextLine(new String(sb), l.toString()); 170 } 171 break; 172 173 case 0x49: // (I) Initialize 174 if (monitorNode.getMonitorPacketBit(SerialFilterFrame.monPktInit)) { 175 StringBuilder sb = new StringBuilder("Init ua="); 176 sb.append(l.getUA()); 177 sb.append(" type="); 178 int ndp=l.getElement(2); // ndp node type 179 sb.append((char)ndp); 180 int len = l.getNumDataElements(); 181 182 switch (ndp) { 183 // SMINI/SUSIC/USIC 184 case SerialNode.NDP_USICSUSIC24: 185 case SerialNode.NDP_USICSUSIC32: 186 case SerialNode.NDP_SMINI: 187 if (len>=5) 188 { 189 sb.append(" DL="); 190 sb.append(l.getElement(3)*256+l.getElement(4)); 191 } 192 193 if (len>=6) 194 { 195 sb.append(" NS="); 196 sb.append(l.getElement(5)); 197 sb.append(" CT: "); 198 for (int i=6; i<l.getNumDataElements(); i++) 199 { 200 sb.append(Integer.toHexString(l.getElement(i)&0x000000ff).toUpperCase()); //c2 201 sb.append(" "); 202 } 203 } 204 break; 205 206 case SerialNode.NDP_CPNODE: // CPNODE 207 case SerialNode.NDP_CPMEGA: // CPMEGA 208 case SerialNode.NDP_ESP32NODE: // ESP32Node -- same init payload layout as CPNODE/CPMEGA 209 if (len>=5) 210 { 211 sb.append(" DL="); 212 sb.append(l.getElement(3)*256+l.getElement(4)); 213 } 214 sb.append(" Opts="); 215 int i=5; 216 while (i<l.getNumDataElements()) { 217 if (l.getElement(i) != _DLE) { // skip DLE 218 sb.append(Integer.toHexString(l.getElement(i)&0x000000ff).toUpperCase()); //c2 219 sb.append(" "); 220 } 221 i++; 222 } 223 break; 224 225 default: 226 sb.append("Unrecognized node type NDP: [").append(ndp).append("] "); 227 break; 228 229 } //ndp case 230 231 sb.append("\n"); 232 nextLine(new String(sb), l.toString()); 233 } 234 break; 235 236 default: 237 nextLine("Unrecognized cmd: \""+l.toString()+"\"\n", ""); 238 } // end packet ID case 239 } 240 241 //------------------- 242 // Receive Packets 243 //------------------- 244 @Override 245 public synchronized void reply(SerialReply l) { 246 247 // Test for node and packets being monitored 248 //------------------------------------------ 249 SerialNode monitorNode = (SerialNode) _memo.getTrafficController().getNodeFromAddress(l.getUA()); 250 251 if (monitorNode == null) { 252 return; 253 } 254 if (!monitorNode.getMonitorNodePackets()) { 255 return; 256 } 257 258 int aPacketTypeID = l.getElement(1); 259 260 // check for valid length 261 if (l.getNumDataElements() < 2) { 262 nextLine("Truncated reply of length " + l.getNumDataElements() + "\n", l.toString()); 263 // CMRInetMetricsData.incMetricErrValue( CMRInetMetricsData.CMRInetMetricTruncReply ); 264 return; 265 } 266 switch (aPacketTypeID) { 267 case 0x52: // (R) Receive (poll reply) 268 if (monitorNode.getMonitorPacketBit(SerialFilterFrame.monPktRead)) { 269 StringBuilder sb = new StringBuilder("Receive ua="); 270 sb.append(l.getUA()); 271 sb.append(" IB="); 272 for (int i = 2; i < l.getNumDataElements(); i++) { 273 if ((rawCheckBox.isSelected()) && (l.getElement(i) == _DLE)) //c2 274 { 275 sb.append("<dle>"); 276 i++; 277 } 278 sb.append(Integer.toHexString(l.getElement(i) & 0x000000ff).toUpperCase()); //c2 279 sb.append(" "); 280 } 281 sb.append("\n"); 282 nextLine(new String(sb), l.toString()); 283 } 284 break; 285 286 case 0x45: // (E) EOT c2 287 if (monitorNode.getMonitorPacketBit(SerialFilterFrame.monPktEOT)) { 288 StringBuilder sb = new StringBuilder("Receive ua="); 289 sb.append(l.getUA()); 290 sb.append(" eot"); 291 sb.append("\n"); 292 nextLine(new String(sb), l.toString()); 293 } 294 break; 295 296 default: 297 // CMRInetMetricsData.incMetricErrValue( CMRInetMetricsData.CMRInetMetricUnrecResponse ); 298 nextLine("Unrecognized response: \"" + l.toString() + "\"\n", ""); 299 break; 300 } 301 } 302 303 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SerialMonFrame.class); 304 305} 306