Skip to content

Commit 9b8d557

Browse files
committed
Fixed BLE Device Name being wrong
1 parent 654b5f3 commit 9b8d557

File tree

7 files changed

+111
-13
lines changed

7 files changed

+111
-13
lines changed

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=lib/main.dart
5+
FLUTTER_TARGET=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/lib/main.dart
66
FLUTTER_BUILD_DIR=build
77
FLUTTER_BUILD_NAME=1.0.0
8-
FLUTTER_BUILD_NUMBER=1769234591
8+
FLUTTER_BUILD_NUMBER=1
99
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
1010
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
11-
DART_DEFINES=QVBQX1ZFUlNJT049QVBQLTE3NjkyMzQ1OTE=,RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43
11+
DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43
1212
DART_OBFUSCATION=false
13-
TRACK_WIDGET_CREATION=false
14-
TREE_SHAKE_ICONS=true
13+
TRACK_WIDGET_CREATION=true
14+
TREE_SHAKE_ICONS=false
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=lib/main.dart"
6+
export "FLUTTER_TARGET=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/lib/main.dart"
77
export "FLUTTER_BUILD_DIR=build"
88
export "FLUTTER_BUILD_NAME=1.0.0"
9-
export "FLUTTER_BUILD_NUMBER=1769234591"
10-
export "DART_DEFINES=QVBQX1ZFUlNJT049QVBQLTE3NjkyMzQ1OTE=,RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43"
9+
export "FLUTTER_BUILD_NUMBER=1"
10+
export "DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43"
1111
export "DART_OBFUSCATION=false"
12-
export "TRACK_WIDGET_CREATION=false"
13-
export "TREE_SHAKE_ICONS=true"
12+
export "TRACK_WIDGET_CREATION=true"
13+
export "TREE_SHAKE_ICONS=false"
1414
export "PACKAGE_CONFIG=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/.dart_tool/package_config.json"

