Skip to content

Commit 087fd0e

Browse files
authored
Merge
Don't know what happened here.. Hopefully good now
2 parents 3ef9436 + a899343 commit 087fd0e

16 files changed

+897
-265
lines changed

.github/workflows/hacs_action.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: "HACS Validate"
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
hacs:
9+
name: "HACS validation"
10+
runs-on: "ubuntu-latest"
11+
steps:
12+
- name: HACS Action
13+
uses: "hacs/action@main"
14+
with:
15+
category: "integration"

.github/workflows/hassfest.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ jobs:
1010
validate:
1111
runs-on: "ubuntu-latest"
1212
steps:
13-
- uses: "actions/checkout@v3"
13+
- uses: "actions/checkout@v4"
1414
- uses: home-assistant/actions/hassfest@master

.github/workflows/release.yml

+17-15
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,33 @@ on:
55
types: [published]
66

77
jobs:
8-
release_zip_file:
8+
release:
99
name: Prepare release asset
1010
runs-on: ubuntu-latest
1111
steps:
12-
- name: Check out repository
13-
uses: actions/checkout@v1
14-
15-
- name: Get version
16-
id: version
17-
uses: home-assistant/actions/helpers/version@master
12+
- name: ⤵️ Check out code from GitHub
13+
uses: actions/checkout@v4
1814

19-
- name: "Set version number"
15+
- name: 🔢 Adjust version number
16+
shell: bash
2017
run: |
21-
python3 ${{ github.workspace }}/manage/update_manifest.py --version ${{ steps.version.outputs.version }}
22-
23-
- name: ZIP files
18+
version="${{ github.event.release.tag_name }}"
19+
version="${version,,}"
20+
version="${version#v}"
21+
yq e -P -o=json \
22+
-i ".version = \"${version}\"" \
23+
"${{ github.workspace }}/custom_components/iphonedetect/manifest.json"
24+
25+
- name: 📦 Created zipped release package
2426
run: |
25-
cd /home/runner/work/iphonedetect/iphonedetect/custom_components/iphonedetect
27+
cd "${{ github.workspace }}/custom_components/iphonedetect"
2628
zip iphonedetect.zip -r ./
27-
- name: Upload zip to release
28-
uses: svenstaro/upload-release-action@v1-release
2929
30+
- name: ⬆️ Upload zip to release
31+
uses: svenstaro/upload-release-action@v2
3032
with:
3133
repo_token: ${{ secrets.GITHUB_TOKEN }}
32-
file: /home/runner/work/iphonedetect/iphonedetect/custom_components/iphonedetect/iphonedetect.zip
34+
file: "${{ github.workspace }}/custom_components/iphonedetect/iphonedetect.zip"
3335
asset_name: iphonedetect.zip
3436
tag: ${{ github.ref }}
3537
overwrite: true

README.md

