Android Open Source - senhancelib Packet Connection






From Project

Back to project page senhancelib.

License

The source code is released under:

GNU Lesser General Public License

If you think the Android project senhancelib listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package de.uos.nbp.senhance.bluetooth;
//from  w w  w  .  ja  va 2s. c om
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.UUID;

import de.uos.nbp.Utils;

/**
 *Provides the definition of a packet-based
 *connection - that is a connection over which
 *entire packets can be received and sent,
 *as opposed to streams.
 *
 * NB: This contains the Packet class, which includes the buffer implementation.
 * It may be more efficient to implement the buffers in the connection class instead.
 *
 *{@link https://ikw.uni-osnabrueck.de/trac/heartFelt/wiki/Software/Android}
 *
 * @author rmuil@UoS.de
 * November 18, 2011
 */
public interface PacketConnection {

  /*
   * Defaults are taken from Corscience protocol, but this is convenience
   * only, not necessary.
   */
  static final int DefStartByte  = 0xFC;
  static final int DefEndByte    = 0xFD;
  static final int DefEscapeByte  = 0xFE;
  static final int DefOctetStuffByte = 0x20;
  static final int DefMaxPacketSize = 232;
  
  enum State {
    /** Socket has been created and address set, but not yet connected. */
    Disconnected,
    /** Connection established, standing by ready to receive a packet */
    Ready,
    /** A valid packet is coming in */
    Incoming,
    /** Inside escape sequence - an escape flag has been received */
    EscapeSequence,
    /** A full packet has been received. */
    PacketReceived,
    /** The socket has been closed - the connection is dead and cannot be revived. */
    Dead
  }
  
  /**
   * Packet is similar to a ByteBuffer in that it maintains a backing byte
   * array and allows reading and writing from it. However, Packet supports
   * reading and writing of unsigned values as well as signed. It also has
   * some particulars such as the start and end time of the reception of
   * the represented packet.
   * 
   * The main reason for implementing this as a separate class like this is
   * to allow sub-classing for specific types of packets.
   *
   * @author rmuil@UoS.de
   * November 24, 2011
   */
  //TODO: In BTPacket wurde bei jedem Zugriff auf payload gepr?ft, ob es null war und in
  //in diesem Fall zur?ckgegeben. Auch hier f?r mData (das jetzige payload) notwendig? 
  //Wann kann dieser Fall auftreten?
  public class Packet {
    /** only affects the getter functions. */
    final boolean mLittleEndian;
    
    
    /** time in milliseconds since Unix epoch of start of packet reception, in Android time */
    long mStartTime;
    /** time in milliseconds since Unix epoch of end of packet reception, in Android time */
    long mEndTime;
    
     /** System elapsedRealtime after reception of start flag for this packet. */
    long packetStartMillis;
     /** System elapsedRealtime after reception of last byte of this packet. */
    long packetEndMillis;

    /**
     * This is the data of the packet.
     * Would rather keep in an array of integers because bytes
     * in java are actually signed, so we must be careful about
     * reading this array to get a an <em>unsigned</em> number (0-255)
     * rather than -128 to 127.
     * Stored in bytes because many Stream write() functions
     * support only byte[] not int[] or short[].
     */
    protected byte [] mData;
    
    /** This points to the element one past where data has been placed */
    protected int mPosition = 0;
    
    Packet (int size, boolean littleEndian) {
      mData = new byte [size];
      mLittleEndian = littleEndian;
    }
    public Packet (int size) {
      this(size, true);
    }
    Packet () {
      this(DefMaxPacketSize, true);
    }
    
    /**
     * Copy constructor, data buffer is a pointer to the
     * original packet - this is not a deep copy.
     * NB: this is probably bad practice, because the position
     * variable is independent between the two but the array is shared.
     * @param pkt
     */
    protected Packet (Packet pkt) {
      this.mLittleEndian= pkt.mLittleEndian;
      this.mData = pkt.mData;
      this.mPosition = pkt.mPosition;
      this.mStartTime = pkt.mStartTime;
      this.mEndTime = pkt.mEndTime;
      this.packetStartMillis = pkt.packetStartMillis;
      this.packetEndMillis = pkt.packetEndMillis;
    }
    
    /**
     * This allows caller to use their own buffer.
     * @param data
     */
    public Packet(byte [] data) {
      mData = data;
      mPosition = data.length;
      mLittleEndian = true;
    }
    
    public int getDataLength() {
      return mPosition;
    }
    
    public int getRemainingLength(int pos) {
      int remainingLength = getDataLength() - pos;
      return remainingLength;
    }
    
    public long getStartTime() {
      return mStartTime;
    }
    public long getEndTime() {
      return mEndTime;
    }
    public byte[] getData() {
      return mData;
    }
    
