package com.happysoftware.easyble.utils; import android.bluetooth.BluetoothGattCharacteristic; /** * Created by zhang on 16/7/18. */ public class ByteUtil { /** * Returns the size of a give value type. */ public static int getTypeLen(int formatType) { return formatType & 0xF; } /** * Convert a signed byte to an unsigned int. */ public static int unsignedByteToInt(byte b) { return b & 0xFF; } /** * Convert signed bytes to a 16-bit unsigned int. */ public static int unsignedBytesToInt(byte b0, byte b1) { return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)); } /** * Convert signed bytes to a 32-bit unsigned int. */ public static int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) { return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)) + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24); } /** * Convert an unsigned integer value to a two's-complement encoded * signed value. */ public static 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 16-bit short float value. */ public static float bytesToFloat(byte b0, byte b1) { int mantissa = unsignedToSigned(unsignedByteToInt(b0) + ((unsignedByteToInt(b1) & 0x0F) << 8), 12); int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4); return (float)(mantissa * Math.pow(10, exponent)); } /** * Convert signed bytes to a 32-bit short float value. */ public static float bytesToFloat(byte b0, byte b1, byte b2, byte b3) { int mantissa = unsignedToSigned(unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8) + (unsignedByteToInt(b2) << 16), 24); return (float)(mantissa * Math.pow(10, b3)); } /** * Return the stored value of this characteristic. * * <p>The formatType parameter determines how the characteristic value * is to be interpreted. For example, settting formatType to * {@link #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 static Integer getIntValue(byte[] data, int formatType, int offset) { if ((offset + getTypeLen(formatType)) > data.length) return null; switch (formatType) { case BluetoothGattCharacteristic.FORMAT_UINT8: return unsignedByteToInt(data[offset]); case BluetoothGattCharacteristic.FORMAT_UINT16: return unsignedBytesToInt(data[offset], data[offset+1]); case BluetoothGattCharacteristic.FORMAT_UINT32: return unsignedBytesToInt(data[offset], data[offset+1], data[offset+2], data[offset+3]); case BluetoothGattCharacteristic.FORMAT_SINT8: return unsignedToSigned(unsignedByteToInt(data[offset]), 8); case BluetoothGattCharacteristic.FORMAT_SINT16: return unsignedToSigned(unsignedBytesToInt(data[offset], data[offset+1]), 16); case BluetoothGattCharacteristic.FORMAT_SINT32: return unsignedToSigned(unsignedBytesToInt(data[offset], data[offset+1], data[offset+2], data[offset+3]), 32); } return null; } /** * Return the stored value of this characteristic. * <p>See {@link #getValue} for details. * * @param formatType The format type used to interpret the characteristic * value. * @param offset Offset at which the float value can be found. * @return Cached value of the characteristic at a given offset or null * if the requested offset exceeds the value size. */ public static Float getFloatValue(byte[] data, int formatType, int offset) { if ((offset + getTypeLen(formatType)) > data.length) return null; switch (formatType) { case BluetoothGattCharacteristic.FORMAT_SFLOAT: return bytesToFloat(data[offset], data[offset+1]); case BluetoothGattCharacteristic.FORMAT_FLOAT: return bytesToFloat(data[offset], data[offset+1], data[offset+2], data[offset+3]); } return null; } }