fetchMeasurement method

  1. @override
Future<VtjCommandResult<FetchMeasurementResult>> fetchMeasurement(
  1. BluetoothDevice device,
  2. MeasurementConfig config, {
  3. int startIndex = 0,
})
override

Start download of last completed measurement. Data will be sent via the RPC Download Characteristic. See BLE Interface Specification Section 7.6

config is required for proper CRC validation when data is compressed.

Implementation

@override
Future<VtjCommandResult<FetchMeasurementResult>> fetchMeasurement(
  BluetoothDevice device,
  MeasurementConfig config, {
  int startIndex = 0,
}) async {
  final manager = _fetchRegistry.getManager(device);
  final deviceId = device.remoteId.str;

  // Store config for CRC validation during fetch completion
  _measurementConfigByDevice[deviceId] = config;

  // Step 1: Get device state to know expected CRC
  final stateResult = await getDeviceState(device);

  return stateResult.when(
    success: (deviceState) async {
      // Check if there's data to fetch
      if (deviceState.measurementState != 2) {
        manager.failFetch('No completed measurement available', 3);
        return const VtjCommandResult.failure(
          'No completed measurement available',
          3,
        );
      }

      final expectedCrc = deviceState.crc;

      // Store expected CRC for later validation
      _expectedCrcByDevice[deviceId] = expectedCrc;

      // Step 2: Initialize fetch state (completion detected by empty array per BLE spec)
      manager.startFetch();

      // Step 3: Set up download characteristic listener
      try {
        await _setupDownloadListener(device);
      } catch (e) {
        manager.failFetch('Failed to set up download listener: $e');
        return VtjCommandResult.failure(
          'Failed to set up download listener: $e',
          null,
        );
      }

      // Step 4: Execute the fetch command
      final result = await _executeCommand<FetchMeasurementResult>(
        device: device,
        createCommand: () => FetchMeasurementCommand(startIndex: startIndex),
      );

      // If command failed, update fetch state
      result.when(
        success: (_) {
          // Fetch started successfully, data will arrive via listener
        },
        failure: (error, code) {
          manager.failFetch(error, code);
        },
      );

      return result;
    },
    failure: (error, code) {
      manager.failFetch('Failed to get device state: $error', code);
      return VtjCommandResult.failure(
        'Failed to get device state: $error',
        code,
      );
    },
  );
}