Skip to main content

OwnTracks (Presence & Geofencing)

OwnTracks is the open-source location app for iOS and Android that reports each person's phone to a self-hosted OwnTracks Recorder. This driver reads that Recorder over HTTP and turns it into GEM presence: it creates one zone per tracked phone under a Location subsystem and keeps each zone's in_geofence value in step with the OwnTracks regions (geofences) that phone is currently inside.

The point of the integration is presence-driven automation — arriving-home lighting and climate warm-up, "everyone left" arming, a mudroom scene when a specific person enters the driveway region. GEM never talks to the phones; it only reads region membership the Recorder already knows, so this is a read-only sensor with no controllable commands. You wire the behavior yourself with triggers and macros against the in_geofence value.

How it fits together

The phones publish location to your OwnTracks Recorder (over MQTT or HTTP — that side is standard OwnTracks and out of scope here). GEM polls the Recorder, not the phones. One GEM device row represents the Recorder connection; each phone the Recorder knows about becomes its own GEM zone.

Prerequisites

  • A running OwnTracks Recorder reachable from the GEM controller over HTTP(S). GEM does not host it.
  • The Recorder must expose an endpoint that returns current per-device state as a JSON object keyed by device name, where each device carries an inregions array (the OwnTracks regions it is inside right now). This is the shape the driver consumes — see Recorder response shape below.
  • HTTP Basic auth credentials for that endpoint (username + password). Put the endpoint behind Basic auth even on a LAN — the driver always sends credentials.
  • At least one phone running the OwnTracks app, publishing to the Recorder, with one or more regions defined in the app. Without regions there is nothing to report and in_geofence stays empty.

Setup steps

  1. Add the device. In the GEM admin console open DevicesAdd Device and choose the driver OwnTracks.
  2. Fill in the connection fields the driver shows:
    • Recorder URL — the full endpoint that returns the keyed JSON above, e.g. https://owntracks.example.com/api/last. Enter the complete URL, not an IP/port.
    • Username and Password — the HTTP Basic credentials for that endpoint. The password is stored encrypted.
    • Poll Interval (ms) — optional. Defaults to 5000 (5 s). For presence, 5 s is unnecessarily aggressive on the Recorder; region membership changes on the order of minutes, so 30000–60000 is a better starting point on a real site.
  3. Save and enable the device. On connect, if the URL, username and password are all set, the driver starts polling; if any of the three is missing it logs a configuration error and does nothing.
  4. Let the first poll run, then check zones. On the first successful poll the driver creates a Location subsystem (if one doesn't already exist) and one zone per phone the Recorder reports. You do not create these zones by hand — open Zones after a poll cycle and you'll see them appear under Location. Each zone's address, name, and label are set to the OwnTracks device key exactly as it appears in the Recorder response.
  5. Confirm live state. Walk a phone into one of its OwnTracks regions (or check one already inside a region). Within one poll interval the matching zone's in_geofence value updates to the region name.
The Location subsystem is created for you

Location is not one of GEM's stock subsystems (AV, Security, Climate, Cameras, Doors, …). The driver adds it automatically the first time it successfully reads the Recorder, so don't be surprised to see a new subsystem appear — that's expected, not a misconfiguration.

Recorder response shape

Each poll issues an HTTP GET to the Recorder URL with your Basic credentials and expects a JSON object keyed by device name, one entry per phone, each carrying an inregions array:

{
"alice-phone": { "inregions": ["home", "driveway"] },
"bob-phone": { "inregions": [] }
}

For every key in that object the driver ensures a zone exists (auto-creating it under Location on first sight) and writes the joined region list to that zone's in_geofence. Only inregions is read — coordinates, accuracy, battery and the rest of the OwnTracks payload are ignored.

Point the Recorder URL at an endpoint that returns this keyed shape. If the endpoint instead returns a plain JSON array of location objects, the driver still runs but names the zones by array index (0, 1, …) rather than by phone, which is rarely what you want — front the Recorder with a view that keys by device name.

Attribute reference

Device attributes

AttributeRequiredDefaultPurpose
urlFull OwnTracks Recorder endpoint returning the keyed JSON above. Shown as Recorder URL.
usernameHTTP Basic username.
passwordHTTP Basic password. Stored encrypted.
status_interval5000Milliseconds between polls. Shown as Poll Interval (ms). Raise it for presence use.

Zone attributes (written by the driver)

AttributeWritten whenMeaning
in_geofenceIt changes for that phoneComma-separated list of the OwnTracks region names the phone is currently inside (e.g. home,driveway). Empty string when the phone is inside no region. This is the value you build automations against.

The zone's address (and its initial name/label) is the OwnTracks device key — the top-level key under which the Recorder publishes that phone.

Using presence in automation

in_geofence is a normal zone attribute, so the standard automation surfaces apply:

  • React to arrivals/departures — create an Attribute Trigger on the phone's Location zone watching in_geofence. Fire it whenever the value changes, then branch in the target macro on whether the value contains the region you care about — e.g. run "arrive home" when in_geofence includes home, and "everyone left" when the last person's zone goes empty.
  • Gate other logic on presence — reference a Location zone's in_geofence inside a macro condition to allow or skip a step (e.g. only run the goodnight macro if a specific person's phone is in the home region).

Because in_geofence is a list of region names (a phone can be inside overlapping regions at once), match on "contains this region name" rather than on strict equality when a phone may occupy more than one region.

What this driver does not do

  • No commands. OwnTracks is inbound only — there is nothing to switch on or off, so the device exposes no controllable actions. Don't look for on/off/level here; the value lives entirely in the in_geofence reads.
  • No coordinate/history tracking. Only current region membership is read. Latitude/longitude, movement history, accuracy, and battery from the OwnTracks payload are not stored.
  • No zone cleanup. A phone that stops appearing in the Recorder response keeps its last zone and its last in_geofence value — the driver never deletes a zone or blanks a stale one. Remove obsolete Location zones by hand if a phone is retired.

Troubleshooting

  • No zones appear after enabling. Hit the Recorder URL from the GEM host with curl using the same Basic credentials. An empty, unauthorized, or wrong-shaped response produces no zones. Confirm the response is an object keyed by device name (see Recorder response shape).
  • Zones exist but in_geofence stays empty. The phones aren't inside any OwnTracks region. Define regions in the OwnTracks app and confirm the app is publishing; with no regions there is nothing to report.
  • The device won't connect / nothing polls. All three of Recorder URL, Username, and Password must be filled — the driver refuses to poll if any is missing and logs a configuration error.
  • Zones are named 0, 1, 2 The Recorder is returning a JSON array instead of an object keyed by device name. Point the Recorder URL at an endpoint that keys by device (see Recorder response shape).
  • Presence updates feel slow. Updates arrive at most once per Poll Interval (ms), and only after OwnTracks itself has registered the region enter/exit on the phone. If you raised the interval for load, lower it toward 15000–30000 for snappier arrivals.
  • Zones — the auto-created Location zones live here.
  • Subsystems — where the Location subsystem shows up.
  • Attributes — how in_geofence is stored and viewed.
  • Triggers and Macros — turn presence into action.