001package jmri.jmrix.nce.packetgen; 002 003import java.awt.Dimension; 004 005import javax.swing.BoxLayout; 006import javax.swing.JPanel; 007 008import jmri.jmrix.nce.*; 009import jmri.util.StringUtil; 010import jmri.util.swing.JmriJOptionPane; 011 012/** 013 * Frame for user input of Nce messages. 014 * 015 * @author Ken Cameron Copyright (C) 2010 derived from: 016 * @author Bob Jacobsen Copyright (C) 2001 017 * @author Dan Boudreau Copyright (C) 2007 018 */ 019public class NcePacketGenPanel extends jmri.jmrix.nce.swing.NcePanel implements jmri.jmrix.nce.NceListener { 020 021 javax.swing.JLabel jLabel1 = new javax.swing.JLabel(); 022 javax.swing.JLabel jLabel2 = new javax.swing.JLabel(); 023 javax.swing.JButton sendButton = new javax.swing.JButton(); 024 javax.swing.JTextField packetTextField = new javax.swing.JTextField(20); 025 javax.swing.JCheckBox checkBoxBinCmd = new javax.swing.JCheckBox(); 026 javax.swing.JTextField replyLenTextField = new javax.swing.JTextField(2); 027 028 private NceTrafficController tc = null; 029 030 public NcePacketGenPanel() { 031 super(); 032 } 033 034 /** 035 * {@inheritDoc} 036 */ 037 @Override 038 public void initContext(Object context) { 039 if (context instanceof NceSystemConnectionMemo) { 040 initComponents((NceSystemConnectionMemo) context); 041 } 042 } 043 044 /** 045 * {@inheritDoc} 046 */ 047 @Override 048 public String getHelpTarget() { 049 return "package.jmri.jmrix.nce.packetgen.NcePacketGenFrame"; 050 } 051 052 /** 053 * {@inheritDoc} 054 */ 055 @Override 056 public String getTitle() { 057 StringBuilder x = new StringBuilder(); 058 if (memo != null) { 059 x.append(memo.getUserName()); 060 } else { 061 x.append("NCE_"); 062 } 063 x.append(": "); 064 x.append(Bundle.getMessage("Title")); 065 return x.toString(); 066 } 067 068 /** 069 * The minimum frame size for font size 16 070 */ 071 @Override 072 public Dimension getMinimumDimension() { 073 return new Dimension(200, 200); 074 } 075 076 /** 077 * {@inheritDoc} 078 */ 079 @Override 080 public void initComponents(NceSystemConnectionMemo m) { 081 this.memo = m; 082 this.tc = m.getNceTrafficController(); 083 084 // the following code sets the frame's initial state 085 jLabel1.setText(Bundle.getMessage("CommandLabel")); 086 jLabel1.setVisible(true); 087 088 sendButton.setText(Bundle.getMessage("MenuItemSendCommand")); 089 sendButton.setVisible(true); 090 sendButton.setToolTipText(Bundle.getMessage("TooltipSendPacket")); 091 092 packetTextField.setText(""); 093 packetTextField.setToolTipText(Bundle.getMessage("EnterHexToolTip")); 094 packetTextField.setMaximumSize(new Dimension(packetTextField 095 .getMaximumSize().width, packetTextField.getPreferredSize().height)); 096 097 checkBoxBinCmd.setText(Bundle.getMessage("Binary")); 098 checkBoxBinCmd.setVisible(true); 099 checkBoxBinCmd.setToolTipText(Bundle.getMessage("TooltipBinary")); 100 checkBoxBinCmd.setSelected(true); 101 102 jLabel2.setText(Bundle.getMessage("BytesLabel")); 103 jLabel2.setVisible(true); 104 105 replyLenTextField.setVisible(true); 106 replyLenTextField.setMaximumSize(new Dimension(50, replyLenTextField.getPreferredSize().height)); 107 replyLenTextField.setToolTipText(Bundle.getMessage("TooltipExpectedBytes")); 108 109 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 110 setPreferredSize(new Dimension(300, 150)); 111 112 JPanel command = new JPanel(); 113 command.setLayout(new BoxLayout(command, BoxLayout.X_AXIS)); 114 command.add(jLabel1); 115 command.add(packetTextField); 116 117 JPanel bytes = new JPanel(); 118 bytes.setLayout(new BoxLayout(bytes, BoxLayout.X_AXIS)); 119 bytes.add(jLabel2); 120 bytes.add(replyLenTextField); 121 122 add(command); 123 add(checkBoxBinCmd); 124 add(bytes); 125 add(sendButton); 126 127 sendButton.addActionListener(this::sendButtonActionPerformed); 128 } 129 130 public void sendButtonActionPerformed(java.awt.event.ActionEvent e) { 131 String input = packetTextField.getText(); 132 // TODO check input + feedback on error. Too easy to cause NPE 133 if (checkBoxBinCmd.isSelected()) { 134 // Binary selected, convert ASCII to hex 135 136 NceMessage m = createPacket(input); 137 if (m == null) { 138 JmriJOptionPane.showMessageDialog(NcePacketGenPanel.this, 139 Bundle.getMessage("DialogHexOnly"), 140 Bundle.getMessage("BinaryTitle"), 141 JmriJOptionPane.ERROR_MESSAGE); 142 return; 143 } 144 m.setBinary(true); 145 int replyLen = getReplyLen(replyLenTextField.getText()); 146 if (replyLen > 0) { 147 m.setReplyLen(replyLen); 148 } else { 149 m.setReplyLen(getMessageLength(m.getOpCode())); 150 } 151 tc.sendNceMessage(m, this); 152 } else { 153 // ASCII Mode selected 154 155 NceMessage m = new NceMessage(input.length()); 156 for (int i = 0; i < input.length(); i++) { 157 m.setElement(i, input.charAt(i)); 158 } 159 160 tc.sendNceMessage(m, this); 161 } 162 } 163 164 /** 165 * {@inheritDoc} 166 */ 167 @Override 168 public void message(NceMessage m) { 169 } // ignore replies 170 171 /** 172 * {@inheritDoc} 173 */ 174 @Override 175 public void reply(NceReply r) { 176 } // ignore replies 177 178 NceMessage createPacket(String s) { 179 // gather bytes in result 180 byte[] b; 181 try { 182 b = StringUtil.bytesFromHexString(s); 183 } catch (NumberFormatException e) { 184 return null; 185 } 186 if (b.length == 0) { 187 return null; // no such thing as a zero-length message 188 } 189 NceMessage m = new NceMessage(b.length); 190 for (int i = 0; i < b.length; i++) { 191 m.setElement(i, b[i]); 192 } 193 return m; 194 } 195 196 private int getReplyLen(String s) { 197 // gather bytes in result 198 int b; 199 try { 200 b = Integer.parseInt(s); 201 } catch (NumberFormatException e) { 202 return 0; 203 } 204 return b; 205 } 206 207 // gets the expected number of bytes returned 208 private int getMessageLength(int opcode) { 209 int replyLen; 210 switch (opcode & 0xFF) { 211 212 case 0xAB: 213 case 0xAC: 214 replyLen = 0; 215 break; 216 217 case 0x82: 218 case 0x9B: 219 case 0xA1: 220 case 0xA7: 221 case 0xA9: 222 replyLen = 2; 223 break; 224 225 case 0x8C: 226 case 0xAA: 227 replyLen = 3; 228 break; 229 230 case 0x8A: 231 replyLen = 4; 232 break; 233 234 case 0x8F: 235 replyLen = 16; 236 break; 237 default: 238 replyLen = 1; 239 } 240 return replyLen; 241 } 242 243 /** 244 * Nested class to create one of these using old-style defaults. 245 */ 246 static public class Default extends jmri.jmrix.nce.swing.NceNamedPaneAction { 247 248 public Default() { 249 super("Open NCE Send Binary Command", 250 new jmri.util.swing.sdi.JmriJFrameInterface(), 251 NcePacketGenPanel.class.getName(), 252 jmri.InstanceManager.getDefault(NceSystemConnectionMemo.class)); 253 } 254 } 255 256}