diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/Models/DexdripPacket.java b/app/src/main/java/com/eveningoutpost/dexdrip/Models/DexdripPacket.java new file mode 100644 index 00000000..946d4d65 --- /dev/null +++ b/app/src/main/java/com/eveningoutpost/dexdrip/Models/DexdripPacket.java @@ -0,0 +1,8 @@ +package com.eveningoutpost.dexdrip.Models; + +/** + * Created by Radu Iliescu on 25.02.2015. + */ +public class DexdripPacket { + public static final int PACKET_DATA = 1; +} \ No newline at end of file diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/Models/TransmitterData.java b/app/src/main/java/com/eveningoutpost/dexdrip/Models/TransmitterData.java index 4b66e379..9bfc829b 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/Models/TransmitterData.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/Models/TransmitterData.java @@ -7,6 +7,7 @@ import com.activeandroid.annotation.Column; import com.activeandroid.annotation.Table; import com.activeandroid.query.Select; +import com.eveningoutpost.dexdrip.utils.PacketUtil; import java.util.Date; import java.util.UUID; @@ -78,6 +79,48 @@ public static TransmitterData create(int raw_data ,int sensor_battery_level, lon return transmitterData; } + public static TransmitterData createFromBinary(byte data[]) { + /* this is the C structure packed in data + needs to be in sync with wixel-DexDrip/libraries/include/dexdrip_packet.h + structure has versioning used only when members are changed; + + Version 1: + struct dexdrip_data_packet { + uint8 version; + uint8 dexcom_battery; + uint16 dexdrip_battery; + uint32 raw; + } dexdrip_data_packet_t; + */ + + int version; + int wixel_battery; + TransmitterData transmitterData = new TransmitterData(); + + version = PacketUtil.uint8FromBuffer(data, 0); + if (version == 1) { + if (data.length != 8) { + /* incompatible ABI with wixel */ + Log.e(TAG, "corrupted packet - data length " + data.length + " is different than expected " + 8); + return null; + } + transmitterData.sensor_battery_level = PacketUtil.uint8FromBuffer(data, 1); + wixel_battery = PacketUtil.uint16FromBuffer(data, 2); + transmitterData.raw_data = PacketUtil.uint32FromBuffer(data, 4); + } else { + Log.e(TAG, "unknown data packet version " + version); + return null; + } + + transmitterData.timestamp = new Date().getTime(); + transmitterData.uuid = UUID.randomUUID().toString(); + Log.d(TAG, "binary transmitter data raw " + transmitterData.raw_data + + " sensor battery " + transmitterData.sensor_battery_level + + " wixel battery " + wixel_battery); + transmitterData.save(); + return transmitterData; + } + public static TransmitterData last() { return new Select() .from(TransmitterData.class) diff --git a/app/src/main/java/com/eveningoutpost/dexdrip/Services/DexCollectionService.java b/app/src/main/java/com/eveningoutpost/dexdrip/Services/DexCollectionService.java index 16f79660..e20ed370 100644 --- a/app/src/main/java/com/eveningoutpost/dexdrip/Services/DexCollectionService.java +++ b/app/src/main/java/com/eveningoutpost/dexdrip/Services/DexCollectionService.java @@ -39,6 +39,7 @@ import com.activeandroid.query.Select; import com.eveningoutpost.dexdrip.Models.ActiveBluetoothDevice; import com.eveningoutpost.dexdrip.Models.BgReading; +import com.eveningoutpost.dexdrip.Models.DexdripPacket; import com.eveningoutpost.dexdrip.Sensor; import com.eveningoutpost.dexdrip.UtilityModels.CollectionServiceStarter; import com.eveningoutpost.dexdrip.UtilityModels.ForegroundServiceStarter; @@ -75,6 +76,17 @@ public class DexCollectionService extends Service { private static final int STATE_CONNECTING = BluetoothProfile.STATE_CONNECTING; private static final int STATE_CONNECTED = BluetoothProfile.STATE_CONNECTED; + private static final int PSTATE_NEW_PACKET = 0; + private static final int PSTATE_PRIOR_READ_LEN = 1; + private static final int PSTATE_INREAD = 2; + + private int mPacketState = PSTATE_NEW_PACKET; + private byte mPacket[]; + private byte mPacketType; + private byte mPacketLen; + private byte mPacketReadBytes; + private long mLastReadTimestamp; + public final static String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE"; public final static UUID DexDripDataService = UUID.fromString(HM10Attributes.HM_10_SERVICE); public final static UUID DexDripDataCharacteristic = UUID.fromString(HM10Attributes.HM_RX_TX); @@ -238,7 +250,7 @@ private void broadcastUpdate(final String action, final byte[] data = characteristic.getValue(); if (data != null && data.length > 0) { - setSerialDataToTransmitterRawData(data, data.length); + setSerialBinaryDataToTransmitterRawData(data, data.length); } } @@ -350,19 +362,104 @@ public void setCharacteristicNotification(BluetoothGattCharacteristic characteri } public void setSerialDataToTransmitterRawData(byte[] buffer, int len) { - - Log.w(TAG, "received some data!"); - TransmitterData transmitterData = TransmitterData.create(buffer, len); + Long timestamp = new Date().getTime(); + TransmitterData transmitterData = TransmitterData.create(buffer, len, timestamp); if (transmitterData != null) { Sensor sensor = Sensor.currentSensor(); if (sensor != null) { sensor.latest_battery_level = transmitterData.sensor_battery_level; sensor.save(); - BgReading bgReading = BgReading.create(transmitterData.raw_data, this); + BgReading bgReading = BgReading.create(transmitterData.raw_data, this, timestamp); } else { Log.w(TAG, "No Active Sensor, Data only stored in Transmitter Data"); } } } + + public void setSerialBinaryDataToTransmitterRawData(byte[] buffer, int len) { + int bufferReadPos = 0; + int i = 0; + Log.w(TAG, "received some data! " + len); + Long timestamp = new Date().getTime(); + if (timestamp - mLastReadTimestamp > 2000) { + //if there was no read notification for over 2s means we had a malformed short packet; + //save the new timestamp and reset state machine + mPacketState = PSTATE_NEW_PACKET; + mLastReadTimestamp = timestamp; + } + + if (mPacketState == PSTATE_NEW_PACKET) { + //beginning of a new packet - get type len and as much as available from packet + if (len > bufferReadPos) { + mPacketType = buffer[bufferReadPos]; + Log.d(TAG, "read packet type " + mPacketType); + if (mPacketType != DexdripPacket.PACKET_DATA) { + Log.e(TAG, "this is not a binary packet switch to old method"); + setSerialDataToTransmitterRawData(buffer, len); + return; + } + + //goto to next state + mPacketState = PSTATE_PRIOR_READ_LEN; + bufferReadPos++; + } + } + + if (mPacketState == PSTATE_PRIOR_READ_LEN) { + //read the packet length + if (len > bufferReadPos) { + mPacketLen = buffer[bufferReadPos]; + Log.d(TAG, "packet len " + mPacketLen); + if (mPacketLen > 20) { + mPacketState = PSTATE_NEW_PACKET; + Log.e(TAG, "malformed packet received"); + return; + } + mPacketState = PSTATE_INREAD; + mPacket = new byte[mPacketLen]; + mPacketReadBytes = 0; + bufferReadPos++; + } + } + + if (mPacketState == PSTATE_INREAD) { + //read the packet + for (i = bufferReadPos; (mPacketReadBytes < mPacketLen) && (i