001package jmri.jmrix.roco.z21.swing.configtool; 002 003import java.awt.GridLayout; 004import java.awt.event.ActionEvent; 005import javax.swing.BorderFactory; 006import javax.swing.BoxLayout; 007import javax.swing.JCheckBox; 008import javax.swing.JLabel; 009import javax.swing.JPanel; 010import javax.swing.JTextField; 011import javax.swing.JToggleButton; 012import jmri.jmrix.roco.z21.RocoZ21CommandStation; 013import jmri.jmrix.roco.z21.Z21Listener; 014import jmri.jmrix.roco.z21.Z21Message; 015import jmri.jmrix.roco.z21.Z21Reply; 016import jmri.jmrix.roco.z21.Z21TrafficController; 017import org.slf4j.Logger; 018import org.slf4j.LoggerFactory; 019 020/** 021 * Frame displaying Version information and broadcast flags for Z21 hardware. 022 * <p> 023 * This is a utility for reading the hardware and software versions of your Z21 024 * command station and along with the flags and the serial number. 025 * 026 * @author Paul Bender Copyright (C) 2016 027 */ 028public class Z21ConfigFrame extends jmri.util.JmriJFrame implements Z21Listener { 029 030 /** 031 * 032 */ 033 private Z21TrafficController tc; 034 private RocoZ21CommandStation cs; 035 036 /* updatable fields and field labels */ 037 private final JToggleButton getSystemInfoButton; 038 private JToggleButton setSystemInfoButton; 039 private final JToggleButton closeButton; 040 private JLabel hardwareVersionLabel; 041 private JTextField hardwareVersionTextField; 042 private JLabel softwareVersionLabel; 043 private JTextField softwareVersionTextField; 044 private JLabel serialNumLabel; 045 private JTextField serialNumTextField; 046 047 // flag checkboxes 048 private JCheckBox xPressNetMessagesCheckBox; 049 private JCheckBox rmBusMessagesCheckBox; 050 private JCheckBox systemStatusMessagesCheckBox; 051 private JCheckBox xPressNetLocomotiveMessagesCheckBox; 052 private JCheckBox railComMessagesCheckBox; 053 private JCheckBox locoNetMessagesCheckBox; 054 private JCheckBox locoNetLocomotiveMessagesCheckBox; 055 private JCheckBox locoNetTurnoutMessagesCheckBox; 056 private JCheckBox locoNetOccupancyMessagesCheckBox; 057 private JCheckBox railComAutomaticCheckBox; 058 private JCheckBox canDetectorCheckBox; 059 060 public Z21ConfigFrame(jmri.jmrix.roco.z21.Z21SystemConnectionMemo memo) { 061 super(Bundle.getMessage("Z21ConfigToolMenuItem")); 062 tc = memo.getTrafficController(); 063 cs = memo.getRocoZ21CommandStation(); 064 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); // prevents strange stretching of content 065 066 // build sub panel for version and serial number 067 getContentPane().add(getSystemInfoPanel()); 068 069 // build sub panel for the flag list. 070 getContentPane().add(getBroadcastFlagsPanel()); 071 072 // build sub panel with the read and close buttons 073 JPanel buttonPanel = new JPanel(); 074 //buttonPanel.setLayout(new GridLayout(1, 2)); 075 076 getSystemInfoButton = new JToggleButton(Bundle.getMessage("GetSystemInfoButtonLabel")); 077 getSystemInfoButton.setToolTipText(Bundle.getMessage("GetSystemInfoButtonToolTip")); 078 closeButton = new JToggleButton(Bundle.getMessage("ButtonClose")); 079 closeButton.setToolTipText(Bundle.getMessage("CloseButtonToolTip")); 080 buttonPanel.add(getSystemInfoButton); 081 buttonPanel.add(closeButton); 082 getContentPane().add(buttonPanel); 083 084 addHelpMenu("package.jmri.jmrix.roco.z21.swing.configtool.ConfigToolFrame", true); 085 086 // and prep for display 087 pack(); 088 089 // Add Get SystemInfo button handler 090 getSystemInfoButton.addActionListener((ActionEvent a) -> getSystemInfo()); 091 092 // install close button handler 093 closeButton.addActionListener((ActionEvent a) -> { 094 setVisible(false); 095 dispose(); 096 }); 097 098 if (tc != null) { 099 tc.addz21Listener(this); 100 } else { 101 log.warn("No Z21 connection, panel won't function"); 102 } 103 } 104 105 private JPanel getSystemInfoPanel() { 106 JPanel panel = new JPanel(); 107 panel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SystemInformationTitle"))); 108 panel.setLayout(new GridLayout(0, 2)); 109 110 hardwareVersionLabel = new JLabel(Bundle.getMessage("HardwareVersionLabel")); 111 hardwareVersionTextField = new JTextField("" + cs.getHardwareVersion()); 112 hardwareVersionTextField.setEnabled(false); 113 panel.add(hardwareVersionLabel); 114 panel.add(hardwareVersionTextField); 115 116 softwareVersionLabel = new JLabel(Bundle.getMessage("SoftwareVersionLabel")); 117 softwareVersionTextField = new JTextField("" + cs.getSoftwareVersion()); 118 softwareVersionTextField.setEnabled(false); 119 panel.add(softwareVersionLabel); 120 panel.add(softwareVersionTextField); 121 122 serialNumLabel = new JLabel(Bundle.getMessage("SerialNumberLabel")); 123 serialNumTextField = new JTextField("" + cs.getSerialNumber()); 124 serialNumTextField.setEnabled(false); 125 126 panel.add(serialNumLabel); 127 panel.add(serialNumTextField); 128 129 return panel; 130 } 131 132 private JPanel getBroadcastFlagsPanel() { 133 JPanel panel = new JPanel(); 134 panel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BroadcastFlagsTitle"))); 135 panel.setLayout(new GridLayout(0, 1)); 136 137 xPressNetMessagesCheckBox = new JCheckBox(Bundle.getMessage("XpressNetMessagesFlagLabel"), cs.getXPressNetMessagesFlag()); 138 xPressNetMessagesCheckBox.setToolTipText(Bundle.getMessage("XpressNetMessagesFlagToolTip")); 139 panel.add(xPressNetMessagesCheckBox); 140 141 rmBusMessagesCheckBox = new JCheckBox(Bundle.getMessage("RMBusMessagesFlagLabel"), cs.getRMBusMessagesFlag()); 142 rmBusMessagesCheckBox.setToolTipText(Bundle.getMessage("RMBusMessagesFlagToolTip")); 143 panel.add(rmBusMessagesCheckBox); 144 145 systemStatusMessagesCheckBox = new JCheckBox(Bundle.getMessage("SystemStatusMessagesFlagLabel"), cs.getSystemStatusMessagesFlag()); 146 systemStatusMessagesCheckBox.setToolTipText(Bundle.getMessage("RMBusMessagesFlagToolTip")); 147 panel.add(systemStatusMessagesCheckBox); 148 149 xPressNetLocomotiveMessagesCheckBox = new JCheckBox(Bundle.getMessage("XpressNetLocomotiveMessagesFlagLabel"), cs.getXPressNetLocomotiveMessagesFlag()); 150 xPressNetLocomotiveMessagesCheckBox.setToolTipText(Bundle.getMessage("XpressNetLocomotiveMessagesFlagToolTip")); 151 panel.add(xPressNetLocomotiveMessagesCheckBox); 152 153 railComMessagesCheckBox = new JCheckBox(Bundle.getMessage("RailComMessagesFlagLabel"), cs.getRailComMessagesFlag()); 154 railComMessagesCheckBox.setToolTipText(Bundle.getMessage("RailComMessagesFlagToolTip")); 155 panel.add(railComMessagesCheckBox); 156 157 railComAutomaticCheckBox = new JCheckBox(Bundle.getMessage("RailComAutomaticFlagLabel"), cs.getRailComAutomaticFlag()); 158 railComMessagesCheckBox.setToolTipText(Bundle.getMessage("RailComAutomaticFlagToolTip")); 159 panel.add(railComAutomaticCheckBox); 160 161 locoNetMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetMessagesFlagLabel"), cs.getLocoNetMessagesFlag()); 162 locoNetMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetMessagesFlagToolTip")); 163 panel.add(locoNetMessagesCheckBox); 164 165 locoNetLocomotiveMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetLocomotiveMessagesFlagLabel"), cs.getLocoNetLocomotiveMessagesFlag()); 166 locoNetLocomotiveMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetLocomotiveMessagesFlagToolTip")); 167 panel.add(locoNetLocomotiveMessagesCheckBox); 168 169 locoNetTurnoutMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetTurnoutMessagesFlagLabel"), cs.getLocoNetTurnoutMessagesFlag()); 170 locoNetTurnoutMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetTurnoutMessagesFlagToolTip")); 171 panel.add(locoNetTurnoutMessagesCheckBox); 172 173 locoNetOccupancyMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetOccupancyMessagesFlagLabel"), cs.getLocoNetOccupancyMessagesFlag()); 174 locoNetOccupancyMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetOccupancyMessagesFlagToolTip")); 175 panel.add(locoNetOccupancyMessagesCheckBox); 176 177 canDetectorCheckBox = new JCheckBox(Bundle.getMessage("canDetectorFlagLabel"), cs.getCanDetectorFlag()); 178 canDetectorCheckBox.setToolTipText(Bundle.getMessage("canDetectorFlagToolTip")); 179 panel.add(canDetectorCheckBox); 180 181 setSystemInfoButton = new JToggleButton(Bundle.getMessage("SetSystemInfoButtonLabel")); 182 setSystemInfoButton.setToolTipText(Bundle.getMessage("SetSystemInfoButtonToolTip")); 183 184 // Add Get SystemInfo button handler 185 setSystemInfoButton.addActionListener((ActionEvent a) -> writeSystemInfo()); 186 panel.add(setSystemInfoButton); 187 188 return panel; 189 } 190 191 /** 192 * Request command station information. 193 */ 194 private void getSystemInfo() { 195 // request the version information 196 tc.sendz21Message(Z21Message.getLanGetHardwareInfoRequestMessage(), this); 197 // request the serial number 198 tc.sendz21Message(Z21Message.getSerialNumberRequestMessage(), this); 199 // request the flags. 200 tc.sendz21Message(Z21Message.getLanGetBroadcastFlagsRequestMessage(), this); 201 } 202 203 /** 204 * Request command station information. 205 */ 206 private void writeSystemInfo() { 207 // set the flags in the command station representation based on the 208 // checkboxes. 209 cs.setXPressNetMessagesFlag(xPressNetMessagesCheckBox.isSelected()); 210 cs.setRMBusMessagesFlag(rmBusMessagesCheckBox.isSelected()); 211 cs.setSystemStatusMessagesFlag(systemStatusMessagesCheckBox.isSelected()); 212 cs.setRailComMessagesFlag(railComMessagesCheckBox.isSelected()); 213 cs.setRailComAutomaticFlag(railComAutomaticCheckBox.isSelected()); 214 cs.setXPressNetLocomotiveMessagesFlag(xPressNetLocomotiveMessagesCheckBox.isSelected()); 215 cs.setLocoNetMessagesFlag(locoNetMessagesCheckBox.isSelected()); 216 cs.setLocoNetLocomotiveMessagesFlag(locoNetLocomotiveMessagesCheckBox.isSelected()); 217 cs.setLocoNetTurnoutMessagesFlag(locoNetTurnoutMessagesCheckBox.isSelected()); 218 cs.setLocoNetOccupancyMessagesFlag(locoNetOccupancyMessagesCheckBox.isSelected()); 219 cs.setCanDetectorFlag(canDetectorCheckBox.isSelected()); 220 221 // send the flags to the command station. 222 tc.sendz21Message(Z21Message.getLanSetBroadcastFlagsRequestMessage(cs.getZ21BroadcastFlags()), this); 223 } 224 225 /** 226 * Listen for responses from the Z21. 227 * 228 * @param zr the reply 229 */ 230 @Override 231 public void reply(Z21Reply zr) { 232 switch (zr.getOpCode()) { 233 // handle replies with the serial number 234 case 0x0010: 235 // the serial number is a 32 bit integer stored in little 236 // endian format starting with the 1st databyte (element 4). 237 int serialNo = (zr.getElement(4)&0xff) + ((zr.getElement(5)&0xff) << 8) 238 + ((zr.getElement(6)&0xff) << 16) + ((zr.getElement(7)&0xff) << 24); 239 cs.setSerialNumber(serialNo); 240 updateSerialNumber(); 241 break; 242 // handle replies with the hardware and software version. 243 case 0x001A: 244 // the hardware version is a 32 bit integer stored in little 245 // endian format starting with the 1st databyte (element 4). 246 int hwversion = zr.getElement(4) + (zr.getElement(5) << 8) 247 + (zr.getElement(6) << 16) + (zr.getElement(7) << 24); 248 cs.setHardwareVersion(hwversion); 249 // the software version is a 32 bit integer stored in little 250 // endian format and written in BCD, starting after the hardware 251 // version (element 8). The least significant byte is to be 252 // treated as a decimal. 253 float swversion = (zr.getElementBCD(8) / 100.0f) 254 + (zr.getElementBCD(9)) 255 + (zr.getElementBCD(10) * 100) 256 + (zr.getElementBCD(11)) * 10000; 257 cs.setSoftwareVersion(swversion); 258 updateVersionInformation(); 259 break; 260 // handle replies with the flags. 261 case 0x0051: 262 // the payload is a 32 bit integer stored in little endian format 263 // starting with the 1st databyte (element 4). 264 int flags = zr.getElement(4) + (zr.getElement(5) << 8) 265 + (zr.getElement(6) << 16) + (zr.getElement(7) << 24); 266 cs.setZ21BroadcastFlags(flags); 267 updateFlagInformation(); 268 break; 269 default: 270 // ignore all other message types. 271 log.debug("unhandled op-code received."); 272 } 273 } 274 275 /** 276 * Listen for the messages sent to the Z21. 277 * 278 * @param zm the message to listen for 279 */ 280 @Override 281 public void message(Z21Message zm) { 282 } 283 284 @Override 285 public void dispose() { 286 // remove the listener for this object. 287 tc.removez21Listener(this); 288 // take apart the JFrame 289 super.dispose(); 290 } 291 292 /** 293 * Read the versions displayed from the command station representation. 294 */ 295 private void updateVersionInformation() { 296 hardwareVersionTextField.setText("0x" + java.lang.Integer.toHexString(cs.getHardwareVersion())); 297 softwareVersionTextField.setText("" + cs.getSoftwareVersion()); 298 } 299 300 /** 301 * Read the serial number from the command station representation. 302 */ 303 private void updateSerialNumber() { 304 serialNumTextField.setText("" + cs.getSerialNumber()); 305 } 306 307 /** 308 * Read the flags displayed from the command station representation. 309 */ 310 private void updateFlagInformation() { 311 xPressNetMessagesCheckBox.setSelected(cs.getXPressNetMessagesFlag()); 312 rmBusMessagesCheckBox.setSelected(cs.getRMBusMessagesFlag()); 313 systemStatusMessagesCheckBox.setSelected(cs.getSystemStatusMessagesFlag()); 314 xPressNetLocomotiveMessagesCheckBox.setSelected(cs.getXPressNetLocomotiveMessagesFlag()); 315 railComMessagesCheckBox.setSelected(cs.getRailComMessagesFlag()); 316 locoNetMessagesCheckBox.setSelected(cs.getLocoNetMessagesFlag()); 317 locoNetLocomotiveMessagesCheckBox.setSelected(cs.getLocoNetLocomotiveMessagesFlag()); 318 locoNetTurnoutMessagesCheckBox.setSelected(cs.getLocoNetTurnoutMessagesFlag()); 319 locoNetOccupancyMessagesCheckBox.setSelected(cs.getLocoNetOccupancyMessagesFlag()); 320 } 321 322 private final static Logger log = LoggerFactory.getLogger(Z21ConfigFrame.class); 323 324}