-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #88 from jsittner/locate-a-person
Locate a person - Blueprint and View
- Loading branch information
Showing
4 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
171 changes: 171 additions & 0 deletions
171
View Assist dashboard and views/views/locate/locate.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
type: custom:button-card | ||
variables: | ||
locatecardversion: 1.0.0 | ||
template: | ||
- variable_template | ||
- body_template | ||
styles: | ||
grid: | ||
- grid-template-areas: | | ||
"title status" | ||
"map map" | ||
"assist assist" | ||
- grid-template-columns: 1.5fr 1.5fr | ||
- grid-template-rows: min-content max-content | ||
card: | ||
- background: black | ||
- background-size: cover | ||
custom_fields: | ||
map: | ||
- align-self: center | ||
- justify-self: center | ||
- width: 100% | ||
- height: 100% | ||
- position: absolute | ||
- justify-content: center | ||
- z-index: 1 | ||
location: | ||
- align-self: center | ||
- justify-self: center | ||
- position: absolute | ||
- z-index: 2 | ||
- top: 70vh | ||
- width: 90% | ||
hold_card: | ||
- align-self: center | ||
- justify-self: center | ||
- position: absolute | ||
- width: 80vw | ||
- z-index: 3 | ||
custom_fields: | ||
title: >- | ||
[[[ return new Date().toLocaleTimeString([], { hour: "numeric", | ||
minute: "2-digit" }).toLowerCase(); ]]] | ||
map: | ||
card: | ||
type: map | ||
entities: | ||
- entity: >- | ||
[[[ try {return | ||
hass.states[variables.var_assistsat_entity].attributes.locate_data['person']} | ||
catch { return ""}]]] | ||
theme_mode: |- | ||
[[[ try { | ||
var var_map_mode = hass.states[variables.var_assistsat_entity].attributes.locate_data.map_mode; | ||
return `${var_map_mode}`} | ||
catch { return "dark"}]]] | ||
default_zoom: 15 | ||
aspect_ratio: 1.5/1 | ||
auto_fit: true | ||
fit_zones: false | ||
card_mod: | ||
style: | ||
ha-map $ ha-entity-marker $: | | ||
.marker { | ||
color: white !important; | ||
background-color: #03a9f4 !important; | ||
opacity: 80% !important; | ||
font-size: 3vw !important; | ||
font-weight: bold !important; | ||
height: 5vw !important; | ||
width: 5vw !important; | ||
} | ||
ha-map$: | | ||
.leaflet-control-attribution { | ||
visibility: hidden; | ||
} | ||
.leaflet-control-zoom { | ||
right: -11px; | ||
top: 24vh; | ||
transform: scale(1.8) | ||
} | ||
ha-icon-button$: | | ||
mwc-icon-button[title="Reset focus"]{ | ||
--mdc-icon-size: 65px; | ||
right: -10px !important; | ||
position: relative !important; | ||
display: flex !important | ||
} | ||
location: | ||
card: | ||
type: custom:button-card | ||
custom_fields: | ||
location_text: |- | ||
[[[ try { | ||
var var_location_text = hass.states[variables.var_assistsat_entity].attributes.locate_data.location_text; | ||
return `${var_location_text}`} | ||
catch { return ""}]]] | ||
updated: |- | ||
[[[ try { | ||
var var_tracker = hass.states[variables.var_assistsat_entity].attributes.locate_data.person; | ||
var var_last_changed = new Date(hass.states[var_tracker].last_changed); | ||
const current_date = new Date(); | ||
const diff = current_date - var_last_changed; | ||
const minutes = Math.floor(diff / (1000 * 60)); | ||
const hours = Math.floor(diff / (1000 * 60 * 60)); | ||
const days = Math.floor(diff / (1000 * 60 * 60 * 24)); | ||
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }); | ||
let last_changed; | ||
if (minutes < 1) { | ||
last_changed = "now"; | ||
} else if (minutes < 60) { | ||
last_changed = rtf.format(-minutes, 'minute'); // e.g., "5 minutes ago" | ||
} else if (hours < 24) { | ||
last_changed = rtf.format(-hours, 'hour'); // e.g., "2 hours ago" | ||
} else { | ||
last_changed = rtf.format(-days, 'day'); // e.g., "3 days ago" | ||
} | ||
return `${"last changed "+last_changed}`} | ||
catch { return ""}]]] | ||
show_icon: false | ||
show_name: false | ||
styles: | ||
grid: | ||
- grid-template-areas: | | ||
"location_text" | ||
"updated" | ||
- grid-template-columns: 1fr | ||
- grid-template-rows: 1fr min-content min-content | ||
card: | ||
- justify-content: center | ||
- align-items: center | ||
- padding: 2% | ||
- border-radius: 1vw | ||
- background-color: grey | ||
- border: none | ||
- filter: opacity(75%) | ||
custom_fields: | ||
location_text: | ||
- font-size: 6vh | ||
- color: black | ||
- text-wrap: wrap | ||
- font-weight: bold | ||
- text-align: center | ||
updated: | ||
- font-size: 4vh | ||
- color: black | ||
hold_card: | ||
card: | ||
type: custom:button-card | ||
show_icon: false | ||
show_name: false | ||
tap_action: | ||
action: call-service | ||
service: python_script.set_state | ||
service_data: | ||
entity_id: '[[[ return variables.var_assistsat_entity ]]]' | ||
mode: hold | ||
double_tap_action: | ||
action: call-service | ||
service: python_script.set_state | ||
service_data: | ||
entity_id: '[[[ return variables.var_assistsat_entity ]]]' | ||
mode: normal | ||
styles: | ||
card: | ||
- top: 10vh | ||
- border-radius: 1vw | ||
- background-color: transparent | ||
- height: 90vh | ||
- width: 100vw | ||
- border: none |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Locate a Person | ||
|
||
<a href="https://github.com/dinki/View-Assist/blob/main/locate-a-person/View_Assist_custom_sentences/Locate_a_Person/locate_example.png"><img src="https://github.com/dinki/View-Assist/blob/main/locate-a-person/View_Assist_custom_sentences/Locate_a_Person/locate_example.png" width="60%"></a> | ||
|
||
[![Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.](https://my.home-assistant.io/badges/blueprint_import.svg)](https://my.home-assistant.io/redirect/blueprint_import/?blueprint_url=https://github.com/dinki/View-Assist/blob/main/View_Assist_custom_sentences/Locate_a_Person/blueprint-locateaperson.yaml) | ||
|
||
This blueprint enables you to display the location of a home assistant user on a map. The map also shows the geocoded address with most recent location update in relative time. If you choose to hold the view, it will provide real-time updates as the tracking device sends new location data. | ||
|
||
Requires [locate](https://github.com/dinki/View-Assist/blob/main/locate-a-person/View%20Assist%20dashboard%20and%20views/views/locate/) view | ||
|
||
Optional requirements for the geocoded tracker sensor in the companion app: | ||
* The **Background location** needs to be enabled. It can be found in the home assistant mobile app -> settings -> companion app -> Location sensors. | ||
* The **Geolocation sensor** needs to be enabled along with it's setting to **Update sensor with location sensors**. It can be found in the home assistant mobile app -> settings -> companion app -> manage sensors. | ||
* The **Background access** also needs to be enabled. It can be found in the home assistant mobile app -> settings -> companion app -> other settings. | ||
|
||
Notes: | ||
* The names should be defined phonetically, as the voice assistant interprets them, followed by the person's name as listed in the People menu under settings. To assist in determining the voice assistant's spelling of the name, a visual display of the name will be shown if it is incorrect. | ||
* The maps pinch-to-zoom and drag controls have been replaced with a tap to hold. The reset focus, along with the plus and minus buttons, function as expected. |
126 changes: 126 additions & 0 deletions
126
View_Assist_custom_sentences/Locate_a_Person/blueprint-locateaperson.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# View Assist - Locate a Person (v 1.0.0) | ||
# Written by - jsittner | ||
blueprint: | ||
name: View Assist - Locate a Person | ||
description: Ask Assist to locate a person (View Assist locateaperson v 1.0.0) | ||
domain: automation | ||
input: | ||
command_prompt: | ||
name: Command Text | ||
description: The phrase you want to use to trigger the automation | ||
default: "(locate|map) [my] {person}" | ||
view_locate: | ||
name: Locate View | ||
description: The View Assist dashboard view used for the locate view | ||
default: /dashboard-viewassist/locate | ||
view_info: | ||
name: Info View | ||
description: The View Assist dashboard view used for the info display | ||
default: /dashboard-viewassist/info | ||
defined_names: | ||
name: Defined Names | ||
description: This is the phonetic name followed by the Person's name as configured in the Home Assistant settings | ||
default: '{"john":"jon","simon":"simon"}' | ||
map_mode: | ||
name: Map Mode Theme | ||
description: This will change the map mode theme | ||
default: dark | ||
selector: | ||
select: | ||
mode: dropdown | ||
options: | ||
- dark | ||
- light | ||
group_entity: | ||
name: Group Entity | ||
description: >- | ||
The group that holds the list of View Assist satellites(example | ||
group.viewassist_satellites) | ||
selector: | ||
entity: | ||
filter: | ||
- domain: | ||
- group | ||
multiple: false | ||
default: group.viewassist_satellites | ||
alias: View Assist - Locate a Person | ||
description: "Ask Assist to locate a person" | ||
variables: | ||
view_locate: !input view_locate | ||
view_info: !input view_info | ||
map_mode: !input map_mode | ||
input_defined_names: !input defined_names | ||
persons_name: "{{ input_defined_names | from_json}}" | ||
group_entity: !input group_entity | ||
target_satellite_device: |- | ||
{% for sat in expand('group.viewassist_satellites') %} | ||
{% if (device_id(sat.attributes.mic_device) == trigger.device_id) or (device_id(sat.attributes.display_device) == trigger.device_id) %} | ||
{{ sat.entity_id }} | ||
{% endif %} | ||
{% endfor %} | ||
target_display_device: "{{ device_id(state_attr(target_satellite_device, 'display_device')) }}" | ||
target_mediaplayer_device: "{{ state_attr(target_satellite_device, 'mediaplayer_device') }}" | ||
target_satellite_device_type: "{{ state_attr(target_satellite_device, 'type') }}" | ||
trigger: | ||
- platform: conversation | ||
command: | ||
- !input command_prompt | ||
condition: [] | ||
actions: | ||
- if: | ||
- condition: template | ||
value_template: "{% if trigger.slots.person in persons_name %}true{%endif%}" | ||
then: | ||
- variables: | ||
person_source: "{{ 'person.'+persons_name[trigger.slots.person] }}" | ||
tracker_source: >- | ||
{{ state_attr('person.'+persons_name[trigger.slots.person], | ||
'source') }} | ||
geocoded_source: >- | ||
{% set geocoded = 'sensor.' + tracker_source.split('.', 1)[1] + | ||
'_geocoded_location'%} {{ geocoded }} | ||
location_source: |- | ||
{% if states(person_source) != 'not_home' %} | ||
{{ states(person_source)|capitalize }} | ||
{% elif not states(geocoded_source) in ['unknown'] %} | ||
{{ states(geocoded_source) }} | ||
{% else %} | ||
{{ "Unknown Location" }} | ||
{% endif %} | ||
- set_conversation_response: |- | ||
{% if states(person_source) == 'not_home' %} | ||
{{ persons_name[trigger.slots.person] }} is away. | ||
{% else %} | ||
{{ persons_name[trigger.slots.person] }} is at {{ states(person_source) }} | ||
{% endif %} | ||
- action: python_script.set_state | ||
data: | ||
entity_id: "{{ target_satellite_device }}" | ||
locate_data: >- | ||
{{ {'person': person_source, 'tracker': tracker_source, 'geocoded': | ||
geocoded_source, 'location_text': location_source, 'map_mode': map_mode } }} | ||
- if: | ||
- condition: template | ||
value_template: >- | ||
{% if target_satellite_device_type != 'audio_only' %}true{% else | ||
%}false{% endif %} | ||
then: | ||
- data: | ||
path: "{{ view_locate }}" | ||
target: | ||
device_id: "{{ target_display_device }}" | ||
action: browser_mod.navigate | ||
else: | ||
- action: python_script.set_state | ||
data: | ||
entity_id: "{{ target_satellite_device }}" | ||
title: "" | ||
message: "{{ trigger.slots.person |capitalize}} hasn't been defined" | ||
message_font_size: 6vw | ||
- set_conversation_response: "{{ trigger.slots.person }} hasn't been defined" | ||
- data: | ||
path: "{{ view_info }}" | ||
target: | ||
device_id: "{{ target_display_device }}" | ||
action: browser_mod.navigate | ||
mode: single |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.