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;
|
return;
|
||||||
}
|
}
|
||||||
debugPrint(
|
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)
|
// Binary responses carry Cayenne LPP telemetry data.
|
||||||
// Other tags may be used for different data types in the future
|
// The data starts with a channel byte — valid LPP always has at least
|
||||||
contactsProvider.updateTelemetry(publicKeyPrefix, responseData);
|
// 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)
|
// When raw binary data is received (PUSH_CODE_RAW_DATA 0x84)
|
||||||
|
|||||||
@@ -926,6 +926,10 @@ class ContactsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update contact telemetry
|
/// 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) {
|
void updateTelemetry(Uint8List publicKeyPrefix, Uint8List lppData) {
|
||||||
debugPrint('📊 [ContactsProvider] updateTelemetry() called');
|
debugPrint('📊 [ContactsProvider] updateTelemetry() called');
|
||||||
debugPrint(
|
debugPrint(
|
||||||
@@ -933,6 +937,21 @@ class ContactsProvider with ChangeNotifier {
|
|||||||
);
|
);
|
||||||
debugPrint(' LPP data size: ${lppData.length} bytes');
|
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
|
// Find contact by public key prefix
|
||||||
final contact = _findContactByPrefix(publicKeyPrefix);
|
final contact = _findContactByPrefix(publicKeyPrefix);
|
||||||
if (contact == null) {
|
if (contact == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user