Quantcast
Channel: Configuration - Home Assistant Community
Viewing all articles
Browse latest Browse all 106367

Pool control with a picture entities card and aqualinkd

$
0
0

I’ve been using the excellent aqualinkd project to bridge my Jandy Aqualink pool control system to Home Assistant via MQTT and I would like to share the dashboard UI that I created for controlling everything about the pool. There is A LOT happening in this UI, so I will break this down into a few sections.

This post will focus on the Lovelace UI. If you are interested in my custom entity configs for aqualinkd, the author of aqualinkd has kindly let me provide my entity configs in his repository as examples. You can find them here.

Note: some of the elements are made from the button-card, and I have some related templates defined that are explained here.

Here is an example of what is displayed most of the time while the pump is running and nothing else is going on. There are several hidden items that appear under certain conditions. I will explain each one separately in the following sections.

image

more screenshots

image
image
image
image
image
image
image
image
image


The Picture Elements Card

This is the main card for the whole thing. All of the other examples are within this card. The main config for this card is all about showing the appropriate background image based on the state of the pool devices. I have a template sensor I defined that gives me a discrete state for each combination of things that I want to show. I’m using state_filter for the off condition to make the background black & white to make it obvious the system is off.

yaml
type: picture-elements
entity: sensor.aqualink_run_mode
image: /local/pictures/pool.jpg
state_filter:
  'off': blur(2px) grayscale(100%)
state_image:
  service: /local/pictures/pool-equipment.jpg
  spa: /local/pictures/spa.jpg
  spa-blowing: /local/pictures/spa.jpg
  spa-heated: /local/pictures/spa.jpg
  spa-heating: /local/pictures/spa.jpg
  timeout: /local/pictures/pool-equipment.jpg
elements:
  #...elements from other sections go here...

Freeze Protection

image
image
image

There are 3 elements to freeze protection:

  1. a switch to enable/disable
  2. a sensor indicating if it’s active
  3. a climate entity for the setpoint

There are 4 elements to this status display, 3 of them conditional. I’m currently using element types that are native to the picture elements card, but now that I have discovered the button-card I think I can dramatically simplify this when I have a chance.

yaml
  - entity: switch.freeze_protection
    prefix: 'freeze protect '
    style:
      background-color: 'rgba(0,0,0,0.4)'
      color: white
      height: 34px
      left: 0
      top: '-3px'
      padding-left: 30px
      transform: none
      width: 100%
    tap_action:
      action: toggle
    type: state-label

  - type: conditional
    conditions:
      - entity: binary_sensor.freeze_protecting
        state: 'off'
    elements:
      - entity: switch.freeze_protection
        icon: 'mdi:snowflake'
        style:
          color: white
          left: 0
          top: '-5px'
          transform: none
          z-index: 1
        tap_action:
          action: toggle
        type: state-icon

  - type: conditional
    conditions:
      - entity: switch.freeze_protection
        state: 'on'
    elements:
      - attribute: temperature
        entity: climate.freeze_protect
        prefix: '@ '
        style:
          color: white
          left: 150px
          top: '-3px'
          transform: none
        suffix: °
        type: state-label

  - type: conditional
    conditions:
      - entity: binary_sensor.freeze_protecting
        state: 'on'
    elements:
      - icon: 'mdi:shield-alert'
        style:
          color: yellow
          left: 8px
          top: 3px
          transform: none
        type: icon

Pool Heater

image
image
image
This is very similar to the freeze protection, but with some extra conditions that the pool pump must be on and the system must be in pool mode. The spa heater displays in the same place when the system is in spa mode, so I have included the yaml for both.

