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

		if (data.size() < 10) {
			onInvalidDataReceived(device, data);
			return;
		}

		int offset = 0;

		final int flags = data.getIntValue(Data.FORMAT_UINT8, offset++);
		final boolean timeOffsetPresent = (flags & 0x01) != 0;
		final boolean glucoseDataPresent = (flags & 0x02) != 0;
		final boolean unitMolL = (flags & 0x04) != 0;
		final boolean sensorStatusAnnunciationPresent = (flags & 0x08) != 0;
		final boolean contextInformationFollows = (flags & 0x10) != 0;

		if (data.size() < 10 + (timeOffsetPresent ? 2 : 0) + (glucoseDataPresent ? 3 : 0)
			+ (sensorStatusAnnunciationPresent ? 2 : 0)) {
			onInvalidDataReceived(device, data);
			return;
		}

		// Required fields
		final int sequenceNumber = data.getIntValue(Data.FORMAT_UINT16_LE, offset);
		offset += 2;
		final Calendar baseTime = DateTimeDataCallback.readDateTime(data, 3);
		offset += 7;

		if (baseTime == null) {
			onInvalidDataReceived(device, data);
			return;
		}

		// Optional fields
		if (timeOffsetPresent) {
			final int timeOffset = data.getIntValue(Data.FORMAT_SINT16_LE, offset);
			offset += 2;

			baseTime.add(Calendar.MINUTE, timeOffset);
		}

		Float glucoseConcentration = null;
		Integer unit = null;
		Integer type = null;
		Integer sampleLocation = null;
		if (glucoseDataPresent) {
			glucoseConcentration = data.getFloatValue(Data.FORMAT_SFLOAT, offset);
			final int typeAndSampleLocation = data.getIntValue(Data.FORMAT_UINT8, offset + 2);
			offset += 3;

			type = typeAndSampleLocation & 0x0F;
			sampleLocation = typeAndSampleLocation >> 4;
			unit = unitMolL ? UNIT_mol_L : UNIT_kg_L;
		}

		GlucoseStatus status = null;
		if (sensorStatusAnnunciationPresent) {
			final int value = data.getIntValue(Data.FORMAT_UINT16_LE, offset);
			// offset += 2;

			status = new GlucoseStatus(value);
		}

		onGlucoseMeasurementReceived(device, sequenceNumber, baseTime /* with offset */,
				glucoseConcentration, unit, type, sampleLocation, status, contextInformationFollows);
	}
@Test
	public void onGlucoseMeasurementReceived() {
		final Data data = new Data(new byte[] {
				(byte) 0b011011,           // Time Offset, Type and Location Present, unit: kg/L, Status Annunciation Present, Context follows
				1, 0,                      // Seq = 1
				(byte) 0xE3, 0x07,         // 2019
				2,                         // February
				27,                        // 27th
				11, 10, 30,                // at 11:10:30
				(byte) 0xFB, (byte) 0xFF,  // Time offset = -5 minutes
				30, 0,                     // Glucose concentration = 30.0 kg/L
				0x12,                      // Type = 2 (TYPE_CAPILLARY_PLASMA), Location = 1 (SAMPLE_LOCATION_FINGER)
				0b101, 0b1                 // Status: Low battery, Device Fault, Sensor Temp too low
		});
		callback.onDataReceived(null, data);
		assertTrue(success);
	}