    public byte [] getUBytes (int pos, int amount) {
      byte [] buf = new byte [amount];
      for (int ii=0; ii < amount; ii++) {
        buf[ii] = (byte) this.getUByte(pos+ii);
      }
      return buf;
    }
    
    /**
     * Adds a data byte to current packet buffer
     * and increments the counter.
     * @param newByte
     * @throws ArrayIndexOutOfBoundsException
     */
    public void putByte(int newByte) throws ArrayIndexOutOfBoundsException {
      mData[mPosition++]=(byte)(newByte&0xFF);
    }
    /**
     * 
     * @param newByte
     * @param pos
     * @throws ArrayIndexOutOfBoundsException
     */
    public void putByte(int newByte, int pos) throws ArrayIndexOutOfBoundsException {
      mData[pos]=(byte)(newByte&0xFF);
      if (mPosition < (pos+1))
        mPosition = pos+1;
    }

    public byte getByte(int pos){
      return mData[pos];
    }
    
    /**
     * 
     * @param pos
     * @return unsigned 8-bit integer (unsigned byte)
     * @throws ArrayIndexOutOfBoundsException
     */
    public int getUByte(int pos) throws ArrayIndexOutOfBoundsException {
      return mData[pos] & 0xFF;
    }

    /**
     * 
     * @param pos
     * @return unsigned 16-bit integer (short)
     * @throws ArrayIndexOutOfBoundsException
     */
    public int getUShort(int pos) {
      int ret;
      if (mLittleEndian) {
        ret = (mData[pos]&0xFF)+((mData[pos+1]>>>8)&0xFF);
      } else {
        ret = (mData[pos+1]&0xFF)+((mData[pos]>>>8)&0xFF);
      }
      return ret;
    }
    
    /**
     * Puts an unsigned 16-bit integer (short) into the current
     * packet buffer at the requested position.
     * @param newShort
     * @param pos
     * @throws ArrayIndexOutOfBoundsException
     */
    public void putUShort(int newShort, int pos) throws ArrayIndexOutOfBoundsException {
      if (mLittleEndian) {
        mData[pos] =         (byte) (newShort&0xFF);
        mData[pos+1] = (byte) ((newShort>>>8)&0xFF);
      } else {
        mData[pos+1] =       (byte) (newShort&0xFF);
        mData[pos] =   (byte) ((newShort>>>8)&0xFF);
      }
      if (mPosition < (pos+2))
        mPosition = pos+2;
    }
    
    public void setData(byte[] data) {
      this.mData = data;
      this.mPosition = data.length;
    }
    
    /**
     * Returns an unsigned integer comprised of the {@value size} bytes
     * in the data from {@value pos}.
     * 
     * This is the general case.
     * 
     * NB: a long in java is signed and 8 bytes, so an 8 byte
     * unsigned integer cannot be represented by it 
     * 
     * @param pos
     * @param size
     * @return unsigned integer
     * @throws IllegalArgumentException if size is greater than 7.
     */
    public long getUInt(int pos, int size) {
      long value = 0;
      
      if (size > 7) {
        throw new IllegalArgumentException("long cannot represent an unsigned integer more than 7 bytes long");
      }
      
      for (int ii = 0; ii < size; ii++) {
        if (mLittleEndian) {
          value += (mData[pos+ii] & 0xff) << (8 * ii);
        } else {
          value = (value << 8) + (mData[pos+ii] & 0xff);
        }
      }
      return value;
    }
    
    /**
     * Returns an unsigned integer constructed of the 4
     * bytes from {@value pos}.
     * 
     * @param pos
     * @return unsigned integer.
     */
    public long getUInt(int pos) {
      return getUInt(pos, 4);
    }
    
    /**
     * Returns a signed long integer of the 8 bytes starting at pos.
     * @param pos
     * @return signed long
     */
    public long getLong(int pos) {
      long value = 0;
      
      for (int i = 0; i < 8; i++) {
        if (mLittleEndian) {
          value |= ((long)mData[pos+i] & 0xff) << (8 * i);
        } else {
          value = (value << 8) | ((long)mData[pos+i] & 0xff);
        }
      }
      return value;
    }
    
    public String getAscii (int pos, int numBytes) {
      String str = new String();
      for (int ii=0; ii < numBytes; ii++) {
        str += (char)this.getUByte(pos+ii);
      }
      return str;
    }
    
    /**
     * Returns a signed integer composed of the 4 bytes,
     * starting at {@value pos}.
     * @param pos
     * @return signed integer
     */
    public int getInt (int pos) {
      int value = 0;
      
      for (int i = 0; i < 4; i++) {
        if (mLittleEndian) {
          value |= ((int)mData[pos+i] & 0xff) << (8 * i);
        } else {
          value = (value << 8) | ((int)mData[pos+i] & 0xff);
        }
      }
      return value;
    }