yaml
  - conditions:
      - entity: switch.filter_pump
        state: 'on'
    elements:
      - conditions:
          - entity: switch.spa_mode
            state: 'off'
        elements:
          - conditions:
              - entity: binary_sensor.pool_heating
                state: 'off'
            elements:
              - entity: switch.pool_heater
                icon: 'mdi:fire'
                style:
                  color: white
                  right: 150px
                  top: 2px
                  transform: none
                tap_action:
                  action: toggle
                  confirmation:
                    text: Are you sure? Heating the pool is expensive!
                type: icon
            type: conditional
          - conditions:
              - entity: binary_sensor.pool_heating
                state: 'on'
            elements:
              - entity: switch.pool_heater
                icon: 'mdi:fire'
                style:
                  color: red
                  right: 150px
                  top: 2px
                  transform: none
                tap_action:
                  action: toggle
                type: icon
            type: conditional
          - entity: switch.pool_heater
            prefix: 'pool heater '
            style:
              color: white
              right: 42px
              top: '-5px'
              transform: none
            tap_action:
              action: toggle
              confirmation:
                text: Are you sure? Heating the pool is expensive!
            type: state-label
          - attribute: temperature
            entity: climate.pool_heater
            prefix: '~ '
            style:
              color: white
              right: 0
              top: '-5px'
              transform: none
            suffix: °
            type: state-label
        type: conditional
      - conditions:
          - entity: switch.spa_mode
            state: 'on'
        elements:
          - conditions:
              - entity: binary_sensor.spa_heating
                state: 'off'
            elements:
              - entity: switch.spa_heater
                icon: 'mdi:fire'
                style:
                  color: white
                  right: 150px
                  top: 3px
                  transform: none
                tap_action:
                  action: toggle
                type: icon
            type: conditional
          - conditions:
              - entity: binary_sensor.spa_heating
                state: 'on'
            elements:
              - entity: switch.spa_heater
                icon: 'mdi:fire'
                style:
                  color: red
                  right: 150px
                  top: 3px
                  transform: none
                tap_action:
                  action: toggle
                type: icon
            type: conditional
          - entity: switch.spa_heater
            prefix: 'spa heater '
            style:
              color: white
              right: 43px
              top: '-3px'
              transform: none
            tap_action:
              action: toggle
            type: state-label
          - attribute: temperature
            entity: climate.spa_heater
            prefix: '~ '
            style:
              color: white
              right: 0
              top: '-3px'
              transform: none
            suffix: °
            type: state-label
        type: conditional
    type: conditional

Large Temperature Displays

image
These are just basic displays of the outside temperature, and if running, the pool or spa temperature. I used some of the button-card’s powerful styling and layout features to make it use most of the circle area.

yaml
  - type: 'custom:button-card'
    entity: sensor.air_temp
    name: Outside
    show_state: true
    show_icon: false
    state_display: '[[[ return Math.trunc(entity.state).toString()+"°" ]]]'
    style:
      transform: none
      top: 35px
      right: 5px
      z-index: 1
    styles:
      grid:
        - grid-template-areas: '"s"'
        - grid-template-columns: 1fr
        - grid-template-rows: 1fr
      card:
        - border-radius: 50%
        - padding: 0.1em 0.75em
        - background-color: 'rgba(0,0,0,0.4)'
      state:
        - font-size: 3.5em
      name:
        - font-size: 0.75em
        - position: absolute
        - transform: 'translate(-50%,0)'
        - bottom: 0
        - left: 50%
        - opacity: 0.5
  - conditions:
      - entity: switch.filter_pump
        state: 'on'
    elements:
      - conditions:
          - entity: switch.spa_mode
            state: 'off'
        elements:
          - type: 'custom:button-card'
            entity: sensor.pool_temp
            name: Pool
            show_state: true
            show_icon: false
            size: 2em
            state_display: '[[[ return Math.trunc(entity.state).toString()+"°" ]]]'
            style:
              transform: none
              top: 115px
              right: 5px
              z-index: 1
            styles:
              grid:
                - grid-template-areas: '"s"'
                - grid-template-columns: 1fr
                - grid-template-rows: 1fr
              card:
                - border-radius: 50%
                - padding: 0.1em 0.75em
                - background-color: 'rgba(0,0,0,0.4)'
              state:
                - font-size: 3.5em
              name:
                - font-size: 0.75em
                - position: absolute
                - transform: 'translate(-50%,0)'
                - bottom: 0
                - left: 50%
                - opacity: 0.5
        type: conditional
      - conditions:
          - entity: switch.spa_mode
            state: 'on'
        elements:
          - type: 'custom:button-card'
            entity: sensor.spa_temp
            name: Spa
            show_state: true
            show_icon: false
            size: 2em
            state_display: '[[[ return Math.trunc(entity.state).toString()+"°" ]]]'
            style:
              transform: none
              top: 115px
              right: 5px
              z-index: 1
            styles:
              grid:
                - grid-template-areas: '"s"'
                - grid-template-columns: 1fr
                - grid-template-rows: 1fr
              card:
                - border-radius: 50%
                - padding: 0.1em 0.75em
                - background-color: 'rgba(0,0,0,0.4)'
              state:
                - font-size: 3.5em
              name:
                - font-size: 0.75em
                - position: absolute
                - transform: 'translate(-50%,0)'
                - bottom: 0
                - left: 50%
                - opacity: 0.5
        type: conditional
    type: conditional

