@Override
	public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
		super.onDataReceived(device, data);

		if (data.size() < 7) {
			onInvalidDataReceived(device, data);
			return;
		}
		// First byte: flags
		int offset = 0;
		final int flags = data.getIntValue(Data.FORMAT_UINT8, offset++);

		// See UNIT_* for unit options
		final int unit = (flags & 0x01) == UNIT_mmHg ? UNIT_mmHg : UNIT_kPa;
		final boolean timestampPresent         = (flags & 0x02) != 0;
		final boolean pulseRatePresent         = (flags & 0x04) != 0;
		final boolean userIdPresent            = (flags & 0x08) != 0;
		final boolean measurementStatusPresent = (flags & 0x10) != 0;

		if (data.size() < 7
				+ (timestampPresent ? 7 : 0) + (pulseRatePresent ? 2 : 0)
				+ (userIdPresent ? 1 : 0) + (measurementStatusPresent ? 2 : 0)) {
			onInvalidDataReceived(device, data);
			return;
		}

		// Following bytes - systolic, diastolic and mean arterial pressure
		final float systolic = data.getFloatValue(Data.FORMAT_SFLOAT, offset);
		final float diastolic = data.getFloatValue(Data.FORMAT_SFLOAT, offset + 2);
		final float meanArterialPressure = data.getFloatValue(Data.FORMAT_SFLOAT, offset + 4);
		offset += 6;

		// Parse timestamp if present
		Calendar calendar = null;
		if (timestampPresent) {
			calendar = DateTimeDataCallback.readDateTime(data, offset);
			offset += 7;
		}

		// Parse pulse rate if present
		Float pulseRate = null;
		if (pulseRatePresent) {
			pulseRate = data.getFloatValue(Data.FORMAT_SFLOAT, offset);
			offset += 2;
		}

		// Read user id if present
		Integer userId = null;
		if (userIdPresent) {
			userId = data.getIntValue(Data.FORMAT_UINT8, offset);
			offset += 1;
		}

		// Read measurement status if present
		BPMStatus status = null;
		if (measurementStatusPresent) {
			final int measurementStatus = data.getIntValue(Data.FORMAT_UINT16_LE, offset);
			// offset += 2;
			status = new BPMStatus(measurementStatus);
		}

		onBloodPressureMeasurementReceived(device, systolic, diastolic, meanArterialPressure, unit, pulseRate, userId, status, calendar);
	}
@Test
	public void onBloodPressureMeasurementReceived_minimal() {
		final DataReceivedCallback callback = new BloodPressureMeasurementDataCallback() {
			@Override
			public void onBloodPressureMeasurementReceived(@NonNull final BluetoothDevice device,
														   final float systolic, final float diastolic, final float meanArterialPressure, final int unit,
														   @Nullable final Float pulseRate, @Nullable final Integer userID,
														   @Nullable final BPMStatus status, @Nullable final Calendar calendar) {
				assertEquals("Systolic", 18.9, systolic, 0.01);
				assertEquals("Diastolic", 11.0, diastolic, 0);
				assertEquals("Mean AP", 15.9, meanArterialPressure, 0.01);
				assertEquals("Unit: mmHg", 0, unit);
				assertNull("Pulse rate not set", pulseRate);
				assertNull("User ID not set", userID);
				assertNull("Status not set", status);
				assertNull("Calendar not set", calendar);
			}

			@Override
			public void onInvalidDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
				assertEquals("Correct BPM reported as invalid", 1, 2);
			}
		};
		final MutableData data = new MutableData(new byte[7]);
		// Flags
		data.setByte((byte) 0b00000, 0);
		// Systolic, diastolic and mean AP in mmHg
		data.setValue(189, -1, Data.FORMAT_SFLOAT, 1);
		data.setValue(11, 0, Data.FORMAT_SFLOAT, 3);
		data.setValue(159, -1, Data.FORMAT_SFLOAT, 5);

		assertArrayEquals(
				new byte[] { 0x00, (byte) 0xBD, (byte) 0xF0, 0xB, 0x0, (byte) 0x9F, (byte) 0xF0 },
				data.getValue()
		);
		callback.onDataReceived(null, data);
	}