public void parseResponse(byte[] rd, BluetoothGattCharacteristic characteristic) {
    Log.d(LOGTAG, "parseResponse: " + Simple.getHexBytesToString(rd));

    if ((rd[0] == (byte) 0xff) && (rd.length == 1)) {
      Log.d(LOGTAG, "parseResponse: Invalid command");

      return;
    }

    try {
      JSONObject sensordata = new JSONObject();

      if (rd.length == 11) {
        //
        // Todays data.
        //

        sensordata.put("type", "TodaysData");

        Calendar calendar = Calendar.getInstance();

        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);

        long targetday = calendar.getTimeInMillis();

        sensordata.put("dts", Simple.timeStampAsISO(targetday));

        byte[] data = new byte[4];

        data[0] = 0;
        data[1] = rd[2];
        data[2] = rd[1];
        data[3] = rd[0];

        sensordata.put("stp", BlueTooth.convertBytesToInt(data));

        data[0] = 0;
        data[1] = 0;
        data[2] = rd[7];
        data[3] = rd[6];

        sensordata.put("sle", BlueTooth.convertBytesToInt(data));

        //
        // Store data.
        //

        JSONObject record = Json.clone(sensordata);
        Json.remove(record, "type");

        HealthData.addRecord("sensor", record);
      }

      if (rd.length == 17) {
        //
        // Step history data.
        //

        sensordata.put("type", "StepHistoryData");

        int day = rd[0];

        Calendar calendar = Calendar.getInstance();

        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);

        long targetday = calendar.getTimeInMillis();

        targetday /= 1000L;
        targetday -= (day + 1) * 86400;
        targetday *= 1000L;

        sensordata.put("dts", Simple.timeStampAsISO(targetday));

        byte[] data = new byte[4];

        data[0] = 0;
        data[1] = rd[3];
        data[2] = rd[2];
        data[3] = rd[1];

        sensordata.put("stp", BlueTooth.convertBytesToInt(data));

        data[0] = 0;
        data[1] = 0;
        data[2] = rd[5];
        data[3] = rd[4];

        sensordata.put("ext", BlueTooth.convertBytesToInt(data));

        data[0] = 0;
        data[1] = (byte) (rd[8] & 0x7f);
        data[2] = rd[7];
        data[3] = rd[6];

        sensordata.put("goa", BlueTooth.convertBytesToInt(data));
        sensordata.put("gou", ((rd[8] & 0x80) == 0) ? 0 : 1);

        data[0] = 0;
        data[1] = 0;
        data[2] = rd[10];
        data[3] = rd[9];

        sensordata.put("std", BlueTooth.convertBytesToInt(data) / 100f);
        sensordata.put("diu", ((rd[13] & 0x80) == 0) ? 0 : 1);

        data[0] = 0;
        data[1] = (byte) (rd[13] & 0x7f);
        data[2] = rd[12];
        data[3] = rd[11];

        sensordata.put("cps", BlueTooth.convertBytesToInt(data) / 100f);

        data[0] = 0;
        data[1] = rd[16];
        data[2] = rd[15];
        data[3] = rd[14];

        sensordata.put("BMR", BlueTooth.convertBytesToInt(data) / 100f);

        //
        // Store data.
        //

        JSONObject record = Json.clone(sensordata);
        Json.remove(record, "type");

        HealthData.addRecord("sensor", record);

        String lastSavedDay = Simple.timeStampAsISO(targetday);

        Json.put(syncStatus, "lastSavedDay", lastSavedDay);

        HealthData.putStatus("sensor", syncStatus);
      }

      if (rd.length == 20) {
        //
        // Sleep history data.
        //

        sensordata.put("type", "SleepHistoryData");

        int position = (rd[0] & 0x7f) + (rd[1] << 7);

        long tenminutes = 10 * 60;
        long postime = ((new Date().getTime() / 1000L) / tenminutes) * tenminutes;
        postime -= position * tenminutes;
        postime *= 1000L;

        sensordata.put("dts", Simple.timeStampAsISO(postime));

        byte[] sd = new byte[18];

        int cnt = 0;
        for (int inx = rd.length - 1; inx >= 2; inx--) sd[cnt++] = rd[inx];

        sensordata.put("sda", Simple.getHexBytesToString(sd));

        //
        // Store data.
        //

        JSONObject record = Json.clone(sensordata);
        Json.remove(record, "type");

        HealthData.addRecord("sensor", record);

        String lastSavedAct = Simple.timeStampAsISO(postime);

        Json.put(syncStatus, "lastSavedAct", lastSavedAct);

        HealthData.putStatus("sensor", syncStatus);
      }

      JSONObject data = new JSONObject();
      data.put("sensor", sensordata);

      if (parent.dataCallback != null)
        parent.dataCallback.onBluetoothReceivedData(parent.deviceName, data);
    } catch (JSONException ex) {
      OopsService.log(LOGTAG, ex);
    }
  }
  private void startSyncSequence() {
    //
    // Initialize sensor device with current
    // goal data and current time.
    //

    parent.gattSchedule.add(new BlueTooth.GattAction(getSetUserSettingWithGoal()));

    //
    // Read todays stuff.
    //

    BlueTooth.GattAction ga = new BlueTooth.GattAction();

    ga.mode = BlueTooth.GattAction.MODE_READ;
    ga.characteristic = parent.currentSecondary;

    parent.gattSchedule.add(ga);

    parent.fireNext(false);

    //
    // Get sync status.
    //

    syncStatus = HealthData.getStatus("sensor");

    //
    // Compute time stuff for step day history records.
    //

    long lastSavedDay = 0;

    if (syncStatus.has("lastSavedDay")) {
      lastSavedDay = Simple.getTimeStamp(Json.getString(syncStatus, "lastSavedDay"));
      lastSavedDay /= 1000L;
    }

    //
    // Get no more than ten days back.
    //

    Calendar calendar = Calendar.getInstance();

    calendar.setTime(new Date());
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);

    long today = calendar.getTimeInMillis();
    today /= 1000L;

    long tendays = 86400 * 10;

    long todoSavedDay = ((today - lastSavedDay) > tendays) ? (today - tendays) : lastSavedDay;

    //
    // Schedule activity days.
    //

    while (todoSavedDay < today) {
      todoSavedDay += 86400;

      int day = (int) ((today - todoSavedDay) / 86400);

      Log.d(LOGTAG, "startSyncSequence: schedule day:" + day);

      parent.gattSchedule.add(new BlueTooth.GattAction(getStepHistoryData(day)));
    }

    //
    // Schedule sleep data positions.
    //

    long lastSavedAct = 0;

    if (syncStatus.has("lastSavedAct")) {
      lastSavedAct = Simple.getTimeStamp(Json.getString(syncStatus, "lastSavedAct"));
      lastSavedAct /= 1000L;
    }

    long now = new Date().getTime();

    calendar.setTimeInMillis(now);
    calendar.set(Calendar.MINUTE, (calendar.get(Calendar.MINUTE) / 10) * 10);
    calendar.set(Calendar.SECOND, 0);

    long nowtenminutes = calendar.getTimeInMillis() / 1000L;

    calendar.set(Calendar.HOUR_OF_DAY, (calendar.get(Calendar.HOUR_OF_DAY) / 3) * 3);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);

    long nowthreehours = calendar.getTimeInMillis() / 1000L;

    int startposition = (int) ((nowtenminutes - nowthreehours) / (10 * 60));
    int lastposition = startposition + (10 * 8 * 18);

    while (lastposition >= startposition) {
      long positiontime = nowtenminutes - (lastposition * 10 * 60);

      if (positiontime >= lastSavedAct) {
        Log.d(LOGTAG, "startSyncSequence: schedule position:" + lastposition);

        parent.gattSchedule.add(new BlueTooth.GattAction(getSleepHistoryData(lastposition)));
      }

      lastposition -= 18;
    }

    //
    // Disconnect after sync.
    //

    parent.gattSchedule.add(new BlueTooth.GattAction(BlueTooth.GattAction.MODE_DISCONNECT));

    parent.fireNext(false);
  }