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