Main Pool Controls

image
For this section I used the paper-buttons-row element. I found this to be very flexible for setting up a grid of buttons and it has a nice clean look to it.

yaml
  - base_config:
      state_styles:
        'on':
          button:
            background-color: lightgreen
          icon:
            color: var(--paper-item-icon-active-color)
          text:
            color: black
      style:
        button:
          border-radius: 10px
          justify-content: center
          margin: 1px
          padding: 0 5px 0 5px
          white-space: nowrap
          width: 100%
    buttons:
      - - entity: sensor.aqualink_pump_mode
          icon: 'mdi:pool'
          name: Pool
          state_icons:
            delay: 'mdi:timer-sand'
          state_styles:
            delay:
              button:
                background-color: yellow
              icon:
                color: black
              text:
                color: black
            pool:
              button:
                background-color: lightgreen
              icon:
                color: var(--paper-item-icon-active-color)
              text:
                color: black
          tap_action:
            action: call-service
            service: python_script.set_pool_mode
            service_data:
              mode: pool
        - entity: switch.pool_heater
          name: Pool Heat
        - entity: switch.cleaner
        - entity: switch.pool_light
          name: Pool Light
      - - entity: sensor.aqualink_pump_mode
          icon: 'mdi:hot-tub'
          name: Spa
          state_icons:
            delay: 'mdi:timer-sand'
          state_styles:
            delay:
              button:
                background-color: yellow
              icon:
                color: black
              text:
                color: black
            spa:
              button:
                background-color: lightgreen
              icon:
                color: var(--paper-item-icon-active-color)
              text:
                color: black
          tap_action:
            action: call-service
            service: python_script.set_pool_mode
            service_data:
              mode: spa
        - entity: switch.spa_heater
          name: Spa Heat
        - entity: switch.spa_blower
          name: Bubbles
        - entity: switch.spa_light
          name: Spa Light
    style:
      background-color: 'rgba(0,0,0,0.4)'
      bottom: 0
      left: 0
      padding: 3px
      right: 0
      transform: none
    type: 'custom:paper-buttons-row'

Pool Filler

image
image
This is a convenient button to turn on one of my sprinkler zones that is set up to fill the pool. Someday I’ll have water level sensors to automate the filling, but for now I am using this button. I timed how long it takes to add 1 inch of water to the pool and use that to set the duration on the sprinkler zone. My RainMachine integration gives me the time remaining, which I display on the button and it will automatically turn off when the duration expires. I’m using a button-card for this because it can handle a conditional templated status display.

yaml
  - type: 'custom:button-card'
    entity: switch.sprinkler_zone_12
    name: |-
      [[[ 
        if (entity.state == "off") return "Fill 1\"";
        var sec = parseInt(entity.attributes.time_remaining);
        const h = Math.floor(sec / 3600);
        const m = Math.floor((sec % 3600) / 60);
        const leftPad = (num) => (num < 10 ? `0${num}` : num);
        return `${leftPad(h)}:${leftPad(m)}`;
      ]]]
    icon: 'mdi:water-pump'
    layout: icon_name
    tap_action:
      action: |
        [[[
          return entity.state == "off" ? 'call-service' : 'toggle'
        ]]]
      service: rainmachine.start_zone
      service_data:
        zone_id: 13
        zone_run_time: 7200
    state:
      - value: 'on'
        styles:
          card:
            - background-color: lightgreen
            - border-radius: 8px
          name:
            - color: black
            - font-weight: bold
    styles:
      card:
        - background-color: transparent
        - box-shadow: unset
        - margin: 5px
        - padding: 1px 3px
        - width: 5em
      name:
        - font: unset
        - font-size: 0.9em
      icon:
        - width: 1.5em
    style:
      background-color: 'rgba(0,0,0,0.4)'
      border-radius: 15px 0 0 0
      bottom: 66px
      color: white
      font-size: 1.2em
      padding-right: 5px
      right: 0
      transform: none

Pool Status Display

