Android Open Source - senhancelib Control Source






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.datasource;
/*  ww w .ja v a2s. c  o  m*/
import java.util.Date;
import java.util.UUID;

import de.uos.nbp.senhance.bluetooth.PacketConnection.Packet;


/**
 * This is the interface for receiving packets that
 * conform to the Senhance control protocol.
 * 
 * This <em>should</em> be the only place one needs to 
 * reference when implementing the Senhance control protocol.
 * 
 * At the moment, this protocol is rather simple, and only the
 * heartFelt ExperimentComputer DataSource supports it. It is also heavily
 * skewed to the needs of the heartFelt application, it should perhaps
 * be in that project, but it could be expanded and made more general.
 * 
 * The protocol allows a connected device to:
 * <ul>
 *  <li>switch between real and dummy DataSource(s)
 *  <li>write strings to the application's DataLogger
 *  <li>retrieve the mean baseline of the primary DataSource
 *  <li>set the baseline of the primary DataSource (this only has
 *    meaning for dummy DataSources)
 *  <li>initiate and end a transient response in the dummy DataSource
 * </ul>
 * 'Baseline' is, for the currently implemented DataSources, RR interval.
 * 
 * NB: The event log strings are restricted to ASCII because the DataLogger
 * (SDLogger) uses a simplification of String.getBytes() which does not support
 * anything but ASCII characters. The simplified method is used for efficiency -
 * necessary because otherwise converting strings is a severe bottle-neck.
 * 
 *  @author rmuil@UoS.de
 */
public interface ControlSource extends DataSource {
  /** UUID generated by rmuil on 2011/11/25 on saturn.nbp.uos.de with uuidgen */
  public static final UUID AndroidControlUUID =
      UUID.fromString("0d42124d-a18b-4269-a2cc-bf0e93a77bfd");

  /** 
   * Possible Control Commands.
   */
  enum Command {
    /** Ping, used to measure latency */
    Ping(0),
    /** Switch current DataSink(s) to real DataSource(s) and enable. */
    OutputReal(1),
    /** Switch current DataSink(s) to dummy DataSource(s) and enable. */
    OutputDummy(2),
    /** Write an ASCII string to the EventLogger */
    EventLog(3),
    /** Retrieve current baseline value from primary data source */
    GetBaseline(4),
    /** Set baseline value of secondary data source */
    SetBaseline(5),
    /** Retrieve current value from primary data source */
    GetCurrentValue(6),
    /** Disable current DataSink(s) */ 
    OutputDisable(7),
    /** Enable current DataSink(s) */ 
    OutputEnable(8),
    /** Start an artificial transient response in the dummy DataSource. */
    StartTransient(9),
    /** End an artificial transient response in the dummy DataSource. */
    EndTransient(10),
    /** Gracefully and deliberately end connection */
    Disconnect(11),
    Unknown(-1);
    
    private final int id;
    Command(int id) {
      this.id = id;
    }
    public int getValue() { 
      return id;
    }
    public static Command byValue(int id) {
      for (int idx = 0; idx < values().length; idx++) {
        if (values()[idx].getValue() == id)
          return values()[idx];
      }
      return Unknown;
    }
  }
  
  
  /**
   * Possible responses from the Android back to
   * the ControlSource device.
   */
  enum Response {
    /** Acknowledged. */
    ACK(1),
    /** Not acknowledged. */
    NACK(2),
    /** Integer value */
    IntValue(3),
    Unknown(-1);
    private final int id;
    Response(int id) {
      this.id = id;
    }
    public int getValue() { 
      return id;
    }
    public static Response byValue(int id) {
      for (int idx = 0; idx < values().length; idx++) {
        if (values()[idx].getValue() == id)
          return values()[idx];
      }
      return Unknown;
    }
  }
  
  
  /**
   * This is the definition of the generic Control Packet.
   * 
   * The packet format that will actually get sent over bluetooth is:
   * <ul>
   *  <li>1 byte, start byte (discarded on reception)
   *  <li>2 bytes, short unsigned integer,  command
   *  <li>8 bytes, signed long integer,    timestamp
   *  <li>...         payload
   *  <li>1 byte, end byte (discarded on reception)
   * </ul>
   * The byte sizes given exclude escape characters that may be needed, and are thus
   * minimum. Maximum possible is twice the stated number of bytes, although this will
   * practically never happen.
   * 
   * The payloads are:
   * <ol>
   *  <li><b>Ping</b>: none
   *  <li><b>OutputReal</b>: none
   *  <li><b>OutputDummy</b>: none
   *  <li><b>EventLog</b>: an ASCII string to be written to the event log.
   *  <li><b>GetBaseline</b>:
   *   <ul>
   *    <li>4 bytes, signed integer, <em>(not yet implemented)</em> the 
   *        deviceID of the source
   *        from which to retrieve the baseline <em>(currently the primary
   *        source is always used)</em> 
   *   </ul>
   *  <li><b>SetBaseline</b>:
   *   <ul>
   *    <li>4 bytes, signed integer, <em>(not yet implemented)</em> the
   *        deviceID of the source whose baseline is to be set
   *        <em>(currently the secondary source is always used)</em>
   *    <li>4 bytes, signed integer, the baseline value. 
   *   </ul>
   *   <li><b>GetCurrentValue</b>:
   *   <ul>
   *    <li>4 bytes, signed integer, <em>(not yet implemented)</em> the
   *        deviceID of the source from which to retrieve the current value
   *        <em>(currently the primary source is always used)</em>
   *    <li>4 bytes, signed integer, the current value.
   *   </ul>
   *   <li><b>OutputDisable</b>: none
   *   <li><b>OutputEnable</b>: none
   *   <li><b>StartTransient</b>:
   *   <ul>
   *    <li>2 bytes, short signed integer, UAmp - the amplitude of the first
   *    component of the transient response, in BPM (offset from baseline).
      *    <li>2 bytes, short signed integer, VAmp - the amplitude of the second
   *    component of the transient response, in BPM (offset from baseline).
   *   </ul>
   *   <li><b>EndTransient</b>: none
   *   <li><b>Disconnect</b>: none

   * </ol>
   * 
   * TODO: allow arbitrary configuration (perhaps through use of strings, like
   * Bundle implementation) for such things as DummySourceThread's 
   * {@value transientULength} parameter.
   * 
   * @author rmuil@UoS.de
   */
  public class ControlPacket extends Packet {
    /** header is command and timestamp */
    public static final int HdrSize = 10;
    
