Skip to content

Commit f16f95c

Browse files
committed
enhance error logging for carpeater detection
1 parent 32e00c3 commit f16f95c

File tree

8 files changed

+272
-75
lines changed

8 files changed

+272
-75
lines changed

android/local.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
sdk.dir=/opt/homebrew/share/android-commandlinetools
22
flutter.sdk=/opt/homebrew/share/flutter
3-
flutter.buildMode=debug
3+
flutter.buildMode=release
44
flutter.versionName=1.0.0
5-
flutter.versionCode=1
5+
flutter.versionCode=1769917500

ios/Flutter/Generated.xcconfig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
FLUTTER_ROOT=/opt/homebrew/share/flutter
33
FLUTTER_APPLICATION_PATH=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App
44
COCOAPODS_PARALLEL_CODE_SIGN=true
5-
FLUTTER_TARGET=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/lib/main.dart
5+
FLUTTER_TARGET=lib/main.dart
66
FLUTTER_BUILD_DIR=build
77
FLUTTER_BUILD_NAME=1.0.0
8-
FLUTTER_BUILD_NUMBER=1
8+
FLUTTER_BUILD_NUMBER=1769917500
99
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
1010
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
11-
DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguOQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049NjczMjNkZTI4NQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NTg3YzE4Zjg3Mw==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC44
11+
DART_DEFINES=QVBQX1ZFUlNJT049QVBQLTE3Njk5MTc1MDA=,RkxVVFRFUl9WRVJTSU9OPTMuMzguOQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049NjczMjNkZTI4NQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NTg3YzE4Zjg3Mw==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC44
1212
DART_OBFUSCATION=false
13-
TRACK_WIDGET_CREATION=true
14-
TREE_SHAKE_ICONS=false
13+
TRACK_WIDGET_CREATION=false
14+
TREE_SHAKE_ICONS=true
1515
PACKAGE_CONFIG=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/.dart_tool/package_config.json

ios/Flutter/flutter_export_environment.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
export "FLUTTER_ROOT=/opt/homebrew/share/flutter"
44
export "FLUTTER_APPLICATION_PATH=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App"
55
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
6-
export "FLUTTER_TARGET=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/lib/main.dart"
6+
export "FLUTTER_TARGET=lib/main.dart"
77
export "FLUTTER_BUILD_DIR=build"
88
export "FLUTTER_BUILD_NAME=1.0.0"
9-
export "FLUTTER_BUILD_NUMBER=1"
10-
export "DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguOQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049NjczMjNkZTI4NQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NTg3YzE4Zjg3Mw==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC44"
9+
export "FLUTTER_BUILD_NUMBER=1769917500"
10+
export "DART_DEFINES=QVBQX1ZFUlNJT049QVBQLTE3Njk5MTc1MDA=,RkxVVFRFUl9WRVJTSU9OPTMuMzguOQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049NjczMjNkZTI4NQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NTg3YzE4Zjg3Mw==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC44"
1111
export "DART_OBFUSCATION=false"
12-
export "TRACK_WIDGET_CREATION=true"
13-
export "TREE_SHAKE_ICONS=false"
12+
export "TRACK_WIDGET_CREATION=false"
13+
export "TREE_SHAKE_ICONS=true"
1414
export "PACKAGE_CONFIG=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/.dart_tool/package_config.json"

ios/Podfile.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
PODS:
22
- audio_session (0.0.1):
33
- Flutter
4+
- connectivity_plus (0.0.1):
5+
- Flutter
46
- DKImagePickerController/Core (4.3.9):
57
- DKImagePickerController/ImageDataManager
68
- DKImagePickerController/Resource
@@ -69,6 +71,7 @@ PODS:
6971

