001package jmri.jmrix.lenz.swing.mon; 002 003import jmri.jmrix.Message; 004import jmri.jmrix.lenz.*; 005import org.reflections.Reflections; 006import org.slf4j.Logger; 007import org.slf4j.LoggerFactory; 008 009import java.lang.reflect.Constructor; 010import java.lang.reflect.InvocationTargetException; 011import java.util.ArrayList; 012import java.util.List; 013import java.util.Set; 014 015/** 016 * Panel displaying (and logging) XpressNet messages derived from XNetMonFrame. 017 * 018 * @author Bob Jacobsen Copyright (C) 2002 019 * @author Paul Bender Copyright (C) 2004-2014 020 * @author Giorgio Terdina Copyright (C) 2007 021 */ 022public class XNetMonPane extends jmri.jmrix.AbstractMonPane implements XNetListener { 023 024 protected XNetTrafficController tc = null; 025 protected XNetSystemConnectionMemo memo = null; 026 027 private List<XPressNetMessageFormatter> formatterList; 028 029 030 @Override 031 public String getTitle() { 032 return (Bundle.getMessage("MenuItemXNetCommandMonitor")); 033 } 034 035 @Override 036 public void initContext(Object context) { 037 if (context instanceof XNetSystemConnectionMemo) { 038 memo = (XNetSystemConnectionMemo) context; 039 tc = memo.getXNetTrafficController(); 040 // connect to the TrafficController 041 tc.addXNetListener(~0, this); 042 try { 043 formatterList = new ArrayList<>(); 044 045 Reflections reflections = new Reflections("jmri.jmrix.lenz.messageformatters"); 046 Set<Class<? extends XPressNetMessageFormatter>> f = reflections.getSubTypesOf(XPressNetMessageFormatter.class); 047 for(Class<?> c : f){ 048 log.debug("Found formatter: {}", f.getClass().getName()); 049 Constructor<?> ctor = c.getConstructor(); 050 formatterList.add((XPressNetMessageFormatter) ctor.newInstance()); 051 } 052 } catch (NoSuchMethodException | SecurityException | InstantiationException | 053 IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 054 log.error("Error instantiating formatter", e); 055 } 056 } 057 } 058 059 /** 060 * Initialize the data source. 061 */ 062 @Override 063 protected void init() { 064 } 065 066 @Override 067 public void dispose() { 068 // disconnect from the LnTrafficController 069 tc.removeXNetListener(~0, this); 070 // and unwind swing 071 super.dispose(); 072 } 073 074 @Override 075 public void logMessage(String messagePrefix, String rawPrefix, Message message){ 076 // display the raw data if requested 077 StringBuilder raw = new StringBuilder(rawPrefix); 078 if (rawCheckBox.isSelected()) { 079 raw.append(message.toString()); 080 } 081 082 // display the decoded data 083 String text = formatterList.stream() 084 .filter(f -> f.handlesMessage(message)) 085 .findFirst().map(f -> f.formatMessage(message)) 086 .orElse(message.toString()); 087 nextLine(messagePrefix + " " + text + "\n", raw.toString()); 088 } 089 090 @Override 091 public synchronized void message(XNetReply l) { // receive an XpressNet message and log it 092 logMessage("","packet:",l); 093 } 094 095 /** 096 * Listen for the messages to the LI100/LI101 097 */ 098 @Override 099 public synchronized void message(XNetMessage l) { 100 logMessage("", "packet:", l); 101 } 102 103 /** 104 * Handle a timeout notification 105 */ 106 @Override 107 public void notifyTimeout(XNetMessage msg) { 108 log.debug("Notified of timeout on message {}", msg.toString()); 109 } 110 111 /** 112 * Nested class to create one of these using old-style defaults 113 */ 114 static public class Default extends jmri.util.swing.JmriNamedPaneAction { 115 116 public Default() { 117 super(Bundle.getMessage("MenuItemXNetCommandMonitor"), XNetMonPane.class.getName()); 118 setContext(jmri.InstanceManager. 119 getDefault(XNetSystemConnectionMemo.class)); 120 } 121 } 122 123 private static final Logger log = LoggerFactory.getLogger(XNetMonPane.class); 124}