feat(location): live GPS location tracking - #246
Open
deaflynx wants to merge 43 commits into
Open
Conversation
…pike page - positionStream now accepts LocationStreamSettings (accuracy tier, distance filter, interval, optional background mode) - background mode uses geolocator foreground service notification on Android and background location updates on iOS - add FOREGROUND_SERVICE / FOREGROUND_SERVICE_LOCATION permissions and the iOS 'location' background mode - add debug-only live tracking spike page (More menu) that streams fixes and saves latitude/longitude/gpsAccuracy telemetry to the current user entity
…cking The ESP32 provisioning branch capped ACCESS_FINE_LOCATION at maxSdkVersion=35, which strips the permission on API 36+ (Android 16). Live GPS tracking then fell back to approximate location and delivered only a single fix. Use tools:remove to drop any dependency-imposed maxSdkVersion so fine location is granted on all API levels.
start() was awaiting the network entity-name lookup before persisting the recoverable "interrupted" record and subscribing to GPS. A force kill (or slow/offline network) in that window left nothing persisted to recover from, and a concurrent stop()/logout could resume start() afterwards and resurrect a subscription and record for a session that had already ended. Reorder start() so the record write, status attributes, GPS subscription and max-duration timer all happen synchronously before any network call, then resolve the name in the background and patch it into the persisted record. The patch is guarded by the session's startedAt so a stop, logout, or newer start() supersedes it and the late name resolution becomes a no-op. Also: - remove the dead liveTrackingNoSession l10n key (its only consumer, the old session page, is gone) and regenerate l10n - tighten two loose test matchers in the location tracking widget tests (findsOneWidget instead of findsWidgets; assert the exact primaryContainer color instead of just isNotNull)
…ping The dashboard now sends the keys to save rather than a fixed pair plus flags: each entry names a location value, the entity key it is written under and whether it lands in server attributes or time series. Replaces latitudeKey, longitudeKey, includeMetadata, mirrorToAttributes and writeStatusAttributes, drops the redundant gpsLastUpdateTime attribute, and switches the maximum duration to seconds to match the wire config.
…oard - carry the web-resolved target name and source dashboard in the tracking wire config and persist them with the last-session record - return trackingInfo (target name, saved keys) from the stop action ack so the dashboard dialog can show what was tracked - tracking page: target entity links to its details (device profile dashboard, asset or customer details), source dashboard opens on tap - tracking page: "Save location to entity" label, play/pause status icon with green/amber color, start/end times without milliseconds
The teardown added in d80b3ba lived only in the legacy TbContext.logout() which no user-facing path calls, so logging out left GPS streaming, kept posting telemetry with a dead token, and resumed the session on the next login. LoginProvider.logout() now stops tracking and clears the record before tbClient.logout(), while the token needed for the gpsActive=false write is still valid. Covers every logout entry point.
Periodic save failures raised the global modal "Connection error" dialog over whatever the user was doing (once per failed save) and toggled the global loading state. Telemetry/attribute saves and the target-name query now carry ignoreErrors+ignoreLoading, so the session screen's error counter and last-error line remain the only surface.
…is lost - Store lastError as a LiveTrackingError cause instead of a raw exception string; the session screen mapped a Dio/ThingsboardError toString() with ten stack frames onto the UI. Causes are classified by status/error code (the 404 arrives with an empty message) and localized in the UI layer; full exception + trace keep going to the logger only. - Clear lastError on a successful fix so a resolved error does not stay on screen forever. - Map geolocator stream errors to the sealed LocationFix cases: turning device location off mid-session previously landed as a generic fix error and the session kept looking healthy. It now pauses visibly and writes gpsActive=false. - Show a system notification while a session is paused, cleared on resume/stop and at app start (a leftover notification must not outlive the process the session died with).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds live GPS location tracking to the mobile app. A dashboard widget can start and stop a tracking session through two new mobile actions (
startLiveLocation/stopLiveLocation); while a session is active the app streams GPS fixes — including in the background — and saves them to the target entity as time series using the key mapping from the widget's action configuration. A new Live tracking page and an app-wide tracking bar show the session state.Changes
Location service (
lib/utils/services/location/)LocationService(ILocationService) wrapping geolocator: one-shotgetCurrentPosition()and a background-capable position stream with configurableLocationStreamSettings.GeoPositionnow exposes accuracy, timestamp, altitude, speed and heading; thegetLocationaction result includes accuracy and timestamp.GetLocationActionrefactored to delegate toLocationService, with shared result mapping viaLocationActionResultMapper.Live tracking session (
lib/utils/services/live_location_tracking/)LiveLocationTrackingServicemanages the session lifecycle: parsesLiveTrackingConfigfrom the widget action, subscribes to the position stream, and saves telemetry throughILiveTrackingRemoteas background requests using the configured key mapping.EntityNameResolver), with a re-check of session identity after the async store read.ILiveTrackingStore(LastTrackingRecordwith end reason and resolved name); tracking is stopped and the record cleared on logout.UI (
lib/modules/location_tracking/)/liveTracking), shown in navigation/More when the mobile bundle layout includes thelive_location_trackingpage: the idle state shows the last session summary with a Start button; the active state shows live session details with a linkable target entity and source dashboard.Mobile actions
WidgetMobileActionTypevalues:startLiveLocation,stopLiveLocation.Platform configuration
ACCESS_FINE_LOCATIONis no longer capped bymaxSdkVersion(live tracking needs fine location on all API levels, including 36+); addedFOREGROUND_SERVICEandFOREGROUND_SERVICE_LOCATIONfor background tracking.locationtoUIBackgroundModes.🤖 Generated with Claude Code