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 private JCheckBox canBoosterCheckBox; 060 private JCheckBox fastClockCheckBox; 061 062 public Z21ConfigFrame(jmri.jmrix.roco.z21.Z21SystemConnectionMemo memo) { 063 super(Bundle.getMessage("Z21ConfigToolMenuItem")); 064 tc = memo.getTrafficController(); 065 cs = memo.getRocoZ21CommandStation(); 066 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); // prevents strange stretching of content 067 068 // build sub panel for version and serial number 069 getContentPane().add(getSystemInfoPanel()); 070 071 // build sub panel for the flag list. 072 getContentPane().add(getBroadcastFlagsPanel()); 073 074 // build sub panel with the read and close buttons 075 JPanel buttonPanel = new JPanel(); 076 //buttonPanel.setLayout(new GridLayout(1, 2)); 077 078 getSystemInfoButton = new JToggleButton(Bundle.getMessage("GetSystemInfoButtonLabel")); 079 getSystemInfoButton.setToolTipText(Bundle.getMessage("GetSystemInfoButtonToolTip")); 080 closeButton = new JToggleButton(Bundle.getMessage("ButtonClose")); 081 closeButton.setToolTipText(Bundle.getMessage("CloseButtonToolTip")); 082 buttonPanel.add(getSystemInfoButton); 083 buttonPanel.add(closeButton); 084 getContentPane().add(buttonPanel); 085 086 addHelpMenu("package.jmri.jmrix.roco.z21.swing.configtool.ConfigToolFrame", true); 087 088 // and prep for display 089 pack(); 090 091 // Add Get SystemInfo button handler 092 getSystemInfoButton.addActionListener((ActionEvent a) -> getSystemInfo()); 093 094 // install close button handler 095 closeButton.addActionListener((ActionEvent a) -> { 096 setVisible(false); 097 dispose(); 098 }); 099 100 if (tc != null) { 101 tc.addz21Listener(this); 102 } else { 103 log.warn("No Z21 connection, panel won't function"); 104 } 105 } 106 107 private JPanel getSystemInfoPanel() { 108 JPanel panel = new JPanel(); 109 panel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SystemInformationTitle"))); 110 panel.setLayout(new GridLayout(0, 2)); 111 112 hardwareVersionLabel = new JLabel(Bundle.getMessage("HardwareVersionLabel")); 113 hardwareVersionTextField = new JTextField("" + cs.getHardwareVersion()); 114 hardwareVersionTextField.setEnabled(false); 115 panel.add(hardwareVersionLabel); 116 panel.add(hardwareVersionTextField); 117 118 softwareVersionLabel = new JLabel(Bundle.getMessage("SoftwareVersionLabel")); 119 softwareVersionTextField = new JTextField("" + cs.getSoftwareVersion()); 120 softwareVersionTextField.setEnabled(false); 121 panel.add(softwareVersionLabel); 122 panel.add(softwareVersionTextField); 123 124 serialNumLabel = new JLabel(Bundle.getMessage("SerialNumberLabel")); 125 serialNumTextField = new JTextField("" + cs.getSerialNumber()); 126 serialNumTextField.setEnabled(false); 127 128 panel.add(serialNumLabel); 129 panel.add(serialNumTextField); 130 131 return panel; 132 } 133 134 private JPanel getBroadcastFlagsPanel() { 135 JPanel panel = new JPanel(); 136 panel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("BroadcastFlagsTitle"))); 137 panel.setLayout(new GridLayout(0, 1)); 138 139 JPanel xNetPanel = new JPanel(); 140 xNetPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("XNetFlagsTitle"))); 141 xNetPanel.setLayout(new GridLayout(0, 2)); 142 143 xPressNetMessagesCheckBox = new JCheckBox(Bundle.getMessage("XpressNetMessagesFlagLabel"), cs.getXPressNetMessagesFlag()); 144 xPressNetMessagesCheckBox.setToolTipText(Bundle.getMessage("XpressNetMessagesFlagToolTip")); 145 xNetPanel.add(xPressNetMessagesCheckBox); 146 147 xPressNetLocomotiveMessagesCheckBox = new JCheckBox(Bundle.getMessage("XpressNetLocomotiveMessagesFlagLabel"), cs.getXPressNetLocomotiveMessagesFlag()); 148 xPressNetLocomotiveMessagesCheckBox.setToolTipText(Bundle.getMessage("XpressNetLocomotiveMessagesFlagToolTip")); 149 xNetPanel.add(xPressNetLocomotiveMessagesCheckBox); 150 151 panel.add(xNetPanel); 152 153 JPanel locoNetPanel = new JPanel(); 154 locoNetPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("LocoNetFlagsTitle"))); 155 locoNetPanel.setLayout(new GridLayout(0, 2)); 156 157 locoNetMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetMessagesFlagLabel"), cs.getLocoNetMessagesFlag()); 158 locoNetMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetMessagesFlagToolTip")); 159 locoNetPanel.add(locoNetMessagesCheckBox); 160 161 locoNetLocomotiveMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetLocomotiveMessagesFlagLabel"), cs.getLocoNetLocomotiveMessagesFlag()); 162 locoNetLocomotiveMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetLocomotiveMessagesFlagToolTip")); 163 locoNetPanel.add(locoNetLocomotiveMessagesCheckBox); 164 165 locoNetTurnoutMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetTurnoutMessagesFlagLabel"), cs.getLocoNetTurnoutMessagesFlag()); 166 locoNetTurnoutMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetTurnoutMessagesFlagToolTip")); 167 locoNetPanel.add(locoNetTurnoutMessagesCheckBox); 168 169 locoNetOccupancyMessagesCheckBox = new JCheckBox(Bundle.getMessage("LocoNetOccupancyMessagesFlagLabel"), cs.getLocoNetOccupancyMessagesFlag()); 170 locoNetOccupancyMessagesCheckBox.setToolTipText(Bundle.getMessage("LocoNetOccupancyMessagesFlagToolTip")); 171 locoNetPanel.add(locoNetOccupancyMessagesCheckBox); 172 173 panel.add(locoNetPanel); 174 175 JPanel canPanel = new JPanel(); 176 canPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("canFlagsTitle"))); 177 canPanel.setLayout(new GridLayout(0, 2)); 178 179 canDetectorCheckBox = new JCheckBox(Bundle.getMessage("canDetectorFlagLabel"), cs.getCanDetectorFlag()); 180 canDetectorCheckBox.setToolTipText(Bundle.getMessage("canDetectorFlagToolTip")); 181 canPanel.add(canDetectorCheckBox); 182 183 canBoosterCheckBox = new JCheckBox(Bundle.getMessage("canBoosterFlagLabel"), cs.getCanBoosterFlag()); 184 canBoosterCheckBox.setToolTipText(Bundle.getMessage("canBoosterFlagToolTip")); 185 canPanel.add(canBoosterCheckBox); 186 187 panel.add(canPanel); 188 189 JPanel systemPanel = new JPanel(); 190 systemPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("SystemFlagsTitle"))); 191 systemPanel.setLayout(new GridLayout(0, 2)); 192 193 rmBusMessagesCheckBox = new JCheckBox(Bundle.getMessage("RMBusMessagesFlagLabel"), cs.getRMBusMessagesFlag()); 194 rmBusMessagesCheckBox.setToolTipText(Bundle.getMessage("RMBusMessagesFlagToolTip")); 195 systemPanel.add(rmBusMessagesCheckBox); 196 197 systemStatusMessagesCheckBox = new JCheckBox(Bundle.getMessage("SystemStatusMessagesFlagLabel"), cs.getSystemStatusMessagesFlag()); 198 systemStatusMessagesCheckBox.setToolTipText(Bundle.getMessage("SystemStatusMessagesFlagToolTip")); 199 systemPanel.add(systemStatusMessagesCheckBox); 200 201 railComMessagesCheckBox = new JCheckBox(Bundle.getMessage("RailComMessagesFlagLabel"), cs.getRailComMessagesFlag()); 202 railComMessagesCheckBox.setToolTipText(Bundle.getMessage("RailComMessagesFlagToolTip")); 203 systemPanel.add(railComMessagesCheckBox); 204 205 railComAutomaticCheckBox = new JCheckBox(Bundle.getMessage("RailComAutomaticFlagLabel"), cs.getRailComAutomaticFlag()); 206 railComMessagesCheckBox.setToolTipText(Bundle.getMessage("RailComAutomaticFlagToolTip")); 207 systemPanel.add(railComAutomaticCheckBox); 208 209 fastClockCheckBox = new JCheckBox(Bundle.getMessage("FastClockFlagLabel"), cs.getFastClockFlag()); 210 fastClockCheckBox.setToolTipText(Bundle.getMessage("FastClockFlagToolTip")); 211 systemPanel.add(fastClockCheckBox); 212 213 panel.add(systemPanel); 214 215 setSystemInfoButton = new JToggleButton(Bundle.getMessage("SetSystemInfoButtonLabel")); 216 setSystemInfoButton.setToolTipText(Bundle.getMessage("SetSystemInfoButtonToolTip")); 217 218 // Add Get SystemInfo button handler 219 setSystemInfoButton.addActionListener((ActionEvent a) -> writeSystemInfo()); 220 panel.add(setSystemInfoButton); 221 222 return panel; 223 } 224 225 /** 226 * Request command station information. 227 */ 228 private void getSystemInfo() { 229 // request the version information 230 tc.sendz21Message(Z21Message.getLanGetHardwareInfoRequestMessage(), this); 231 // request the serial number 232 tc.sendz21Message(Z21Message.getSerialNumberRequestMessage(), this); 233 // request the flags. 234 tc.sendz21Message(Z21Message.getLanGetBroadcastFlagsRequestMessage(), this); 235 } 236 237 /** 238 * Request command station information. 239 */ 240 private void writeSystemInfo() { 241 // set the flags in the command station representation based on the 242 // checkboxes. 243 cs.setXPressNetMessagesFlag(xPressNetMessagesCheckBox.isSelected()); 244 cs.setRMBusMessagesFlag(rmBusMessagesCheckBox.isSelected()); 245 cs.setSystemStatusMessagesFlag(systemStatusMessagesCheckBox.isSelected()); 246 cs.setRailComMessagesFlag(railComMessagesCheckBox.isSelected()); 247 cs.setRailComAutomaticFlag(railComAutomaticCheckBox.isSelected()); 248 cs.setXPressNetLocomotiveMessagesFlag(xPressNetLocomotiveMessagesCheckBox.isSelected()); 249 cs.setLocoNetMessagesFlag(locoNetMessagesCheckBox.isSelected()); 250 cs.setLocoNetLocomotiveMessagesFlag(locoNetLocomotiveMessagesCheckBox.isSelected()); 251 cs.setLocoNetTurnoutMessagesFlag(locoNetTurnoutMessagesCheckBox.isSelected()); 252 cs.setLocoNetOccupancyMessagesFlag(locoNetOccupancyMessagesCheckBox.isSelected()); 253 cs.setCanDetectorFlag(canDetectorCheckBox.isSelected()); 254 cs.setCanBoosterFlag(canBoosterCheckBox.isSelected()); 255 cs.setFastClockFlag(fastClockCheckBox.isSelected()); 256 257 // send the flags to the command station. 258 tc.sendz21Message(Z21Message.getLanSetBroadcastFlagsRequestMessage(cs.getZ21BroadcastFlags()), this); 259 } 260 261 /** 262 * Listen for responses from the Z21. 263 * 264 * @param zr the reply 265 */ 266 @Override 267 public void reply(Z21Reply zr) { 268 switch (zr.getOpCode()) { 269 // handle replies with the serial number 270 case 0x0010: 271 // the serial number is a 32 bit integer stored in little 272 // endian format starting with the 1st databyte (element 4). 273 int serialNo = (zr.getElement(4)&0xff) + ((zr.getElement(5)&0xff) << 8) 274 + ((zr.getElement(6)&0xff) << 16) + ((zr.getElement(7)&0xff) << 24); 275 cs.setSerialNumber(serialNo); 276 updateSerialNumber(); 277 break; 278 // handle replies with the hardware and software version. 279 case 0x001A: 280 // the hardware version is a 32 bit integer stored in little 281 // endian format starting with the 1st databyte (element 4). 282 int hwversion = zr.getElement(4) + (zr.getElement(5) << 8) 283 + (zr.getElement(6) << 16) + (zr.getElement(7) << 24); 284 cs.setHardwareVersion(hwversion); 285 // the software version is a 32 bit integer stored in little 286 // endian format and written in BCD, starting after the hardware 287 // version (element 8). The least significant byte is to be 288 // treated as a decimal. 289 float swversion = (zr.getElementBCD(8) / 100.0f) 290 + (zr.getElementBCD(9)) 291 + (zr.getElementBCD(10) * 100) 292 + (zr.getElementBCD(11)) * 10000; 293 cs.setSoftwareVersion(swversion); 294 updateVersionInformation(); 295 break; 296 // handle replies with the flags. 297 case 0x0051: 298 // the payload is a 32 bit integer stored in little endian format 299 // starting with the 1st databyte (element 4). 300 int flags = zr.getElement(4) + (zr.getElement(5) << 8) 301 + (zr.getElement(6) << 16) + (zr.getElement(7) << 24); 302 cs.setZ21BroadcastFlags(flags); 303 updateFlagInformation(); 304 break; 305 default: 306 // ignore all other message types. 307 log.debug("unhandled op-code received."); 308 } 309 } 310 311 /** 312 * Listen for the messages sent to the Z21. 313 * 314 * @param zm the message to listen for 315 */ 316 @Override 317 public void message(Z21Message zm) { 318 } 319 320 @Override 321 public void dispose() { 322 // remove the listener for this object. 323 tc.removez21Listener(this); 324 // take apart the JFrame 325 super.dispose(); 326 } 327 328 /** 329 * Read the versions displayed from the command station representation. 330 */ 331 private void updateVersionInformation() { 332 hardwareVersionTextField.setText("0x" + java.lang.Integer.toHexString(cs.getHardwareVersion())); 333 softwareVersionTextField.setText("" + cs.getSoftwareVersion()); 334 } 335 336 /** 337 * Read the serial number from the command station representation. 338 */ 339 private void updateSerialNumber() { 340 serialNumTextField.setText("" + cs.getSerialNumber()); 341 } 342 343 /** 344 * Read the flags displayed from the command station representation. 345 */ 346 private void updateFlagInformation() { 347 xPressNetMessagesCheckBox.setSelected(cs.getXPressNetMessagesFlag()); 348 rmBusMessagesCheckBox.setSelected(cs.getRMBusMessagesFlag()); 349 systemStatusMessagesCheckBox.setSelected(cs.getSystemStatusMessagesFlag()); 350 xPressNetLocomotiveMessagesCheckBox.setSelected(cs.getXPressNetLocomotiveMessagesFlag()); 351 railComMessagesCheckBox.setSelected(cs.getRailComMessagesFlag()); 352 locoNetMessagesCheckBox.setSelected(cs.getLocoNetMessagesFlag()); 353 locoNetLocomotiveMessagesCheckBox.setSelected(cs.getLocoNetLocomotiveMessagesFlag()); 354 locoNetTurnoutMessagesCheckBox.setSelected(cs.getLocoNetTurnoutMessagesFlag()); 355 locoNetOccupancyMessagesCheckBox.setSelected(cs.getLocoNetOccupancyMessagesFlag()); 356 } 357 358 private final static Logger log = LoggerFactory.getLogger(Z21ConfigFrame.class); 359 360}