Weasley Location Clock

This isn’t a 100% Home Assistant project, but I did use Home Assistant as an integral part of this project. I built a Weasley Clock like the one in Harry Potter that uses hands on a dial to display the location of my family members.

demo3 (1)

I use the Life360 integration for location and speed data, the unifi integration to track which wifi AP people are attached to, and the HACS Zwift integration to know when people were using Zwift (VR indoor bicycle riding). From that data I determine each person’s location/state and update a sensor. When someone’s Weasley Clock state changes I publish a MQTT event that the physical clock controlled by a raspberry pi and my own custom python code. The Pi then controls some servos that move the hands to the corresponding sector on the clock. When the Pi comes online (boots or the server restarts) it sends an update request to Home Assistant that then publishes all the family member states.

Here’s an example of how one person’s Weasley Clock state is computed:

  #
  # Sensor produces Weasley Clock states
  #
  #  home, garden, school, work, intransit, mortalperil, lost, error
  # 
  #  home/school/work/lost/intransit/lost is determined by life360 location
  #  garden is based on which of the home WiFi access points is being used
  #  mortalperil is triggered by life360 detecting speeds over 75
  #  error is triggered if the life360 device_tracker returns None type
  #  
  - platform: template
    sensors:
      weasley_clock_user1:
        entity_id:
          - sensor.home_ap_user1
          - device_tracker.life360_user1
        icon_template: >-
          {% set icon = 'mdi:clock-outline' %}
          {% set s = 'sensor.weasley_clock_user1' %}
          {% if states(s) == 'school' %}
          {%   set icon = 'mdi:school' %}
          {% elif states(s) == 'home' %}
          {%   set icon = 'mdi:home' %}
          {% elif states(s) == 'barn' %}
          {%   set icon = 'mdi:barn' %}
          {% elif states(s) == 'lost' %}
          {%   set icon = 'mdi:map-marker-question' %}
          {% elif states(s) == 'intransit' %}
          {%   set icon = 'mdi:train-car' %}
          {% elif states(s) == 'work' %}
          {%   set icon = 'mdi:briefcase' %}
          {% elif states(s) == 'garden' %}
          {%   set icon = 'mdi:flower' %}
          {% elif states(s) == 'mortalperil' %}
          {%   set icon = 'mdi:speedometer' %}
          {% elif states(s) == 'quidditch' %}
          {%   set icon = 'mdi:broom' %}
          {% endif %}
          {{ icon }}
        value_template: >-
          {%- set home_ap_sensor = 'sensor.home_ap_user1' %}
          {%- set tracker = 'device_tracker.life360_user1' %}
          {%- set ns = namespace(wc='lost') %}
          {%- set state = states( tracker ) %}
          {%- if not state %}
          {%-   set ns.wc = 'error' %}
          {%- elif state == 'home' %}
          {%-   set home_ap = states( home_ap_sensor ) %}
          {%-   if home_ap == 'GardenAP' %}
          {%-       set ns.wc = 'garden' -%}
          {%-   else %}
          {%-       set ns.wc = 'home' -%}
          {%-   endif %}
          {%- elif state == 'moving' or state == 'driving' %}
          {%-   set ns.wc = 'intransit'  %}
          {%-   set speed  = state_attr( tracker, 'speed') %}
          {%-   if speed and speed > 75 %}
          {%-     set ns.wc = 'mortalperil' %}
          {%-   endif %}
          {%- else %}
          {%-   set place = state.lower() %}
          {%-   if place == 'your local high school' or place == 'your local middle school'%}
          {%-     set ns.wc = 'school' %}
          {%-   elif place == 'work' %}
          {%-     set ns.wc = 'work' %}
          {%-   else %}
          {%-     set ns.wc = 'lost' %}
          {%-   endif %}
          {%- endif -%}
          {{ ns.wc }}
2 Likes

Crazy cool!

1 Like

This is really awesome !
I’ll will keep it in my “Todo” project list for when I find time !

1 Like

Just made a simple version Weasley clock for my family, all I did was use a picture element card with a bunch of conditional images in the correct locations based of HA locations. Kids are pretty impressed, so winning there :wink:

1 Like

Ooh, any more info on that setup?

