Smart Lawn Irrigation Automation - Variables in a script data_template

Hello - I am trying to automate my lawn irrigation zones which aims to irrigate a total of 25mm of water per week (configurable amount), per zone. The automation makes a decision on how much to water by taking inputs such as;

  • The amount of irrigation manually turned on this week
  • The amount of actual rain this week
  • The amount and chance of rain forecast from BOM.

The script runs twice per week, so the first run aims for a total of 12.5mm of water, and the second run tops up to the total amount (25mm).

At the moment, I have this working via an automation, but considering I have three zones which need to run twice per week, I am having to duplicate the logic (with only some slight changes) into 6 individual automations.

I am thinking a script with variables will allow me to write the logic once, and just have 6 automations pass variables into the script.

Here is my current script:

smart_lawn_irrigation:
  description: 'Smart irrigation for lawn which tops up the required water levels (up to the maximum configured per week) if its not going to rain'
  fields:
    lawn_zone:
      description: 'The lawn zone we are automating'
      example: 'Backyard Grass'
    top_up_irrigation_amount:
      description: 'The amount of irrigation required in mm'
      example: 'input_number.backyard_grass_top_up_irrigation_amount'
    total_water_weekly:
      description: 'The amount of water required weekly'
      example: 'input_number.backyard_grass_total_water_weekly'
    run_number:
      description: 'The run number in the week'
      example: '2'
    total_rain_irrigation:
      description: 'The total amount of rain and irrigation in the last 7 days in mm'
      example: 'sensor.backyard_rain_irrigation_on_in_the_last_7_days_mm'
    top_up_irrigation_amount_min:
      description: 'The amount of irrigation required in minutes'
      example: 'input_number.backyard_grass_top_up_irrigation_amount_min'
    top_up_irrigation_volume_p_min:
      description: 'The flow rate in mm of irrigation per minute'
      example: 'input_number.backyard_grass_irrigation_volume_p_minute'
    irrigation_trigger:
      description: 'The irrigation zone to trigger'
      example: 'switch.backyard_irrigation_grass'
  sequence:
          
    # First, calculate how much water is required in mm
    - service: input_number.set_value
      data_template:
        entity_id: '{{ top_up_irrigation_amount }}'
        value: >
          {% if (states('{{ total_water_weekly }}') | float / {{ run_number }}) - (states('{{ total_rain_irrigation }}') | float) | round (0) > 0  %}
            {{ (states('{{ total_water_weekly }}') | float / {{ run_number }}) - (states('{{ total_rain_irrigation }}') | float) | round (0)}}
          {% else %}
            0
          {% endif %}

    # Then, based on the irrigation volume p/minute (flow rate) calculate how long (min) the irrigation needs to be turned on for.
    - service: input_number.set_value
      data_template:
        entity_id: '{{ top_up_irrigation_amount_min }}'
        value: "{{ (states('{{ top_up_irrigation_amount }}') | float ) * (states('{{ top_up_irrigation_volume_p_min }}') | float) }}"
    
    # If the forecast of rain is greater than 50% and greater than 1mm, then don't switch on the irrigation. Otherwise, turn on the irrigation.
    - service: >
        {% if (states('sensor.bom_melbourne_chance_of_rain_0') | float > 50) and (states('sensor.bom_melbourne_possible_rainfall_0_mm') | float > 1) or (states('{{ top_up_irrigation_amount }}') | float == 0) %}
          homeassistant.turn_off
        {% else %}
          homeassistant.turn_on
          {% endif %}
        data_template:
          entity_id: {{ irrigation_trigger }}

    # Turn off the irrigation after the calculated number of minutes
    - delay: "{{ '00:{:02}:00'.format(states('{{ top_up_irrigation_amount_min }}') | int) }}"
    - service: homeassistant.turn_off
      entity_id: '{{ irrigation_trigger }}'

    # Once it's completed, send a summary notification to my device.
    - alias: Send a push notification
      service: notify.mobile_app_iphone
      data_template:
        title: 'Lawn Irrigation Monitor - {{ lawn_zone }}'
        message: >
          {% if (states('sensor.bom_melbourne_chance_of_rain_0') | float > 50) and (states('sensor.bom_melbourne_possible_rainfall_0_mm') | float > 1)  %}
            Today's forecast is {{ states('sensor.bom_melbourne_chance_of_rain_0') }}% chance of {{ states('sensor.bom_melbourne_possible_rainfall_0_mm') }}mm rain. No irrigation is required!
          {% elif (states('{{ top_up_irrigation_amount }}') | float == 0) %}
            No irrigation is required! We already have enough water for today's run.
          {% else %}
            Today's forecast is {{ states('sensor.bom_melbourne_chance_of_rain_0') }}% chance of {{ states('sensor.bom_melbourne_possible_rainfall_0_mm') }}mm rain so the irrigation was on for {{ states('{{ top_up_irrigation_amount_min }}') }} minutes and topped up {{ states('{{ top_up_irrigation_amount }}') }} mm.
          {% endif %}

The script is returning the following error though:

2020-09-28 20:07:35 ERROR (MainThread) [homeassistant.config] Invalid config for [script]: invalid template (TemplateSyntaxError: expected token ':', got '}') for dictionary value @ data['script']['smart_lawn_irrigation']['sequence'][0]['data_template']['value']. Got "{% if (states('{{ total_water_weekly }}') | float / {{ run_number }}) - (states('{{ total_rain_irrigation }}') | float) | round (0) > 0 %}\n {{ (states('{{ total_water_weekly }}') | float / {{ run_number }}) - (states('{{ total_rain_irrigation }}') | float) | round (0)}}\n{% else %}\n 0\n{% endif %}\n". (See /config/configuration.yaml, line 37). Please check the docs at https://www.home-assistant.io/integrations/script

Any ideas? Also open to ideas on making this simpler!

Faced the same situation with an ever increasing complexity as the system grows. Seems simple at first but then gets quickly out of hand. To this end I created an integration. You can find it here.


Cheers