diff --git a/lib/core/bluetooth/bt_poller.dart b/lib/core/bluetooth/bt_poller.dart index c546799..616db1d 100644 --- a/lib/core/bluetooth/bt_poller.dart +++ b/lib/core/bluetooth/bt_poller.dart @@ -87,6 +87,12 @@ class BtPoller { final Uint8List frame = Uint8List.fromList(_rxBuf.sublist(startIdx, startIdx + 128)); + if (ecuType == EcuType.s300 && _isS300PlaceholderFrame(frame)) { + droppedFrames++; + _rxBuf.removeRange(0, startIdx + 128); + continue; + } + final checksumOk = validateFrame(frame); final canUseFrame = checksumOk || ecuType == EcuType.s300; @@ -119,4 +125,31 @@ class BtPoller { stop(); _frameController.close(); } + + bool _isS300PlaceholderFrame(Uint8List frame) { + if (frame.length != 128) return false; + + // The S300 Bluetooth stream can interleave a valid-checksum placeholder + // frame that is not the SManager live sensor frame. It has a fixed header + // and zero/overflow values for speed, TPS, injection and ignition, then it + // overwrites the dashboard with stale/empty values. Filter only this exact + // signature so true idle/stopped live frames can still pass. + return frame[0] == 0x1B && + frame[1] == 0x00 && + frame[2] == 0x14 && + frame[3] == 0x00 && + frame[4] == 0x00 && + frame[5] == 0xFF && + frame[6] == 0xFF && + frame[7] == 0xF2 && + frame[8] == 0x03 && + frame[9] == 0x18 && + frame[10] == 0x00 && + frame[11] == 0x00 && + frame[12] == 0x10 && + frame[13] == 0x00 && + frame[14] == 0x00 && + frame[15] == 0x00 && + frame[16] == 0xC4; + } }