diff --git a/lib/providers/app_provider.dart b/lib/providers/app_provider.dart index 6e536b6..80ae80c 100644 --- a/lib/providers/app_provider.dart +++ b/lib/providers/app_provider.dart @@ -1338,11 +1338,14 @@ class AppProvider with ChangeNotifier { return; } debugPrint( - '📊 [AppProvider] Binary response (0x8C) received - updating contact telemetry', + '📊 [AppProvider] Binary response (0x8C tag=$tag) received', ); - // Binary response tag 0 = telemetry data (Cayenne LPP format) - // Other tags may be used for different data types in the future - contactsProvider.updateTelemetry(publicKeyPrefix, responseData); + // Binary responses carry Cayenne LPP telemetry data. + // The data starts with a channel byte — valid LPP always has at least + // 3 bytes (channel + type + value). Skip clearly non-telemetry payloads. + if (responseData.length >= 3) { + contactsProvider.updateTelemetry(publicKeyPrefix, responseData); + } }; // When raw binary data is received (PUSH_CODE_RAW_DATA 0x84) diff --git a/lib/providers/contacts_provider.dart b/lib/providers/contacts_provider.dart index 15039f0..c43af78 100644 --- a/lib/providers/contacts_provider.dart +++ b/lib/providers/contacts_provider.dart @@ -926,6 +926,10 @@ class ContactsProvider with ChangeNotifier { } /// Update contact telemetry + // Dedup: track last telemetry data hash per contact to avoid processing + // the same payload twice (0x8B + 0x8C can both fire for the same data). + final Map _lastTelemetryHash = {}; + void updateTelemetry(Uint8List publicKeyPrefix, Uint8List lppData) { debugPrint('📊 [ContactsProvider] updateTelemetry() called'); debugPrint( @@ -933,6 +937,21 @@ class ContactsProvider with ChangeNotifier { ); debugPrint(' LPP data size: ${lppData.length} bytes'); + // Deduplicate: same data for same contact within 2 seconds = skip + final prefixHex = publicKeyPrefix + .map((b) => b.toRadixString(16).padLeft(2, '0')) + .join(); + final dataHash = lppData.fold(0, (h, b) => h * 31 + b); + final now = DateTime.now(); + final last = _lastTelemetryHash[prefixHex]; + if (last != null && + last.$1 == dataHash && + now.difference(last.$2).inSeconds < 2) { + debugPrint(' ⏭️ Duplicate telemetry payload, skipping'); + return; + } + _lastTelemetryHash[prefixHex] = (dataHash, now); + // Find contact by public key prefix final contact = _findContactByPrefix(publicKeyPrefix); if (contact == null) {