image
This is the main situational status display. This is driven by a template sensor entity where I have composited the important device states of the system. There is also a secondary element to show if the battery needs to be replaced in the Jandy Aqualink panel.

more status images

image
image
image
image
image
image
image
image
image
image
image
image
image
image
image
image

yaml
  - buttons:
      - entity: sensor.aqualink_run_mode
        state_styles:
          cleaner-delay:
            text:
              color: yellow
          cleaning:
            text:
              color: lightgreen
          filling:
            text:
              color: lightblue
          filter-delay:
            text:
              color: yellow
          freeze:
            text:
              color: cyan
          lights:
            text:
              color: white
          'off':
            icon:
              color: inherit
          pool:
            text:
              color: lightgreen
          pool-heated:
            icon:
              color: crimson
            text:
              color: orange
          pool-heating:
            icon:
              color: crimson
            text:
              color: orangered
          service:
            text:
              color: red
          spa:
            text:
              color: aquamarine
          spa-blowing:
            text:
              color: orange
          spa-heated:
            icon:
              color: crimson
            text:
              color: orange
          spa-heating:
            icon:
              color: crimson
            text:
              color: orangered
          timeout:
            text:
              color: red
        state_text:
          cleaner-delay: Cleaner Delay
          cleaning: Cleaning The Pool
          filling: Adding Water
          filter-delay: Filter Delay
          freeze: Freeze Protect Active
          lights: Lights Are On
          'off': System Off
          pool: Pool Is Running
          pool-heated: Pool Is Heated
          pool-heating: Pool Is Heating Up
          service: Service Mode
          spa: Spa Is Running
          spa-blowing: Spa Is Extra Bubbly
          spa-heated: Spa Is Heated
          spa-heating: Spa Is Heating Up
          timeout: Temporary Service Mode
        style:
          icon:
            background-color: 'rgba(0,0,0,0.4)'
            border-radius: 30%
            color: var(--paper-item-icon-active-color)
            padding: 2px
      - entity: binary_sensor.aqualink_battery
        state_icons:
          'on': 'mdi:battery-alert-variant'
        state_text:
          'off': ​
          'on': Replace
        style:
          icon:
            color: yellow
          text:
            color: yellow
    style:
      '--mdc-icon-size': 30px
      background-color: 'rgba(0,0,0,0.4)'
      border-radius: 0 15px 0 0
      bottom: 66px
      font-size: 1.5em
      font-weight: bold
      left: 0
      transform: none
    type: 'custom:paper-buttons-row'

Special Overlays

image
image
image
For fun I added some circular image overlays for certain conditions.

yaml
  - entity: sensor.aqualink_run_mode
    filter: opacity(0)
    image: /local/pictures/pool.jpg
    state_filter:
      cleaner-delay: opacity(1)
      cleaning: opacity(1)
      filling: opacity(1)
      filter-delay: opacity(1)
      lights: opacity(1)
    state_image:
      cleaner-delay: /local/pictures/pool-cleaner.jpg
      cleaning: /local/pictures/pool-cleaner.jpg
      filling: /local/pictures/pool-filling.jpg
      filter-delay: /local/pictures/pool-valve.jpg
      lights: /local/pictures/pool-light.jpg
    style:
      border-radius: 50%
      bottom: 120px
      left: 10px
      transform: none
      width: 30%
    type: image

Temporary System Messages

The Jandy Aqualink occasionally has special informational messages to display. I didn’t bother getting a picture of it, but I have them conditionally displayed right in the center of the UI with a simple markdown card.

yaml
  - conditions:
      - entity: binary_sensor.aqualink_has_message
        state: 'on'
    elements:
      - card_type: markdown
        content: |
          {{ states.sensor.aqualink_message.state }}
        style:
          background-color: 'rgba(0,0,0,0.6)'
          border-radius: 10px
          font-size: 1.5em
          left: 50%
          text-align: center
          top: 50%
          z-index: 1
        type: 'custom:hui-element'
    type: conditional

Pool View Blinds

image
All of my windows on the house with a view of the pool have automated iBlinds, so why not have a nice control for them right on the pool UI?

The control I am using for the blinds is described on my other post here, so I’m not going to cover that in this post.


##Summary
There is a lot of config here. Feel free to ask questions. Hopefully a few people find some inspiration from it :slight_smile:

1 post - 1 participant

Read full topic


Viewing all articles
Browse latest Browse all 106367

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>