aaronpk / Overland-iOS

πŸ“Œ GPS logger for iOS devices
https://overland.p3k.app
Apache License 2.0
607 stars 93 forks source link
corelocation gps gps-tracker gpslogger hacktoberfest ios trip

Overland GPS Tracker for iOS

This app tracks your location in the background and sends the data to a server of your choosing. The app tracks:

The app gathers data even when the phone is offline, and the data is sent to the server in a batch at an interval set by the user.

There are many settings available in the settings tab which allow you to adjust properties of the CoreLocation API.

The app sends data to an HTTP endpoint. You can use an existing backend or build your own. The app works with:

Looking for the Android version? β†’ https://github.com/OpenHumans/overland_android

Documentation

Tracker Screen

The Tracker screen is where you control whether the app is active, and shows you some basic stats of what the app is doing. This is also where you start and stop trips.

Settings

The Settings screen allows you to set the various options in the Overland app as well as parameters of the iOS CoreLocation API, which gives you fine-grained control over how the tracker behaves.

iOS Settings

The settings in this section set properties on the CoreLocation API. They are meant to give you direct control over how you want to tell the operating system to deliver data to the app. It is worth reading the iOS documentation for more details, but a summary of them is below.

Overland Settings

The settings in this section control features specific to the Overland app.

Trip Settings

The "Trip Settings" tab contains most of the same options as the main settings tab, but these values only apply when a trip is in progress. When a trip starts, the app will apply these settings, and when a trip ends, will revert to the main settings.

You can use this for example to record low-frequency updates continusouly, but then log high-frequency updates when you start a trip.

There are some additional settings specific to trips:

System Settings

There are some additional settings in the iOS Settings app that are not exposed in the app interface itself. This is for settings that are infrequently changed or uncommon.

Configuration by Custom URL

You can send people a custom URL that will configure the app by clicking on it. Create a URL with your endpoint, token and device ID like the following:

overland://setup?url=https%3A%2F%2Fexample.com%2Fapi&token=1234&device_id=1&unique_id=yes

Tapping that URL on a device with the app installed will launch the app and save the values in the configuration. This is a quick way to configure many devices since it bypasses the need to enter the values in the settings screen.

Query Parameters:

Usage Profiles

You should decide what kind of data you are hoping to get out of this application. The controls provided will give you a lot of knobs you can turn to adjust the way the app collects data. Below are some recommended presets for different applications.

High Resolution Tracking

To get high resolution data, you should set the following:

While moving, you will receive up to one point per second. When you're not moving, such as when you're at your desk, etc, there may be several minutes between location updates received. This will use a lot of battery, but will result in data that can be used to generate a picture similar to this level of detail.

GPS Logs

Battery Saving / Low Resolution

To use very little battery, you can still get enough location info to know what neighborhood you're in, and likely also when you leave and return home.

This will use much less battery than high resolution, while still gathering enough data you can use to roughly geotag posts or know what neighborhood you're in. For even more battery savings, you can set Significant Location Only, which will drastically reduce the amount of data you log but will use almost no battery.

API

The app will post the location data to the configured endpoint.

If the endpoint URL has any template parameters, they will be replaced with the value of the most recent location update. The template parameters you can use are below:

For example, you can use the URL below to receive all the data in the query string:

https://example.com/input?ts=%TS&lat=%LAT&lon=%LON&acc=%ACC&spd=%SPD&bat=%BAT&alt=%ALT

The POST request body will be a JSON object containing a property locations which is an array of GeoJSON objects. The default batch size is 200 but can be set in the settings. This request will look something like the following:

POST /api HTTP/1.1
Authorization: Bearer xxxxxx
Content-Type: application/json

{
  "locations": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -122.030581, 
          37.331800
        ]
      },
      "properties": {
        "timestamp": "2015-10-01T08:00:00-0700",
        "altitude": 0,
        "speed": 4,
        "horizontal_accuracy": 30,
        "vertical_accuracy": -1,
        "motion": ["driving","stationary"],
        "pauses": false,
        "activity": "other_navigation",
        "desired_accuracy": 100,
        "deferred": 1000,
        "significant_change": "disabled",
        "locations_in_payload": 1,
        "battery_state": "charging",
        "battery_level": 0.80,
        "device_id": "",
        "wifi": ""
      }
    }
  ],
  "current": { ... }, (optional)
  "trip": { ... } (optional)
}

