Initial work on a presence tracker. Inspired by @helto4real

This commit is contained in:
Thomas Lovén 2019-08-05 13:39:03 +02:00
parent 3e61dcda71
commit 7305d719ee
4 changed files with 206 additions and 4 deletions

View File

@ -0,0 +1,79 @@
from entities import Entities
from timers import Timers
class Presence(Timers, Entities):
HOME = 'home'
AWAY = 'not_home'
ARRIVED = 'just_arrived'
LEFT = 'just_left'
TIMEOUT = 300
def initialize(self):
super().initialize()
attr = self.args.get('attributes', {})
self.register_entity('tracker', self.args['name'], managed=True, default="not_home", attributes=self.args.get('attributes',{}))
self.tracker = self.e['tracker']
if(self.tracker.state in [self.ARRIVED, self.LEFT]):
self.tracker.state = self.AWAY
self.devices = []
for i,d in enumerate(self.args['devices']):
name = f"device{i}"
self.register_entity(name, d);
self.e[name].listen(self.update, {"name": name})
self.devices.append(self.e[name])
self.update()
def update(self, old=None, new=None, kwarg=None):
if not old or isinstance(old, str):
timeout = False
elif old is None:
timeout = False
else:
timeout = old.get('trigger', False)
new_state = self.is_home()
old_state = self.tracker.state
if new_state:
if old_state == self.AWAY:
self.run_in('timeout', self.update, self.TIMEOUT, trigger = "timeout")
state = self.ARRIVED
elif old_state == self.LEFT:
self.cancel_timer('timeout')
state = self.HOME
elif old_state == self.ARRIVED and timeout:
state = self.HOME
else:
state = old_state
else:
if old_state == self.HOME:
self.run_in('timeout', self.update, self.TIMEOUT, trigger = "timeout")
state = self.LEFT
elif old_state == self.ARRIVED:
self.cancel_timer('timeout')
state = self.AWAY
elif old_state == self.LEFT and timeout:
state = self.AWAY
else:
state = old_state
self.tracker.state = state
self.tracker.push()
def is_home(self):
for d in self.devices:
if d.domain == 'device_tracker':
if d.attr['source_type'] in ['router']:
if d.state == 'home':
return True
if d.domain == 'sensor':
if d.state != 'unknown' and int(d.state) > 0:
return True
return False

View File

@ -0,0 +1,37 @@
presence_thomas:
module: presence
class: Presence
global_dependencies:
- entities
- timers
dependencies:
- entity_manager
name: device_tracker.thomas_presence
attributes: {}
devices:
- device_tracker.thomas_iphone_beta
- device_tracker.thomas_iphone_2
- sensor.thomas_iphone_bt
- sensor.thomas_iphone_bt2
presence_anneli:
module: presence
class: Presence
global_depencencies:
- entities
- timers
dependencies:
- entity_manager
name: device_tracker.anneli_presence
attributes: {}
devices:
- device_tracker.anneli_lovn
- device_tracker.anneli_loven
- sensor.anneli_iphone_bt
- sensor.anneli_iphone_bt2
# - sensor.anneli_klocka_bt
# - sensor.anneli_klocka_bt2

View File

@ -21,6 +21,43 @@ popup_cards:
- type: history-graph
entities: *door_entities
device_tracker.thomas_presence:
title: Thomas
large: true
card:
type: vertical-stack
cards:
- type: entities
entities: &thomas_entities
- device_tracker.thomas_iphone_beta
- device_tracker.thomas_iphone_2
- sensor.thomas_iphone_bt
- sensor.thomas_iphone_bt2
- type: history-graph
entities:
- device_tracker.thomas_presence
- type: history-graph
entities: *thomas_entities
device_tracker.anneli_presence:
title: Anneli
large: true
card:
type: vertical-stack
cards:
- type: entities
entities: &anneli_entities
- device_tracker.anneli_lovn
- device_tracker.anneli_loven
- sensor.anneli_iphone_bt
- sensor.anneli_iphone_bt2
- sensor.anneli_klocka_bt
- sensor.anneli_klocka_bt2
- type: history-graph
entities:
- device_tracker.anneli_presence
- type: history-graph
entities: *anneli_entities
cards:
- type: custom:layout-card
layout: vertical
@ -56,10 +93,22 @@ cards:
- break
- type: horizontal-stack
cards:
- type: picture
image: /local/images/thomas_clr.jpg
- type: picture
image: /local/images/anneli_clr.png
- type: picture-entity
entity: device_tracker.thomas_presence
image: /local/images/thomas_bw.jpg
show_name: false
show_state: false
state_image:
"home": /local/images/thomas_clr.jpg
"just_arrived": /local/images/thomas_clr.jpg
- type: picture-entity
entity: device_tracker.anneli_presence
image: /local/images/anneli_bw.png
show_name: false
show_state: false
state_image:
"home": /local/images/anneli_clr.png
"just_arrived": /local/images/anneli_clr.png
- type: horizontal-stack
cards:
- type: entity-button

37
packages/presence.yaml Normal file
View File

@ -0,0 +1,37 @@
homeassistant:
customize:
package.node_anchors:
common: &common
package: 'security'
binary_sensor.home_occupied:
<<: *common
automation.adm_rescan_monitor_on_restart:
<<: *common
binary_sensor:
- platform: template
sensors:
home_occupied:
friendly_name: Anyone home
value_template: >-
{{ (is_state('device_tracker.thomas_presence', 'home') or
is_state('device_tracker.anneli_presence', 'home')) }}
device_tracker:
- platform: unifi
host: unifi
username: !secret unifi_username
password: !secret unifi_password
verify_ssl: false
ssid_filter: !secret unifi_ssids
automation:
- alias: ADM - Rescan monitor on restart
trigger:
platform: homeassistant
event: start
action:
- service: mqtt.publish
data:
topic: "monitor/scan/restart"