mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
fix: Deduplicate telemetry from 0x8B + 0x8C double delivery
When firmware sends telemetry via both pushTelemetryResponse (0x8B) and pushBinaryResponse (0x8C), the same LPP data was parsed and applied twice, causing duplicate sensor entries. Added hash-based dedup: same payload for same contact within 2s is skipped. Also added minimum length check for binary responses.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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<String, (int, DateTime)> _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<int>(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) {
|
||||
|
||||
Reference in New Issue
Block a user