If you've configured an access token, it will be sent in the HTTP Authorization header preceded by the text Bearer.

The properties on the location objects are as follows:

The following properties are included only if the "Include Tracking Stats" option is selected:

Response

Your server must reply with a JSON response containing:

{
  "result": "ok"
}

This indicates to the app that the batch was received, and it will delete those points from the local cache. If the app receives any other response, it will keep the data locally and try to send it again at the next interval.

If you are unable to return this JSON, you can set the "Consider HTTP 2XX Successful" in the Settings app, and then any HTTP 2xx response will be considered successful.

Configuration by Server Response

You can configure all of the settings in the app by having your server return new settings in the JSON response when it uploads data. The documentation of the JSON structure and all possible config values is below.


{
  "result": "ok",
  "set": {
    "send_interval": "1s|5s|10s|15s|30s|1m|2m|5m|10m|30m|off",
    "trip_mode": "walk|run|bicycle|car|taxi|bus|tram|train|metro|gondola|monorail|sleigh|plane|boat|scooter",
    "main": {
      "tracking_mode": "off|standard|significant|both",
      "visit_tracking": true|false,
      "desired_accuracy": "nav|best|10m|100m|1km|3km",
      "activity_type": "other|car|fitness|nav|air",
      "background_indicator": true|false,
      "pause_automatically": true|false,
      "logging_mode": "all|latest|owntracks",
      "batch_size": 50|100|200|500|1000,
      "resume_with_geofence": "off|100m|200m|500m|1km|2km",
      "min_distance": "off|1m|10m|50m|100m|500m",
      "min_time": "1s|5s|10s|30s|1m|5m",
    },
    "trip": {
      "desired_accuracy": "nav|best|10m|100m|1km|3km",
      "activity_type": "other|car|fitness|nav|air",
      "background_indicator": true|false,
      "prevent_screen_lock": true|false,
      "logging_mode": "all|latest|owntracks",
      "batch_size": 50|100|200|500|1000,
      "min_distance": "off|1m|10m|50m|100m|500m",
      "min_time": "1s|5s|10s|30s|1m|5m",
    }
  }
}

Note that most values are strings, with the exception of some that are numbers or boolean.

The settings under main correspond to the settings in the main settings screen in the UI, and the settings under trip correspond to the settings when a trip is in progress.

IMPORTANT: It is very possible to send a setting to the phone that will disable logging completely, which creates a dead end, since the phone will then never check back with the server for updated settings! The main setting that can cause this to happen is send_interval=off. Setting tracking_mode=off means only "visits" will be tracked, which will be received extremely infrequently, so you won't have a chance to change the setting to something else until after the phone checks in after that.

It is best to only send properties in the response that you want to change at that moment, rather than always sending the values on every response. Treat it like pressing the button in the UI, only send the response when you want to press the button.

Current Location

If the number of locations in the queue are more than twice the batch size, then the request will also contain a property current with the most recent location point stored by the device. (This point will not be one of the ones in the batch.) If you need your backend to be aware of the current location, this allows you to ignore the batch being uploaded and instead use just that point.

Current Trip

If a trip is active, an object called trip will be included in the request as well, with information about the current trip. This object will contain the following properties:

Home Assistant Integration

Setting the Logging Mode to "Owntracks" will record the data in a format that can be used with Home Assistant.

https://www.home-assistant.io/integrations/owntracks/

Only the latest point will be sent every interval, so you can experiment with the various settings to get this to record as much or as little data as you want.

In the Overland Server URL setup, set the "Device ID" to the Owntracks topic you want, for example "username/device". This will be appended to the string "owntracks/" for the topic URL. Use the "Access Token" field for your Home Assistant username.

Development Setup

This assumes you have Xcode and Homebrew installed. A paid Apple Developer account is not needed.

License

Contributions from 2017 onward are copyright by Aaron Parecki and contributors

Contributions from 2013-2016 are copyright by Esri, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.