Skip to content

Commit

Permalink
Add support for UINT48 values
Browse files Browse the repository at this point in the history
  • Loading branch information
weliem committed Oct 15, 2022
1 parent b7ad481 commit ffef9fc
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 38 deletions.
54 changes: 35 additions & 19 deletions blessed/src/main/java/com/welie/blessed/BluetoothBytesParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ public class BluetoothBytesParser {
*/
public static final int FORMAT_UINT32 = 0x14;

/**
* Characteristic value format type uint48
*/
public static final int FORMAT_UINT48 = 0x16;

/**
* Characteristic value format type uint64
*/
public static final int FORMAT_UINT64 = 0x18;

/**
* Characteristic value format type sint8
*/
Expand Down Expand Up @@ -178,8 +188,8 @@ public BluetoothBytesParser(@NotNull final byte[] value, final int offset, @NotN
* @throws IllegalArgumentException if there are not enough bytes for a long value
*/
@NotNull
public Long getLongValue() {
return getLongValue(internalByteOrder);
public Long getLongValue(final int formatType) {
return getLongValue(formatType, internalByteOrder);
}

/**
Expand All @@ -191,10 +201,10 @@ public Long getLongValue() {
* @throws NullPointerException if the value of byteOrder is null
*/
@NotNull
public Long getLongValue(@NotNull final ByteOrder byteOrder) {
public Long getLongValue(final int formatType, @NotNull final ByteOrder byteOrder) {
Objects.requireNonNull(byteOrder);
long result = getLongValue(internalOffset, byteOrder);
internalOffset += 8;
long result = getLongValue(formatType, internalOffset, byteOrder);
internalOffset += getTypeLen(formatType);
return result;
}

Expand All @@ -208,21 +218,22 @@ public Long getLongValue(@NotNull final ByteOrder byteOrder) {
* @throws NullPointerException if the value of byteOrder is null
*/
@NotNull
public Long getLongValue(final int offset, @NotNull final ByteOrder byteOrder) {
public Long getLongValue(final int formatType, final int offset, @NotNull final ByteOrder byteOrder) {
Objects.requireNonNull(byteOrder);
int length = getTypeLen(formatType);
if (offset < 0) throw new IllegalArgumentException(OFFSET_MUST_BE_GREATER_OR_EQUAL_TO_ZERO);
if ((offset + 8) > mValue.length) throw new IllegalArgumentException(INVALID_OFFSET);
if ((offset + length) > mValue.length) throw new IllegalArgumentException(INVALID_OFFSET);

if (byteOrder == LITTLE_ENDIAN) {
long value = 0x00FF & mValue[offset + 7];
for (int i = 6; i >= 0; i--) {
long value = 0x00FF & mValue[offset + length - 1];
for (int i = length - 2; i >= 0; i--) {
value <<= 8;
value += 0x00FF & mValue[i + offset];
}
return value;
} else if (byteOrder == BIG_ENDIAN) {
long value = 0x00FF & mValue[offset];
for (int i = 1; i < 8; i++) {
for (int i = 1; i < length; i++) {
value <<= 8;
value += 0x00FF & mValue[i + offset];
}
Expand Down Expand Up @@ -595,31 +606,36 @@ public void setIntValue(final int value, final int formatType) {
* Set byte array to a long. This will increment the internal offset
*
* @param value New long value for this byte array
* @param formatType Long format type used to transform the value parameter
*/
public void setLong(final long value) {
setLong(value, internalOffset);
internalOffset += 8;
public void setLong(final long value, final int formatType) {
setLong(value, formatType, internalOffset);
internalOffset += getTypeLen(formatType);
}

/**
* Set byte array to a long
*
* @param value New long value for this byte array
* @param formatType Long format type used to transform the value parameter
* @param offset Offset at which the value should be placed
* @throws IllegalArgumentException if the offset is invalid
*/
public void setLong(final long value, final int offset) {
public void setLong(final long value, final int formatType, final int offset) {
if (offset < 0) throw new IllegalArgumentException(OFFSET_MUST_BE_GREATER_OR_EQUAL_TO_ZERO);
prepareArray(offset + 8);
if (!(formatType == FORMAT_UINT48 | formatType == FORMAT_UINT64)) throw new IllegalArgumentException("format type not allowed");

int length = getTypeLen(formatType);
prepareArray(offset + length);

long newValue = value;
if (internalByteOrder == ByteOrder.BIG_ENDIAN) {
for (int i = 7; i >= 0; i--) {
for (int i = length - 1; i >= 0; i--) {
mValue[i + offset] = (byte) (newValue & 0xFF);
newValue >>= 8;
}
} else {
for (int i = 0; i < 8; i++) {
for (int i = 0; i < length; i++) {
mValue[i + offset] = (byte) (newValue & 0xFF);
newValue >>= 8;
}
Expand Down Expand Up @@ -664,9 +680,9 @@ public void setFloatValue(final int mantissa, final int exponent, final int form
mValue[newOffset++] = (byte) (newMantissa & 0xFF);
mValue[newOffset++] = (byte) ((newMantissa >> 8) & 0xFF);
mValue[newOffset++] = (byte) ((newMantissa >> 16) & 0xFF);
mValue[newOffset] += (byte) (newExponent & 0xFF);
mValue[newOffset] = (byte) (newExponent & 0xFF);
} else {
mValue[newOffset++] += (byte) (newExponent & 0xFF);
mValue[newOffset++] = (byte) (newExponent & 0xFF);
mValue[newOffset++] = (byte) ((newMantissa >> 16) & 0xFF);
mValue[newOffset++] = (byte) ((newMantissa >> 8) & 0xFF);
mValue[newOffset] = (byte) (newMantissa & 0xFF);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import static com.welie.blessed.BluetoothBytesParser.FORMAT_UINT16;
import static com.welie.blessed.BluetoothBytesParser.FORMAT_UINT24;
import static com.welie.blessed.BluetoothBytesParser.FORMAT_UINT32;
import static com.welie.blessed.BluetoothBytesParser.FORMAT_UINT48;
import static com.welie.blessed.BluetoothBytesParser.FORMAT_UINT64;
import static com.welie.blessed.BluetoothBytesParser.FORMAT_UINT8;
import static java.nio.ByteOrder.BIG_ENDIAN;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
Expand Down Expand Up @@ -340,33 +342,33 @@ public void parseLong_BigEndianTest() {
BluetoothBytesParser parser;

parser = new BluetoothBytesParser(new byte[]{0,0,0,0,0,0,0,1}, BIG_ENDIAN);
assertEquals(1L, (long) parser.getLongValue());
assertEquals(1L, (long) parser.getLongValue(FORMAT_UINT64));

parser = new BluetoothBytesParser(new byte[]{0,0,0,0,0,0,1,1}, BIG_ENDIAN);
assertEquals(257L, (long) parser.getLongValue());
assertEquals(257L, (long) parser.getLongValue(FORMAT_UINT64));

parser = new BluetoothBytesParser(new byte[]{1,1,1,1,1,1,1,1}, BIG_ENDIAN);
assertEquals(72340172838076673L, (long) parser.getLongValue());
assertEquals(72340172838076673L, (long) parser.getLongValue(FORMAT_UINT64));

parser = new BluetoothBytesParser(new byte[]{1,2,3,4,5,6,7,8}, BIG_ENDIAN);
assertEquals(72623859790382856L, (long)parser.getLongValue());
assertEquals(72623859790382856L, (long)parser.getLongValue(FORMAT_UINT64));
}

@Test
public void parseLong_LittleEndianTest() {
BluetoothBytesParser parser;

parser = new BluetoothBytesParser(new byte[]{1,0,0,0,0,0,0,0}, LITTLE_ENDIAN);
assertEquals(1L, (long) parser.getLongValue());
assertEquals(1L, (long) parser.getLongValue(FORMAT_UINT64));

parser = new BluetoothBytesParser(new byte[]{1,1,0,0,0,0,0,0}, LITTLE_ENDIAN);
assertEquals(257L, (long) parser.getLongValue());
assertEquals(257L, (long) parser.getLongValue(FORMAT_UINT64));

parser = new BluetoothBytesParser(new byte[]{1,1,1,1,1,1,1,1}, LITTLE_ENDIAN);
assertEquals(72340172838076673L, (long) parser.getLongValue());
assertEquals(72340172838076673L, (long) parser.getLongValue(FORMAT_UINT64));

parser = new BluetoothBytesParser(new byte[]{8,7,6,5,4,3,2,1}, LITTLE_ENDIAN);
assertEquals(72623859790382856L, (long) parser.getLongValue());
assertEquals(72623859790382856L, (long) parser.getLongValue(FORMAT_UINT64));
}

@Test (expected = IllegalArgumentException.class)
Expand Down Expand Up @@ -778,38 +780,40 @@ public void setSINT32_BigEndianTest() {
@Test
public void setLong_LittleEndianTest() {
BluetoothBytesParser parser = new BluetoothBytesParser(LITTLE_ENDIAN);
parser.setLong(1234567890123L);
assertEquals(1234567890123L, (long) parser.getLongValue(0, LITTLE_ENDIAN));
parser.setLong(1234567890123L, FORMAT_UINT64);
parser.setLong(946684800L, FORMAT_UINT48);
assertEquals(1234567890123L, (long) parser.getLongValue(FORMAT_UINT64, 0, LITTLE_ENDIAN));
assertEquals(946684800L, (long) parser.getLongValue(FORMAT_UINT48, 8, LITTLE_ENDIAN));

parser = new BluetoothBytesParser(LITTLE_ENDIAN);
parser.setIntValue(123, FORMAT_UINT8);
parser.setLong(1234567890123L);
parser.setLong(1234567890123L, FORMAT_UINT64);
assertEquals(9, parser.getValue().length);
parser.setOffset(0);
assertEquals(123, (int) parser.getIntValue(FORMAT_UINT8));
assertEquals(1234567890123L, (long) parser.getLongValue(LITTLE_ENDIAN));
assertEquals(1234567890123L, (long) parser.getLongValue(FORMAT_UINT64, LITTLE_ENDIAN));
}

@Test
public void setLong_BigEndianTest() {
BluetoothBytesParser parser = new BluetoothBytesParser(BIG_ENDIAN);
parser.setLong(1234567890123L);
assertEquals(1234567890123L, (long) parser.getLongValue(0, BIG_ENDIAN));
parser.setLong(1234567890123L, FORMAT_UINT64);
assertEquals(1234567890123L, (long) parser.getLongValue(FORMAT_UINT64, 0, BIG_ENDIAN));

parser = new BluetoothBytesParser(BIG_ENDIAN);
parser.setIntValue(123, FORMAT_UINT8);
parser.setLong(1234567890123L);
parser.setLong(1234567890123L, FORMAT_UINT64);
assertEquals(9, parser.getValue().length);

parser.setOffset(0);
assertEquals(123, (int) parser.getIntValue(FORMAT_UINT8));
assertEquals(1234567890123L, (long) parser.getLongValue(BIG_ENDIAN));
assertEquals(1234567890123L, (long) parser.getLongValue(FORMAT_UINT64, BIG_ENDIAN));

parser.setLong(987654321L);
parser.setLong(987654321L, FORMAT_UINT64);
parser.setOffset(0);
assertEquals(123, (int) parser.getIntValue(FORMAT_UINT8));
assertEquals(1234567890123L, (long) parser.getLongValue());
assertEquals(987654321L, (long) parser.getLongValue());
assertEquals(1234567890123L, (long) parser.getLongValue(FORMAT_UINT64));
assertEquals(987654321L, (long) parser.getLongValue(FORMAT_UINT64));
}

@Test
Expand Down

0 comments on commit ffef9fc

Please sign in to comment.