    /**
     * Returns a short signed integer composed of the 2 bytes
     * starting at {@value pos}.
     * 
     * @param pos
     * @return short signed integer
     */
    public short getShort (int pos) {
      int MSB = mLittleEndian ? pos+1:pos;
      int LSB = mLittleEndian ? pos:pos+1;

      return (short) ((((short)mData[MSB]) << 8) | ((short)mData[LSB]) & 0xff);
    }
    
    /**
     * Puts a signed integer of 4 bytes into the buffer.
     * @param pos
     * @return signed integer
     */
    public void putInt (int value, int pos) {
      final int count = 4;
      for (int i = 0; i < count; i++) {
        if (mLittleEndian) {
          mData[pos+i] = (byte) ((value >>> (8 * i))&0xFF);
        } else {
          mData[pos+i] = (byte) ((value >>> (8 * (count-i)))&0xFF);
        }
      }
      if (mPosition < (pos+count))
        mPosition = pos+count;
    }
    
     /**
      * Returns the value of the elapsedRealtime system clock as it was
      * after reception of the start flag for this packet.
      * @return packetStartMillis
      */
    public long getStartMillis() {
      return packetStartMillis;
    }
    /**
      * Returns the value of the elapsedRealtime system clock as it was
      * after reception of the <em>last</em> byte of this packet.
      * @return packetEndMillis
      */
    public long getEndMillis() {
      return packetEndMillis;
    }
    
    @Override
    public String toString() {
      //StringBuilder builder = new StringBuilder();
      //builder.append("Packet ");
      //builder.append(Utils.ByteArrayToHexa(mData, mPosition));
      return Utils.ByteArrayToHexa(mData, mPosition);
    }
  }
  
  /**
   * Attempt to establish a connection based on a service record
   * identified by the given UUID.
   * 
   * @param uuid
   * @return true on success
   * @throws IOException 
   */
  public void connect(UUID uuid) throws IOException;
  
  /**
   * Attempt to establish the connection directly using.
   * 
   * Exceptions are unfortunately necessary to allow use
   * of low-level workaround in implementation.
   * 
   * @return success or failure
   * @throws NoSuchMethodException 
   * @throws SecurityException 
   * @throws InvocationTargetException 
   * @throws IllegalAccessException 
   * @throws IllegalArgumentException 
   * @throws IOException 
   */
  public void connect(int port) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException;
  
  public void connect() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException;
  
  /**
   * This is function relies on the class state. It reads the next byte
   * from the input stream and processes it according to the
   * current connection state.
   * 
   * If the byte is data, it should be written to the connection's
   * packet buffer.
   * 
   * When a full packet is ready in the buffer, this function must
   * return true.
   *
   * @return whether full packet is ready.
   * @throws IOException
   *
  public boolean read() throws IOException;
  
  /**
   * Blocks until a complete packet has been received.
   * 
   * @return the time of the start of the packet
   *
  public Packet readPacket () throws IOException;
  
  /**
   * Should discard any data that has already have been received
   * and revert connection to the <tt>Ready</tt> state (unless currently
   * disconnected).
   */
  public void discard();
  
  /**
   * Sends a packet to the connected host,
   * must append the start byte, prepend the end byte,
   * and perform escaping as required.
   * 
   * @param pkt the packet to send
   * @throws IOException
   */
  public void send (Packet pkt) throws IOException;

  /**
   * Returns true if the connection is alive. Will be
   * false if the state is either <tt>Disconnected</tt> or
   * <tt>Dead</tt>. 
   * @return true if connection exists.
   */
  public boolean isConnected ();
  
}




Java Source Code List

de.uos.nbp.BooleanProperties.java
de.uos.nbp.Utils.java
de.uos.nbp.senhance.DataLogger.java
de.uos.nbp.senhance.ECGCsvReader.java
de.uos.nbp.senhance.EventLoggingActivity.java
de.uos.nbp.senhance.EventSequenceAdapter.java
de.uos.nbp.senhance.EventTag.java
de.uos.nbp.senhance.LoggerApplication.java
de.uos.nbp.senhance.SDLogger.java
de.uos.nbp.senhance.bluetooth.BluetoothPacketConnection.java
de.uos.nbp.senhance.bluetooth.BluetoothService.java
de.uos.nbp.senhance.bluetooth.DeviceListActivity.java
de.uos.nbp.senhance.bluetooth.FramedPacketConnection.java
de.uos.nbp.senhance.bluetooth.PacketConnectionHandler.java
de.uos.nbp.senhance.bluetooth.PacketConnection.java
de.uos.nbp.senhance.datasource.ControlSource.java
de.uos.nbp.senhance.datasource.DataSink.java
de.uos.nbp.senhance.datasource.DataSourceBase.java
de.uos.nbp.senhance.datasource.DataSource.java
de.uos.nbp.senhance.datasource.DummySourceThread.java