import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../bluetooth/bt_poller.dart'; import '../protocol/kpro_parser.dart'; import '../protocol/s300_parser.dart'; import '../protocol/sensor_state.dart'; import 'bt_provider.dart'; import 'settings_provider.dart'; /// Emits a parsed [SensorState] for every live data frame received from the ECU. /// Automatically picks S300 or KPro parser based on [settingsProvider]. final sensorStateProvider = StreamProvider((ref) async* { final ecuType = ref.watch(settingsProvider).ecuType; final btNotifier = ref.watch(btProvider.notifier); await for (final frame in btNotifier.frameStream) { if (ecuType == EcuType.s300) { if (isS300PlaceholderFrame(frame) && !hasS300TailRpmPayload(frame)) { continue; } yield parseS300(frame, validateChecksum: false); } else { yield parseKPro(frame); } } }); /// Last successfully parsed sensor state (never null after first frame). /// Falls back to SensorState.zero() before any data arrives. final latestSensorProvider = Provider((ref) { return ref.watch(sensorStateProvider).whenData((s) => s).value ?? SensorState.zero(); });