7072
DEPENDENCIES:
7173
- audio_session (from `.symlinks/plugins/audio_session/ios`)
74+
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
7275
- file_picker (from `.symlinks/plugins/file_picker/ios`)
7376
- Flutter (from `Flutter`)
7477
- flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`)
@@ -93,6 +96,8 @@ SPEC REPOS:
9396
EXTERNAL SOURCES:
9497
audio_session:
9598
:path: ".symlinks/plugins/audio_session/ios"
99+
connectivity_plus:
100+
:path: ".symlinks/plugins/connectivity_plus/ios"
96101
file_picker:
97102
:path: ".symlinks/plugins/file_picker/ios"
98103
Flutter:
@@ -122,6 +127,7 @@ EXTERNAL SOURCES:
122127

123128
SPEC CHECKSUMS:
124129
audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0
130+
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
125131
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
126132
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
127133
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be

lib/providers/app_state_provider.dart

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,14 @@ class AppStateProvider extends ChangeNotifier {
11081108
// Create TX tracker (stored for use by PingService)
11091109
_txTracker = TxTracker();
11101110

1111+
// Log TX carpeater drops to error log (without navigating to error tab)
1112+
_txTracker!.onCarpeaterDrop = (String repeaterId, String reason) {
1113+
debugLog('[APP] TX carpeater drop: repeater=$repeaterId, reason=$reason');
1114+
logError('TX Echo Dropped\nPossible carpeater: $repeaterId\n$reason',
1115+
severity: ErrorSeverity.warning, autoSwitch: false);
1116+
};
1117+
debugLog('[APP] TxTracker.onCarpeaterDrop callback SET');
1118+
11111119
// Create RX logger (stored for use when enabling Passive Mode)
11121120
_rxLogger = RxLogger(
11131121
// Function to check if repeater should be ignored (carpeater filter)
@@ -1269,6 +1277,13 @@ class AppStateProvider extends ChangeNotifier {
12691277
if (pos == null) return null;
12701278
return (lat: pos.latitude, lon: pos.longitude);
12711279
},
1280+
1281+
// Log carpeater drops to error log (without navigating to error tab)
1282+
onCarpeaterDrop: (String repeaterId, String reason) {
1283+
debugLog('[APP] Carpeater drop: repeater=$repeaterId, reason=$reason');
1284+
logError('RX Dropped\nPossible carpeater: $repeaterId\n$reason',
1285+
severity: ErrorSeverity.warning, autoSwitch: false);
1286+
},
12721287
);
12731288

12741289
// Create packet validator with ALL allowed channels (#wardriving, #testing, #ottawa, Public)
@@ -1628,13 +1643,16 @@ class AppStateProvider extends ChangeNotifier {
16281643
}
16291644

16301645
/// Log a user-facing error message
1631-
void logError(String message, {ErrorSeverity severity = ErrorSeverity.error}) {
1646+
/// Set [autoSwitch] to false to log without navigating to error log tab
1647+
void logError(String message, {ErrorSeverity severity = ErrorSeverity.error, bool autoSwitch = true}) {
16321648
_errorLogEntries.add(UserErrorEntry(
16331649
timestamp: DateTime.now(),
16341650
message: message,
16351651
severity: severity,
16361652
));
1637-
_requestErrorLogSwitch = true; // Auto-switch to error log
1653+
if (autoSwitch) {
1654+
_requestErrorLogSwitch = true; // Auto-switch to error log
1655+
}
16381656
notifyListeners();
16391657
}
16401658

lib/services/meshcore/rx_logger.dart

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ class RxLogger {
3030
/// Returns true if the repeater should be filtered out
3131
final bool Function(String repeaterId)? shouldIgnoreRepeater;
3232

33+
/// Callback for carpeater drops (for quiet error logging)
34+
/// Called with repeater ID and reason when a packet is dropped due to carpeater detection
35+
final void Function(String repeaterId, String reason)? onCarpeaterDrop;
36+
3337
RxLogger({
3438
required this.onRxEntry,
3539
this.onObservation,
3640
required this.getGpsLocation,
3741
this.shouldIgnoreRepeater,
42+
this.onCarpeaterDrop,
3843
});
3944

4045
/// Start passive RX wardriving
@@ -67,14 +72,20 @@ class RxLogger {
6772
debugLog('[RX LOG] Ignoring: no path (direct transmission, not via repeater)');
6873
return false;
6974
}
70-
75+
76+
// Extract LAST hop from path (the repeater that directly delivered to us)
77+
// Do this early so we have repeater ID for carpeater logging
78+
// Mask to last byte only (0xFF) for consistent 2-character display
79+
final lastHopId = metadata.lastHop! & 0xFF;
80+
final repeaterId = lastHopId.toRadixString(16).padLeft(2, '0').toUpperCase();
81+
7182
// Get current GPS location
7283
final gpsLocation = getGpsLocation();
7384
if (gpsLocation == null) {
7485
debugLog('[RX LOG] No GPS fix available, skipping entry');
7586
return false;
7687
}
77-
88+
7889
// PACKET FILTER: Validate packet before logging
7990
final validation = await validator.validate(metadata);
8091
if (!validation.valid) {
@@ -83,12 +94,13 @@ class RxLogger {
8394
.join(' ');
8495
debugLog('[RX LOG] ❌ Packet dropped: ${validation.reason}');
8596
debugLog('[RX LOG] Dropped packet hex: $rawHex');
97+
98+
// Log carpeater drops to error log (without auto-switching)
99+
if (validation.reason == 'carpeater-rssi') {
100+
onCarpeaterDrop?.call(repeaterId, 'RSSI too strong (${metadata.rssi} dBm)');
101+
}
86102
return false;
87103
}
88-
89-
// Extract LAST hop from path (the repeater that directly delivered to us)
90-
final lastHopId = metadata.lastHop!;
91-
final repeaterId = lastHopId.toRadixString(16).padLeft(2, '0').toUpperCase();
92104

93105
debugLog('[RX LOG] Packet heard via last hop: $repeaterId, '
94106
'SNR=${metadata.snr}, path_length=${metadata.pathLength}');

lib/services/meshcore/tx_tracker.dart

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class TxTracker {
2626
/// Parameters: (repeaterId, snr, rssi, isNew) - isNew is true for first time seeing this repeater
2727
void Function(String repeaterId, double snr, int rssi, bool isNew)? onEchoReceived;
2828

29+
/// Callback for carpeater drops (for quiet error logging)
30+
/// Called with repeater ID and reason when an echo is dropped due to carpeater detection
31+
void Function(String repeaterId, String reason)? onCarpeaterDrop;
32+
2933
/// Start tracking echoes for a sent ping
3034
///
3135
/// @param payload - The message text sent (for content verification)
@@ -94,10 +98,23 @@ class TxTracker {
9498
}
9599
debugLog('[TX LOG] Header validation passed: 0x${metadata.header.toRadixString(16).padLeft(2, '0')}');
96100

97-
// VALIDATION STEP 1.5: Check RSSI (carpeater failsafe)
101+
// VALIDATION STEP 1.5: Path length check (must have hops to identify repeater)
102+
// Moved before RSSI check so we can log the repeater ID on carpeater drops
103+
if (metadata.pathLength == 0) {
104+
debugLog('[TX LOG] Ignoring: no path (direct transmission, not a repeater echo)');
105+
return false;
106+
}
107+
108+
// Extract first hop (first repeater) for use in validation and logging
109+
final firstHopId = metadata.firstHop!;
110+
final pathHex = firstHopId.toRadixString(16).padLeft(2, '0');
111+
112+
// VALIDATION STEP 2: Check RSSI (carpeater failsafe)
98113
if (PacketValidator.isCarpeater(metadata.rssi)) {
99114
debugLog('[TX LOG] ❌ DROPPED: RSSI too strong (${metadata.rssi} ≥ ${PacketValidator.maxRssiThreshold}) '
100-
'- possible carpeater (RSSI failsafe)');
115+
'- possible carpeater (RSSI failsafe), repeater=$pathHex');
116+
debugLog('[TX LOG] onCarpeaterDrop callback is ${onCarpeaterDrop != null ? "SET" : "NULL"}');
117+
onCarpeaterDrop?.call(pathHex, 'RSSI too strong (${metadata.rssi} dBm)');
101118
return false; // Mark as handled (dropped)
102119
}
103120
debugLog('[TX LOG] ✓ RSSI OK (${metadata.rssi} < ${PacketValidator.maxRssiThreshold})');
@@ -174,15 +191,7 @@ class TxTracker {
174191
debugWarn('[MESSAGE_CORRELATION] Proceeding without message content verification (less reliable)');
175192
}
176193

177-
// VALIDATION STEP 4: Path length check (must have hops)
178-
if (metadata.pathLength == 0) {
179-
debugLog('[TX LOG] Ignoring: no path (direct transmission, not a repeater echo)');
180-
return false;
181-
}
182-
183-
// Extract first hop (first repeater)
184-
final firstHopId = metadata.firstHop!;
185-
final pathHex = firstHopId.toRadixString(16).padLeft(2, '0');
194+
// Path length and first hop already validated/extracted earlier (before RSSI check)
186195

187196
debugLog('[PING] Repeater echo accepted: first_hop=$pathHex, SNR=${metadata.snr}, '
188197
'full_path_length=${metadata.pathLength}');

0 commit comments

Comments
 (0)