lib/providers/app_state_provider.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,12 @@ class AppStateProvider extends ChangeNotifier {
11951195
Future<bool> sendPing() async {
11961196
if (_pingService == null) return false;
11971197

1198+
// Check session validity before starting (skip in offline mode)
1199+
if (!_preferences.offlineMode) {
1200+
final sessionCheck = await _checkSessionBeforeAction();
1201+
if (!sessionCheck) return false;
1202+
}
1203+
11981204
// Set sending state immediately for instant UI feedback
11991205
_isPingSending = true;
12001206
notifyListeners();
@@ -1209,6 +1215,27 @@ class AppStateProvider extends ChangeNotifier {
12091215
}
12101216
}
12111217

1218+
/// Check session validity before starting a wardrive action
1219+
/// Returns true if session is valid, false if expired (triggers disconnect)
1220+
Future<bool> _checkSessionBeforeAction() async {
1221+
final pos = _gpsService?.lastPosition;
1222+
final result = await _apiService.checkSessionValid(
1223+
lat: pos?.latitude,
1224+
lon: pos?.longitude,
1225+
);
1226+
1227+
if (!result.isValid) {
1228+
debugWarn('[APP] Session check failed before action: ${result.reason} - ${result.message}');
1229+
_statusMessageService.setDynamicStatus(
1230+
result.message ?? 'Session expired',
1231+
StatusColor.error,
1232+
);
1233+
// Note: onSessionError callback will trigger disconnect for critical errors
1234+
return false;
1235+
}
1236+
return true;
1237+
}
1238+
12121239
/// Toggle auto-ping mode (TX/RX or RX-only)
12131240
/// Returns false if blocked by cooldown (TX/RX Auto only - RX Auto ignores cooldown)
12141241
Future<bool> toggleAutoPing(AutoMode mode) async {
@@ -1266,6 +1293,12 @@ class AppStateProvider extends ChangeNotifier {
12661293
debugLog('[RX AUTO] Stopped - no cooldown (passive mode)');
12671294
}
12681295
} else {
1296+
// Check session validity before starting (skip in offline mode)
1297+
if (!_preferences.offlineMode) {
1298+
final sessionCheck = await _checkSessionBeforeAction();
1299+
if (!sessionCheck) return false;
1300+
}
1301+
12691302
// Block starting if shared cooldown is active (TX/RX Auto only)
12701303
// RX Auto is passive listening and can start during cooldown
12711304
if (!isRxOnly && _cooldownTimer.isRunning) {
@@ -2258,6 +2291,11 @@ class AppStateProvider extends ChangeNotifier {
22582291
name: _rememberedDevice!.name,
22592292
);
22602293

2294+
// Pre-populate the BLE scan cache with remembered device info
2295+
// This ensures the device name is available during connect()
2296+
// (normally populated by scanning, but we're skipping the scan)
2297+
_bluetoothService.cacheDeviceInfo(device);
2298+
22612299
await connectToDevice(device);
22622300
}
22632301

lib/services/api_service.dart

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ class ApiService {
253253
};
254254
}
255255

256-
// Log the full request payload
257-
debugLog('[HEARTBEAT] POST $wardriveEndpoint');
258-
debugLog('[HEARTBEAT] Payload: ${json.encode(payload)}');
256+
// Log heartbeat request (hide sensitive payload details)
257+
final hasCoords = lat != null && lon != null;
258+
debugLog('[HEARTBEAT] POST (with GPS: $hasCoords)');
259259

260260
final response = await _client.post(
261261
Uri.parse(wardriveEndpoint),
@@ -282,6 +282,50 @@ class ApiService {
282282
}
283283
}
284284

285+
/// Check if session is still valid by sending a heartbeat
286+
/// Use this before starting any wardrive action (Send Ping, Active Mode, Passive Mode)
287+
/// Returns (isValid, errorReason, errorMessage)
288+
Future<({bool isValid, String? reason, String? message})> checkSessionValid({
289+
double? lat,
290+
double? lon,
291+
}) async {
292+
if (_sessionId == null) {
293+
debugWarn('[SESSION] No session to validate');
294+
return (isValid: false, reason: 'no_session', message: 'No active session');
295+
}
296+
297+
debugLog('[SESSION] Checking session validity via heartbeat...');
298+
final result = await sendHeartbeat(lat: lat, lon: lon);
299+
300+
if (result == null) {
301+
debugWarn('[SESSION] Session check failed: no response');
302+
return (isValid: false, reason: 'no_response', message: 'Server did not respond');
303+
}
304+
305+
if (result['success'] == true) {
306+
debugLog('[SESSION] Session is valid (expires_at: ${result['expires_at']})');
307+
return (isValid: true, reason: null, message: null);
308+
}
309+
310+
// Session is invalid - check reason
311+
final reason = result['reason'] as String?;
312+
final message = result['message'] as String?;
313+
debugWarn('[SESSION] Session invalid: $reason - $message');
314+
315+
// Trigger session error callback for critical errors
316+
const criticalErrors = {
317+
'session_expired', 'session_invalid', 'session_revoked', 'bad_session',
318+
'invalid_key', 'unauthorized', 'bad_key',
319+
'outside_zone', 'zone_full',
320+
};
321+
if (criticalErrors.contains(reason)) {
322+
_clearSession();
323+
onSessionError?.call(reason, message);
324+
}
325+
326+
return (isValid: false, reason: reason, message: message);
327+
}
328+
285329
/// Enable heartbeat mode (called when auto mode starts)
286330
/// Heartbeat is scheduled based on expires_at from API responses
287331
/// @param gpsProvider Callback to get current GPS coordinates for heartbeat

lib/services/bluetooth/bluetooth_service.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ abstract class BluetoothService {
6969
/// Write data to device
7070
Future<void> write(Uint8List data);
7171

72+
/// Pre-populate device cache with known device info
73+
/// Used for remembered devices to ensure name is available during connect
74+
void cacheDeviceInfo(DiscoveredDevice device);
75+
7276
/// Dispose of resources
7377
void dispose();
7478
}

lib/services/bluetooth/mobile_bluetooth.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,12 @@ class MobileBluetoothService implements BluetoothService {
408408
await _rxCharacteristic!.write(data, withoutResponse: false);
409409
}
410410

411+
@override
412+
void cacheDeviceInfo(DiscoveredDevice device) {
413+
_scannedDevices[device.id] = device;
414+
print('[BLE] Cached device info: ${device.name} (${device.id})');
415+
}
416+
411417
@override
412418
void dispose() {
413419
_isDisposed = true;

lib/services/bluetooth/web_bluetooth.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ class WebBluetoothService implements BluetoothService {
250250
await _rxCharacteristic!.writeValueWithoutResponse(data);
251251
}
252252

253+
@override
254+
void cacheDeviceInfo(DiscoveredDevice device) {
255+
// Web Bluetooth uses _pendingDevice from requestDevice dialog
256+
// No caching needed - this method is for mobile remembered devices
257+
}
258+
253259
@override
254260
void dispose() {
255261
_notificationSubscription?.cancel();

0 commit comments

Comments
 (0)