handleDataResponsePart method

Stream<Uint8List> handleDataResponsePart(
  1. Stream<OnCharacteristicReceivedEvent> source
)

Handles data response parts from the device.

Implementation

Stream<Uint8List> handleDataResponsePart(
    Stream<OnCharacteristicReceivedEvent> source) async* {
  Uint8List? ongoingDataResponse;
  Uint8List? ongoingPhotoResponse;
  int? ongoingDataResponseChunkCount;
  int? ongoingPhotoResponseChunkCount;

  await for (final event in source) {
    if (event.value[0] == _frameDataPrefix &&
        event.value[1] == FrameDataTypePrefixes.longData.value) {
      // ongoing long data
      if (ongoingDataResponse == null ||
          ongoingDataResponseChunkCount == null) {
        ongoingDataResponse = Uint8List(0);
        ongoingDataResponseChunkCount = 0;
        _log.fine("Starting receiving new long data");
      }
      ongoingDataResponse =
          Uint8List.fromList(ongoingDataResponse + event.value.sublist(2));
      ongoingDataResponseChunkCount++;
      _log.finer(
          "Received long data chunk #$ongoingDataResponseChunkCount: ${event.value.sublist(2).length} bytes");
      if (ongoingDataResponse.length > maxReceiveBuffer) {
        _log.severe(
            "Buffered received long data is more than $maxReceiveBuffer bytes: ${ongoingDataResponse.length} bytes received");
        throw BrilliantBluetoothException(
            "Buffered received long data is more than $maxReceiveBuffer bytes: ${ongoingDataResponse.length} bytes received");
      }
    } else if (event.value[0] == _frameDataPrefix &&
        event.value[1] == FrameDataTypePrefixes.longDataEnd.value) {
      final totalExpectedChunkCount = event.value.length == 2
          ? 0
          : int.parse(utf8.decode(event.value.sublist(2)));
      _log.finer(
          "Received final long data chunk count: $totalExpectedChunkCount");
      if (ongoingDataResponseChunkCount != totalExpectedChunkCount) {
        _log.warning(
            "Chunk count mismatch in long received data (expected $totalExpectedChunkCount, got $ongoingDataResponseChunkCount)");
        throw BrilliantBluetoothException(
            "Chunk count mismatch in long received data (expected $totalExpectedChunkCount, got $ongoingDataResponseChunkCount)");
      }
      final completeDataResponse = ongoingDataResponse!;
      ongoingDataResponse = null;
      ongoingDataResponseChunkCount = null;
      _log.fine(
          "Finished receiving long data: ${completeDataResponse.length} bytes");
      yield completeDataResponse;
    } else if (event.value[0] == _frameDataPrefix &&
        event.value[1] == FrameDataTypePrefixes.photoData.value) {
      // ongoing photo
      if (ongoingPhotoResponse == null ||
          ongoingPhotoResponseChunkCount == null) {
        ongoingPhotoResponse = Uint8List(0);
        ongoingPhotoResponseChunkCount = 0;
        _log.fine("Starting receiving new photo");
      }
      ongoingPhotoResponse =
          Uint8List.fromList(ongoingPhotoResponse + event.value.sublist(2));
      ongoingPhotoResponseChunkCount++;
      _log.finer(
          "Received photo chunk #$ongoingPhotoResponseChunkCount: ${event.value.sublist(2).length} bytes");
      if (ongoingPhotoResponse.length > maxReceiveBuffer) {
        _log.severe(
            "Buffered received photo is more than $maxReceiveBuffer bytes: ${ongoingPhotoResponse.length} bytes received");
        throw BrilliantBluetoothException(
            "Buffered received photo is more than $maxReceiveBuffer bytes: ${ongoingPhotoResponse.length} bytes received");
      }
    } else if (event.value[0] == _frameDataPrefix &&
        event.value[1] == FrameDataTypePrefixes.photoDataEnd.value) {
      final totalExpectedChunkCount = event.value.length == 2
          ? 0
          : int.parse(utf8.decode(event.value.sublist(2)));
      _log.finer(
          "Received final photo chunk count: $totalExpectedChunkCount");
      if (ongoingPhotoResponseChunkCount != totalExpectedChunkCount) {
        _log.warning(
            "Chunk count mismatch in long received photo (expected $totalExpectedChunkCount, got $ongoingPhotoResponseChunkCount)");
        throw BrilliantBluetoothException(
            "Chunk count mismatch in long received photo (expected $totalExpectedChunkCount, got $ongoingPhotoResponseChunkCount)");
      }
      final completePhotoResponse = Uint8List.fromList(
          [FrameDataTypePrefixes.photoData.value, ...ongoingPhotoResponse!]);
      ongoingPhotoResponse = null;
      ongoingPhotoResponseChunkCount = null;
      _log.fine(
          "Finished receiving photo: ${completePhotoResponse.length} bytes");
      yield completePhotoResponse;
    } else if (event.value[0] == _frameDataPrefix) {
      _log.finer(
          "Received other single data: ${event.value.length - 1} bytes");

      yield Uint8List.fromList(event.value.sublist(1));
    }
  }
}