001package jmri.jmrix.can; 002 003import javax.annotation.Nonnull; 004import jmri.jmrix.AbstractMRMessage; 005 006/** 007 * Base class for messages in a CANbus based message/reply protocol. 008 * <p> 009 * It is expected that any CAN based system will be based upon basic CANbus 010 * concepts such as ID (standard or extended), Normal and RTR frames and a data 011 * field. 012 * <p> 013 * The _dataChars[] and _nDataChars members refer to the data field, not the 014 * entire message. 015 * <p> 016 * "header" refers to the full 11 or 29 bit header; which mode is separately set 017 * via the "extended" parameter 018 * <p> 019 * CBUS uses a 2-bit "Pri" field and 7-bit "ID" ("CAN ID") field, with separate 020 * accessors. CBUS ID is set as a layout connection preference and registered by 021 * the traffic controller. 022 * 023 * @author Andrew Crosland Copyright (C) 2008 024 * @author Bob Jacobsen Copyright (C) 2008, 2009, 2010 025 */ 026public class CanMessage extends AbstractMRMessage implements CanMutableFrame { 027 028 private boolean _translated = false; 029 030 /** 031 * Create a new CanMessage with 8 data bytes 032 * @param header The CAN Frame header value 033 */ 034 public CanMessage(int header) { 035 _header = header; 036 _isExtended = false; 037 _isRtr = false; 038 _nDataChars = 8; 039 super.setBinary(true); 040 _dataChars = new int[8]; 041 } 042 043 /** 044 * Create a new CanMessage of given length 045 * @param numDataBytes number of CAN Frame data bytes, max 8 046 * @param header The CAN Frame header value 047 */ 048 public CanMessage(int numDataBytes, int header) { 049 this(header); 050 _nDataChars = (numDataBytes <= 8) ? numDataBytes : 8; 051 } 052 053 /** 054 * Create a new CanMessage from an int array 055 * @param d array of CAN Frame data bytes, max 8 056 * @param header The CAN Frame header value 057 */ 058 public CanMessage(int[] d, int header) { 059 this(header); 060 setData(d); 061 setNumDataElements((d.length <= 8) ? d.length : 8); 062 } 063 064 /** 065 * Create a new CanMessage from a byte array 066 * @param d array of CAN Frame data bytes, max 8 067 * @param header The CAN Frame header value 068 */ 069 public CanMessage(byte[] d, int header) { 070 this(header); 071 setData(d); 072 setNumDataElements((d.length <= 8) ? d.length : 8); 073 } 074 075 /** 076 * Create a new CanMessage from an existing CanMessage 077 * @param m The existing CanMessage 078 */ 079 public CanMessage(@Nonnull CanMessage m) { 080 this(m.getHeader()); 081 _isExtended = m.isExtended(); 082 _isRtr = m.isRtr(); 083 super.setBinary(true); 084 setData(java.util.Arrays.copyOf(m.getData(),m.getNumDataElements())); 085 setNumDataElements(m.getNumDataElements()); 086 } 087 088 /** 089 * Create a new CanMessage from an existing CanReply 090 * @param m The existing CanReply 091 */ 092 public CanMessage(@Nonnull CanReply m) { 093 this(m.getHeader()); 094 _isExtended = m.isExtended(); 095 _isRtr = m.isRtr(); 096 super.setBinary(true); 097 setData(m.getData()); 098 setNumDataElements(m.getNumDataElements()); 099 } 100 101 /** 102 * Tag whether translation is needed. 103 * a "native" message has been converted already. 104 * @param translated true or false to set flag as required 105 */ 106 public void setTranslated(boolean translated) { 107 _translated = translated; 108 } 109 110 /** 111 * Check if translation flag has been set. 112 * @return false by default 113 */ 114 public boolean isTranslated() { 115 return _translated; 116 } 117 118 /** 119 * Hash on the header 120 */ 121 @Override 122 public int hashCode() { 123 return _header; 124 } 125 126 /** 127 * Note that a CanMessage and a CanReply can be tested for equality. 128 * @param a CanMessage or CanReply to test against 129 */ 130 @Override 131 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "EQ_UNUSUAL", 132 justification = "Equality test done in CanFrame") 133 public boolean equals(Object a) { 134 return isEqual(this,a); 135 } 136 137 /** 138 * {@inheritDoc} 139 * This format matches {@link CanReply} 140 */ 141 @Override 142 public String toString() { 143 return getToString(); 144 } 145 146 /** 147 * {@inheritDoc} 148 * This format matches {@link CanReply} 149 */ 150 @Override 151 public String toMonitorString() { 152 return monString(); 153 } 154 155 /** 156 * {@inheritDoc} 157 * @return always false 158 */ 159 @Override 160 public boolean replyExpected() { 161 return false; 162 } 163 164 /** 165 * {@inheritDoc} 166 */ 167 @Override 168 public int getNumDataElements() { 169 return _nDataChars; 170 } 171 172 /** 173 * {@inheritDoc} 174 */ 175 @Override 176 public final void setNumDataElements(int n) { 177 _nDataChars = n; 178 } 179 180 /** 181 * {@inheritDoc} 182 */ 183 @Override 184 public int getElement(int n) { 185 return _dataChars[n]; 186 } 187 188 /** 189 * {@inheritDoc} 190 */ 191 @Override 192 public void setElement(int n, int v) { 193 _dataChars[n] = v; 194 } 195 196 /** 197 * Get the data bytes in array form. 198 * @return the actual int array 199 */ 200 public int[] getData() { 201 return _dataChars; 202 } 203 204 /** 205 * {@inheritDoc} 206 */ 207 @Override 208 public int getHeader() { 209 return _header; 210 } 211 212 /** 213 * {@inheritDoc} 214 */ 215 @Override 216 public void setHeader(int h) { 217 _header = h; 218 } 219 220 /** 221 * {@inheritDoc} 222 */ 223 @Override 224 public boolean isExtended() { 225 return _isExtended; 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 @Override 232 public void setExtended(boolean b) { 233 _isExtended = b; 234 } 235 236 /** 237 * {@inheritDoc} 238 */ 239 @Override 240 public boolean isRtr() { 241 return _isRtr; 242 } 243 244 /** 245 * {@inheritDoc} 246 */ 247 @Override 248 public void setRtr(boolean b) { 249 _isRtr = b; 250 } 251 252 // contents (package access) 253 int _header; 254 boolean _isExtended; 255 boolean _isRtr; 256}