@Override
	public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
		super.onDataReceived(device, data);
		
		if (data.size() != 5 && data.size() != 7) {
			onInvalidDataReceived(device, data);
			return;
		}

		final int timeOffset = data.getIntValue(Data.FORMAT_UINT16_LE, 0);
		final int warningStatus = data.getIntValue(Data.FORMAT_UINT8, 2);
		final int calibrationTempStatus = data.getIntValue(Data.FORMAT_UINT8, 3);
		final int sensorStatus = data.getIntValue(Data.FORMAT_UINT8, 4);

		final boolean crcPresent = data.size() == 7;
		if (crcPresent) {
			final int actualCrc = CRC16.MCRF4XX(data.getValue(), 0, 5);
			final int expectedCrc = data.getIntValue(Data.FORMAT_UINT16_LE, 5);
			if (actualCrc != expectedCrc) {
				onContinuousGlucoseMonitorStatusReceivedWithCrcError(device, data);
				return;
			}
		}

		final CGMStatus status = new CGMStatus(warningStatus, calibrationTempStatus, sensorStatus);
		onContinuousGlucoseMonitorStatusChanged(device, status, timeOffset, crcPresent);
	}
@Test
	public void onContinuousGlucoseMonitorStatusChanged_withCrc() {
		final DataReceivedCallback callback = new CGMStatusDataCallback() {
			@Override
			public void onContinuousGlucoseMonitorStatusChanged(@NonNull final BluetoothDevice device, @NonNull final CGMStatus status,
																final int timeOffset, final boolean secured) {
				assertNotNull("Status present", status);
				assertTrue(status.sessionStopped);
				assertTrue(status.deviceBatteryLow);
				assertTrue(status.sensorTypeIncorrectForDevice);
				assertTrue(status.sensorMalfunction);
				assertTrue(status.deviceSpecificAlert);
				assertTrue(status.generalDeviceFault);
				assertTrue(status.timeSyncRequired);
				assertTrue(status.calibrationNotAllowed);
				assertTrue(status.calibrationRecommended);
				assertTrue(status.calibrationRequired);
				assertTrue(status.sensorTemperatureTooHigh);
				assertTrue(status.sensorTemperatureTooLow);
				assertTrue(status.sensorResultLowerThenPatientLowLevel);
				assertTrue(status.sensorResultHigherThenPatientHighLevel);
				assertTrue(status.sensorResultLowerThenHypoLevel);
				assertTrue(status.sensorResultHigherThenHyperLevel);
				assertTrue(status.sensorRateOfDecreaseExceeded);
				assertTrue(status.sensorRateOfIncreaseExceeded);
				assertTrue(status.sensorResultLowerThenDeviceCanProcess);
				assertTrue(status.sensorResultHigherThenDeviceCanProcess);
				assertEquals("Time offset", 5, timeOffset);
				assertTrue(secured);
			}

			@Override
			public void onContinuousGlucoseMonitorStatusReceivedWithCrcError(@NonNull final BluetoothDevice device, @NonNull final Data data) {
				assertEquals("Correct data reported as CRC error", 1, 2);
			}

			@Override
			public void onInvalidDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
				assertEquals("Correct data reported as invalid", 1, 2);
			}
		};
		final MutableData data = new MutableData(new byte[7]);
		data.setValue(5, Data.FORMAT_UINT16_LE, 0);
		data.setValue(0xff3f3f, Data.FORMAT_UINT24_LE, 2); // all flags set
		data.setValue(0xE0A7, Data.FORMAT_UINT16_LE, 5);
		callback.onDataReceived(null, data);
	}