BowlerKernel
BowlerDatagram.java
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright 2010 Neuron Robotics, LLC
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  ******************************************************************************/
32 package com.neuronrobotics.sdk.common;
33 
34 // TODO: Auto-generated Javadoc
42 
44  public static final byte REVISION = 3;
45 
47  public static final int HEADER_SIZE = 11;
48 
50  public static final int CRC_INDEX = 10;
51 
53  public static final int MAX_PACKET_SIZE = HEADER_SIZE+255;
54 
56  private MACAddress address = new MACAddress();
57 
60 
62  private byte namespaceResolutionID;
63 
65  private boolean upstream;
66 
68  private byte crc;
69 
71  private byte dataCrc;
72 
74  private ByteList data = new ByteList();
75 
78  //private long timestamp;
79 
80  private boolean isPackedAvailibleForLoading = true;
81 
84 
86  private static boolean useBowlerV4 =true;
87 
88 
95  validate(factory);
96  setFree(true,factory);
97  }
98 
107  private static byte genCRC(int index, int len, ByteList data) {
108  int check = 0;
109  try{
110  for(int i = index; i < len+index; i++) {
111  check += data.getByte(i);
112  }
113  }catch(IndexOutOfBoundsException e){
114  throw new IndexOutOfBoundsException("Attempting from: "+index+ " to: "+len+" in: "+data.size()+" data: "+data);
115  }
116  return (byte)(check&0x000000ff);
117  }
118 
125  private static byte genCrc(ByteList data){
126  return genCRC(0, (BowlerDatagram.HEADER_SIZE-1), data);
127  }
128 
135  private static byte getCRC(ByteList data){
137  }
138 
144  private byte getCrc() {
146  return crc;
147  }
148 
149 
155  private void setCrc(byte crc) {
157  this.crc = crc;
158  }
159 
160 
167  public static byte genDataCrc(ByteList data){
169  }
170 
177  private static byte getDataCrc(ByteList data){
179  }
180 
186  private byte getDataCrc() {
188  return dataCrc;
189  }
190 
191 
197  private void setDataCrc(byte crc) {
199  this.dataCrc = crc;
200  }
201 
210  validate(factory);
211  parse(data);
212  }
213 
219  private void validate(BowlerDatagramFactory factory){
220  if(!isFree()){
221  throw new RuntimeException("Packet is in use, be sure to use the factory");
222  }
223  timeout.initialize(BowlerDatagramFactory.getPacketTimeout(), this);
224  }
225 
231  public void parse(ByteList raw) {
233  // Every valid Bowler packet has 11 characters from the header.
234  if(raw.size() < HEADER_SIZE) {
235  throw new MalformattedDatagram("Datagram does not have a valid Bowler header size.");
236  }
237 
238  // Make sure that the revisions match
239  if(raw.getByte(0) != REVISION) {
240  throw new MalformattedDatagram("Datagram is revision " + raw.getByte(0) + ". Must be of revision " + REVISION);
241  }
242 
243  setAddress(new MACAddress(raw.getBytes(1,6)));
245  if(getMethod() == null){
247  System.err.println("Method was invalid!! Value="+raw.getUnsigned(7));
248  Log.error("Method was invalid!! Value="+raw.getUnsigned(7));
249  }
250 
251  setNamespaceResolutionID((byte) (raw.getUnsigned(8)&0x7f));
252  setUpstream((raw.getByte(8)<0));
253  // Make sure that the size of the data payload is the stated length
254  int dataLength = raw.getUnsigned(9);
255  //Either legacy parser or the v4 parser
256  if((dataLength != raw.getBytes(11).length-1) && (dataLength != raw.getBytes(11).length) ) {
257  throw new MalformattedDatagram("Datagram payload length is mismatched expected "+dataLength+" got "+raw.getBytes(11).length);
258  }
259  // Put the remaining data into the data payload
260  setData(raw.getBytes(HEADER_SIZE,dataLength));
261 
262  // Validate the CRC
263  if(!CheckCRC(raw,true) ) {
264  throw new MalformattedDatagram("CRC does not match: "+raw);
265  }else{
266  setCrc(getCRC(raw));
267  setDataCrc(raw.getByte(raw.size()-1));
268  }
269  setFree(false);
270  }
271 
277  public void setData(byte[] bs){
279  data.clear();
280  data.add(bs);
281  }
282 
290  return new ByteList(data.getBytes());
291  }
292 
300  return address;
301  }
302 
308  public byte getRevision() {
310  return REVISION;
311  }
312 
320  return method;
321  }
322 
328  public byte getNamespaceResolutionID() {
330  return (byte) namespaceResolutionID;
331  }
332 
338  public boolean isSyncronous() {
340 // if(namespaceResolutionID != 0 && method == BowlerMethod.ASYNCHRONOUS){
341 // Log.error("Device firmware out of date, should be using BowlerMethod.ASYNCHRONOUS rather than transactionID != 0" + this);
342 // }
343  return getMethod() != BowlerMethod.ASYNCHRONOUS;
344  }
345 
351  public boolean isUpstream(){
353  return upstream;
354  }
355 
361  public byte getTransactionUpstream(){
363  byte back=(byte) (getNamespaceResolutionID()|(isUpstream()?0x80:0));
364  return back;
365  }
366 
372  public byte getCRC() {
374  return getCrc();
375  }
380  public String getRPC() {
382  try{
383  return new String(data.getBytes(0, 4));
384  }catch(Exception e){
385  //e.printStackTrace();
386  return "****";
387  }
388  }
389 
395  private int getSessionID() {
398  }
399 
405  public ByteList getData() {
407  return new ByteList(data.getBytes(4));
408  }
409  /* (non-Javadoc)
410  * @see com.neuronrobotics.sdk.common.ISendable#getBytes()
411  */
412  public byte[] getBytes() {
414  ByteList bl = new ByteList();
415  bl.add(REVISION);
416  bl.add(getAddress());
417  bl.add(getMethod().getValue());
419  bl.add(data.size());
420  //calculate the CRC
421  setCrc(genCrc(bl));
422 
423 
424  bl.add(getCRC());
425  bl.add(data);
426  if(isUseBowlerV4()){
427  //Log.warning("parsing v4 ");
428  setDataCrc(genDataCrc(bl));
429  bl.add(getDataCrc());
430  }
431  return bl.getBytes();
432  }
433 
434  /* (non-Javadoc)
435  * @see java.lang.Object#toString()
436  */
437  @Override
438  public String toString(){
439  if(isFree())
440  return "Empty Packet";
441  String str="";
442  if(!Log.isPrinting()){
443  return str;
444  }
445  str += "\tRaw Packet:\t";
446  for (byte x : getBytes()){
447  // This writes out the hex values of all the data Bytes
448  str += String.format("%02x ", x);
449  }
450  str += "\n";
451  str += "\tRevision: \t" + (int) REVISION + '\n';
452  str += "\tMAC address: \t" + getAddress() + '\n';
453  str += "\tMethod: \t" + getMethod() + '\n';
454  str += "\tDirection: \t";
455  str += isUpstream() ? "Upstream\n" : "Downstream\n";
456  str += "\tRPC Namespace Index: \t" + getSessionID();
457  str += "\n\tData Size: \t" + (int) data.size() + '\n';
458  str += "\tCRC: \t\t";
459  str += String.format("%02x ", getCrc());
460  if(isUseBowlerV4()){
461  str += "\n\tD-CRC: \t\t";
462  str += String.format("%02x ", getDataCrc());
463  }
464 
465  str += "\n\tRPC: \t\t";
466  str += getRPC();// This extracts the opcode as ascii
467  str += "\n\tData: \t\t";
468  for (byte x : getData().getBytes()){
469  // This writes out the hex values of all the data Bytes
470  str += String.format("%02x ", x);
471  }
472  str += '\n';
473  return str;
474  }
475 
483  static boolean CheckCRC(ByteList buffer, boolean checkData) {
484  try{
485  byte generated,inPacket;
486  generated = genCrc(buffer);
487  inPacket = getCRC(buffer);
488  if(generated != inPacket){
489  Log.error("CRC of packet is: "+generated+" Expected: "+inPacket);
490  return false;
491  }
492 
493  if(checkData && isUseBowlerV4()){
494  generated = genDataCrc(buffer);
495  inPacket = getDataCrc(buffer);
496  if(generated != inPacket){
497  Log.error("Data CRC of packet is: "+generated+" Expected: "+inPacket);
498  return false;
499  }
500  }
501  }catch(Exception ex){
502  if(InterruptedException.class.isInstance(ex))throw new RuntimeException(ex);
503  ex.printStackTrace();
504  return false;
505  }
506  return true;
507  }
508 
514  public long getTimestamp() {
516  return timeout.getStartTime();
517  }
518 
524  public void setAsAsync(int id) {
525  setNamespaceResolutionID((byte) id);
528  }
529 
530 
534  public void clear() {
535  data.clear();
536  }
537 
538 
546  this.address = address;
547  }
548 
549 
557  this.method = method;
558  }
559 
560 
568  this.namespaceResolutionID = namespaceResolutionID;
569  }
570 
571 
577  public void setUpstream(boolean upstream) {
579  this.upstream = upstream;
580  calcCRC();
581  }
582 
583 
584 
585 
589  private void checkValidPacket(){
590  if(isFree() && timeout.isTimedOut()){
591  throw new RuntimeException("This packet has timed out and the data has been cleared marked="+isFree());
592  }else{
593  setFree(false);
594  }
595  }
596 
597 
603  public boolean isFree() {
605  }
606 
607 
614  public void setFree(boolean isFree, BowlerDatagramFactory factory) {
615  BowlerDatagramFactory.validateFactory(factory);
616  setFree(isFree);
617  }
618 
622  private void setNotFree(){
623  clear();
624  timeout.stop();
625  }
626 
630  private void setToFree(){
631  timeout.initialize(BowlerDatagramFactory.getPacketTimeout(), this);
632  }
633 
639  void setFree(boolean isFree) {
640  if(isFree== true){
641  setNotFree();
642  }else{
643  setToFree();
644  }
645  this.isPackedAvailibleForLoading = isFree;
646  }
647 
648  /* (non-Javadoc)
649  * @see com.neuronrobotics.sdk.common.IthreadedTimoutListener#onTimeout(java.lang.String)
650  */
651  @Override
652  public void onTimeout(String message) {
653  if(!isFree() ){
654  long timeoutTime= System.currentTimeMillis()-timeout.getStartTime();
655  if(timeout.getAmountOfTimeForTimerToRun() < timeoutTime){
656  setFree(true);
657  }else{
658  Log.error("Packet fucked up. Expected "+timeout.getAmountOfTimeForTimerToRun()+" ms, took "+timeoutTime+" ms");
659  timeout.initialize(BowlerDatagramFactory.getPacketTimeout(), this);
660  }
661  }
662  }
663 
664 
668  public void calcCRC() {
670  getBytes();
671  }
672 
673 
679  public void setRpc(String opCode) {
680  // TODO Auto-generated method stub
681 
682  }
683 
689  public static boolean isUseBowlerV4() {
690  return useBowlerV4;
691  }
692 
698  public static void setUseBowlerV4(boolean useBowlerV4) {
699  Log.warning("Setting V4 mode = "+useBowlerV4);
700  //new Exception().printStackTrace();
702  }
703 }
void validate(BowlerDatagramFactory factory)
BowlerDatagram(ByteList data, BowlerDatagramFactory factory)
BowlerDatagram(BowlerDatagramFactory factory)
void setFree(boolean isFree, BowlerDatagramFactory factory)
static void setUseBowlerV4(boolean useBowlerV4)
void setNamespaceResolutionID(byte namespaceResolutionID)
static byte genCRC(int index, int len, ByteList data)
synchronized boolean add(byte data)
Definition: ByteList.java:149
static void error(String message)
Definition: Log.java:92
static void warning(String message)
Definition: Log.java:101
static boolean isPrinting()
Definition: Log.java:436
void initialize(long sleepTime, IthreadedTimoutListener listener)
static BowlerMethod get(byte code)