So picture element card with the custom clock in the middle.
(clock2.png image is just the background color)

type: picture-elements
image: /local/clock2.png
elements:
  - type: custom:clock-card
    style:
      top: 50%
      left: 50%
    time_zone: Australia/Brisbane
    size: 120
    font_size: 100
    disable_seconds: true
    theme:
      background: black
      hands: orange
      numbers: white
      border: grey
    view_layout:
      position: sidebar

Then A LOT of conditional pics

  - type: conditional
    conditions:
      - entity: person.kate
        state: home
    elements:
      - type: image
        entity: person.kate
        image: /local/kate_home.png
        style:
          top: 22%
          left: 81%
          width: 9%
  - type: conditional
    conditions:
      - entity: person.michael
        state: home
    elements:
      - type: image
        entity: person.michael
        image: /local/michael.png
        style:
          top: 22%
          left: 72%
          width: 8%
  - type: conditional
    conditions:
      - entity: person.kate
        state: School
    elements:
      - type: image
        entity: person.kate
        image: /local/kate.png
        style:
          top: 7%
          left: 55%
          width: 10%
  - type: conditional
    conditions:
      - entity: person.michael
        state: School
    elements:
      - type: image
        entity: person.michael
        image: /local/michael.png
        style:
          top: 18%
          left: 63%
          width: 8%

The way I did it I have one conditional pic for each combination of person and location state. You can call multiple locations the same name and it still works, so 3 kids at 3 different schools, they still all show up in the weasly clock school area.
The hardest part was to tweak the style percentages in the image card to place each persons thumbnail in the right place without overlapping someone else.

1 Like

Either make a very large map zone called Travelling, or you could do the same with a zone = not_home.

Follow up with a tts script:

    Beds empty. No note. Car gone. You could have died. You could have been seen,
    {% if states('person.kate') == 'not_home' -%} Kate is travelling,
    and {% elif states('person.kate') != 'home' -%} Kate is at {{
    states('person.kate') }}, {%- endif %}  {% if states('person.michael')
    == 'not_home' -%} Michael is travelling, {% elif
    states('person.michael') != 'home' -%} Michael is at {{
    states('person.michael') }}, {%- endif %}  {% if
    states('person.william') == 'not_home' -%} William is travelling, {%
    elif states('person.william') != 'home' -%} William is at {{
    states('person.william') }}, {%- endif %}  {% if states('person.ellena')
    == 'not_home' -%} Ellena is travelling, {% elif
    states('person.ellena') != 'home' -%} Ellena is at {{
    states('person.ellena') }}, {%- endif %}  {% if states('person.andrew')
    == 'not_home' -%} Andrew is travelling, {% elif
    states('person.andrew') != 'home' -%} Andrew is at {{
    states('person.andrew') }}, {%- endif %}  but your here now,
    time for a spot of 
    {% if now().hour * 60 + now().minute < 10 * 60 %}
    breakfast.
    {% elif (now().hour * 60 + now().minute > 10 * 60) 
    and (now().hour * 60 + now().minute < 17 * 60) %}
    lunch
    {% elif now().hour * 60 + now().minute > 17 * 60 %}
    dinner.
    {% endif %}
1 Like

New version is a little bit easier to implement with auto entities and mushroom person card

Using a 3 column grid card, each grid can be something like:

type: custom:auto-entities
card:
  square: false
  columns: 2
  type: grid
  title: Home
card_param: cards
filter:
  exclude:
    - entity_id: person.mqttlink
  include:
    - domain: person
      state: home
      options:
        type: custom:mushroom-person-card
        icon_type: entity-picture
        layout: vertical
        primary_info: none
        secondary_info: none

or

type: custom:auto-entities
card:
  square: false
  columns: 2
  type: grid
  title: School
card_param: cards
filter:
  exclude:
    - entity_id: person.mqttlink
  include:
    - domain: person
      state: School
      options:
        type: custom:mushroom-person-card
        icon_type: entity-picture
        layout: vertical
        primary_info: none
        secondary_info: none
    - domain: person
      state: University
      options:
        type: custom:mushroom-person-card
        icon_type: entity-picture
        layout: vertical
        primary_info: none
        secondary_info: none

a digital version of the clock

type: custom:digital-clock
view_layout:
  position: main