    public static final int MaxEventLogSize = 200;
    /** payload is variable */
    public static final int MaxPayloadSize = MaxEventLogSize;
    
    /**
     * Maximum size of the packet data after stripping
     * of start and end bytes and after escaping.
     */
    public static final int MaxPacketSize = HdrSize + MaxPayloadSize;
    
    /**
     * This is an index into the received data, after stripping
     * of start and end bytes and after escaping.
     */
    public static final int PayloadStart = HdrSize;
    public static final int DevIDPos = PayloadStart;
    public static final int ValuePos = DevIDPos+4;
    public static final int UAmpPos = PayloadStart;
    public static final int VAmpPos = UAmpPos+2;
    
    public ControlPacket() {
      super(MaxPacketSize);
    }
    
    /**
     * This simply wraps the {@link Packet} in
     * a ControlPacket.
     * 
     * @param pkt
     */
    public ControlPacket(Packet pkt) {
      super(pkt);
    }
    
    /**
     * @hide
     * @return command
     */
    public Command getCommand () {
      return Command.byValue(this.getUShort(0));
    }
    
    /**
     * Returns the timestamp that was written into the packet by the 
     * source. This is distinct from start and end times which are the times
     * at <em>reception</em> on the destination system.
     * @return signed long, milliseconds past Unix epoch
     */
    public long getTimestamp() {
      return this.getLong(2);
    }
    
    public int getDevID() {
      return this.getInt(DevIDPos);
    }
    
    public int getIntValue() {
      return this.getInt(ValuePos);
    }
    
    public String toString() {
      StringBuilder sb = new StringBuilder(getCommand().toString());
      Date dt = new Date(getTimestamp());
      sb.append('@').append(dt.toString());
      return sb.toString();
    }
  }
  
  /**
   * This is the definition of the generic response Packet, sent
   * from Android back to control source.
   * 
   * The packet format that will actually get sent over bluetooth is:
   * <ul>
   *  <li>1 byte, start byte (discarded on reception)
   *  <li>2 bytes, short unsigned integer,  response
   *  <li>... payload
   *  <li>1 byte, end byte (discarded on reception)
   * </ul>
   * 
   * The payloads are:
   * <ol>
   *  <li><b>ACK</b>: none
   *  <li><b>NACK</b>: none
   *  <li><b>IntValue</b>:
   *  <ul>
   *    <li>4 bytes, signed integer, the deviceID of the source
   *    <li>4 bytes, signed integer, the requested value (e.g. RR value)
   *   </ul>
   * </ol>
   * 
   * @author rmuil@UoS.de
   */
  public class ResponsePacket extends Packet {
    public static final int HdrSize = 2;
    public static final int PayloadStart = HdrSize;
    public static final int IntValueDevIDPos = PayloadStart;
    public static final int IntValuePos = IntValueDevIDPos+4;
    public static final int PayloadSizeIntValue = 8;
    public static final int MaxPayloadSize = PayloadSizeIntValue;
    /**
     * Maximum size of data of the packet, without start 
     * and end bytes or escaping.
     */
    public static final int MaxPacketSize = HdrSize + MaxPayloadSize;

    public ResponsePacket() {
      super(MaxPacketSize);
    }
    
    public ResponsePacket (Response response) {
      this();
      this.setResponse(response);
    }
    
    public void setResponse(Response response) {
      this.putUShort(response.getValue(), 0);
    }
    
    public void setIntValue(int value) {
      this.putInt(value, IntValuePos);
    }
    
    public void setIntValueDevID(int devID) {
      this.putInt(devID, IntValueDevIDPos);
    }
    
    /** The primary information in the packet, its response. */
    public Response getResponse() {
      return Response.byValue(this.getUShort(0));
    }
    
    public String toString() {
      StringBuilder sb = new StringBuilder(getResponse().toString());
      sb.append('[').append(super.toString()).append(']');
      return sb.toString();
    }
  }
  
  void send(ResponsePacket pkt);
}




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