Compare commits

..

1 Commits

Author SHA1 Message Date
Janez T
ba0f1fc141 feat: Add fast GPS send logs 2026-03-23 21:00:41 +01:00
8 changed files with 100 additions and 14 deletions

View File

@@ -489,7 +489,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 126; CURRENT_PROJECT_VERSION = 128;
DEVELOPMENT_TEAM = JND55328G8; DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -511,7 +511,7 @@
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 126; CURRENT_PROJECT_VERSION = 128;
DEVELOPMENT_TEAM = JND55328G8; DEVELOPMENT_TEAM = JND55328G8;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
@@ -530,7 +530,7 @@
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 126; CURRENT_PROJECT_VERSION = 128;
DEVELOPMENT_TEAM = JND55328G8; DEVELOPMENT_TEAM = JND55328G8;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
@@ -547,7 +547,7 @@
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 126; CURRENT_PROJECT_VERSION = 128;
DEVELOPMENT_TEAM = JND55328G8; DEVELOPMENT_TEAM = JND55328G8;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
@@ -679,7 +679,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 126; CURRENT_PROJECT_VERSION = 128;
DEVELOPMENT_TEAM = JND55328G8; DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -702,7 +702,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 126; CURRENT_PROJECT_VERSION = 128;
DEVELOPMENT_TEAM = JND55328G8; DEVELOPMENT_TEAM = JND55328G8;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;

View File

@@ -43,7 +43,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>126</string> <string>128</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>

View File

@@ -5,22 +5,22 @@
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000231"> <testcase classname="fastlane.lanes" name="0: default_platform" time="0.00073">
</testcase> </testcase>
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.728696"> <testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.659743">
</testcase> </testcase>
<testcase classname="fastlane.lanes" name="2: build_app" time="101.589371"> <testcase classname="fastlane.lanes" name="2: build_app" time="105.547745">
</testcase> </testcase>
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="690.798016"> <testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="252.935458">
</testcase> </testcase>

View File

@@ -2879,8 +2879,13 @@ class AppProvider with ChangeNotifier {
timestampSeconds: DateTime.now().millisecondsSinceEpoch ~/ 1000, timestampSeconds: DateTime.now().millisecondsSinceEpoch ~/ 1000,
); );
debugPrint( debugPrint(
'📍 [AppProvider] Sending fast GPS update ($reason): ' '📤 [AppProvider] Fast GPS send '
'${position.latitude}, ${position.longitude} via channel $channelIdx', 'reason=$reason '
'sender=$senderKey6 '
'channel=$channelIdx '
'lat=${position.latitude} '
'lon=${position.longitude} '
'ts=${packet.timestampSeconds}',
); );
try { try {
await connectionProvider.sendChannelData( await connectionProvider.sendChannelData(
@@ -2888,11 +2893,32 @@ class AppProvider with ChangeNotifier {
dataType: MeshCoreConstants.dataTypeDev, dataType: MeshCoreConstants.dataTypeDev,
payload: packet.encodeBinary(), payload: packet.encodeBinary(),
); );
debugPrint(
'✅ [AppProvider] Fast GPS sent '
'sender=$senderKey6 channel=$channelIdx ts=${packet.timestampSeconds}',
);
} catch (e) { } catch (e) {
debugPrint('⚠️ [AppProvider] Fast GPS send failed: $e'); debugPrint('⚠️ [AppProvider] Fast GPS send failed: $e');
} }
} }
Future<bool> sendTestFastLocationUpdate() async {
if (!connectionProvider.deviceInfo.isConnected) {
return false;
}
final position = await locationTrackingService.getCurrentPosition(
timeLimit: const Duration(seconds: 10),
retryCount: 1,
);
if (position == null) {
return false;
}
await _sendFastLocationUpdate(position, reason: 'test');
return true;
}
Contact? _resolveVoiceFetchRequester(VoiceFetchRequest request) { Contact? _resolveVoiceFetchRequester(VoiceFetchRequest request) {
final liveContact = _resolveContactByPrefixHex(request.requesterKey6); final liveContact = _resolveContactByPrefixHex(request.requesterKey6);
if (liveContact != null) { if (liveContact != null) {

View File

@@ -1143,13 +1143,34 @@ class ContactsProvider with ChangeNotifier {
), ),
); );
debugPrint(
'📥 [ContactsProvider] Fast GPS received '
'sender=${packet.senderKey6} '
'contact=${contact.displayName} '
'contactKey=${contact.publicKeyHex} '
'lat=${packet.latitude} '
'lon=${packet.longitude} '
'ts=${packet.timestampSeconds}',
);
final updatedContact = contact.copyWith( final updatedContact = contact.copyWith(
telemetry: updatedTelemetry, telemetry: updatedTelemetry,
lastAdvert: packet.timestampSeconds, lastAdvert: packet.timestampSeconds,
lastMod: packet.timestampSeconds,
advLat: _coordinateToAdvertMicrodegrees(packet.latitude), advLat: _coordinateToAdvertMicrodegrees(packet.latitude),
advLon: _coordinateToAdvertMicrodegrees(packet.longitude), advLon: _coordinateToAdvertMicrodegrees(packet.longitude),
); );
_contacts[contact.publicKeyHex] = updatedContact; _contacts[contact.publicKeyHex] = updatedContact;
_estimatedLocations[contact.publicKeyHex] = LatLng(
packet.latitude,
packet.longitude,
);
debugPrint(
'✅ [ContactsProvider] Fast GPS applied '
'contact=${updatedContact.displayName} '
'contactKey=${updatedContact.publicKeyHex} '
'lastAdvert=${updatedContact.lastAdvert}',
);
_persistContacts(); _persistContacts();
notifyListeners(); notifyListeners();
} }

