|
| 1 | +# Composite Device Tracker |
| 2 | + |
| 3 | +This platform creates a composite device tracker from one or more other device trackers and/or binary sensors. It will update whenever one of the watched entities updates, taking the last_seen/last_updated (and possibly GPS and battery) data from the changing entity. The result can be a more accurate and up-to-date device tracker if the "input" device tracker's update irregularly. |
| 4 | + |
| 5 | +Currently device_tracker's with a source_type of bluetooth, bluetooth_le, gps or router are supported, as well as binary_sensor's. |
| 6 | + |
| 7 | +## Installation |
| 8 | + |
| 9 | +Follow either the HACS or manual installation instructions below. |
| 10 | +Then add the desired configuration. Here is an example of a typical configuration: |
| 11 | + |
| 12 | +```yaml |
| 13 | +device_tracker: |
| 14 | + - platform: composite |
| 15 | + name: me |
| 16 | + time_as: device_or_local |
| 17 | + entity_id: |
| 18 | + - device_tracker.platform1_me |
| 19 | + - device_tracker.platform2_me |
| 20 | +``` |
| 21 | +
|
| 22 | +### HACS |
| 23 | +
|
| 24 | +See [HACS](https://github.com/custom-components/hacs), especially the **Add custom repositories** section on [this page](https://custom-components.github.io/hacs/usage/settings/). |
| 25 | +
|
| 26 | +### Manual |
| 27 | +
|
| 28 | +Alternatively, place a copy of: |
| 29 | +
|
| 30 | +[`__init__.py`](custom_components/composite/__init__.py) at `<config>/custom_components/composite/__init__.py` |
| 31 | +[`device_tracker.py`](custom_components/composite/device_tracker.py) at `<config>/custom_components/composite/device_tracker.py` |
| 32 | +[`manifest.json`](custom_components/composite/manifest.json) at `<config>/custom_components/composite/manifest.json` |
| 33 | + |
| 34 | +where `<config>` is your Home Assistant configuration directory. |
| 35 | + |
| 36 | +>__NOTE__: Do not download the file by using the link above directly. Rather, click on it, then on the page that comes up use the `Raw` button. |
| 37 | + |
| 38 | +### numpy on Raspberry Pi |
| 39 | + |
| 40 | +To determine time zone from GPS coordinates (see `time_as` configuration variable below) the package [timezonefinderL](https://pypi.org/project/timezonefinderL/) is used. That package requires the package [numpy](https://pypi.org/project/numpy/). These will both be installed automatically by HA. Note, however, that numpy on Pi _usually_ requires libatlas to be installed. (See [this web page](https://www.raspberrypi.org/forums/viewtopic.php?t=207058) for more details.) It can be installed using this command: |
| 41 | +``` |
| 42 | +sudo apt install libatlas3-base |
| 43 | +``` |
| 44 | +>Note: This is the same step that would be required if using a standard HA component that uses numpy (such as the [Trend Binary Sensor](https://www.home-assistant.io/components/binary_sensor.trend/)), and is only required if you use `device_or_utc` or `device_or_local` for `time_as`. |
| 45 | + |
| 46 | +## Configuration variables |
| 47 | + |
| 48 | +- **name**: Object ID (i.e., part of entity ID after the dot) of composite device. For example, `NAME` would result in an entity ID of `device_tracker.NAME`. |
| 49 | +- **time_as** (*Optional*): One of `utc`, `local`, `device_or_utc` or `device_or_local`. Default is `utc` which shows time attributes in UTC. `local` shows time attributes per HA's `time_zone` configuration. `device_or_utc` and `device_or_local` attempt to determine the time zone in which the device is located based on its GPS coordinates. The name of the time zone (or `unknown`) will be shown in a new attribute named `time_zone`. If the time zone can be determined, then time attributes will be shown in that time zone. If the time zone cannot be determined, then time attributes will be shown in UTC if `device_or_utc` is selected, or in HA's local time zone if `device_or_local` is selected. |
| 50 | +- **entity_id**: Entity IDs of watched device tracker devices. Can be a single entity ID, a list of entity IDs, or a string containing multiple entity IDs separated by commas. |
| 51 | + |
| 52 | +## Watched device notes |
| 53 | + |
| 54 | +Watched GPS-based devices must have, at a minimum, the following attributes: `latitude`, `longitude` and `gps_accuracy`. If they don't they will not be used. |
| 55 | + |
| 56 | +For watched non-GPS-based devices, which states are used and whether any GPS data (if present) is used depends on several factors. E.g., if GPS-based devices are in use then the 'not_home'/'off' state of non-GPS-based devices will be ignored. If only non-GPS-based devices are in use, then the composite device will be 'home' if any of the watched devices are 'home'/'on', and will be 'not_home' only when _all_ the watched devices are 'not_home'/'off'. |
| 57 | + |
| 58 | +If a watched device has a `last_seen` attribute, that will be used in the composite device. If not, then `last_updated` from the entity's state will be used instead. |
| 59 | + |
| 60 | +If a watched device has a `battery` or `battery_level` attribute, that will be used to update the composite device's `battery` attribute. If it has a `battery_charging` or `charging` attribute, that will be used to udpate the composite device's `battery_charging` attribute. |
| 61 | + |
| 62 | +## known_devices.yaml |
| 63 | + |
| 64 | +The watched devices, and the composite device, should all have `track` set to `true`. |
| 65 | + |
| 66 | +It's recommended, as well, to set `hide_if_away` to `true` for the watched devices (but leave it set to `false` for the composite device.) This way the map will only show the composite device (of course when it is out of the home zone.) **NOTE:** The downside to hiding the watched devices, though, is that their history (other than when they're home) will not get recorded and hence will not be available in history views. (In history views they will appear to always be home.) Also they are hidden *everywhere* in the UI when not home (not just the map.) |
| 67 | + |
| 68 | +Lastly, it is also recommended to _not_ use the native merge feature of the device tracker component (i.e., do not add the MAC address from network-based trackers to a GPS-based tracker. See more details in the [Device Tracker doc page](https://www.home-assistant.io/components/device_tracker/#using-gps-device-trackers-with-local-network-device-trackers).) |
| 69 | + |
| 70 | +## Attributes |
| 71 | + |
| 72 | +Attribute | Description |
| 73 | +-|- |
| 74 | +battery | Battery level (in percent, if available.) |
| 75 | +battery_charging | Battery charging status (True/False, if available.) |
| 76 | +entity_id | IDs of entities that have contributed to the state of the composite device. |
| 77 | +gps_accuracy | GPS accuracy radius (in meters, if available.) |
| 78 | +last_entity_id | ID of the last entity to update the composite device. |
| 79 | +last_seen | Date and time when current location information was last updated. |
| 80 | +latitude | Latitude of current location (if available.) |
| 81 | +longitude | Longitude of current location (if available.) |
| 82 | +source_type | Source of current location information: `binary_sensor`, `bluetooth`, `bluetooth_le`, `gps` or `router`. |
| 83 | +time_zone | The name of the time zone in which the device is located, or `unknown` if it cannot be determined. Only exists if `device_or_utc` or `device_or_local` is chosen for `time_as`. |
| 84 | + |
| 85 | +## Examples |
| 86 | +### Time zone examples |
| 87 | + |
| 88 | +This example assumes `time_as` is set to `device_or_utc` or `device_or_local`. It determines the difference between the time zone in which the device is located and the `time_zone` in HA's configuration. A positive value means the device's time zone is ahead of (or later than, or east of) the local time zone. |
| 89 | +```yaml |
| 90 | +sensor: |
| 91 | + - platform: template |
| 92 | + sensors: |
| 93 | + my_tz_offset: |
| 94 | + friendly_name: My time zone offset |
| 95 | + unit_of_measurement: hr |
| 96 | + value_template: > |
| 97 | + {% set state = states.device_tracker.me %} |
| 98 | + {% if state.attributes is defined and |
| 99 | + state.attributes.time_zone is defined and |
| 100 | + state.attributes.time_zone != 'unknown' %} |
| 101 | + {% set n = now() %} |
| 102 | + {{ (n.astimezone(state.attributes.last_seen.tzinfo).utcoffset() - |
| 103 | + n.utcoffset()).total_seconds()/3600 }} |
| 104 | + {% else %} |
| 105 | + unknown |
| 106 | + {% endif %} |
| 107 | +``` |
| 108 | +This example converts a time attribute to the local time zone. It works no matter which time zone the attribute is in. |
| 109 | +```yaml |
| 110 | +sensor: |
| 111 | + - platform: template |
| 112 | + sensors: |
| 113 | + my_last_seen_local: |
| 114 | + friendly_name: My last_seen time in local time zone |
| 115 | + value_template: > |
| 116 | + {{ state_attr('device_tracker.me', last_seen').astimezone(now().tzinfo) }} |
| 117 | +``` |
0 commit comments