Skip to content

Commit

Permalink
Merge pull request #24 from inovait/release/0.9.3
Browse files Browse the repository at this point in the history
Release 0.9.3
  • Loading branch information
mihakrajnc authored May 15, 2017
2 parents 9db6ead + fca1846 commit 88e0423
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## Version 0.9.3
- Fixed: #21 - BluetoothGattCharacteristic needed to extract value on subscription

## Version 0.9.2
- Fixed: #17 - Subscriptions are not working - Type not found.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ It provides a single entry point for all BTLE related operations.
Include the NeatLE library in your Android project as a Gradle dependency:
```groovy
dependencies {
compile 'si.inova:neatle:0.9.1'
compile 'si.inova:neatle:0.9.3'
}
```

Expand Down
16 changes: 16 additions & 0 deletions neatle/src/main/java/si/inova/neatle/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
Expand All @@ -38,6 +39,7 @@

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

Expand Down Expand Up @@ -108,6 +110,20 @@ public BluetoothDevice getDevice() {
return device;
}

@Override
public BluetoothGattService getService(UUID serviceUUID) {
synchronized (lock) {
return gatt == null ? null : gatt.getService(serviceUUID);
}
}

@Override
public List<BluetoothGattService> getServices() {
synchronized (lock) {
return gatt == null ? null : gatt.getServices();
}
}

@Override
public int getState() {
synchronized (lock) {
Expand Down
24 changes: 24 additions & 0 deletions neatle/src/main/java/si/inova/neatle/monitor/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
package si.inova.neatle.monitor;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattService;

import java.util.List;
import java.util.UUID;

import si.inova.neatle.Neatle;
Expand Down Expand Up @@ -131,4 +134,25 @@ public interface Connection {
* @return the associated BluetoothDevice
*/
BluetoothDevice getDevice();

/**
* Returns a {@link BluetoothGattService}, if the requested UUID is
* supported by the remote device.
*
* @param serviceUUID UUID of the requested service
* @return BluetoothGattService if supported, or null if the requested
* service is not offered by the remote device.
* @see BluetoothGatt#getService(UUID)
*/
BluetoothGattService getService(UUID serviceUUID);

/**
* Returns a list of GATT services offered by the remote device.
*
* @return List of services on the remote device. Returns an empty list
* if service discovery has not yet been performed.
* @see BluetoothGatt#getServices()
*/
List<BluetoothGattService> getServices();

}
102 changes: 102 additions & 0 deletions neatle/src/main/java/si/inova/neatle/operation/CommandResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,36 @@
*/
public class CommandResult {

/**
* Characteristic value format type uint8
*/
public static final int FORMAT_UINT8 = 0x11;

/**
* Characteristic value format type uint16
*/
public static final int FORMAT_UINT16 = 0x12;

/**
* Characteristic value format type uint32
*/
public static final int FORMAT_UINT32 = 0x14;

/**
* Characteristic value format type sint8
*/
public static final int FORMAT_SINT8 = 0x21;

/**
* Characteristic value format type sint16
*/
public static final int FORMAT_SINT16 = 0x22;

/**
* Characteristic value format type sint32
*/
public static final int FORMAT_SINT32 = 0x24;

private final UUID uuid;
private final byte[] data;
private final int status;
Expand Down Expand Up @@ -100,6 +130,45 @@ public int getValueAsInt() {
return ret;
}

/**
* Return the stored value of this characteristic.
* <p>
* <p>The formatType parameter determines how the characteristic value
* is to be interpreted. For example, settting formatType to
* {@link BluetoothGattCharacteristic#FORMAT_UINT16} specifies that the first two bytes of the
* characteristic value at the given offset are interpreted to generate the
* return value.
*
* @param formatType The format type used to interpret the characteristic
* value.
* @param offset Offset at which the integer value can be found.
* @return Cached value of the characteristic or null of offset exceeds
* value size.
*/
public Integer getFormattedIntValue(int formatType, int offset) {
if ((offset + formatType & 0xF) > data.length) return null;

switch (formatType) {
case FORMAT_UINT8:
return unsignedByteToInt(data[offset]);
case FORMAT_UINT16:
return unsignedBytesToInt(data[offset], data[offset + 1]);
case FORMAT_UINT32:
return unsignedBytesToInt(data[offset], data[offset + 1],
data[offset + 2], data[offset + 3]);
case FORMAT_SINT8:
return unsignedToSigned(unsignedByteToInt(data[offset]), 8);
case FORMAT_SINT16:
return unsignedToSigned(unsignedBytesToInt(data[offset],
data[offset + 1]), 16);
case FORMAT_SINT32:
return unsignedToSigned(unsignedBytesToInt(data[offset],
data[offset + 1], data[offset + 2], data[offset + 3]), 32);
}

return null;
}

/**
* Returns the UUID of the characteristic this data was read from.
*
Expand Down Expand Up @@ -137,6 +206,39 @@ public boolean wasSuccessful() {
return status == BluetoothGatt.GATT_SUCCESS;
}

/**
* Convert signed bytes to a 16-bit unsigned int.
*/
private int unsignedBytesToInt(byte b0, byte b1) {
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
}

/**
* Convert a signed byte to an unsigned int.
*/
private int unsignedByteToInt(byte b) {
return b & 0xFF;
}

/**
* Convert an unsigned integer value to a two's-complement encoded
* signed value.
*/
private int unsignedToSigned(int unsigned, int size) {
if ((unsigned & (1 << size - 1)) != 0) {
unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1)));
}
return unsigned;
}

/**
* Convert signed bytes to a 32-bit unsigned int.
*/
private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
+ (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24);
}

@Override
public String toString() {
return "CommandResult[status: " + status + ", uuid:" + uuid + ", data:" + (data == null ? "null" : data.length) + "]";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,19 @@ public void testFactoryMethods() {
assertEquals(Neatle.createUUID(3), result4.getUUID());
assertTrue(result4.wasSuccessful());
}

@Test
public void testFormattedIntValue() {
BluetoothGattCharacteristic gattCharacteristic = Mockito.mock(BluetoothGattCharacteristic.class);
Mockito.when(gattCharacteristic.getValue()).thenReturn(new byte[]{-1, 11, 22, 12, 44});
Mockito.when(gattCharacteristic.getUuid()).thenReturn(Neatle.createUUID(1));

CommandResult result = CommandResult.createCharacteristicRead(gattCharacteristic, BluetoothGatt.GATT_SUCCESS);
assertEquals(255, (int) result.getFormattedIntValue(CommandResult.FORMAT_UINT8, 0));
assertEquals(3071, (int) result.getFormattedIntValue(CommandResult.FORMAT_UINT16, 0));
assertEquals(202771455, (int) result.getFormattedIntValue(CommandResult.FORMAT_UINT32, 0));
assertEquals(-1, (int) result.getFormattedIntValue(CommandResult.FORMAT_SINT8, 0));
assertEquals(3071, (int) result.getFormattedIntValue(CommandResult.FORMAT_SINT16, 0));
assertEquals(202771455, (int) result.getFormattedIntValue(CommandResult.FORMAT_SINT32, 0));
}
}

0 comments on commit 88e0423

Please sign in to comment.