View File

@@ -426,6 +426,23 @@ class _SettingsScreenState extends State<SettingsScreen> {
return 'Channel $channelIdx unavailable'; return 'Channel $channelIdx unavailable';
} }
Future<void> _sendTestFastLocationUpdate() async {
final appProvider = context.read<AppProvider>();
final sent = await appProvider.sendTestFastLocationUpdate();
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
sent
? 'Test fast GPS update sent.'
: 'Unable to send test fast GPS update.',
),
backgroundColor: sent ? Colors.green : Colors.orange,
),
);
}
Future<void> _editFastLocationChannel() async { Future<void> _editFastLocationChannel() async {
final channels = final channels =
List<Contact>.from(context.read<ContactsProvider>().channels) List<Contact>.from(context.read<ContactsProvider>().channels)
@@ -1854,6 +1871,15 @@ class _SettingsScreenState extends State<SettingsScreen> {
trailing: const Icon(Icons.chevron_right), trailing: const Icon(Icons.chevron_right),
onTap: _editFastLocationChannel, onTap: _editFastLocationChannel,
), ),
ListTile(
leading: const Icon(Icons.send),
title: const Text('Test send update'),
subtitle: const Text(
'Send one fast GPS update immediately to the configured channel.',
),
trailing: const Icon(Icons.chevron_right),
onTap: _sendTestFastLocationUpdate,
),
ListTile( ListTile(
leading: Icon(Icons.location_on), leading: Icon(Icons.location_on),
title: Text(AppLocalizations.of(context)!.locationPermission), title: Text(AppLocalizations.of(context)!.locationPermission),

View File

@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 2026.0323.2+41 version: 2026.0323.3+42
environment: environment:
sdk: ^3.9.2 sdk: ^3.9.2

View File

@@ -781,6 +781,19 @@ void main() {
expect(updated.advLat, equals((44.123456 * 1e6).round())); expect(updated.advLat, equals((44.123456 * 1e6).round()));
expect(updated.advLon, equals((13.654321 * 1e6).round())); expect(updated.advLon, equals((13.654321 * 1e6).round()));
expect(updated.lastAdvert, equals(1700001234)); expect(updated.lastAdvert, equals(1700001234));
expect(updated.lastMod, equals(1700001234));
expect(
provider.estimatedLocationFor(updated.publicKeyHex),
isNotNull,
);
expect(
provider.estimatedLocationFor(updated.publicKeyHex)!.latitude,
closeTo(44.123456, 0.000001),
);
expect(
provider.estimatedLocationFor(updated.publicKeyHex)!.longitude,
closeTo(13.654321, 0.000001),
);
}); });
test('ignores unknown sender prefix safely', () { test('ignores unknown sender prefix safely', () {