+88-38
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,94 @@
1-
[![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg)](https://github.com/custom-components/hacs)
2-
![GitHub release](https://img.shields.io/github/release/mudape/iphonedetect.svg)
3-
# iPhone Detect
4-
This integration sends a message to the defined hosts on UDP port 5353.
5-
The iPhone responds, _even when in deep sleep_, and an entry in the ARP cache is made .
1+
# iPhone Detect for Home-Assistant
62

7-
Uses Home Assistant's [device_tracker](https://www.home-assistant.io/components/device_tracker/) and idea/script from [return01](https://community.home-assistant.io/u/return01)
3+
[![Validate with hassfest](https://github.com/mudape/iphonedetect/actions/workflows/hassfest.yaml/badge.svg)](https://github.com/mudape/iphonedetect/actions/workflows/hassfest.yaml)
4+
[![HACS Validate](https://github.com/mudape/iphonedetect/actions/workflows/hacs_action.yml/badge.svg)](https://github.com/mudape/iphonedetect/actions/workflows/hacs_action.yml)
5+
[![hacs_badge](https://img.shields.io/badge/HACS-Default-blue.svg)](https://github.com/custom-components/hacs)
86

9-
Only **IP addresses** will work, _no hostnames_!
10-
You have to assign a **static** IP address(es) to your iPhones, probably in your router.
7+
![downloads](https://img.shields.io/github/downloads/mudape/iphonedetect/total.svg)
8+
![downloads](https://img.shields.io/github/downloads/mudape/iphonedetect/1.4.2/total.svg)
9+
![downloads](https://img.shields.io/github/downloads/mudape/iphonedetect/latest/total.svg)
1110

12-
_The interval_seconds time must be shorter than the timeout in which the ARP cache is cleared (usally 15-45sec), or the phone will be marked not_home._
13-
_So, leave it at the default value (12sec) or make it shorter._
11+
This integration sends a mDNS message to defined hosts.
12+
The device responds if it's connected to the network, even when in deep sleep, and an entry in the ARP cache is made and read.
13+
Usefull as a [device_tracker](https://www.home-assistant.io/integrations/device_tracker/) for your [person](https://www.home-assistant.io/integrations/person/) integration to see if users are at home.
1414

15-
<a href="https://www.buymeacoffee.com/MudApe" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
15+
## Installation
16+
17+
After installation you need to **restart** Home-Assistant before using the integration.
18+
19+
### Using HACS
20+
21+
If you dont' have [HACS](https://hacs.xyz) installed yet, I highly recommend it.
22+
[![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=mudape&repository=iphonedetect&category=integration) or search for `iPhone Device Tracker`.
23+
24+
### Manual
25+
26+
Download the `iphonedetect` directory and place in your `<config>/custom_component`
27+
28+
## Configuration
29+
30+
### Network
31+
32+
Assign a **static** IP address to the device you want to track, probably in your router.
33+
Alternative, set a manual IP in your device WiFi configuration.
34+
Avoid automatically connect to differtent SSID's (2.4 and 5 ghz bands)
35+
36+
### Setup
37+
38+
[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=iphonedetect)
39+
40+
If you don't have [My Home Assistant](https://my.home-assistant.io/) redirects set up, go to Settings -> Devices & Services
41+
Click "Add integration" and search for `iPhone Device Tracker`
42+
43+
Give the entity a unique `name` and enter its IP address.
44+
45+
![image](https://github.com/user-attachments/assets/c4583955-72d8-4c3a-81b4-062a134af11e)
1646

17-
## Example configuration.yaml
18-
19-
```yaml
20-
device_tracker:
21-
- platform: iphonedetect
22-
consider_home: 60
23-
scan_interval: 12
24-
new_device_defaults:
25-
track_new_devices: true
26-
hosts:
27-
hostname1: 192.168.0.17
28-
hostname2: 192.168.0.24
29-
```
30-
This will create `device_tracker.hostname1` and `device_tracker.hostname2` once the devices have been detected on your network.
31-
(Re)start the Wi-Fi on your device/phone to trigger their creation on first run.
32-
33-
__Note__
34-
If you have `track_new_devices: false` (in this or any integrations specified before this) for the device_tracker component you need to manually change `track:` to true for each device in `known_devices.yaml`
35-
(see component settings for [device_tracker](https://www.home-assistant.io/components/device_tracker/#configuring-a-device_tracker-platform))
36-
```yaml
37-
hostname1:
38-
icon:
39-
mac:
40-
name: hostname1
41-
picture:
42-
track: true
43-
```
47+
This will create an entity `device_tracker.<name>`
4448

49+
Repeat the steps for additional entities.
50+
51+
#### Options
52+
53+
You can change the consider home timeout per tracked device in the UI.
54+
Default is 24 seconds.
55+
![image](https://github.com/user-attachments/assets/caf31775-333d-448c-b8f2-660534d856d7)
56+
57+
#### Reconfigure
58+
59+
You can change the IP address of the tracked device in the UI.
60+
![image](https://github.com/user-attachments/assets/4fc98224-eee6-4451-aaf1-b16c858014d2)
61+
62+
## Troubleshooting | FAQ
63+
64+
<details>
65+
<summary>Private Wi-Fi address</summary>
66+
The device private MAC address will remain the same for each network, as long as the network isn't recreated or rotating (iOS 18+) MAC is used.
67+
68+
In other words, if a tracked device no longer can be found the user have propably recreated the connection to your Wi-Fi forcing a new random MAC address to be used.
69+
<br />
70+
Note that if your WiFi has different SSID for the 2.4 and 5 ghz bands, and the phone has private network enabled, two different MAC will be presented to the DHCP.
71+
Most likely that will require the integration to track two IP's per user/Person.
72+
<br />
73+
So, for best result only have/connect to one SSID, turn off private network and assign static IP.
74+
</details>
75+
<details>
76+
<summary>False or flaky not_home status</summary>
77+
Especially when the network has multiple Access Points, tracked devices sometimes are marked as not_home when actually connected to the network.
78+
Increasing the consider home timeout might help this.
79+
Most likely it's a network issue though, try placing your AP's at different locations.
80+
81+
Devices might auto-update during night, they of course then will be not_home for awhile.
82+
</details>
83+
84+
## Attribution
85+
86+
Original idea from [return01](https://community.home-assistant.io/u/return01)
87+
88+
## Disclaimer
89+
90+
Author is in no way affiliated with Apple Inc.
91+
Author does not guarantee functionality of this integration and is not responsible for any damage.
92+
All product names, trademarks and registered trademarks in this repository, are property of their respective owners.
93+
94+
<a href="https://www.buymeacoffee.com/MudApe" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
+115-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,115 @@
1-
""" iPhone Detect """
1+
"""iPhone Device Tracker"""
2+
3+
from __future__ import annotations
4+
5+
import logging
6+
from datetime import timedelta
7+
from typing import TYPE_CHECKING
8+
9+
from homeassistant.components.device_tracker import CONF_CONSIDER_HOME
10+
from homeassistant.config_entries import ConfigEntry
11+
from homeassistant.const import CONF_DEVICES, CONF_IP_ADDRESS, Platform
12+
from homeassistant.exceptions import PlatformNotReady
13+
from homeassistant.helpers import config_validation as cv
14+
from homeassistant.helpers.event import async_track_time_interval
15+
16+
from .const import DOMAIN, PROBE_INTERVAL
17+
from .coordinator import IphoneDetectUpdateCoordinator
18+
from .scanner import (
19+
DeviceData,
20+
Scanner,
21+
ScannerException,
22+
async_get_scanner,
23+
async_update_devices,
24+
)
25+
26+
if TYPE_CHECKING:
27+
from homeassistant.core import HomeAssistant
28+
from homeassistant.helpers.typing import ConfigType
29+
30+
_LOGGER = logging.getLogger(__name__)
31+
32+
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
33+
PLATFORMS = [Platform.DEVICE_TRACKER]
34+
TRACKER_INTERVAL = timedelta(seconds=PROBE_INTERVAL)
35+
36+
37+
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
38+
"""Set up the integration."""
39+
devices: dict[str, DeviceData]
40+
devices = hass.data.setdefault(DOMAIN, {})[CONF_DEVICES] = {}
41+
42+
try:
43+
scanner: Scanner = await async_get_scanner(hass)
44+
except ScannerException as error:
45+
raise PlatformNotReady(error)
46+
47+
async def _update_devices(*_) -> None:
48+
"""Update reachability for all tracked devices."""
49+
await async_update_devices(hass, scanner, devices)
50+
51+
async_track_time_interval(hass, _update_devices, TRACKER_INTERVAL, cancel_on_shutdown=True)
52+
53+
return True
54+
55+
56+
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
57+
"""Set up config entries."""
58+
_LOGGER.debug("Adding '%s' to tracked devices", entry.options[CONF_IP_ADDRESS])
59+
60+
device = hass.data[DOMAIN][CONF_DEVICES][entry.entry_id] = DeviceData(
61+
ip_address=entry.options[CONF_IP_ADDRESS],
62+
consider_home=timedelta(seconds=entry.options[CONF_CONSIDER_HOME]),
63+
title=entry.title,
64+
)
65+
66+
coordinator = IphoneDetectUpdateCoordinator(hass, device)
67+
await coordinator.async_config_entry_first_refresh()
68+
hass.data[DOMAIN].setdefault("coordinators", {})[entry.entry_id] = coordinator
69+
70+
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
71+
entry.async_on_unload(entry.add_update_listener(async_reload_entry))
72+
73+
return True
74+
75+
76+
async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
77+
"""Update options."""
78+
_LOGGER.debug("Reloading entity '%s' with '%s'", entry.title, entry.options)
79+
await hass.config_entries.async_reload(entry.entry_id)
80+
81+
82+
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
83+
"""Handle removal of an entry."""
84+
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
85+
if unload_ok:
86+
_LOGGER.debug("Removing '%s' from tracked devices", entry.options[CONF_IP_ADDRESS])
87+
hass.data[DOMAIN][CONF_DEVICES].pop(entry.entry_id)
88+
89+
return unload_ok
90+
91+
92+
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
93+
"""Migrate old config entry to a new format."""
94+
95+
if config_entry.version == 1:
96+
_LOGGER.debug("Migrating from version 1")
97+
# Move IP address from data to options
98+
new_options = config_entry.options.copy()
99+
if config_entry.data.get(CONF_IP_ADDRESS):
100+
new_options[CONF_IP_ADDRESS] = config_entry.data[CONF_IP_ADDRESS]
101+
102+
# Set unique_id
103+
new_unique_id = config_entry.unique_id
104+
if not new_unique_id:
105+
new_unique_id = f"{DOMAIN}_{config_entry.title}".lower()
106+
107+
hass.config_entries.async_update_entry(
108+
config_entry,
109+
unique_id=new_unique_id,
110+
data={},
111+
options=new_options,
112+
version=2,
113+
)
114+
115+
return True

0 commit comments

Comments
 (0)