Hello @ all,
sorry windows user, i have no access to a windows machine running home-assistant. So this will not work
for you.
I found a little script in a german forum for openhab: http://openhabforum.de/viewtopic.php?f=16&t=137
Based on this script an the original ping device tracker from home-assistant i wrote a little script.
The idea behind this is to send a message to the iPhone on udp port 5353. The iPhone responds in
some way so that an entry in the arp cache is made even when it is in deep sleep. This entry is detectet
by the script.
Howto setup:
Create a file in your configuration directory:
<config_dir>/custom_components/device_tracker/iphonedetect.py
and save this Code in this file:
"""
Tracks iPhones by sending a udp message to port 5353.
An entry in the arp cache is then made and checked.
device_tracker:
- platform: iphonedetect
hosts:
host_one: 192.168.2.12
host_two: 192.168.2.25
"""
import logging
import subprocess
import sys
from datetime import timedelta
import socket
import voluptuous as vol
from homeassistant.components.device_tracker import (
PLATFORM_SCHEMA, DEFAULT_SCAN_INTERVAL, SOURCE_TYPE_ROUTER)
from homeassistant.helpers.event import track_point_in_utc_time
from homeassistant import util
from homeassistant import const
import homeassistant.helpers.config_validation as cv
DEPENDENCIES = []
_LOGGER = logging.getLogger(__name__)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(const.CONF_HOSTS): {cv.string: cv.string},
})
class Host:
"""Host object with arp detection."""
def __init__(self, ip_address, dev_id, hass, config):
"""Initialize the Host."""
self.hass = hass
self.ip_address = ip_address
self.dev_id = dev_id
def detectiphone(self):
"""Send udp message to port 5353
and return True if an arp chache entry is made success.
"""
aSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
aSocket.settimeout(1)
addr = (self.ip_address, 5353)
message = b'Steve Jobs'
aSocket.sendto(message, addr)
try:
output = subprocess.check_output('arp -na', shell=True)
output = output.decode('utf-8').split('\n')
for entry in output:
mac = entry.split(' ')
if mac[0] != '':
rcvd_ip = mac[1]
rcvd_ip = rcvd_ip[:-1] # remove last Klammer
rcvd_ip = rcvd_ip[1:] # remove first Klammer
mac = mac[3]
mac = mac.split(':')
if rcvd_ip == self.ip_address:
if len(mac) == 6:
return True
except subprocess.CalledProcessError:
return False
return False
def update(self, see):
"""Update device state."""
if self.detectiphone():
see(dev_id=self.dev_id, source_type=SOURCE_TYPE_ROUTER)
return True
_LOGGER.debug("iPhone on ip=%s not present", self.ip_address)
def setup_scanner(hass, config, see, discovery_info=None):
"""Setup the Host objects and return the update function."""
hosts = [Host(ip, dev_id, hass, config) for (dev_id, ip) in
config[const.CONF_HOSTS].items()]
interval = timedelta(seconds=len(hosts)) + DEFAULT_SCAN_INTERVAL
_LOGGER.info("Started iphonedetect with interval=%s on hosts: %s",
interval, ",".join([host.ip_address for host in hosts]))
def update(now):
"""Update all the hosts on every interval time."""
for host in hosts:
host.update(see)
track_point_in_utc_time(hass, update, now + interval)
return True
return update(util.dt.utcnow())
Add the following to your configuration.yaml:
device_tracker:
- platform: iphonedetect
hosts:
host_one: your ip adress
host_two: 192.168.2.25 # <- for example
Only ip adresses will work, no hostnames! So you have to assign a static ip adress to your iPhone,
probably with an entry in your router. Leave the default scan interval at the default value or make it
shorter. The arp cache is cleared by my system every 60 seconds. So udp messages must send in
this timeslot or the iPhone is detected as away.
I hope you have fun. Feel free to ask your questions and provide your feedback.