From 64d1bced629e19e19df28c38189ddf80ba831e1e Mon Sep 17 00:00:00 2001 From: mviamin <42081894+mviamin@users.noreply.github.com> Date: Tue, 30 Jul 2019 11:33:45 -0700 Subject: [PATCH 01/51] Update README.md --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c26940a..137338f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # Home-Assistant -This might one day have my whole config but at the moment I have only posted a few sections which are (mostly) self contained packages. +I have adapted the code to an ESP32 and an 8 relay board. -1. My **Garden Irrigation** system, + See here for more information in the OP - https://community.home-assistant.io/t/my-garden-irrigation/99686 - See here for more information - https://community.home-assistant.io/t/my-garden-irrigation/99686 - - -2. My **Guest Mode** implemenation which allows for an ad-hoc setting along with two (or more) regular schedules From fac19358a5dffdd8b2adfd6e36133591718e3135 Mon Sep 17 00:00:00 2001 From: mviamin <42081894+mviamin@users.noreply.github.com> Date: Tue, 30 Jul 2019 11:35:12 -0700 Subject: [PATCH 02/51] Delete view_guest_mode.yaml --- lovelace/views/view_guest_mode.yaml | 76 ----------------------------- 1 file changed, 76 deletions(-) delete mode 100644 lovelace/views/view_guest_mode.yaml diff --git a/lovelace/views/view_guest_mode.yaml b/lovelace/views/view_guest_mode.yaml deleted file mode 100644 index 76dd1d9..0000000 --- a/lovelace/views/view_guest_mode.yaml +++ /dev/null @@ -1,76 +0,0 @@ -#################################################### -# THIS IS ONLY A PARTIAL EXTRACT OF ONE OF MY VIEWS -# -# IT IS HERE PURELY AS AN AID TO RECREATING WHAT I -# SHOW IN MY SCREENSHOTS. -# -# IF YOU LIKE IT YOU WILL NEED TO ADAPT IT TO FIT -# IN YOUR OWN LOVELACE SETUP -##################################################### - - - - type: custom:fold-entity-row - head: - entity: binary_sensor.guest_mode - items: - - type: divider - - #=== Guest Schedules - #=== Schedule once - - type: custom:fold-entity-row - head: - type: custom:toggle-lock-entity-row - entity: input_boolean.guest_mode_once - name: Guest mode once - icon: mdi:human-handsup - items: - - input_number.guest_mode_once_duration - - type: divider - - #=== Schedule 1 - - type: custom:fold-entity-row - head: - type: custom:toggle-lock-entity-row - entity: input_boolean.guest_mode_schedule_1 - name: Guest schedule (1) - icon: mdi:numeric-1-box-outline - items: - - input_text.guest_mode_schedule_1_name - - input_select.guest_mode_schedule_1_day - - type: custom:time-input-row - entity: input_datetime.guest_mode_schedule_1_start_time - - input_number.guest_mode_schedule_1_duration - - type: divider - - #=== Schedule 2 - - type: custom:fold-entity-row - head: - type: custom:toggle-lock-entity-row - entity: input_boolean.guest_mode_schedule_2 - name: Guest schedule (2) - icon: mdi:numeric-2-box-outline - items: - - input_text.guest_mode_schedule_2_name - - input_select.guest_mode_schedule_2_day - - type: custom:time-input-row - entity: input_datetime.guest_mode_schedule_2_start_time - - input_number.guest_mode_schedule_2_duration -# - type: divider - - - #======================== - #=== Active Guest Timers - #======================== - - type: custom:card-modder - style: - --primary-text-color: 'yellow' - card: - type: entity-filter - show_header_toggle: false - entities: - - timer.guest_mode_once_duration - - timer.guest_mode_schedule_1_duration - - timer.guest_mode_schedule_2_duration - state_filter: - - "active" - show_empty: false From e4c58d36e4b41f5239fc697c66c9ec51bb3211f8 Mon Sep 17 00:00:00 2001 From: mviamin <42081894+mviamin@users.noreply.github.com> Date: Tue, 30 Jul 2019 11:37:10 -0700 Subject: [PATCH 03/51] Delete garden_dash_button.yaml --- packages/garden/garden_dash_button.yaml | 120 ------------------------ 1 file changed, 120 deletions(-) delete mode 100644 packages/garden/garden_dash_button.yaml diff --git a/packages/garden/garden_dash_button.yaml b/packages/garden/garden_dash_button.yaml deleted file mode 100644 index 0b02433..0000000 --- a/packages/garden/garden_dash_button.yaml +++ /dev/null @@ -1,120 +0,0 @@ - -#============ -#=== Scripts -#============ -script: - - #=========================================== - #=== DASH Button - start or stop irrigation - #=== (called from the Dashio add-on) - #=========================================== - dash_irrigation: - sequence: - - - service_template: > - {% if is_state('input_boolean.irrigation_master_control_switch', 'off') %} - script.dash_irrigation_not_started - {% elif is_state('input_boolean.cycle1_running', 'off') and - is_state('input_boolean.cycle2_running', 'off') %} - script.dash_start_irrigation - {% else %} - script.dash_stop_irrigation - {% endif %} - - - #================================================================ - #=== Script to start irrigation cycle 1 when DASH button pressed - #================================================================ - dash_start_irrigation: - sequence: - - - wait_template: > - {{ is_state('script.announce' , 'off') }} - timeout: '00:00:05' - - #=== Set sonos parameters - - service: script.setup_sonos_parameters - data: - room: kitchen - volume: 0.3 - - #=== Prepare Sonos devices (Snapshot, Unjoin and set Volume) - - service: script.prepare_sonos_devices - - #=== Wait for Sonos devices to be ready - - delay: "00:00:01" - - - wait_template: "{{ is_state('script.prepare_sonos_devices', 'off') }}" - - #=== Announce irrigation - - service: script.announce_irrigation_started - - - service: input_boolean.turn_on - data: - entity_id: input_boolean.cycle1_manual_run - - - wait_template: "{{ is_state('script.announce_irrigation_started' , 'on') }}" - timeout: '00:00:02' - - - wait_template: "{{ is_state('script.announce_irrigation_started' , 'off') }}" - - #=== Restore Sonos - - service: media_player.sonos_restore - data_template: - entity_id: > - {{ 'media_player.' ~ states('input_select.announce_room') }} - with_group: 'true' - - - #======================================================== - #=== Script to stop irrigation when DASH button pressed - #=== This stops any cycle even if it was not initiated - #=== by the dash button - #======================================================== - dash_stop_irrigation: - sequence: - - service: input_boolean.turn_off - data: - entity_id: - - input_boolean.cycle1_manual_run - - input_boolean.cycle2_manual_run - - - #================================================================ - #=== Script when irrigation doesn't run when DASH button pressed - #================================================================ - dash_irrigation_not_started: - sequence: - - - wait_template: > - {{ is_state('script.announce' , 'off') }} - timeout: '00:00:05' - - #=== Set sonos parameters - - service: script.setup_sonos_parameters - data: - room: kitchen - volume: 0.3 - - #=== Prepare Sonos devices (Snapshot, Unjoin and set Volume) - - service: script.prepare_sonos_devices - - #=== Wait for Sonos devices to be ready - - delay: "00:00:01" - - - wait_template: "{{ is_state('script.prepare_sonos_devices', 'off') }}" - - #=== Announce irrigation - - service: script.announce_irrigation_not_started - - - wait_template: "{{ is_state('script.announce_irrigation_not_started' , 'on') }}" - timeout: '00:00:02' - - - wait_template: "{{ is_state('script.announce_irrigation_not_started' , 'off') }}" - - #=== Restore Sonos - - service: media_player.sonos_restore - data_template: - entity_id: > - {{ 'media_player.' ~ states('input_select.announce_room') }} - with_group: 'true' From eb6ba6db5554232609013fb91fa342daef9190ae Mon Sep 17 00:00:00 2001 From: mviamin <42081894+mviamin@users.noreply.github.com> Date: Tue, 30 Jul 2019 11:38:25 -0700 Subject: [PATCH 04/51] Update README.md --- packages/garden/README.md | 48 +-------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/packages/garden/README.md b/packages/garden/README.md index 1affc4c..524bfdf 100644 --- a/packages/garden/README.md +++ b/packages/garden/README.md @@ -3,50 +3,4 @@
-
-__The Morning Cycle showing the Schedule__
-
-
-
-__The Morning Cycle showing the Weather Adjustments__
-
-
-
-__Showing the Irrigation History__
-
-
+Adapted for an ESP32 and 8-zone relay.
From be9a32e2cbe95d0ecdc73555da9946ec8bb198dd Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:38:47 -0700
Subject: [PATCH 05/51] Delete garden_weather_data_collection.yaml
---
.../garden_weather_data_collection.yaml | 348 ------------------
1 file changed, 348 deletions(-)
delete mode 100644 packages/garden/garden_weather_data_collection.yaml
diff --git a/packages/garden/garden_weather_data_collection.yaml b/packages/garden/garden_weather_data_collection.yaml
deleted file mode 100644
index 580f7e1..0000000
--- a/packages/garden/garden_weather_data_collection.yaml
+++ /dev/null
@@ -1,348 +0,0 @@
-
-#==================
-#=== Input_Numbers
-#==================
-input_number:
- # Temperature
- temp_minus0:
- name: Temp today
- min: 0
- max: 40
- icon: mdi:thermometer
-
- temp_minus1:
- name: Temp yesterday
- min: 0
- max: 40
- icon: mdi:thermometer
-
- temp_minus2:
- name: Temp 2 days ago
- min: 0
- max: 40
- icon: mdi:thermometer
-
- temp_minus3:
- name: Temp 3 days ago
- min: 0
- max: 40
- icon: mdi:thermometer
-
- temp_minus4:
- name: Temp 4 days ago
- min: 0
- max: 40
- icon: mdi:thermometer
-
- temp_high_2days:
- name: Avg 2 day temp
- min: 0
- max: 40
- mode: box
- icon: mdi:thermometer
-
- temp_high_5days:
- name: Avg 5 day temp
- min: 0
- max: 40
- mode: box
- icon: mdi:thermometer
-
-
- # Rainfall
- rain_minus0:
- name: Rain today
- min: 0
- max: 100
- icon: mdi:weather-rainy
-
- rain_minus1:
- name: Rain yesterday
- min: 0
- max: 100
- icon: mdi:weather-rainy
-
- rain_minus2:
- name: Rain 2 days ago
- min: 0
- max: 100
- icon: mdi:weather-rainy
-
- rain_minus3:
- name: Rain 3 days ago
- min: 0
- max: 100
- icon: mdi:weather-rainy
-
- rain_3days_total:
- name: Last 3 days rain
- min: 0
- max: 500
- mode: box
- icon: mdi:weather-rainy
-
- rain_3days_ratio:
- name: Last 3 days rain adj
- min: 0
- max: 100
- step: 0.01
- mode: box
- icon: mdi:weather-rainy
-
-
-#============
-#=== Sensors
-#============
-sensor:
- - platform: template
- sensors:
- # Weather information sensors
- # Temperature
- temp_minus0:
- friendly_name: Temp today
- value_template: "{{ states('input_number.temp_minus0') }}"
- unit_of_measurement: "°C"
-
- temp_minus1:
- friendly_name: Temp yesterday
- value_template: "{{ states('input_number.temp_minus1') }}"
- unit_of_measurement: "°C"
-
- temp_minus2:
- friendly_name: Temp 2 days ago
- value_template: "{{ states('input_number.temp_minus2') }}"
- unit_of_measurement: "°C"
-
- temp_minus3:
- friendly_name: Temp 3 days ago
- value_template: "{{ states('input_number.temp_minus3') }}"
- unit_of_measurement: "°C"
-
- temp_minus4:
- friendly_name: Temp 4 days ago
- value_template: "{{ states('input_number.temp_minus4') }}"
- unit_of_measurement: "°C"
-
- temp_high_2days:
- friendly_name: Avg 2 day temp
- value_template: "{{ states('input_number.temp_high_2days') }}"
- unit_of_measurement: "°C"
-
- temp_high_5days:
- friendly_name: Avg 5 day temp
- value_template: "{{ states('input_number.temp_high_5days') }}"
- unit_of_measurement: "°C"
-
-
- # Rainfall
- # rain_minus0:
- # friendly_name: Rain today
- # value_template: "{{ states('input_number.rain_minus0') | int }}"
- # unit_of_measurement: "mm"
-
- rain_minus0:
- friendly_name: Rain today
- value_template: "{{ states('sensor.smartweather_rain_today') }}"
- unit_of_measurement: "mm"
-
- rain_minus1:
- friendly_name: Rain yesterday
- value_template: "{{ states('input_number.rain_minus1') }}"
- unit_of_measurement: "mm"
-
- rain_minus2:
- friendly_name: Rain 2 days ago
- value_template: "{{ states('input_number.rain_minus2') }}"
- unit_of_measurement: "mm"
-
- rain_minus3:
- friendly_name: Rain 3 days ago
- value_template: "{{ states('input_number.rain_minus3') }}"
- unit_of_measurement: "mm"
-
- rain_3days_ratio:
- friendly_name: Last 3 days rain adj. multiplyer
- value_template: "{{ states('input_number.rain_3days_ratio') }}"
-
-
-#=================
-# === Automations
-#=================
-automation:
-
- #================================================
- #=== Collect new and cycle historic weather data
- #================================================
- - alias: Irrigation Weather Data - Collect new and cycle historic weather data
- initial_state: 'on'
- trigger:
- - platform: time
- at: '01:00:00'
-
- action:
- # These scripts pass the count of entities but in this case as I
- # have numbered them beginning with zero pass the count minus 1
-
- # Cycle the temperature figures
- - service: script.garden_temperature_data
- data_template:
- loop_count: >
- {% set ns = namespace(count = 0) %}
- {% for item in states if item.entity_id.startswith('input_number.temp_minus') %}
- {% set ns.count = loop.index %}
- {% endfor %}
- {{ (ns.count - 1) }}
-
- # Cycle the rainfall figures
- - service: script.garden_rainfall_data
- data_template:
- loop_count: >
- {% set ns = namespace(count = 0) %}
- {% for item in states if item.entity_id.startswith('input_number.rain_minus') %}
- {% set ns.count = loop.index %}
- {% endfor %}
- {{ (ns.count - 1) }}
-
-###### EXTRA AUTOMATION NEEDED HERE
-###### TO COLLECT RAINFALL DATA EVERY HOUR
-###### INTO input_number.rain_minus0
-###### USING sensor.smartweather_precpitation_last_1hr
-######
-###### This could be done before irrigation starts by
-###### by using sensor.smartweather_rain_today if
-###### weather adjustments are being made as it is not
-###### needed for cycling the history
-
-#=============
-# === Scripts
-#=============
-script:
-
- #====================================================
- #=== Collect new and cycle historic TEMPERATURE data
- #====================================================
- garden_temperature_data:
- sequence:
-
- # Cycle the temperature figures.
- # Passed {{ loop_count}} which is the number relating to the highest entity
- # e.g. input_number.temp_minus4
-
- # Setting the temperature for today:
- # DarkSky dark_sky_forecast_temperature_high_0 is used as the high temperature.
-
- # ===== THIS NEEDS TO BE LOOKED AT
- # The average weather calculations happen every 30 mins and will
- # only update todays temperature if it goes up.
- # This is because the DarkSky max temperature appears to change during
- # the day to reflect max temperature for the remainder of the day???
-
- - service: input_number.set_value
- data_template:
- entity_id: >
- input_number.temp_minus{{ loop_count }}
- value: >
- {% if loop_count | int == 0 %}
- {{ states('sensor.dark_sky_forecast_daytime_high_temperature_0d') | float }}
- {% else %}
- {{ states('input_number.temp_minus' ~ (loop_count | int - 1) | string) }}
- {% endif %}
-
- # Stop when count is 0
- - condition: template
- value_template: >
- {{ loop_count | int > 0 }}
-
- # Stop the looping script...
- - service: homeassistant.turn_off
- entity_id: script.loop_garden_temperature_data
-
- # ...before looping
- - service: script.loop_garden_temperature_data
- data_template:
- loop_count: >
- {{ loop_count }}
-
-
- #============================================
- #=== Loop the script garden_temperature_data
- #============================================
- loop_garden_temperature_data:
- sequence:
-
- # Stop the calling script...
- - service: homeassistant.turn_off
- entity_id: script.garden_temperature_data
-
- # ...then restart it
- - service: script.garden_temperature_data
- data_template:
- loop_count: >
- {{ loop_count | int - 1 }}
-
-
- #=================================================
- #=== Collect new and cycle historic RAINFALL data
- #=================================================
- garden_rainfall_data:
- sequence:
-
- # Cycle the rainfall figures.
- # Passed {{ loop_count}} which is the number relating to the highest entity
- # e.g. input_number.rain_minus3
-
- # Now using sensor.smartweather_rain_yesterday
- # Make todays rain zero
-
- - service: input_number.set_value
- data_template:
- entity_id: >
- input_number.rain_minus{{ loop_count }}
- value: >
- {% if loop_count | int == 0 %}
- 0
- {% elif loop_count | int == 1 %}
- {{ states('sensor.smartweather_rain_yesterday') }}
- {% else %}
- {{ states('input_number.rain_minus' ~ (loop_count | int - 1) | string) }}
- {% endif %}
-
- # # Stop when count is 0
- # - condition: template
- # value_template: >
- # {{ loop_count | int > 0 }}
-
- # Stop when count is 1 because day zero is rain today which
- # is collected directly from the sensor.smartweather_rain_today
- - condition: template
- value_template: >
- {{ loop_count | int > 1 }}
-
- # Stop the looping script...
- - service: homeassistant.turn_off
- entity_id: script.loop_garden_rainfall_data
-
- # ...before looping
- - service: script.loop_garden_rainfall_data
- data_template:
- loop_count: >
- {{ loop_count }}
-
-
- #=========================================
- #=== Loop the script garden_rainfall_data
- #=========================================
- loop_garden_rainfall_data:
- sequence:
-
- # Stop the calling script...
- - service: homeassistant.turn_off
- entity_id: script.garden_rainfall_data
-
- # ...then restart it
- - service: script.garden_rainfall_data
- data_template:
- loop_count: >
- {{ loop_count | int - 1 }}
-
-
From 4668cd4dcbb491646b2170ffc0c3e3a7057dc23b Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:38:56 -0700
Subject: [PATCH 06/51] Delete garden_weather_calculations.yaml
---
.../garden/garden_weather_calculations.yaml | 316 ------------------
1 file changed, 316 deletions(-)
delete mode 100644 packages/garden/garden_weather_calculations.yaml
diff --git a/packages/garden/garden_weather_calculations.yaml b/packages/garden/garden_weather_calculations.yaml
deleted file mode 100644
index cd26ada..0000000
--- a/packages/garden/garden_weather_calculations.yaml
+++ /dev/null
@@ -1,316 +0,0 @@
-#=================
-# === Automations
-#=================
-automation:
-
- #=====================================================================
- #=== Adjust weather durations if:
- #=== the baseline duration is changed
- #=== the temperature threshold or rainfall baseline are changed
- #=== use weather adjustment is turn on
- #=====================================================================
-
- # Duration changed cycle 1
- - alias: Irrigation Weather - Adjust durations with change in cycle1 baseline duration
- initial_state: 'on'
- trigger:
- - platform: state
- entity_id:
- - input_number.cycle1_zone1_duration
- - input_number.cycle1_zone2_duration
- - input_number.cycle1_zone3_duration
- - input_number.cycle1_zone4_duration
- - input_number.cycle1_zone5_duration
-
- action:
- - wait_template: "{{ is_state('script.adjust_cycle1_durations', 'off') }}"
-
- - service: script.adjust_cycle1_durations
-
-
- # Duration changed cycle 1
- - alias: Irrigation Weather - Adjust durations with change in cycle2 baseline duration
- initial_state: 'on'
- trigger:
- - platform: state
- entity_id:
- - input_number.cycle2_zone1_duration
- - input_number.cycle2_zone2_duration
- - input_number.cycle2_zone3_duration
- - input_number.cycle2_zone4_duration
- - input_number.cycle2_zone5_duration
- action:
- - wait_template: "{{ is_state('script.adjust_cycle2_durations', 'off') }}"
-
- - service: script.adjust_cycle2_durations
-
- # Baselines changed
- - alias: Irrigation Weather - Adjust durations with change in rain or temp baseline
- initial_state: 'on'
- trigger:
- - platform: state
- entity_id:
- - input_number.temperature_baseline
- - input_number.rainfall_threshold
- action:
- - service: script.calculate_average_weather_conditions
-
- - wait_template: "{{ is_state('script.calculate_average_weather_conditions', 'off') }}"
-
- - service: script.adjust_cycle1_durations
-
- - service: script.adjust_cycle2_durations
-
- # Weather adjustment turned on
- - alias: Irrigation Weather - Option to use weather adjustment turned on
- initial_state: 'on'
- trigger:
- - platform: state
- entity_id:
- - input_boolean.cycle1_use_weather_adjustment
- - input_boolean.cycle2_use_weather_adjustment
- to: 'on'
- action:
- - service_template: >
- {% if trigger.entity_id == 'input_boolean.cycle1_use_weather_adjustment' %}
- script.adjust_cycle1_durations
- {% else %}
- script.adjust_cycle2_durations
- {% endif %}
-
-
- #============================================================
- #=== Recalculate average weather conditions every 30 minutes
- #=== And recalculate Cycle durations
- #============================================================
- - alias: Irrigation Weather - Update average weather conditions every 30 mins
- initial_state: 'on'
- trigger:
- - platform: time_pattern
- minutes: '/30'
- seconds: 00
- action:
- - service: script.calculate_average_weather_conditions
-
- - wait_template: "{{ is_state('script.calculate_average_weather_conditions', 'off') }}"
-
- # Adjust Cycle 1 durations
- - service: script.adjust_cycle1_durations
- - wait_template: "{{ is_state('script.adjust_cycle1_durations', 'off') }}"
-
- # Adjust Cycle 2 durations
- - service: script.adjust_cycle2_durations
- - wait_template: "{{ is_state('script.adjust_cycle2_durations', 'off') }}"
-
-
-#============
-#=== Scripts
-#============
-script:
-
- #=========================================
- #=== Calculate average weather conditions
- #=========================================
- calculate_average_weather_conditions:
- sequence:
-
- # Set today's forecast high temperature
- # but only if it has gone up
- # temp_minus0 is set to low every night at 23:50 in the automation that
- # cycles the weather information
- - service: input_number.set_value
- data_template:
- entity_id: input_number.temp_minus0
- value: >
- {% if states.input_number.temp_minus0.state | float < states.sensor.dark_sky_forecast_daytime_high_temperature_0.state | float %}
- {{ states('sensor.dark_sky_forecast_daytime_high_temperature_0') }}
- {% else %}
- {{ states('input_number.temp_minus0') }}
- {% endif %}
-
- # Calculate average high temp for today and yesterday
- - service: input_number.set_value
- data_template:
- entity_id: input_number.temp_high_2days
- value: >
- {{ ((float(states.input_number.temp_minus0.state) +
- float(states.input_number.temp_minus1.state)) / 2 ) | round }}
-
- # Calculate average high temp for the today and yesterday and previous 3 days
- - service: input_number.set_value
- data_template:
- entity_id: input_number.temp_high_5days
- value: >
- {{ ((float(states.input_number.temp_minus0.state) +
- float(states.input_number.temp_minus1.state) +
- float(states.input_number.temp_minus2.state) +
- float(states.input_number.temp_minus3.state) +
- float(states.input_number.temp_minus4.state)) / 5) | round }}
-
- # Adjust the total amount of rain depending on how many days ago it was.
- # If 3 days ago take 20% of the rain.
- # If 2 days ago take 50% of the rain.
- # If yesterday take 80% of the rain.
- - service: input_number.set_value
- data_template:
- entity_id: input_number.rain_3days_total
- value: >
- {{ (float(states.input_number.rain_minus1.state) * 0.8) +
- (float(states.input_number.rain_minus2.state) * 0.5) +
- (float(states.input_number.rain_minus3.state) * 0.2) }}
-
- # Add in todays forecast rain
- - service: input_number.set_value
- data_template:
- entity_id: input_number.rain_3days_total
- value: >
- {{ float(states.input_number.rain_3days_total.state) +
- (float(states.input_number.rain_minus0.state)) }}
-
- # Convert into a ratio (maximum 1.00) used to reduce irrigation time or stop it altogether:
- # Rain needed in last 3 days to stop grass irrigation is set in RainfallThreshold
- # Rain levels less than this amount will be used to reduce irrigation run times proportionally
- - service: input_number.set_value
- data_template:
- entity_id: input_number.rain_3days_ratio
- value: >
- {{ states.input_number.rain_3days_total.state | float / states.input_number.rainfall_threshold.state | float }}
-
- # Make sure ratio is not greater than 1
- - service: input_number.set_value
- data_template:
- entity_id: input_number.rain_3days_ratio
- value: >
- {% if states.input_number.rain_3days_ratio.state | float > 1 %}
- 1
- {% else %}
- {{ states.input_number.rain_3days_ratio.state }}
- {% endif %}
-
-
- #=========================================
- #=== Adjust duration for zones in cycle 1
- #=========================================
- adjust_cycle1_durations:
- sequence:
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '1'
- zone: '1'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '1'
- zone: '2'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '1'
- zone: '3'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '1'
- zone: '4'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '1'
- zone: '5'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
-
- #=========================================
- #=== Adjust duration for zones in cycle 2
- #=========================================
- adjust_cycle2_durations:
- sequence:
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '2'
- zone: '1'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '2'
- zone: '2'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '2'
- zone: '3'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '2'
- zone: '4'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
- - service: script.calculate_adjusted_zone_durations
- data:
- cycle: '2'
- zone: '5'
- - wait_template: "{{ is_state('script.calculate_adjusted_zone_durations', 'off') }}"
-
-
- #========================================================
- #=== Adjust zone duration for average weather conditions
- #=== is passed:
- #=== {{ cycle }}
- #=== {{ zone }}
- #========================================================
- calculate_adjusted_zone_durations:
- sequence:
-
- # Adjust for average daily temperature
-
- # Calculate any change in run time based on daily average temperature.
- # The default run time will occur at TemperatureBaseline degrees.
- # As the daily average temperature increases above this the run time will
- # also increase.
- # As the average temp drops below TemperatureBaseline the run time decreases.
- # The forumla used ‐ based on a 20 degree TemperatureBaseline would be:
- # (((TwoDayHighAverageTemp ‐ 20) / 20) +1) * BaseLineDuration
- # So: the percentage change in duration is the same as the percentage
- # difference between the actual temperature and the baseline temperature
- # i.e. a 10% increase in duration when the baseline temperataure
- # is 20 degrees and the actual temperature is 22 degrees
-
- # First adjust for temperature
- - service: input_number.set_value
- data_template:
- entity_id: input_number.adjusted_cycle{{ cycle }}_zone{{ zone }}_duration
- value: >
- {% set duration = states('input_number.cycle' + cycle + '_zone' + zone + '_duration') %}
- {{ (((float(states.input_number.temp_high_2days.state) - float(states.input_number.temperature_baseline.state)) / float(states.input_number.temperature_baseline.state)) + 1) * float(duration) }}
-
- # Then adjust for average daily rainfall
- - service: input_number.set_value
- data_template:
- entity_id: input_number.adjusted_cycle{{ cycle }}_zone{{ zone }}_duration
- value: >
- {% set normal_duration = states('input_number.cycle' + cycle + '_zone' + zone + '_duration') %}
- {% set adj_duration = states('input_number.adjusted_cycle' + cycle + '_zone' + zone + '_duration') %}
- {{ float(adj_duration) - (float(normal_duration) * float(states.input_number.rain_3days_ratio.state)) }}
-
- # Make sure new duration is not less than zero
- - service: input_number.set_value
- data_template:
- entity_id: input_number.adjusted_cycle{{ cycle }}_zone{{ zone }}_duration
- value: >
- {% if states('input_number.adjusted_cycle' + cycle + '_zone' + zone + '_duration') | float < 0 %}
- 0
- {% else %}
- {{ states('input_number.adjusted_cycle' + cycle + '_zone' + zone + '_duration') }}
- {% endif %}
-
-# This elif was removed when zone 5 was allowed to go to 59 minutes
-# {% elif states('input_number.adjusted_cycle' + cycle + '_zone' + zone + '_duration') | float > 30 %}
-# 30
From 65984215d70ba74769dc5ef8fabdecaa05109a00 Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:39:05 -0700
Subject: [PATCH 07/51] Delete garden_valves_failsafe.yaml
---
packages/garden/garden_valves_failsafe.yaml | 188 --------------------
1 file changed, 188 deletions(-)
delete mode 100644 packages/garden/garden_valves_failsafe.yaml
diff --git a/packages/garden/garden_valves_failsafe.yaml b/packages/garden/garden_valves_failsafe.yaml
deleted file mode 100644
index 7bf4cfa..0000000
--- a/packages/garden/garden_valves_failsafe.yaml
+++ /dev/null
@@ -1,188 +0,0 @@
-#============================================================================
-#=== Not that I don't trust my programming but...
-#=== 1. Turn off valves and schedules when master control switch is off
-#=== 2. Turn off all valves when HA starts
-#=== 3. Don't allow more than one valve on at one time
-#=== 4. Turn off valve 1 to 4 if it is on for longer than 30 minutes
-#=== Turn off valve 5 if it is on for longer than 59 minutes
-#=== Better safe than sorry!
-#============================================================================
-
-#================
-#=== Automations
-#================
-automation:
-
- #====================================================================
- #=== Master Control Switch
- #=== Turn off valves and schedules when master control switch is off
- #====================================================================
- - alias: Irrigation Failsafe - master control switch
- initial_state: on
- trigger:
- - platform: state
- entity_id: input_boolean.irrigation_master_control_switch
- to: 'off'
-
- - platform: homeassistant
- event: start
-
- action:
- - service: homeassistant.turn_off
- entity_id:
- - input_boolean.cycle1_enable
- - input_boolean.cycle2_enable
- - input_boolean.cycle1_manual_run
- - input_boolean.cycle2_manual_run
- - switch.zone1_valve
- - switch.zone2_valve
- - switch.zone3_valve
- - switch.zone4_valve
- - switch.zone5_valve
-
-
- #=======================================
- #=== Home Assistant starts
- #=== Turn off all valves when HA starts
- #=======================================
- - alias: Irrigation Failsafe - HA start
- initial_state: on
- trigger:
- - platform: homeassistant
- event: start
-
- action:
- - service: homeassistant.turn_off
- entity_id:
- - switch.zone1_valve
- - switch.zone2_valve
- - switch.zone3_valve
- - switch.zone4_valve
- - switch.zone5_valve
-
-
- #==================================================================
- #=== Don't allow more than one valve on at one time.
- #=== And
- #=== Turn off valve 1 to 4 if it is on for longer than 30 minutes.
- #=== Turn off valve 5 if it is on for longer than 59 minutes.
- #==================================================================
- #=== Valve 1 ON
- - alias: Irrigation Failsafe - Valve 1 on
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - switch.zone1_valve
- to: 'on'
-
- action:
- - service: homeassistant.turn_off
- entity_id:
- - switch.zone2_valve
- - switch.zone3_valve
- - switch.zone4_valve
- - switch.zone5_valve
-
- - wait_template: "{{ is_state('switch.zone1_valve', 'off') }}"
- timeout: '00:30:15'
-
- - service: homeassistant.turn_off
- entity_id: switch.zone1_valve
-
-
- #=== Valve 2 ON
- - alias: Irrigation Failsafe - Valve 2 on
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - switch.zone2_valve
- to: 'on'
-
- action:
- - service: homeassistant.turn_off
- entity_id:
- - switch.zone1_valve
- - switch.zone3_valve
- - switch.zone4_valve
- - switch.zone5_valve
-
- - wait_template: "{{ is_state('switch.zone2_valve', 'off') }}"
- timeout: '00:30:15'
-
- - service: homeassistant.turn_off
- entity_id: switch.zone2_valve
-
-
- #=== Valve 3 ON
- - alias: Irrigation Failsafe - Valve 3 on
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - switch.zone3_valve
- to: 'on'
-
- action:
- - service: homeassistant.turn_off
- entity_id:
- - switch.zone1_valve
- - switch.zone2_valve
- - switch.zone4_valve
- - switch.zone5_valve
-
- - wait_template: "{{ is_state('switch.zone3_valve', 'off') }}"
- timeout: '00:30:15'
-
- - service: homeassistant.turn_off
- entity_id: switch.zone3_valve
-
-
- #=== Valve 4 ON
- - alias: Irrigation Failsafe - Valve 4 on
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - switch.zone4_valve
- to: 'on'
-
- action:
- - service: homeassistant.turn_off
- entity_id:
- - switch.zone1_valve
- - switch.zone2_valve
- - switch.zone3_valve
- - switch.zone5_valve
-
- - wait_template: "{{ is_state('switch.zone4_valve', 'off') }}"
- timeout: '00:30:15'
-
- - service: homeassistant.turn_off
- entity_id: switch.zone4_valve
-
-
- #=== Valve 5 ON
- - alias: Irrigation Failsafe - Valve 5 on
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - switch.zone5_valve
- to: 'on'
-
- action:
- - service: homeassistant.turn_off
- entity_id:
- - switch.zone1_valve
- - switch.zone2_valve
- - switch.zone3_valve
- - switch.zone4_valve
-
- - wait_template: "{{ is_state('switch.zone5_valve', 'off') }}"
- timeout: '00:59:15'
-
- - service: homeassistant.turn_off
- entity_id: switch.zone5_valve
-
From 96d688b5371de9381ae1f2418c6ce1602c84f3da Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:39:18 -0700
Subject: [PATCH 08/51] Delete garden_notifications.yaml
---
packages/garden/garden_notifications.yaml | 101 ----------------------
1 file changed, 101 deletions(-)
delete mode 100644 packages/garden/garden_notifications.yaml
diff --git a/packages/garden/garden_notifications.yaml b/packages/garden/garden_notifications.yaml
deleted file mode 100644
index 8e47b6d..0000000
--- a/packages/garden/garden_notifications.yaml
+++ /dev/null
@@ -1,101 +0,0 @@
-#================
-#=== Automations
-#================
-automation:
-
- #===================================================
- #=== Notify about irrigation events when on holiday
- #===================================================
- - alias: Irrigation - Notify about irrigation events when on holiday
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - input_boolean.cycle1_running
- - input_boolean.cycle2_running
-
- condition:
- - condition: state
- entity_id: binary_sensor.holiday_mode
- state: 'on'
-
- action:
- - service_template: >
- {% if trigger.to_state.state == 'on' %}
- script.notify_irrigation_start
- {% else %}
- script.notify_irrigation_end
- {% endif %}
- data_template:
- cycle: >
- {% if trigger.entity_id == 'input_boolean.cycle1_running' %}
- 1
- {% else %}
- 2
- {% endif %}
-
-
-#============
-#=== Scripts
-#============
-script:
-
- #===============================
- #=== Notify when a cycle starts
- #=== Called with
- #=== {{ cycle }}
- #===============================
- notify_irrigation_start:
- sequence:
- - service: script.notify
- data_template:
- tell: steve_and_sarah
- message: >
- {% set cycle_map = {
- '1': 'morning',
- '2': 'afternoon'
- } %}
- {% set cycle_time = cycle_map[cycle] %}
-
- {% if is_state('input_boolean.cycle' + cycle + '_use_weather_adjustment', 'off') %}
- {% set total_time = states('input_number.cycle' + cycle + '_zone1_duration') | int
- + states('input_number.cycle' + cycle + '_zone2_duration') | int
- + states('input_number.cycle' + cycle + '_zone3_duration') | int
- + states('input_number.cycle' + cycle + '_zone4_duration') | int
- + states('input_number.cycle' + cycle + '_zone5_duration') | int %}
-
- {% else %}
- {% set total_time = states('input_number.adjusted_cycle' + cycle + '_zone1_duration') | int
- + states('input_number.adjusted_cycle' + cycle + '_zone2_duration') | int
- + states('input_number.adjusted_cycle' + cycle + '_zone3_duration') | int
- + states('input_number.adjusted_cycle' + cycle + '_zone4_duration') | int
- + states('input_number.adjusted_cycle' + cycle + '_zone5_duration') | int %}
- {% endif %}
-
- I thought you'd like to know that the {{cycle_time}} irrigation cycle has just started.
-
-
- I expect it will take about {{ total_time }} minutes to finish but I'll let you know when it has.
-
-
- Don't worry your garden is safe with me. I hope you're having a lovely holiday!
-
-
- #=============================
- #=== Notify when a cycle ends
- #=== Called with
- #=== {{ cycle }}
- #=============================
- notify_irrigation_end:
- sequence:
- - service: script.notify
- data_template:
- tell: steve_and_sarah
- message: >
- {% set cycle_map = {
- '1': 'morning',
- '2': 'afternoon'
- } %}
- {% set cycle_time = cycle_map[cycle] %}
-
- All the {{cycle_time}} watering is done.
From 86daf32b843aaa4eef898946472f66d61c3f172d Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:39:26 -0700
Subject: [PATCH 09/51] Delete garden_master_control.yaml
---
packages/garden/garden_master_control.yaml | 53 ----------------------
1 file changed, 53 deletions(-)
delete mode 100644 packages/garden/garden_master_control.yaml
diff --git a/packages/garden/garden_master_control.yaml b/packages/garden/garden_master_control.yaml
deleted file mode 100644
index f9ae7c1..0000000
--- a/packages/garden/garden_master_control.yaml
+++ /dev/null
@@ -1,53 +0,0 @@
-#=================
-# === Automations
-#=================
-automation:
-
- #====================================================================
- #=== Master Control switch
- #===
- #=== This turns on or off,
- #=== All the Irrigation automations.
- #=== All the automations related to Weather used in Irrigation.
- #===
- #=== i.e. all automations with a name beginning with either
- #=== 'Irrigation - ' or
- #=== 'Irrigation Weather - '
- #===
- #=== Also checks when HA starts.
- #====================================================================
- - alias: Irrigation Master Control Switch
- initial_state: 'on'
- trigger:
- - platform: state
- entity_id: input_boolean.irrigation_master_control_switch
-
- - platform: homeassistant
- event: start
-
- action:
- #=== Turn all Irrigation automations on or off
- - service_template: >
- {% if is_state('input_boolean.irrigation_master_control_switch', 'on') %}
- automation.turn_on
- {% else %}
- automation.turn_off
- {% endif %}
- data_template:
- entity_id: >
- {% for item in states['automation'] if item.name.startswith('Irrigation - ') -%}
- {% if not loop.first %},{% endif %}{{ item.entity_id }}
- {%- endfor %}
-
- #=== Turn all Weather Irrigation automations on or off
- - service_template: >
- {% if is_state('input_boolean.irrigation_master_control_switch', 'on') %}
- automation.turn_on
- {% else %}
- automation.turn_off
- {% endif %}
- data_template:
- entity_id: >
- {% for item in states['automation'] if item.name.startswith('Irrigation Weather - ') -%}
- {% if not loop.first %},{% endif %}{{ item.entity_id }}
- {%- endfor %}
From 0768e6683028b6f587399785050c09d132acb2ec Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:39:38 -0700
Subject: [PATCH 10/51] Delete garden_irrigation.yaml
---
packages/garden/garden_irrigation.yaml | 519 -------------------------
1 file changed, 519 deletions(-)
delete mode 100644 packages/garden/garden_irrigation.yaml
diff --git a/packages/garden/garden_irrigation.yaml b/packages/garden/garden_irrigation.yaml
deleted file mode 100644
index f9eb6bc..0000000
--- a/packages/garden/garden_irrigation.yaml
+++ /dev/null
@@ -1,519 +0,0 @@
-
-#================
-#=== Automations
-#================
-automation:
-
- #============================================================
- #=== Set next run time when schedule enabled or time changed
- #============================================================
- - alias: Irrigation - Set next run time when schedule enabled or time changed
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - input_boolean.cycle1_enable
- - input_boolean.cycle2_enable
- to: 'on'
-
- - platform: state
- entity_id:
- - input_select.cycle1_schedule_time
- - input_select.cycle2_schedule_time
-
- - platform: state
- entity_id:
- - input_select.cycle1_watering_days
- - input_select.cycle2_watering_days
-
- action:
- - service: input_datetime.set_datetime
- data_template:
- entity_id: >
- {% if 'cycle1' in trigger.entity_id %}
- input_datetime.cycle1_next_run_time
- {% else %}
- input_datetime.cycle2_next_run_time
- {% endif %}
- date: >
- {% if 'cycle1' in trigger.entity_id %}
- {% set time = states('input_select.cycle1_schedule_time') %}
- {% else %}
- {% set time = states('input_select.cycle2_schedule_time') %}
- {% endif %}
- {% if now().strftime('%H:%M') < time %}
- {{ as_timestamp(now()) | timestamp_custom("%Y-%m-%d") }}
- {% else %}
- {{ (as_timestamp(now()) + 24 * 3600 ) | timestamp_custom("%Y-%m-%d") }}
- {% endif %}
- time: >
- {% if 'cycle1' in trigger.entity_id %}
- {{ states('input_select.cycle1_schedule_time') }}
- {% else %}
- {{ states('input_select.cycle2_schedule_time') }}
- {% endif %}
-
-
-#==================================================================
-#=== Run irrigation cycles at the right time and on the right days
-#==================================================================
-
- #=== Cycle 1
- - alias: Irrigation - Run Cycle 1
- initial_state: 'on'
- trigger:
- - platform: time_pattern
- minutes: 00
- seconds: 00
-
- condition:
- - condition: template
- value_template: >
- {{ now().strftime('%Y-%m-%d %H:%M:00') == states('input_datetime.cycle1_next_run_time') }}
-
- - condition: state
- entity_id: input_boolean.cycle1_enable
- state: 'on'
-
- action:
- - service: script.irrigation_run_a_cycle
- data_template:
- cycle: 1
-
- - service: script.update_next_runtime
- data_template:
- cycle: 1
-
- #=== Cycle 2
- - alias: Irrigation - Run Cycle 2
- initial_state: 'on'
- trigger:
- - platform: time_pattern
- minutes: 00
- seconds: 00
-
- condition:
- - condition: template
- value_template: >
- {{ now().strftime('%Y-%m-%d %H:%M:00') == states('input_datetime.cycle2_next_run_time') }}
-
- - condition: state
- entity_id: input_boolean.cycle2_enable
- state: 'on'
-
- action:
- - service: script.irrigation_run_a_cycle
- data_template:
- cycle: 2
-
- - service: script.update_next_runtime
- data_template:
- cycle: 2
-
-
- #======================
- # Run A Cycle Manually
- #======================
- - alias: Irrigation - Run a cycle manually
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - input_boolean.cycle1_manual_run
- - input_boolean.cycle2_manual_run
- from: 'off'
- to: 'on'
-
- condition:
- #=== Don't run if the other cycle is already running
- - condition: template
- value_template: >
- {% if trigger.entity_id == 'input_boolean.cycle1_manual_run' %}
- {{ states('sensor.cycle2_running') == 'Not running' }}
- {% else %}
- {{ states('sensor.cycle1_running') == 'Not running' }}
- {% endif %}
-
- action:
- #=== Update progress in ui
- - service: input_text.set_value
- data_template:
- entity_id: >
- {% if trigger.entity_id == 'input_boolean.cycle1_manual_run' %}
- input_text.cycle1_current_zone
- {% else %}
- input_text.cycle2_current_zone
- {% endif %}
- value: 'Initialising...'
-
- #=== Make sure nothing in the system is running
- #=== Turn off valves
- - service: homeassistant.turn_off
- data_template:
- entity_id: group.irrigation_switches
-
- #=== turn off scripts
- - service: homeassistant.turn_off
- entity_id: script.irrigation_run_a_cycle
-
- - service: homeassistant.turn_off
- entity_id: script.irrigation_irrigate_a_zone
-
- # #=== Save the current state of both cycle_enabled booleans
- - service_template: >
- {% if is_state('input_boolean.cycle1_enable', 'on') %}
- input_boolean.turn_on
- {% else %}
- input_boolean.turn_off
- {% endif %}
- data:
- entity_id: input_boolean.cycle1_enable_saved_state
-
- - service_template: >
- {% if is_state('input_boolean.cycle2_enable', 'on') %}
- input_boolean.turn_on
- {% else %}
- input_boolean.turn_off
- {% endif %}
- data:
- entity_id: input_boolean.cycle2_enable_saved_state
-
- #=== Disable both programmes
- - service: homeassistant.turn_off
- entity_id:
- - input_boolean.cycle1_enable
- - input_boolean.cycle2_enable
-
- #=== Run a cycle
- - service: script.irrigation_run_a_cycle
- data_template:
- cycle: >
- {% if trigger.entity_id == 'input_boolean.cycle1_manual_run' %}
- 1
- {% else %}
- 2
- {% endif %}
-
- #=== Wait until script is finished
- - wait_template: "{{ is_state('script.irrigation_run_a_cycle', 'off') }}"
-
- #=== Turn off both manual run booleans (in case one was turned on
- #=== while the other was already running)
- - service: homeassistant.turn_off
- entity_id:
- - input_boolean.cycle1_manual_run
- - input_boolean.cycle2_manual_run
-
- # #=== Restore the previous state of both cycle_enabled booleans
- - service_template: >
- {% if is_state('input_boolean.cycle1_enable_saved_state', 'on') %}
- input_boolean.turn_on
- {% else %}
- input_boolean.turn_off
- {% endif %}
- data:
- entity_id: input_boolean.cycle1_enable
-
- - service_template: >
- {% if is_state('input_boolean.cycle2_enable_saved_state', 'on') %}
- input_boolean.turn_on
- {% else %}
- input_boolean.turn_off
- {% endif %}
- data:
- entity_id: input_boolean.cycle2_enable
-
-
- #=======================
- # Cancel A Manual Cycle
- #=======================
- - alias: Irrigation - Cancel a manual cycle
- initial_state: on
- trigger:
- - platform: state
- entity_id:
- - input_boolean.cycle1_manual_run
- - input_boolean.cycle2_manual_run
- from: 'on'
- to: 'off'
-
- action:
- #=== Turn off valves
- - service: homeassistant.turn_off
- data_template:
- entity_id: group.irrigation_switches
-
- #=== Turn off scripts
- - service: homeassistant.turn_off
- entity_id: script.irrigation_run_a_cycle
-
- - service: homeassistant.turn_off
- entity_id: script.irrigation_irrigate_a_zone
-
- #=== Cancel the timer
- - service: timer.cancel
- data_template:
- entity_id: >
- {% if trigger.entity_id == 'input_boolean.cycle1_manual_run' %}
- timer.cycle1_zone_duration
- {% else %}
- timer.cycle2_zone_duration
- {% endif %}
-
- #=== Update progress in ui
- - service: homeassistant.turn_off
- data_template:
- entity_id: >
- {% if trigger.entity_id == 'input_boolean.cycle1_manual_run' %}
- input_boolean.cycle1_running
- {% else %}
- input_boolean.cycle2_running
- {% endif %}
-
- - service: input_text.set_value
- data_template:
- entity_id: >
- {% if trigger.entity_id == 'input_boolean.cycle1_manual_run' %}
- input_text.cycle1_current_zone
- {% else %}
- input_text.cycle2_current_zone
- {% endif %}
- value: 'None'
-
-
- #===================================================
- #=== Update the last time an irrigation cycle ended
- #===================================================
- - alias: Irrigation - Update the last time a cycle ended
- initial_state: on
- trigger:
- - platform: state
- entity_id: group.irrigation_switches
- to: 'off'
- for: '00:00:05'
-
- action:
- - service: input_datetime.set_datetime
- data_template:
- entity_id: input_datetime.last_irrigated_time
- date: >
- {{ as_timestamp(now()) | timestamp_custom("%Y-%m-%d") }}
- time: >
- {{ as_timestamp(now()) | timestamp_custom("%H:%M") }}
-
-
-#============
-#=== Scripts
-#============
-script:
-
- #==========================
- #=== Script to run a cycle
- #=== is passed:
- #=== {{ cycle }}
- #==========================
- irrigation_run_a_cycle:
- sequence:
-
- #=== Only continue if no cycle is running
- - condition: state
- entity_id: 'sensor.cycle1_running'
- state: 'Not running'
-
- - condition: state
- entity_id: 'sensor.cycle2_running'
- state: 'Not running'
-
- #=== Update ui to show cycle is running
- - service: homeassistant.turn_on
- data_template:
- entity_id: input_boolean.cycle{{ cycle }}_running
-
- #=== Call the script to irrigate zone 1
- - service: script.irrigation_irrigate_a_zone
- data_template:
- cycle: '{{ cycle }}'
- zone: 1
-
- #=== Wait for script.irrigation_irrigate_a_zone to end
- - wait_template: "{{ is_state('script.irrigation_irrigate_a_zone', 'off') }}"
-
- #=== Call the script to irrigate zone 2
- - service: script.irrigation_irrigate_a_zone
- data_template:
- cycle: '{{ cycle }}'
- zone: 2
-
- #=== Wait for script.irrigation_irrigate_a_zone to end
- - wait_template: "{{ is_state('script.irrigation_irrigate_a_zone', 'off') }}"
-
- #=== Call the script to irrigate zone 3
- - service: script.irrigation_irrigate_a_zone
- data_template:
- cycle: '{{ cycle }}'
- zone: 3
-
- #=== Wait for script.irrigation_irrigate_a_zone to end
- - wait_template: "{{ is_state('script.irrigation_irrigate_a_zone', 'off') }}"
-
- #=== Call the script to irrigate zone 4
- - service: script.irrigation_irrigate_a_zone
- data_template:
- cycle: '{{ cycle }}'
- zone: 4
-
- #=== Wait for script.irrigation_irrigate_a_zone to end
- - wait_template: "{{ is_state('script.irrigation_irrigate_a_zone', 'off') }}"
-
- #=== Call the script to irrigate zone 5
- - service: script.irrigation_irrigate_a_zone
- data_template:
- cycle: '{{ cycle }}'
- zone: 5
-
- #=== Wait for script.irrigation_irrigate_a_zone to end
- - wait_template: "{{ is_state('script.irrigation_irrigate_a_zone', 'off') }}"
-
- #=== Update progress in ui
- - service: input_text.set_value
- data_template:
- entity_id: input_text.cycle{{ cycle }}_current_zone
- value: 'None'
-
- - service: homeassistant.turn_off
- data_template:
- entity_id: input_boolean.cycle{{ cycle }}_running
-
- #=== Turn off schedule if run 'Once' selected
- - service_template: >
- {% if states('input_select.cycle' + cycle + '_watering_days') == 'Once' %}
- input_boolean.turn_off
- {% else %}
- input_boolean.turn_on
- {% endif %}
- data_template:
- entity_id: input_boolean.cycle{{ cycle }}_enabled
-
-
- #==============================
- #=== Script to irrigate a zone
- #=== is passed:
- #=== {{ cycle }}
- #=== {{ zone }}
- #==============================
- irrigation_irrigate_a_zone:
- sequence:
-
- #=== Don't continue if switch is unavailable
- - condition: template
- value_template: >
- {{ states('switch.zone' + zone + '_valve') != 'unavailable' }}
-
- #=== Don't continue if duration is zero
- - condition: template
- value_template: >
- {% if is_state('input_boolean.cycle' + cycle + '_use_weather_adjustment', 'on') %}
- {% set n = states('input_number.adjusted_cycle' + cycle + '_zone' + zone + '_duration') | int %}
- {% else %}
- {% set n = states('input_number.cycle' + cycle + '_zone' + zone + '_duration') | int %}
- {% endif %}
- {{ n != 0 }}
-
- #=== Call the script to set the sonoff PULSETIME
- - service: script.set_sonoff_pulsetime
- data_template:
- cycle: '{{ cycle }}'
- zone: '{{ zone }}'
-
- #=== Wait 5 seconds for good measure to ensure previous zone is completly finished
- - delay: "00:00:05"
-
- #=== Update progress in ui
- - service: input_text.set_value
- data_template:
- entity_id: 'input_text.cycle{{ cycle }}_current_zone'
- value: '{{ zone }}'
-
- - service: switch.turn_on
- data_template:
- entity_id: switch.zone{{ zone }}_valve
-
- #=== Start timer for zone duration
- - service: timer.start
- data_template:
- entity_id: timer.cycle{{ cycle }}_zone_duration
- duration: >
- {% set duration = states('input_number.cycle' + cycle + '_zone' + zone + '_duration') | int %}
- {% set adj_duration = states('input_number.adjusted_cycle' + cycle + '_zone' + zone + '_duration') | int %}
- {% if is_state('input_boolean.cycle' + cycle + '_use_weather_adjustment', 'on') %}
- 00:{{ '%02i' | format(adj_duration) }}:00
- {% else %}
- 00:{{ '%02i' | format(duration) }}:00
- {% endif %}
-
- - wait_template: >
- {% set entity = 'timer.cycle' + cycle + '_zone_duration' %}
- {{ is_state(entity , 'idle') }}
-
- - service: switch.turn_off
- data_template:
- entity_id: switch.zone{{ zone }}_valve
-
- #=== Update progress in ui
- - service: input_text.set_value
- data_template:
- entity_id: input_text.cycle{{ cycle }}_current_zone
- value: 'Changing zone...'
-
- #=== Be sure the current zone switch is off
- - wait_template: >
- {% set entity = 'switch.zone' + zone + '_valve' %}
- {{ is_state(entity , 'off') }}
-
-
- #==================================
- #=== Script to update next runtime
- #=== is passed:
- #=== {{ cycle }}
- #==================================
- update_next_runtime:
- sequence:
- - service: input_datetime.set_datetime
- data_template:
- entity_id: input_datetime.cycle{{ cycle }}_next_run_time
- date: >
- {% if states('input_select.cycle' + cycle + '_watering_days') == 'Daily' %}
- {{ (as_timestamp(now() ) + 24 * 3600 ) | timestamp_custom("%Y-%m-%d") }}
- {% elif states('input_select.cycle' + cycle + '_watering_days') == 'Alternate' %}
- {{ (as_timestamp(now() ) + 48 * 3600 ) | timestamp_custom("%Y-%m-%d") }}
- {% else %}
- {{ states('input_datetime.cycle' + cycle + '_next_run_time').split(' ')[0] }}
- {% endif %}
- time: >
- {{ states('input_select.cycle' + cycle + '_schedule_time') }}
-
-
- #========================================================================
- #=== Set Sonoff PULSETIME to 30 seconds longer than the zone runtime
- #=== is passed:
- #=== {{ cycle }}
- #=== {{ zone }}
- #===
- #=== This acts as a fail safe in the event of any communication failure
- #=== between HA and the Sonoff. The Sonoff will switch off under its own
- #=== control so closing the valve.
- #===
- #=== Note: From the Tasmota wiki, for a Pulsetime greater than 11 seconds
- #=== it should be set to 100 + (minutes * 60)
- #========================================================================
- set_sonoff_pulsetime:
- sequence:
- - service: mqtt.publish
- data_template:
- topic: >
- sonoff4ch01/cmnd/pulsetime{{ zone }}
- payload: >
- {% set payload = states('input_number.cycle' + cycle + '_zone' + zone + '_duration') | int %}
- {% set payload = 100 + (payload * 60) + 30 %}
- {{ payload }}
-
From 1dfde0da157b045762683c77b07b2897efe25ac7 Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:39:49 -0700
Subject: [PATCH 11/51] Delete garden_globals.yaml
---
packages/garden/garden_globals.yaml | 492 ----------------------------
1 file changed, 492 deletions(-)
delete mode 100644 packages/garden/garden_globals.yaml
diff --git a/packages/garden/garden_globals.yaml b/packages/garden/garden_globals.yaml
deleted file mode 100644
index c2e3346..0000000
--- a/packages/garden/garden_globals.yaml
+++ /dev/null
@@ -1,492 +0,0 @@
-
-#===========
-#=== Groups
-#===========
-group:
- irrigation_switches:
- entities:
- - switch.zone1_valve
- - switch.zone2_valve
- - switch.zone3_valve
- - switch.zone4_valve
- - switch.zone5_valve
-
-
-#===================
-#=== Input_Booleans
-#===================
-input_boolean:
-
- irrigation_master_control_switch:
- name: Master Control Switch
- icon: mdi:bomb
-
- cycle1_enable:
- name: Enable schedule
- icon: mdi:pipe
-
- cycle2_enable:
- name: Enable schedule
- icon: mdi:pipe
-
- cycle1_enable_saved_state:
-
- cycle2_enable_saved_state:
-
- cycle1_use_weather_adjustment:
- name: Use weather adjustment
- icon: mdi:weather-partlycloudy
-
- cycle2_use_weather_adjustment:
- name: Use weather adjustment
- icon: mdi:weather-partlycloudy
-
- cycle1_manual_run:
- name: Run morning cycle now
- icon: mdi:arrow-right-drop-circle
-
- cycle2_manual_run:
- name: Run afternoon cycle now
- icon: mdi:arrow-right-drop-circle
-
- cycle1_running:
- name: Cycle 1 running
-
- cycle2_running:
- name: Cycle 2 running
-
-
-#================
-#=== Input_Texts
-#================
-input_text:
- cycle1_current_zone:
- name: Cycle 1 current zone
-
- cycle2_current_zone:
- name: Cycle 2 current zone
-
-
-#==================
-#=== Input_Selects
-#==================
-input_select:
-
- cycle1_watering_days:
- name: Morning cycle watering days
- options:
- - 'Daily'
- - 'Alternate'
- - 'Once'
- icon: mdi:calendar
-
- cycle2_watering_days:
- name: Afternoon cycle watering days
- options:
- - 'Daily'
- - 'Alternate'
- - 'Once'
- icon: mdi:calendar
-
- cycle1_schedule_time:
- name: Morning cycle schedule start time
- options:
- - '08:00'
- - '09:00'
- - '10:00'
- - '11:00'
- - '12:00'
- icon: mdi:alarm
-
- cycle2_schedule_time:
- name: Afternoon cycle schedule start time
- options:
- - '16:00'
- - '17:00'
- - '18:00'
- - '19:00'
- - '20:00'
- icon: mdi:alarm
-
-
-#====================
-#=== Input_Datetimes
-#====================
-input_datetime:
- cycle1_next_run_time:
- has_date: true
- has_time: true
-
- cycle2_next_run_time:
- has_date: true
- has_time: true
-
- last_irrigated_time:
- has_date: true
- has_time: true
-
-
-#==================
-#=== Input_Numbers
-#==================
-input_number:
-
- # CYCLE 1
- cycle1_zone1_duration:
- name: Zone 1 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle1_zone2_duration:
- name: Zone 2 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle1_zone3_duration:
- name: Zone 3 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle1_zone4_duration:
- name: Zone 4 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle1_zone5_duration:
- name: Zone 5 duration
- min: 0
- max: 59
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- # CYCLE 2
- cycle2_zone1_duration:
- name: Zone 1 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle2_zone2_duration:
- name: Zone 2 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle2_zone3_duration:
- name: Zone 3 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle2_zone4_duration:
- name: Zone 4 duration
- min: 0
- max: 30
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- cycle2_zone5_duration:
- name: Zone 5 duration
- min: 0
- max: 59
- step: 1
- icon: mdi:camera-timer
- unit_of_measurement: mins
-
- # The temperature above or below which the duration is adjusted
- temperature_baseline:
- name: Temperature baseline
- min: 20
- max: 30
- icon: mdi:thermometer
- unit_of_measurement: '°C'
-
- # How much rain is needed before the duration is reduced
- rainfall_threshold:
- name: Rainfall threshold
- min: 5
- max: 30
- icon: mdi:weather-rainy
- unit_of_measurement: 'mm'
-
- # Adjusted duration times can be extreme during calculations
- # depending on weather conditions so min and max are set high
- adjusted_cycle1_zone1_duration:
- name: Adjusted cycle1 zone1 duration
- min: -60
- max: 60
-
- adjusted_cycle1_zone2_duration:
- name: Adjusted cycle1 zone2 duration
- min: -60
- max: 60
-
- adjusted_cycle1_zone3_duration:
- name: Adjusted cycle1 zone3 duration
- min: -60
- max: 60
-
- adjusted_cycle1_zone4_duration:
- name: Adjusted cycle1 zone4 duration
- min: -60
- max: 60
-
- adjusted_cycle1_zone5_duration:
- name: Adjusted cycle1 zone5 duration
- min: -60
- max: 120
-
- adjusted_cycle2_zone1_duration:
- name: Adjusted cycle1 zone1 duration
- min: -60
- max: 60
-
- adjusted_cycle2_zone2_duration:
- name: Adjusted cycle1 zone2 duration
- min: -60
- max: 60
-
- adjusted_cycle2_zone3_duration:
- name: Adjusted cycle1 zone3 duration
- min: -60
- max: 60
-
- adjusted_cycle2_zone4_duration:
- name: Adjusted cycle1 zone4 duration
- min: -60
- max: 60
-
- adjusted_cycle2_zone5_duration:
- name: Adjusted cycle1 zone5 duration
- min: -60
- max: 120
-
-
-#===========
-#=== timers
-#===========
-timer:
- cycle1_zone_duration:
- name: Time remaining
-
- cycle2_zone_duration:
- name: Time remaining
-
-
-#============
-#=== Sensors
-#============
-sensor:
- - platform: template
- sensors:
-
- cycle1_next_run_time:
- friendly_name: "Next scheduled run time"
- value_template: >
- {% if is_state('input_boolean.cycle1_enable', 'on') %}
- {{ state_attr('input_datetime.cycle1_next_run_time', 'timestamp') | timestamp_custom("%a %d %h at %H:%M") }}
- {% else %}
- None
- {% endif %}
-
- cycle2_next_run_time:
- friendly_name: "Next scheduled run time"
- value_template: >
- {% if is_state('input_boolean.cycle2_enable', 'on') %}
- {{ state_attr('input_datetime.cycle2_next_run_time', 'timestamp') | timestamp_custom("%a %d %h at %H:%M") }}
- {% else %}
- None
- {% endif %}
-
- cycle1_running:
- friendly_name: "Morning cycle"
- value_template: >
- {% if is_state('input_boolean.cycle1_running', 'on') %}
- Running
- {% else %}
- Not running
- {% endif %}
- icon_template: >
- {% if is_state('input_boolean.cycle1_running', 'on') %}
- mdi:run
- {% else %}
- mdi:human-handsdown
- {% endif %}
-
- cycle2_running:
- friendly_name: "Afternoon cycle"
- value_template: >
- {% if is_state('input_boolean.cycle2_running', 'on') %}
- Running
- {% else %}
- Not running
- {% endif %}
- icon_template: >
- {% if is_state('input_boolean.cycle2_running', 'on') %}
- mdi:run
- {% else %}
- mdi:human-handsdown
- {% endif %}
-
- cycle1_zone_being_watered:
- friendly_name: "Zone being watered"
- value_template: "{{ states('input_text.cycle1_current_zone') }}"
-
- cycle2_zone_being_watered:
- friendly_name: "Zone being watered"
- value_template: "{{ states('input_text.cycle2_current_zone') }}"
-
- last_irrigated_time:
- friendly_name: "Last irrigation cycle ended"
- value_template: >
- {{ (as_timestamp(states.input_datetime.last_irrigated_time.state)) | timestamp_custom("%a %d %h at %H:%M") }}
-
- # Zone Times - templated on history_stats sensors
- zone1_time_today:
- friendly_name: Zone 1 total watering time today
- value_template: >
- {% set duration = states('sensor.zone1_time') %}
- {{ duration|float|multiply(60)|round }}
- unit_of_measurement: mins
-
- zone2_time_today:
- friendly_name: Zone 2 total watering time today
- value_template: >
- {% set duration = states('sensor.zone2_time') %}
- {{ duration|float|multiply(60)|round }}
- unit_of_measurement: mins
-
- zone3_time_today:
- friendly_name: Zone 3 total watering time today
- value_template: >
- {% set duration = states('sensor.zone3_time') %}
- {{ duration|float|multiply(60)|round }}
- unit_of_measurement: mins
-
- zone4_time_today:
- friendly_name: Zone 4 total watering time today
- value_template: >
- {% set duration = states('sensor.zone4_time') %}
- {{ duration|float|multiply(60)|round }}
- unit_of_measurement: mins
-
- zone5_time_today:
- friendly_name: Zone 5 total watering time today
- value_template: >
- {% set duration = states('sensor.zone5_time') %}
- {{ duration|float|multiply(60)|round }}
- unit_of_measurement: mins
-
-
- cycle1_zone1_duration_adjusted:
- friendly_name: "Zone 1 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle1_zone1_duration') | int }}"
- unit_of_measurement: mins
-
- cycle1_zone2_duration_adjusted:
- friendly_name: "Zone 2 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle1_zone2_duration') | int }}"
- unit_of_measurement: mins
-
- cycle1_zone3_duration_adjusted:
- friendly_name: "Zone 3 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle1_zone3_duration') | int }}"
- unit_of_measurement: mins
-
- cycle1_zone4_duration_adjusted:
- friendly_name: "Zone 4 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle1_zone4_duration') | int }}"
- unit_of_measurement: mins
-
- cycle1_zone5_duration_adjusted:
- friendly_name: "Zone 5 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle1_zone5_duration') | int }}"
- unit_of_measurement: mins
-
- cycle2_zone1_duration_adjusted:
- friendly_name: "Zone 1 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle2_zone1_duration') | int }}"
- unit_of_measurement: mins
-
- cycle2_zone2_duration_adjusted:
- friendly_name: "Zone 2 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle2_zone2_duration') | int }}"
- unit_of_measurement: mins
-
- cycle2_zone3_duration_adjusted:
- friendly_name: "Zone 3 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle2_zone3_duration') | int }}"
- unit_of_measurement: mins
-
- cycle2_zone4_duration_adjusted:
- friendly_name: "Zone 4 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle2_zone4_duration') | int }}"
- unit_of_measurement: mins
-
- cycle2_zone5_duration_adjusted:
- friendly_name: "Zone 5 adjusted duration"
- value_template: "{{ states('input_number.adjusted_cycle2_zone5_duration') | int }}"
- unit_of_measurement: mins
-
- # History sensors
- # Zone Times
- - platform: history_stats
- name: zone1_time
- entity_id: switch.zone1_valve
- state: 'on'
- type: time
- start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
- end: '{{ now() }}'
-
- - platform: history_stats
- name: zone2_time
- entity_id: switch.zone2_valve
- state: 'on'
- type: time
- start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
- end: '{{ now() }}'
-
- - platform: history_stats
- name: zone3_time
- entity_id: switch.zone3_valve
- state: 'on'
- type: time
- start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
- end: '{{ now() }}'
-
- - platform: history_stats
- name: zone4_time
- entity_id: switch.zone4_valve
- state: 'on'
- type: time
- start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
- end: '{{ now() }}'
-
- - platform: history_stats
- name: zone5_time
- entity_id: switch.zone5_valve
- state: 'on'
- type: time
- start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
- end: '{{ now() }}'
-
From 7a329019976fb422f02b150c8af86e57303262a8 Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:40:42 -0700
Subject: [PATCH 12/51] Delete README.md
---
packages/occupancy/README.md | 65 ------------------------------------
1 file changed, 65 deletions(-)
delete mode 100644 packages/occupancy/README.md
diff --git a/packages/occupancy/README.md b/packages/occupancy/README.md
deleted file mode 100644
index 685bfad..0000000
--- a/packages/occupancy/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-__Guest Mode 'ON'__
-
-
-
-
-__Guest Mode 'ON' expanded__
-
-
-
-
-__Guest Mode 'ON' fully expanded__
-
-
-
-
-__Guest Mode 'ON' two schedules fully expanded__
-
-
-
-
-__Guest Mode popup__
-
-
From d35e3328a790e5418a197a5516be072c72f8d1e4 Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:40:57 -0700
Subject: [PATCH 13/51] Delete occupancy_guest_mode_globals.yaml
---
.../occupancy_guest_mode_globals.yaml | 124 ------------------
1 file changed, 124 deletions(-)
delete mode 100644 packages/occupancy/occupancy_guest_mode_globals.yaml
diff --git a/packages/occupancy/occupancy_guest_mode_globals.yaml b/packages/occupancy/occupancy_guest_mode_globals.yaml
deleted file mode 100644
index 9f4591a..0000000
--- a/packages/occupancy/occupancy_guest_mode_globals.yaml
+++ /dev/null
@@ -1,124 +0,0 @@
-#===================
-#=== Input booleans
-#===================
-input_boolean:
-
- # Guest mode is used when a guest is in the house but either does not
- # have a known device or is not 'trusted' indefinitely e.g. the cleaner.
- guest_mode_once:
- name: Guest mode (once)
- icon: mdi:human-handsup
-
- guest_mode_schedule_1:
- name: Guest mode schedule (1)
- icon: mdi:human-handsup
-
- guest_mode_schedule_2:
- name: Guest mode schedule (2)
- icon: mdi:human-handsup
-
- holiday_mode_on:
- name: Holiday mode on
- icon: mdi:beach
-
-
-#================
-#=== Input texts
-#================
-input_text:
- guest_mode_schedule_1_name:
- name: Name
-
- guest_mode_schedule_2_name:
- name: Name
-
-
-#===================
-#=== Input numbers
-#===================
-input_number:
- guest_mode_once_duration:
- name: Duration
- icon: mdi:camera-timer
- min: 0
- max: 360
- step: 30
- unit_of_measurement: 'mins'
-
- guest_mode_schedule_1_duration:
- name: Duration
- icon: mdi:camera-timer
- min: 0
- max: 360
- step: 30
- unit_of_measurement: 'mins'
-
- guest_mode_schedule_2_duration:
- name: Duration
- icon: mdi:camera-timer
- min: 0
- max: 360
- step: 30
- unit_of_measurement: 'mins'
-
-
-#==================
-#=== Input selects
-#==================
-input_select:
- guest_mode_schedule_1_day:
- name: Day
- options:
- - 'Every Day'
- - 'Monday'
- - 'Tuesday'
- - 'Wednesday'
- - 'Thursday'
- - 'Friday'
- - 'Sataurday'
- - 'Sunday'
- icon: mdi:calendar
-
- guest_mode_schedule_2_day:
- name: Day
- options:
- - 'Every Day'
- - 'Monday'
- - 'Tuesday'
- - 'Wednesday'
- - 'Thursday'
- - 'Friday'
- - 'Sataurday'
- - 'Sunday'
- icon: mdi:calendar
-
-
-#====================
-#=== Input datetimes
-#====================
-input_datetime:
- guest_mode_schedule_1_start_time:
- name: Start time
- has_date: false
- has_time: true
-
- guest_mode_schedule_2_start_time:
- name: Start time
- has_date: false
- has_time: true
-
-
-#===========
-#=== timers
-#===========
-timer:
- guest_mode_once_duration:
- name: Time remaining (once)
-
- guest_mode_schedule_1_duration:
- name: Time remaining (schedule 1)
-
- guest_mode_schedule_2_duration:
- name: Time remaining (schedule 2)
-
-
From f4cd686b272556c8a67d7c52c912c79c493e1e95 Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:41:04 -0700
Subject: [PATCH 14/51] Delete occupancy_guest_mode.yaml
---
packages/occupancy/occupancy_guest_mode.yaml | 354 -------------------
1 file changed, 354 deletions(-)
delete mode 100644 packages/occupancy/occupancy_guest_mode.yaml
diff --git a/packages/occupancy/occupancy_guest_mode.yaml b/packages/occupancy/occupancy_guest_mode.yaml
deleted file mode 100644
index 0cb5b76..0000000
--- a/packages/occupancy/occupancy_guest_mode.yaml
+++ /dev/null
@@ -1,354 +0,0 @@
-#================
-#=== Automations
-#================
-automation:
-
- #====================================================
- #=== Check Guest mode schedule timers at HA start up
- #===
- #=== If the house is not in holiday mode and
- #=== if they are turned on, it is the right day and
- #=== the time now is during the on time then set
- #=== the timer to run until the scheduled end time.
- #====================================================
- #=== Guest Schedule 1
- - alias: Guest mode schedule 1 check at startup
- # initial_state: on
- trigger:
- - platform: homeassistant
- event: start
-
- condition:
- - condition: state
- entity_id: binary_sensor.holiday_mode
- state: 'off'
-
- - condition: state
- entity_id: input_boolean.guest_mode_schedule_1
- state: 'on'
-
- - condition: or
- conditions:
- - condition: template
- value_template: "{{ states('input_select.guest_mode_schedule_1_day') == now().strftime('%A') }}"
-
- - condition: state
- entity_id: input_select.guest_mode_schedule_1_day
- state: 'Every Day'
-
- - condition: template
- value_template: >
- {% set time_now = as_timestamp(now()) %}
- {% set start_time = states('input_datetime.guest_mode_schedule_1_start_time') %}
- {% set start_time = as_timestamp(now()) | timestamp_custom('%Y-%m-%d') + ' ' + start_time %}
- {% set duration = states('input_number.guest_mode_schedule_1_duration') | int * 60 %}
- {% set end_time = as_timestamp(start_time) + duration %}
-
- {{ time_now > as_timestamp(start_time) and time_now < end_time }}
-
- action:
- - service: timer.start
- data_template:
- entity_id: timer.guest_mode_schedule_1_duration
- duration: >
- {% set time_now = as_timestamp(now()) %}
- {% set start_time = states('input_datetime.guest_mode_schedule_1_start_time') %}
- {% set start_time = as_timestamp(now()) | timestamp_custom('%Y-%m-%d') + ' ' + start_time %}
- {% set duration = states('input_number.guest_mode_schedule_1_duration') | int * 60 %}
- {% set end_time = as_timestamp(start_time) + duration %}
- {% set seconds_left = end_time - time_now %}
- {% set hours_left = seconds_left // 3600 %}
- {% set minutes_left = (seconds_left - (hours_left * 3600)) // 60 %}
-
- {{ '%02i' | format(hours_left) }}:{{ '%02i' | format(minutes_left) }}:01
-
-
- #=== Guest Schedule 2
- - alias: Guest mode schedule 2 check at startup
- # initial_state: on
- trigger:
- - platform: homeassistant
- event: start
-
- condition:
- - condition: state
- entity_id: binary_sensor.holiday_mode
- state: 'off'
-
- - condition: state
- entity_id: input_boolean.guest_mode_schedule_2
- state: 'on'
-
- - condition: or
- conditions:
- - condition: template
- value_template: "{{ states('input_select.guest_mode_schedule_2_day') == now().strftime('%A') }}"
-
- - condition: state
- entity_id: input_select.guest_mode_schedule_2_day
- state: 'Every Day'
-
- - condition: template
- value_template: >
- {% set time_now = as_timestamp(now()) %}
- {% set start_time = states('input_datetime.guest_mode_schedule_2_start_time') %}
- {% set start_time = as_timestamp(now()) | timestamp_custom('%Y-%m-%d') + ' ' + start_time %}
- {% set duration = states('input_number.guest_mode_schedule_2_duration') | int * 60 %}
- {% set end_time = as_timestamp(start_time) + duration %}
-
- {{ time_now > as_timestamp(start_time) and time_now < end_time }}
- action:
- - service: timer.start
- data_template:
- entity_id: timer.guest_mode_schedule_2_duration
- duration: >
- {% set time_now = as_timestamp(now()) %}
- {% set start_time = states('input_datetime.guest_mode_schedule_2_start_time') %}
- {% set start_time = as_timestamp(now()) | timestamp_custom('%Y-%m-%d') + ' ' + start_time %}
- {% set duration = states('input_number.guest_mode_schedule_2_duration') | int * 60 %}
- {% set end_time = as_timestamp(start_time) + duration %}
- {% set seconds_left = end_time - time_now %}
- {% set hours_left = seconds_left // 3600 %}
- {% set minutes_left = (seconds_left - (hours_left * 3600)) // 60 %}
-
- {{ '%02i' | format(hours_left) }}:{{ '%02i' | format(minutes_left) }}:01
-
-
- #====================
- #===
- #=== Guest Mode Once
- #===
- #====================
- #==================================================
- #=== Start the Guest Mode once timer
- #===
- #=== This is allowed when house is in holiday mode
- #=== to allow it to be turned on from Telegram but
- #=== in that case when timer is finished it will
- #=== then turn on Holiday Mode (Forced)
- #==================================================
- - alias: Guest Mode once start timer
- # initial_state: on
- trigger:
- - platform: state
- entity_id: input_boolean.guest_mode_once
- to: 'on'
-
- - platform: state
- entity_id: input_number.guest_mode_once_duration
-
- condition:
- - condition: state
- entity_id: input_boolean.guest_mode_once
- state: 'on'
-
- action:
- # Cancel the timer
- - service: timer.cancel
- data_template:
- entity_id: timer.guest_mode_once_duration
-
- # Re-start timer with new duration
- # Note that 00:00:00 doesn't work as a duration so always include one second
- - service: timer.start
- data_template:
- entity_id: timer.guest_mode_once_duration
- duration: >
- {% set duration = states('input_number.guest_mode_once_duration') | int %}
- {% set hours = duration // 60 %}
- {% set minutes = duration - (hours * 60) %}
- {{ '%02i' | format(hours) }}:{{ '%02i' | format(minutes) }}:01
-
-
- #==============================================================
- #=== Turn off Guest Mode once when the timer is finished and
- #=== turn holiday mode back on if it was on when timer started
- #==============================================================
- - alias: Guest Mode once timer finished
- # initial_state: on
- trigger:
- - platform: event
- event_type: timer.finished
- event_data:
- entity_id: timer.guest_mode_once_duration
-
- action:
- - service: input_boolean.turn_off
- data:
- entity_id: input_boolean.guest_mode_once
-
-
- #======================================
- #=== Turn off Guest Mode once manually
- #======================================
- - alias: Guest Mode once off
- # initial_state: on
- trigger:
- - platform: state
- entity_id: input_boolean.guest_mode_once
- to: 'off'
-
- action:
- - service: timer.finish
- data_template:
- entity_id: timer.guest_mode_once_duration
-
-
- #==========================
- #===
- #=== Guest Mode Schedule 1
- #===
- #==========================
- #===========================================
- #=== Start the scheduled Guest Mode 1 timer
- #=== If the house is not in holiday mode
- #=== At the right time
- #=== If it is the right day
- #===========================================
- - alias: Guest Mode schedule 1 start timer
- # initial_state: on
- trigger:
- - platform: template
- value_template: "{{ states('sensor.time') ~ ':00' == states('input_datetime.guest_mode_schedule_1_start_time') }}"
-
- condition:
- - condition: state
- entity_id: binary_sensor.holiday_mode
- state: 'off'
-
- - condition: state
- entity_id: input_boolean.guest_mode_schedule_1
- state: 'on'
-
- - condition: template
- value_template: "{{ states('input_select.guest_mode_schedule_1_day') == now().strftime('%A') or
- states('input_select.guest_mode_schedule_1_day') == 'Every Day' }}"
-
- action:
- # Cancel the timer
- - service: timer.cancel
- data_template:
- entity_id: timer.guest_mode_schedule_1_duration
-
- # Re-start timer with new duration
- # Note that 00:00:00 doesn't work as a duration so always include one second
- - service: timer.start
- data_template:
- entity_id: timer.guest_mode_schedule_1_duration
- duration: >
- {% set duration = states('input_number.guest_mode_schedule_1_duration') | int %}
- {% set hours = duration // 60 %}
- {% set minutes = duration - (hours * 60) %}
- {{ '%02i' | format(hours) }}:{{ '%02i' | format(minutes) }}:01
-
- - service: browser_mod.command
- data:
- command: popup
- title: Guest Mode Schedule 1 has started
- card:
- type: entity-filter
- show_header_toggle: false
- entities:
- - timer.guest_mode_once_duration
- - timer.guest_mode_schedule_1_duration
- - timer.guest_mode_schedule_2_duration
- state_filter:
- - "active"
- deviceID:
- - MYPC
-
-
- #=============================================
- #=== Turn off scheduled Guest Mode 1 manually
- #=============================================
- - alias: Guest Mode schedule 1 off
- # initial_state: on
- trigger:
- - platform: state
- entity_id: input_boolean.guest_mode_schedule_1
- to: 'off'
-
- action:
- - service: timer.finish
- data_template:
- entity_id: timer.guest_mode_schedule_1_duration
-
-
- #==========================
- #===
- #=== Guest Mode Schedule 2
- #===
- #==========================
- #===========================================
- #=== Start the scheduled Guest Mode 2 timer
- #=== If the house is not in holiday mode
- #=== At the right time
- #=== If it is the right day
- #===========================================
- - alias: Guest Mode schedule 2 start timer
- # initial_state: on
- trigger:
- - platform: template
- value_template: "{{ states('sensor.time') ~ ':00' == states('input_datetime.guest_mode_schedule_2_start_time') }}"
-
- condition:
- - condition: state
- entity_id: binary_sensor.holiday_mode
- state: 'off'
-
- - condition: state
- entity_id: input_boolean.guest_mode_schedule_2
- state: 'on'
-
- - condition: template
- value_template: "{{ states('input_select.guest_mode_schedule_2_day') == now().strftime('%A') or
- states('input_select.guest_mode_schedule_2_day') == 'Every Day' }}"
-
- action:
- # Cancel the timer
- - service: timer.cancel
- data_template:
- entity_id: timer.guest_mode_schedule_2_duration
-
- # Re-start timer with new duration
- # Note that 00:00:00 doesn't work as a duration so always include one second
- - service: timer.start
- data_template:
- entity_id: timer.guest_mode_schedule_2_duration
- duration: >
- {% set duration = states('input_number.guest_mode_schedule_2_duration') | int %}
- {% set hours = duration // 60 %}
- {% set minutes = duration - (hours * 60) %}
- {{ '%02i' | format(hours) }}:{{ '%02i' | format(minutes) }}:01
-
- - service: browser_mod.command
- data:
- command: popup
- title: Guest Mode Schedule 2 has started
- card:
- type: entity-filter
- show_header_toggle: false
- entities:
- - timer.guest_mode_once_duration
- - timer.guest_mode_schedule_1_duration
- - timer.guest_mode_schedule_2_duration
- state_filter:
- - "active"
- deviceID:
- - MYPC
-
-
- #=============================================
- #=== Turn off scheduled Guest Mode 2 manually
- #=============================================
- - alias: Guest Mode schedule 2 off
- # initial_state: on
- trigger:
- - platform: state
- entity_id: input_boolean.guest_mode_schedule_2
- to: 'off'
-
- action:
- - service: timer.finish
- data_template:
- entity_id: timer.guest_mode_schedule_2_duration
From 680660603167ac1a75b13a9ccf84a7c9123a9bc8 Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:47:41 -0700
Subject: [PATCH 15/51] Update view_garden.yaml
---
lovelace/views/view_garden.yaml | 374 ++++++++++----------------------
1 file changed, 113 insertions(+), 261 deletions(-)
diff --git a/lovelace/views/view_garden.yaml b/lovelace/views/view_garden.yaml
index 3c8678c..738f3d5 100644
--- a/lovelace/views/view_garden.yaml
+++ b/lovelace/views/view_garden.yaml
@@ -1,265 +1,117 @@
-#================================
-#===
-#=== GARDEN
-#===
-#================================
-title: Garden
-icon: mdi:flower
-cards:
-
- - type: custom:compact-custom-header
-
- #==========================
- #=== Master Control Switch
- #==========================
- - type: vertical-stack
+ - badges: []
cards:
-
- - type: picture-entity
- entity: input_boolean.irrigation_master_control_switch
- image: /local/lovelace/lawn-sprinkler.jpg
- tap_action:
- action: toggle
-
- - type: conditional
+ - cards:
+ - entity: input_boolean.irrigation_master_control_switch
+ state_image:
+ 'off': /local/sprinkler-off.png
+ 'on': /local/sprinkler-on.png
+ tap_action:
+ action: toggle
+ type: picture-entity
+ - card:
+ cards:
+ - cards:
+ - entity: input_boolean.cycle1_manual_run
+ name: Morning Cycle
+ tap_action:
+ action: toggle
+ type: 'custom:toggle-lock-entity-row'
+ - entity: input_boolean.cycle2_manual_run
+ name: Afternoon Cycle
+ tap_action:
+ action: toggle
+ type: 'custom:toggle-lock-entity-row'
+ type: horizontal-stack
+ - entities:
+ - entity: switch.zone1
+ icon: 'mdi:engine'
+ - entity: switch.zone2
+ icon: 'mdi:engine'
+ - entity: switch.zone3
+ icon: 'mdi:engine'
+ - entity: switch.zone4
+ icon: 'mdi:engine'
+ - entity: switch.zone5
+ icon: 'mdi:engine'
+ type: glance
+ - entities:
+ - head:
+ entity: sensor.last_irrigated_time
+ icon: 'mdi:update'
+ items:
+ - entity: sensor.zone1_time_today
+ icon: 'mdi:water'
+ - entity: sensor.zone2_time_today
+ icon: 'mdi:water'
+ - entity: sensor.zone3_time_today
+ icon: 'mdi:water'
+ - entity: sensor.zone4_time_today
+ icon: 'mdi:water'
+ - entity: sensor.zone5_time_today
+ icon: 'mdi:water'
+ type: 'custom:fold-entity-row'
+ show_header_toggle: false
+ title: Irrigation History
+ type: entities
+ type: vertical-stack
+ conditions:
+ - entity: input_boolean.irrigation_master_control_switch
+ state: 'on'
+ type: conditional
+ type: vertical-stack
+ - card:
+ entities:
+ - sensor.cycle1_running
+ - entity: sensor.cycle1_zone_being_watered
+ icon: 'mdi:fountain'
+ - timer.cycle1_zone_duration
+ - input_number.cycle1_zone1_duration
+ - input_number.cycle1_zone2_duration
+ - input_number.cycle1_zone3_duration
+ - input_number.cycle1_zone4_duration
+ - input_number.cycle1_zone5_duration
+ - head:
+ entity: input_boolean.cycle1_enable
+ type: 'custom:toggle-lock-entity-row'
+ items:
+ - entity: sensor.cycle1_next_run_time
+ icon: 'mdi:clock-start'
+ - input_select.cycle1_schedule_time
+ - input_select.cycle1_watering_days
+ type: 'custom:fold-entity-row'
+ show_header_toggle: false
+ title: Area 1
+ type: entities
conditions:
- entity: input_boolean.irrigation_master_control_switch
state: 'on'
- card:
- type: vertical-stack
- cards:
-
- #=== Manual control buttons
- - type: horizontal-stack
- cards:
- - type: custom:toggle-lock-entity-row
-# - type: entity-button
- entity: input_boolean.cycle1_manual_run
- name: Morning Cycle
- tap_action:
- action: toggle
-
- - type: custom:toggle-lock-entity-row
-# - type: entity-button
- entity: input_boolean.cycle2_manual_run
- name: Afternoon Cycle
- tap_action:
- action: toggle
-
- #=== Valve information
- - type: 'custom:config-template-card'
- entities:
- - switch.zone1_valve
- - switch.zone2_valve
- - switch.zone3_valve
- - switch.zone4_valve
- - switch.zone5_valve
- - sensor.zone1to4_valve
- - sensor.zone5_valve
- variables:
- - states['sensor.zone1to4_valve'].state
- - states['sensor.zone5_valve'].state
- card:
- type: 'custom:hui-glance-card'
- entities:
- - entity: switch.zone1_valve
- icon: mdi:engine
- - entity: switch.zone2_valve
- icon: mdi:engine
- - entity: switch.zone3_valve
- icon: mdi:engine
- - entity: switch.zone4_valve
- icon: mdi:engine
- - entity: switch.zone5_valve
- icon: mdi:engine
- - entity: sensor.zone1to4_valve
- name: ''
- icon: "${vars[0] >= 100 ? 'mdi:wifi' : vars[0] >= 80 ? 'mdi:wifi-strength-3' : vars[0] >= 60 ? 'mdi:wifi-strength-2' : vars[0] > 0 ? 'mdi:wifi-strength-1' : 'mdi:wifi-off' }"
- - entity: sensor.zone1to4_valve
- name: ''
- icon: "${vars[0] >= 100 ? 'mdi:wifi' : vars[0] >= 80 ? 'mdi:wifi-strength-3' : vars[0] >= 60 ? 'mdi:wifi-strength-2' : vars[0] > 0 ? 'mdi:wifi-strength-1' : 'mdi:wifi-off' }"
- - entity: sensor.zone1to4_valve
- name: ''
- icon: "${vars[0] >= 100 ? 'mdi:wifi' : vars[0] >= 80 ? 'mdi:wifi-strength-3' : vars[0] >= 60 ? 'mdi:wifi-strength-2' : vars[0] > 0 ? 'mdi:wifi-strength-1' : 'mdi:wifi-off' }"
- - entity: sensor.zone1to4_valve
- name: ''
- icon: "${vars[0] >= 100 ? 'mdi:wifi' : vars[0] >= 80 ? 'mdi:wifi-strength-3' : vars[0] >= 60 ? 'mdi:wifi-strength-2' : vars[0] > 0 ? 'mdi:wifi-strength-1' : 'mdi:wifi-off' }"
- - entity: sensor.zone5_valve
- name: ''
- icon: "${vars[1] >= 100 ? 'mdi:wifi' : vars[1] >= 80 ? 'mdi:wifi-strength-3' : vars[1] >= 60 ? 'mdi:wifi-strength-2' : vars[1] > 0 ? 'mdi:wifi-strength-1' : 'mdi:wifi-off' }"
-
- #=== Temperature and Rainfall
- - type: entities
- title: Temperature and Rainfall
- show_header_toggle: false
- entities:
- - input_number.temperature_baseline
- - input_number.rainfall_threshold
- - type: custom:fold-entity-row
- head:
- type: section
- label: Weather History
- items:
- - type: section
- label: Temperature
-
- - entity: sensor.temp_high_2days
- icon: mdi:thermometer
- - entity: sensor.temp_high_5days
- icon: mdi:thermometer
-
- - type: divider
- style:
- height: 15px
-
- - entity: sensor.temp_minus0
- icon: mdi:thermometer
- - entity: sensor.temp_minus1
- icon: mdi:thermometer
- - entity: sensor.temp_minus2
- icon: mdi:thermometer
- - entity: sensor.temp_minus3
- icon: mdi:thermometer
- - entity: sensor.temp_minus4
- icon: mdi:thermometer
-
- - type: section
- label: Rainfall
-
- - entity: sensor.rain_3days_ratio
- icon: mdi:weather-rainy
-
- - type: divider
- style:
- height: 15px
-
- - entity: sensor.rain_minus0
- icon: mdi:weather-rainy
- - entity: sensor.rain_minus1
- icon: mdi:weather-rainy
- - entity: sensor.rain_minus2
- icon: mdi:weather-rainy
- - entity: sensor.rain_minus3
- icon: mdi:weather-rainy
-
- #=== Irrigation History
- - type: entities
- title: Irrigation History
- show_header_toggle: false
- entities:
- - type: custom:fold-entity-row
- head:
- entity: sensor.last_irrigated_time
- icon: mdi:update
- items:
- - entity: sensor.zone1_time_today
- icon: mdi:water
- - entity: sensor.zone2_time_today
- icon: mdi:water
- - entity: sensor.zone3_time_today
- icon: mdi:water
- - entity: sensor.zone4_time_today
- icon: mdi:water
- - entity: sensor.zone5_time_today
- icon: mdi:water
-
- #==================
- #=== Morning Cycle
- #==================
- - type: conditional
- conditions:
- - entity: input_boolean.irrigation_master_control_switch
- state: 'on'
- card:
- #=== Morning Cycle details
- type: entities
- title: Morning Cycle
- show_header_toggle: false
- entities:
- - sensor.cycle1_running
- - entity: sensor.cycle1_zone_being_watered
- icon: mdi:fountain
- - timer.cycle1_zone_duration
- - input_number.cycle1_zone1_duration
- - input_number.cycle1_zone2_duration
- - input_number.cycle1_zone3_duration
- - input_number.cycle1_zone4_duration
- - input_number.cycle1_zone5_duration
-
- #=== Morning Schedule details
- - type: custom:fold-entity-row
- head:
- type: custom:toggle-lock-entity-row
- entity: input_boolean.cycle1_enable
- items:
- - entity: sensor.cycle1_next_run_time
- icon: mdi:clock-start
- - input_select.cycle1_schedule_time
- - input_select.cycle1_watering_days
-
- #=== Morning Weather Adjustment details
- - type: custom:fold-entity-row
- head:
- entity: input_boolean.cycle1_use_weather_adjustment
- items:
- - entity: sensor.cycle1_zone1_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle1_zone2_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle1_zone3_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle1_zone4_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle1_zone5_duration_adjusted
- icon: mdi:camera-timer
-
- #====================
- #=== Afternoon Cycle
- #====================
- - type: conditional
- conditions:
- - entity: input_boolean.irrigation_master_control_switch
- state: 'on'
- card:
- #=== Afternoon Cycle details
- type: entities
- title: Afternoon Cycle
- show_header_toggle: false
- entities:
- - sensor.cycle2_running
- - entity: sensor.cycle2_zone_being_watered
- icon: mdi:fountain
- - timer.cycle2_zone_duration
- - input_number.cycle2_zone1_duration
- - input_number.cycle2_zone2_duration
- - input_number.cycle2_zone3_duration
- - input_number.cycle2_zone4_duration
- - input_number.cycle2_zone5_duration
-
- #=== Afternoon Schedule details
- - type: custom:fold-entity-row
- head:
- type: custom:toggle-lock-entity-row
- entity: input_boolean.cycle2_enable
- items:
- - entity: sensor.cycle2_next_run_time
- icon: mdi:clock-start
- - input_select.cycle2_schedule_time
- - input_select.cycle2_watering_days
-
- #=== Afternoon Weather Adjustment details
- - type: custom:fold-entity-row
- head:
- entity: input_boolean.cycle2_use_weather_adjustment
- items:
- - entity: sensor.cycle2_zone1_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle2_zone2_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle2_zone3_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle2_zone4_duration_adjusted
- icon: mdi:camera-timer
- - entity: sensor.cycle2_zone5_duration_adjusted
- icon: mdi:camera-timer
-
+ type: conditional
+ - card:
+ entities:
+ - sensor.cycle2_running
+ - entity: sensor.cycle2_zone_being_watered
+ icon: 'mdi:fountain'
+ - timer.cycle2_zone_duration
+ - input_number.cycle2_zone1_duration
+ - input_number.cycle2_zone2_duration
+ - input_number.cycle2_zone3_duration
+ - input_number.cycle2_zone4_duration
+ - input_number.cycle2_zone5_duration
+ - head:
+ entity: input_boolean.cycle2_enable
+ type: 'custom:toggle-lock-entity-row'
+ items:
+ - entity: sensor.cycle2_next_run_time
+ icon: 'mdi:clock-start'
+ - input_select.cycle2_schedule_time
+ - input_select.cycle2_watering_days
+ type: 'custom:fold-entity-row'
+ show_header_toggle: false
+ title: Afternoon Cycle
+ type: entities
+ conditions:
+ - entity: input_boolean.irrigation_master_control_switch
+ state: 'on'
+ type: conditional
+ icon: 'mdi:flower'
+ title: Garden
From f28cb7ee79ebd851bfea34c420cbef4c356c85e3 Mon Sep 17 00:00:00 2001
From: mviamin <42081894+mviamin@users.noreply.github.com>
Date: Tue, 30 Jul 2019 11:49:25 -0700
Subject: [PATCH 16/51] Delete GuestModeOff.png
---
packages/occupancy/screenshots/GuestModeOff.png | Bin 13763 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 packages/occupancy/screenshots/GuestModeOff.png
diff --git a/packages/occupancy/screenshots/GuestModeOff.png b/packages/occupancy/screenshots/GuestModeOff.png
deleted file mode 100644
index e33d5432284e7f8a73b6e6709db7970651491b9a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 13763
zcmY*=byQnVv^A7s1xgFWN+A`bxU@)-0HwGUXz@UCcY-G=#frDM7I)V`u;T7ca4C>L
za1HYKy|>o4*7wJiS$EyJbN4wjd(W9OA)i&{$R0g^goA@arXc@G0|y6p?*9G@5yAa=
zm{FzT{(|eOA@>odZ1}~_ec_>{l!_D%PGuCywK4vEnb=8Q*A)lnamRlLZjWPu84iws
zj>0FYFP?^bX~Y@KGQZ1?Q+*uwS3-#jW=A95au>WMdf>1U^s-<(oIbq&wZl)~@`P8U
zF3eDoM=^84 zb>T^jX&2P7I*tIkI4m(tz-Q-l{_ec zLl=|(JZzp65XGtGn@ay?OavXOg hBsse%1)4CBjHQdW=={8B6v_>g z>mhVckL_PKa24g@KnlOM&q=SDfL0C03Z4pPK(0NMnN6;A-o6EVWuR?|K9%Tv>VFB& zgT-;^zE@0AF#~|EI=*w!1%xhtD@!Zr1U%Jh;yxCje_xvNf>L?*F}rQSE3Fb*CnHXc z9;bAfR$ Mg>OBVLuF9)gH8+$GH@!>nC&YZCtnPncGy)YUm$ouCvxa{@uYLQ!B$Y9>u zmbG8p30FON7>ZU=v`}g8{VRC(!>cEF8flbewnobm@#?)9Pkg;U!U^eL1=#tkY13(H zbiO?NR#6zoAh1BLHfwO2(r3n>tPX&c=yy|0mI8J2qr$*8ttC zK~6$_SU)2`S34#!w$}D;E^m*v&eG{?Df&6XBhw?;Yw84ZP7t91d{?7R64{G*7BXWT zlG7jZtl@nq{GW)Q2&_%M>oYMzA%tl%&`6`m{VMA8R#C9Fs@iY&!Hw}jp#1lCp*B zlO84mKhiKDR4+seV0qcbT1c|_Il=oc7%E!#ycnuPKNR;Q%dRUPVe^5SXpfN7h)si4 zp*FBs%7G(r3_MtyzRzMUnWAG_`>m0MuiVU%eh$C2HToVES9|~tiL4vZcn?4DLZ4Xs z4LFk)VZAIgUKO~!3r(VC@Iy0IO!h>kilPb+lTWvw53=jD(bitE rnQo=o0tYW<+;|N0?kQo;d+)(>bs3G|dycD^kAg%xTx&4-o^H!6Dg1Zs74d z9oQNrJJqf}Vy}`*LR2emvgxBy-K!6suZ@{0(4loZu2sUk{qS)!y7F}XXJ~p88C3S8 zoD=4sL+z0BYyR-!XO~Q_>|R-%08bN6P}9=s-3U>qvb>EEWwFWVtj?%@eaEnj=Pr)U zt5lHqH+0ZQpWwOJvyK2#LKLrW1Kwjr?U^!2%^X>BqM2ATW!>47pv7EdV*k>S >w#nzGrL*@^P!~;%GnKJ~R3Vdr?+lGNc?|}^n~rx1nON@b ze|O|H5##|PS14eVxzQ?IBT=hWSj30)YffaCiz=^W9A#r@^HBtxPfBz7X9y*PGi8^l zWa|d^M-&Vvb^=Sx<4>00m2`yX8%p^d#QBJG`Do*(iQ6oUt}q2-UohvCHiIWm|IT88 zX8vasojPgjTgkNqR$-9D_`{Mz`CUifN35XgqX@MmWtMk}dcy$OP~pe$c4F$@0Ni$| zI`Kq_13A$;__Yo*vZi^{l3|6bk^8S2R kkTuZ6{M?Jc&cvQxGb5gVb&T!&v~#XBN- zsb=qz22)4lUucZJn!e)$-H5z0A#>rKahI>*jOIRMzcFEBe!YI-n5xC{LV8~JFI>4E zcYudV3Dr=tS9Drb%Kh#Lm)BuN5cC^O@Wi6`^P5+!bNA3$ZsToL5RMz)$cDV=c-uWe zjkgycp|#_jyEYy3n@SY*3or0Mh_iBK#;N8pg@$rt!1>~yVEm4CszFT`>2?gmOR!F9 zXH7WiAcHFBfVw%qt2`<&ea>Z-Rphj8AHnk(@iW(=#3@2Mk?aNy)HID#%Md)xy#Z$x zkMY*AxJeW`+tz@PF|}-n6QL3^Hx2o06fVb@O@J3gOKwRn@nyx56JYf>X~Wa`Z3_3< zr~^{bjsLtD41Lio4J(DzcKzC$b&hS`Twb!|bo h#| nqIzl;qygT%j5xL8--+P)@=o7Sa zqss_t%7GIWz#7wM_6$|PLB5+pDQ0JTeMD^hJ$cd%WO--E&HRK28f&mbarRNLi#$Gt z>u%PI9&uN9m;pj=b7<)XTPw*&wJ65%Yq~@anem?+O-j|+j?Yd0>WD`_VT`shWK}g7 zSH-?`R*6 2w(Y+0EnI&5f87@= zM88fX_5juQ*5G%b3pfp>Q20ziz;KFi+uc4J-MrI6Gu$a|wxVcJ_Gq31SZP=nELcc# z^-@^}esvKnWjLkRe*7|!fH5`Xe_i(`5`{a)p*T1AcG_ fBIBJ_qoa*~LI1Z!gBAq2(K?TMJKvBW6q@B& zE7mZ+iKLoCm7{49FHOG=NF_dX|6nSJW)j`?NFKf+_&aCL_U0xV{8YfLZtgqlVM#uI z%3o<}Pcx_F>9{WR%^mZqyE>aOMybd((4`jgEZ`=_J5(vm_{_MuOt49{%Bb*-x@%Ns z1@F#kp^iGLoNJp->?Ph#Pi{%V51zb)Q+}wzoZ6g+; zaa&}?r7}w3!dPFi`Qc60V(XoPl6}e%9u tv@2111>kqk|}P7SE58j`EM|+ zEatDqbiS4T5ju9D#j%{^)yG5|26DAZwSzF=O=Y_*NhH~;GOngFJmRkRr|QXno1`sn zpZ;O7`rg4`Q0(i5*!x>5F+4UslMy0`#GaEs1g%r?X!z&R+D8p(^UfoE=aHsT84$gm zxNox`=)wjbRGHfXi4^Xt3?OU*r@w7%&q4x!dg}L?rs3-!UYR7+L5)9Q14L4b%JI8V z{@|*vs+cdx4g*CHYUXo$o5+*L#mrTu)398<)0nz(m7ZTbGkU&K&FBoPBiz%oE53oy zSKznI*mZWT^!}>F`59c4Sb2RdYNDuW)wFn% K6qLF9Ki9#hta_hZj{7G28qYUv!vJB;9C)zudGV;ogYtJ5D zFEO*S?y*w-4A>K<+c|rkq#)kUsglvKrd6A8$~Kj^96SYP;J_c$;3v+!Y@cd)mP}?t zejFWR#}d=9{E9p_lkxG-+rI;f?K7eumnz>UE{_%fZ6GL{9zNZ^pMjMoJML`w2Js2O z>X!5R84VQtU!JIAk3;Y#Y8=?;2zIm;s*bd#HokbxrQItMeTt)(R*Z5Sd+#JhBa>fO zq5QF&SKU8y@pkiLDBsNVv754;D$7{b*n+qsHz^Wc&aM%Nly!9Yv>Hr S8R_VxW=C&EM5^TgHqLmyOy=1OX}(q*o>!fK)VLB^M0 zg_`(u&UaLxlL--(E&>wcEPzf-<)~JO$`_NT{g7{OgAw4~n3`0~`m0inU!A|DUWFjL z#NoyrK{~_t$Z|zpNeNS15Ha+dTAvk&KNT-(qkqq=Cmu{u9AV0Qlhg9b-S2&-3nWFb zN7A-h=BF|75?+hrjR^ctG|D?P3x7FgHHI@>$%*cT4%`9MVxF2LP=sBKSDIm^6=JR1 z;0j)>s&W+E%~xsUWe74YjQA$Bjn1^amRdW)Q 0L$iCOfPc J=?D1)AM$X$PS~vX_lb*Z#8Ev z*esTJ+6M&fMwGJ^pd11>4cUOl)@P-Ep*`aSr79QM^&;-uaJ%XpV(W=6L(@y8#qRFs za*5|Ubk8b>2 b*}U;AO~ zUYHEBkVG!}Ugzb;W{{GQ&0pqppU~rGM-uuDb}Bl<;=`i_U=1^+`PZ|6?1vmcfbG*3 z#W(GEtMBMisY-OKyB9r{pO=r^+jr1{=<%NHAM2~>*N{ySO0#Hsh4BeYK}>+HHa6-v z!uS@W3yEqxUlJ&jP@SoOAY3AewOI8GM}S;e>?`!Wv&*l)Q}*d8)|@Z7dO+8N@99bq z*H?8cq+i~^H-qOOGP8Gb?TJ7u-Ct)}x|j!4hqBb~aL@hDjrNeZ1%;mN73(NC-nuJ=jVW||?iR<^KVX`e(3C28voPSO&)2_R`CeGXUobNUmpr2U zE$d&hCkp!7cu_L1mafj;%c5tsTiaA&Lau@F4Y>Bmp;U4z8a}K2klI(KiYC61rd qEDObk4mWRMu4mzJm&0yb$^8Kv5# zWu65(P-;eZt(>}dx9pnR%$F`#v~czP_+{m6wA9MD8Xm!+^&THU9o#07D1akoSdwbE zBQpD~Qod#m-ow!*f+k~yDbtctj0BCli}_dml6aD_GwzWRQTt|QItishsH&n_eWudo z;O#f1FHd #J g#My|NUm<@A9U52iu|XlTsr@|-A@!UY7MM9e7?DwwgL#TCLx%YC zXQNuLsk+IO{=lJXOS%4Jsxe(SDrqc(4M9e%n+9L^+C5Q`-l`AG@0y0G Fx7Jmy zQ;aWFD4c3bn$PwI=%B+;fwDD+!2Z8#j58^b9Q86BeCK^t+Fzobb}NC*UlnUiW54`1 zfc)r6ENGB3C+ijp3>)i9G^4R=)tvbAT8r~~MSa%Zw4LEe?QI$na4*sYZ#%>>d+2^$ zz3r+5sR-jnr?J&K=n2_HGvt)^#al MbCT}pyqZg zc#*UFq3Zg|1li{vvdOA&$+r-BXRfhFK>{{7>1|{LUCTcuVUADFu__Nl{S*2 Df@roUO ky^<&VBz|a4)90)p;gRcc;i7CF^YDcPi=eNy3%a&<7kcrT`Tc zGN{TcT&xM(c{bD}Rm-TP`X9ynOB|p~FgF#R)uK-7v$L2ztry(=Oz0ShwZ`XDlFh>p zs#X5o9~l(1%G9(aB64G%4fU5S^3 R>-zQn6t`Y1 z(h`s2{VAVvN~?XG`*8(Nyo<#Ai|AcXgSF4WL`T1RsyV^Ctx|!4h@z7&b1$0q=jlBM zF-$kF@6pY*PtYkKPcfT7a#KIE(_V bO-G52IqdKOCAw41l;(FEJL&&_EE8hvh|!+hxe*R{TBHh^fbRnz`Ur9y zW|;;~$H@uB%lX%xbX! } zRw5YQGq4e>R(14{_rG!Z!!P#Sl_$mEc)Q2nKtaFNzZ) ;nZpm(cjYxo{>j|fJUd~CTx{ksQ1+leB;rPAA%SOE3VxAArpeXdOviH zx3 i(AQ0zvN*Xu=a)gZo0r)xGL>>b1D>gy133BprqRYp-d10`jm^>& z<61wmULVjrx7tDH0-(=_g)SxDyDF7v-+nGft&p=JKZ+X8*mbPqbS3KLkPQ%yPZAjG zEyvVaiGI$Z?Q|Rk&N6b${6jL=)vWTj?BVIygG>aCyGrcdj^|FRpfAMd@)EUP^zrUx zA4q}9Jt(tLuC&S5EC*{*r2MkBSf>xQdl%xm+g$Y9^}~V&3HyDD01^kah>oKKgz<9B z6dcOIM+VDVUfnT~?Or`Mo0A(!??k18LD#;oBUJn^R+T&sK7fkFccgRRAWothvV!e` z?Jarr9kr&%->E1kdrXmjd36t}tgEU_a=QPzS{QfvHJ^u&12>Uf_rZ*6eDxO_ZxFy| zZY(n?7;?@OO7BR-Al*nQwSsEZf6s}>b` zb!@& AD@r{O9 *aSY=tf} zPFNwj>wJqHK@G?t_ke^x3=?dldYIs6XG;N1N7O&aWIy?y0NQrR2 ^*;cF+XUQFc zE7@6hY!2PW4sT_jEfFJI*vC So( z$l*zkpU8_7cD-7m +7I !d+L9q+rxBzalf^u3;U-lB-Q)KO}05$bT&BLgc0FKTX^l!0y!Bhr(tDxb` zDUPm)kV4YBiQ4DtJb3RzhG|kc%-Z<$kYF#S)#P!keI{@bjrHgECPIuFlBq{%zqws_ z$?);|ZaX{tQ^Dbd-eemEF$21Hy;GyrD9~#ZS>Yn^NhJ<4Ml-dfyRFzds%D*QByB~$ z?gwzhV~+vRx_$|v-K8XgT L!v9Vt@YTHWBwwjmB|1*{mZBPgz;{0#L%xp>}uDp;BoaU6N`S*4BX^ zoWwFGwVOQM$fjyeXd~IZEyAtlZ$F{7A@F-QeUbs1RVO>~V!H)V=93MQ)^Bdrd3m6B zzw_WM_4|EH(SAL_mG7SfneLQsO;-u2u*qdj_tOgdi(O`h4Xj&YRJmW>3`4xB+vs80 zg8{j6@0;`ArBD+;UQ>1r)6=U=xUKMCrRGf|HPzK`+?ChK-4E(@kzdiqNQLC9wLP0T zH(m0GaMP}u?`aFIHqfkO<*H9r5*qnSBVCT|YmZsXZkU*rt2ow2fr~MYr1-pAMA5rJ z+>idj2>iUpF;{G-17rO86dv45JY{4JbFWX}>#Lygw$x?v6FwBp> zhv(??(TPIriaBLOQnaHumk#eT>rAT7{Tmh&LFGASuiv8g6keJ72Z-`HGJ>2Uwf{ZS zZm8nMU;Z37n9SccoRYXTa9{g7&idc^5}_vd^Rk#|I>r~<`)b=!CvI_T+}?zA^z+3Qu_$tS#@>OlP@Sm p(VhZWp~SWeQV-6so>#! zrS`ZV?}HfWna`v#?!mCq)T=O4;5EtOtrRq4Jcl5XH-CkB*| zonM~G|HIw==4#z^y)r(D>|~gao^&FRk!D{w+e~Y^nfYG^WVo(b=3-%;l((Cg!&PNa zYaxOR@ORVCS8z2fSt_aY@X&qp;>=z3oB @fo8%^uPaJ5dr;>c*3{*; za>K*FMw4|5)BWB0_MZcMc}6aH+A-3Y`%vx`TT%obYg8Q*Kj+W?sLdF__SK3I^>(#b l&VuDy*EtW!xOFSB>ZF`vvimgbe&ZF6f{f~?vX9?>{12qk7?%J5 From 6045402ab2eeb2c910e2e283d3352550b72448ad Mon Sep 17 00:00:00 2001 From: mviamin <42081894+mviamin@users.noreply.github.com> Date: Tue, 30 Jul 2019 11:49:34 -0700 Subject: [PATCH 17/51] Delete GuestModeOn.png --- packages/occupancy/screenshots/GuestModeOn.png | Bin 27538 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/occupancy/screenshots/GuestModeOn.png diff --git a/packages/occupancy/screenshots/GuestModeOn.png b/packages/occupancy/screenshots/GuestModeOn.png deleted file mode 100644 index 4b9299241bf55d6858dabdc6efff25bcd0b69f77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27538 zcmY(qWk6fa^9Bkn?oyx>E5(Yt6iO&itT@Hpf)oN2w?MICEmGXwJ-7ue7M!BN-GXbd z%lrG^`{8~#vLDXu?(FPyW}cZ1S5uM0$9aQ;f`WptApcnd1qF5O`MnGa ZU0!xKoo*P~#x^tvC9zGetT^eswVI_B!X-JU$m^&WD~RazT_0%Dbdg_4 zKRT!dpH3^7Kd=!^FiCh*)i|0^(G)Af3kl0Mh5nR+K@GX((M;3EciqWJA0+eXR2q}g z1Y@pl-A2V&w~b!xd03cZ3s)L`VxbNCV@So9!oPVc9Es85kFV)9@6Br% TX>i*MpbzW)m*cEQ` 5~*3_k4@%g$>FN~e}(*6PFJPrWt&V<0tLg0h-o>>P< zdw&157q6G6(LtVnav-Hp&xf)r-dK4K%#&B^8kg#`+K;&AW7vV07aHqgHEJgH4tklA zib+E;EvU8G5-Uw1eHxe;bUBw;_1wIYnTeG&5L@?FZ5uAEdKlR3;-aS!ke_!c01#uF z+G+u3%--C8GiPgA0UmTYt=M6!WVdYz7Jx3c4TQAAt-F8lubsxG@K83S&i%@xGzXaT zn+<+K#u}Yd*!ER53~uo%-}bqOgR*cyiYw3*Cn(4#F#Kvvy1ZpLk@Z(ie-!w1`1ku` z1MOo2>#TOJ4e+m_k$}XqB&cCGaRxR&^c}}}sX6^I#bM-~bS>^1=_QPv`NTx$a@#_A ze*sd9rJu%cRV_=(@pH3774{+ThjKuaANcdnt{#o!3LoP3accSOgNNjGt{V51bPsy1 zx=Cn-zs1E&>nEMe 2PoPr0xpmh`y=j!e=BK?d?UzETrXW3XH4A zRsx2q gI46+A<*Kk!j}+`;uJB zj^7%s)#Gad&+@XnmFgbk&yG&fZC9dLj!r)>)|XYEkro-cpJE;o6lHg?**2U-=P6!f zO2a2*0>(_p_7}*kb8powAO3=o3+0p15Iydkhxps+>3nXG`BmL-sY#ASKeC)?S_P4% z1IxDv7VWofW>f>N<^^v%ZZV(_10n8Tryb4wrKB2KH1}`s1=PIX7;U@sh_>bb=o=7_ z^fKC(ZlL-?8gD(JCPwY*+tqLVl?=3h&IEI9KO|h*`*#WO|Ep*5odbqk%Nv@D->J}) zti&vkmI4VdXxZ+r=Z?+0*SUStk<-EHE_+p%V|VyEoD3br(3-Ky{MBRf8@(!4#UlDe zIEE_S_7j8@!d<1>sUP}&0oWZwa9|5I8BYNI!(_#~o8b3GWW{d97nXBO9ef$^-Y1Q$ zZ*=3M3A)U$9ELe}&(eio$*4K81tIb)RA3*~g@l3|rY_% &dCNnL7TtZad)Vky1DOVnk8;On+F+aZ% R*4P(Za**k9UUO}B^zsN z*{v19#pskwKQX)wPGptwKoHPp7=2wk+o9M$j}Ouimc4K8l=I<@C<$e3wp2p6nr~ZF zu63>oBIqhC&Zm9l>u5G=xf^U{NWL|eOK6&0m^dAgP(n=)&lzAiel%SVsHgL<;AW?d za*ELG@xc1!Gd@=7hNYEIepCK)gaGi*f}{v Uy!n>bo&k8` z#4ybTT`+%rW0XzC(hm}GivsJ(VJ*~{fA!fP{uKL&*x0=U_aSx35HDvJ3sR+#8v;w+ zZ++cJO!Q(zTL{jwj)OS);iOOXWr%&d+_`>ds&Gdd#eT!N8$@J`ap-|QH=7NA7M)bm zlpU9nU|Oz9F$giXsNqtzK?J>WO&QsUNJZy7hbKpCRb?PgQitR(PB}rWBX{8(EUwF| ztgyXi#w2xke4;3ggTg>(Ih@~% ZxOW zM8>pCw@1$*8Xf&w=*7z#P>{nXSlT#e2KLt;UWM{E y7P9%!fmC{I&yTsw>Wkb!drsH2T` z`xW@RsG<~+B;_adPJMnmOl(b$M;u=n{(+P~)IlDnJACLBA#;*E2gT-1<6*u`Hn$gF z#lC@EEDdhlxy+tg2H^~MF&Uzqo8^M=e8HcCD9tKeSxKPfmkPwSG4put&K~TCWzyU* zRy6Vs=RjK$DWulYoB8cSGS6XXUto=2q$o)Sq2xFE@OQ5iv@DfPq$eYBjB~sU7R-XVO)o;qb64(G*M&>Bwa5Aa++`$-4e=ps88 z^WNv4OSDF_Nv>mD4Sbr|2Gi8D-0~c0naX6XxkQPyIH%6l>@L6jOuzT?Gq)EYQFe?dZVmH3bxz#=%CI!c+(AuiXchK8n z52 cVA;&iB@y5V=6<*}lb4Pd(QZpAq8ErL-t@%`A z;k|00`vmRrHpQD+xq44NsTEa5_a2Dp6Z6K(m5f}f!Lh%$%Ah{0z+3QsoYZfT< bdqm7OA7R%P8uhqA7q_hC+XK*an z!i9=p%q7S0@`yd+N2Ga*I%$i&wS&`lVe!i0GSbp_cBCNQL9aI^aSs2i1r~bx-Y*fc z#l1Vo4-*Ycq7U?br|PDcRr8}S;7{^w)%qN!WdwZcYFNr$Ad}1DZ_ZuLx$9Ltu*Q{3 zHFpRr!@9|E;YPE7R$8Hi?EsI>q}ck)g{Kmg#ooX*lOw5jpoo>U7b{7e;2l)C)D~1$vrYFcp;Yl+h(~SOKTvdwy`neKJSv+4^7=G0`j%?aoe_WD zi+c!LV^|F;%D~>qdg5<7={D&?r!ahxb+_o>lQ`AjtbYq7T8^Y?%uqTxQ!A(fih^8W z^Vnb~c+})fv_b3V+~lJ2kCX3yY7zlXe;ndsCVNoFRFqde20s`GzjnLLdO{L<-to$H zD>sh(@Bp7E-E8i3;4LjJo$T>TpgD@K^Arhs-d{F$2>g+c&rvmIHd)Kx398(Lozxc@ zu#4sJ_05E{S1ZyPhA1LTwt+Dx=y-t+oc#`RJLi6M<)o15M(KKEEbTaCyk)F>23w;^ zebAKZ)9XXX0qsfW!*#c+pEK?K?U+sv@}QECCF>q_&Z*~jx;B(XD%!4L)V<`=EfYI| z6hH^zu!5;cC~z{;A3m-T?yIZ!tMXtSM9EWfByzBenlKOfUMjX4nSXE@hu(Dt_#9(j zkEEm1A^%yg%}{!DYWYLSN84A6wj++Kg9w~b!+Rq_R6irp1c~ywky$diaPzeE3VEHJ z97RQIgX*Gkv9a&s2fH8hf*`{#Jj}6IUf+kXl6cccU2EI$QT)JCh0?k{N#E6s6Tefn zh^x3j17OF^J5V04A Z^r=PDxDKZx^o-p@s6! zsrhhrm}*8ty`FPs%w_K;t3eB-oO7n+T>_Vq)atLfov&ZaFe>bS{!_XcGKgHM@S46T zAJ%zlHP9Jmv;P1j`9=MK Uh9b0jz-v9WHj&Pco{&=(NoU@2_(1*8Y1g zPV1+RAt{Z9m|q){ZGtEJ=^m^sdek15{f%Ghm^jl9w_J*Pu2&kYUfDgNSc7j|n~pp> zgl_wfny|U ?DAcjZ>1wv!S$k@M4rpVgzG4^ z=_mY8%E){zypp%~73^ZGiz^=8inyHvUjDm3T>R3&FUu>R9_hqZ({vl&y%u+l*W=P} z>*Yw>!p(YQJZu`7ak^@j_~DUxMeKPMLa~}hCqj0$4Av1r ;&78Gk1`^td=Z zxu$a9Yiyo1bitpq$`bC%Q~hWgJgM_|$~|f!J6mnWV}8SPGhXzB3w6C}%xQ1OSCQCS zS*2}r5?Omm_jASMTzKv~yke~>&mQH88?Q+W)QW$<+8wzTMye7BKW-*m4nch)rSp|| z#xa~x(T$hY^L Modr`WbuR>e2yCU@9*SPgc~ AP~{h^mebDll; zYjM`;R{NyvwBSEex1~3SZ9oUsi2zVFlITovizB^Cby@cAJ&a$|nEW4%bs;Xrh#Udt zdhl+r_nhUaHLTmkueHqdHE-~GYkS{xT8U=b-Ez=l 3d~S{opRvz0CE4 z1p28w_Q7w{Osvc6n3e7unt9+s$*=ve`k55d#F@-QX1i>ikhwn0%gD@+XV_qrFDvxN zWM5}z2Cm-^x+<`cDvMy9r`}i+-2yO{+sEEGY_`6361+u{k^TVt;#eow9=DNYwmbeL zPDM@n&Vw-rDpC%iDqJCufZk{{A);DW_w62WdU&0Vpi@!Ru6r8iy{rFN Y>zVV)pe+i%th1rz2IrpIr~EZ9F1`+rw$05BUbiKAoH4q-%X}hfunQdyS@}LW5Nu z9V2{44t@ItQJbvx@7sVkT&-u{lE2T2JMC?C{M}lr{=1#l#U*xR>Pk{ZP!p$5Ngd{; zH=U%zZOWb%&qVgeH>E!Boyt^^8(u=}jdf4k@O~TkYqe@PzS361mL=fh&Mh@r%f1}d zWQA5&oT@l#lCd}OXe! ^3GJ4-BbzEZH%*#j!c+rGiFS6ry zP8F@7Q9KRr*AT)93gCv6OSjc!YDDF6Cf)QQfyGtnjAaZyiMo2)EZCT48hBwIGHT^1 zMz&eKt2COC$8SwH wz2vajA>l&)t6Pr+edXN$3ioD@DXHsoI(QOspg8u#WglD%yR!mV z-jUI!F5uAt7Ta_mH>bv$NPe(n`jKz9U-04eQwkcrCK~HFF*h^Zg`3Gn)4a6k|J9fB zz_J=E<{;#}X@;4GQ0d6iYkI@@9aBNwhDtBz 27+{f3S}N )AgfUiQ0T1|WDPTO=rRo{UuoR+$b z_M(3>(t Qg=GYq94lt#P_=_;?@uOP#~0!BC_Y$I4QTW zHMu(ZR%R}yuHHj%ax?D1S%2HBgU4?~_e0kxTy(*sI-1$>Zg3+s$ShGHim?tLx)gfJ zxEVK-M*%N?r`U>+7G{u*>ic-rHE2c3(o?<0VEPz%%j|fqd>2CPj>kEJF{>&cO-!w7 zc(r~zm*^oSTv*c9I1)wm8&=V{j7MQ~!LSh-c$DcwXR{gq6@&r>AxB;pbMqX?Oh)R+ zGhQ6XrZeyLm`!?-FRJI@_SaMH^#)au3gajw5nlk&rkZkmbN$_-TE<1spf0;{@s=V- zMUE>)n9!#++NM(~@sl~#M9Q2CFYAlW)4PjY6)XRtoc5F5=%j9ZYmc7mkC(8QIKfq; zS%j@eb?shStQboeh4AJ#se6+MxXIHIVf7w?kAUS_ >72#ZX8fgCuO2eEzX>#@G!gj;dWC2WRUY5$ cGeH?UCmYH{~hViwv(^+XKx%`!sO6N zG;~xfUpdp4(mw$G`YZhO;GdyO3vB; zBx0E9bJE$N1js|Ux30I@M63=@fZLV}fMLLpt)Q9N2f$)UgMUVs?16%TrqNxRz} z*`M`L@v^e1q-Xk?d_M`(W913O@Uq{|lmw$9E7OOd?KURJ^mxgGzjmRf$%V_;B6cDV z-f^Iuj8c^D`GUIT3F_4S-7z5c$mO5^G9L}C&$@!h#gB)zjpx6Pef2WhO)q6pmtc~~ z3%RyElsVI&%T=TP_Gz@G?; yYuC zg~MP5zo_j1P2}*$gXvIj_(_oCJ)z;nl4G~`L8YB52|Hnkg^&}TU7gYHoFnCC$9SQl zO_Sj?46y&{@W9{3zSwZ)7IY4p)3dyxW<4$0g@^{|HtxYzL?6gKFKXn>b~4;U_$AI1 z<~*_<)^0Xbel$|MP`5oIrM^0XbD##?2o}`@QMmA)9ESP&%-(IAtx0p#bzYla_KBz( zKkp#eg4`(7G-W=fC+)tkye~u<9eUx|elq&-oy~;a>Cfm)+H 1{KAgI6w}pwujg)D>GJNvu895p6iC!f;B6qr Jdc)G6AjwkU%k$S0qlvKfvX#7Waz=|xY2 z8prhX;9Ln4VA!p&VnQ@MIE68y!GcT&bPz&g=G^4$eD+pACthOFgfG*yqM6F-H8bz3}RADO4dmZt7urjU{+0iQEM%MQA?XiX~V!^ zqDp6M>9piB26)Nc{*f?|!x&HEE5GT?T2 P1g%6XgH|(Vi;ODW vG+HVY;`$nO{eo;9o>qX9Db%q7-IB@8Wp}%bRubbpzIm><*`ke)G~=zIXlpG z=m-n+AS<;GE2T^J@M9>N3iUICaQ77mQpWzowv|P|BnMWJ(!}^Zsp%N^GN#c5I+TFm&{*KUMt9 zl-B~r;s~EnN)aRYNMRSi#{cp 0otK&b{)amcryn}0 zpK>G4`bHDf0h0+InY?kyIet`Da-G*$%*er2kxkzhMeY{W!e;!Kf6eth GCApe#-%7)1HKRkjAdHq9}huB z_ze~KOMN9~`i&WU;1)6s%stg;9a{q+n7d5p=6(;t# F!bz>e=OO)|056sYOE|cC35{{r~8HWB-hx+~HgAluu*}oraR87g%T8^5c z`BFQ?X&*E? i|&GKA `5#eiRWO-6XSqc_WSd@*!LkS5*&3- zJMG$FC3Qifsi5x=l>^@Lv2l=Z#;lFbKbCVA-|za!Nw2_jKzj^Vj+>=%L~s1WpFl25 z{fK&%UqU;?L+2FLo39eo_~~Qk+NyEC7^^-Fwj?K~IN9)Eyqrg?mlKOVW@C+&XH3Lh zPmk}|( d=)76P=C*V^YndA(UWwBhOPYy+NDHmMMA*=Gs_Y z#T|H~XB8(@byo^<6UVfmj49Dip{(Pihe2Fx2>HfthNQ;D>VmJ>PmMJ3m=`3ftmX9s z?v!*ZiiZd>AWxk7NzVdpGRZSSOEc3IR6B~EGXyDPcT>NrlrU=oNWLY7obyTnJoU=Q zcDB$lO1u~GvG%H_q2MO?1ao`0&6R^|nMd_!@S!!`<*E3R=!I?WlyZf2oW*|Pv>t#e zXXT@*^glc9i|n$e#P7|HSs5!jnd40wUfOb9Jxs(V*{3667RT6A;p%>xEK{!cmX%E( z*J0|12~3)ql2E-SgivkW!_a2{4J}S(d?KMGFO*N%MCgeS>x?pH9LlWySGo?u2VxLT z{b!TuPNZ+vA{y60s`qxew$P@pKs*+H1f!|r(o!yKP%qRGc2e;7X5j>tm5)I(ec8ZS zV6QYTV)|_c?O9@7$A<`6ROrseVL0S++~z@d`9AX(Y)T{3l@T&*Oq^! Xsmsi}gs~5OedOQL)V}a@as!le!?wyfCGfT`&=Aby$RIG8n zLY6h>WjguY(63luLa#}U^=VYj`7Gs5m|{XM3^i73N4PS_ @D|?3p-0*--p;>WA)ta`>OZq5)kNSqw4dH!Q=f>$*mtDqMFo= znjC`~QvKYSH8YQh_{{bE_t^3&BtUEhd$~vl9WvDbFae4JBuJ`MiR((UjdsO|q{CkY zlZN*?OK1N0fDqgJ@_tUxf Dx4dA?XPCGosqzbvm^6>~;!>4t{${!jwPEeC-iZ4@xdAF7zm#Tk^u)N8ujCH) zt-ls$hMXs;c`p!3D$sna^B;wsalGyaVe82T%%NF4lR?|8`)b;WWC!OPub# 6@HHKSn)V3mNY{$(lHI}gWd;3gDgrRWYqQKs_=9s`|)X{a=CAF(% zS+GLrhaXC_BfoA3?Sn;I Wkv~=tX5I<>qcA4>4vTfe|lIl9o~2e=c3V(z-_f2yWJ- z&T8Go6P$!P@c+}fMFW*{f~sDc1<0?M@48Dp%-FO;Sc0TAZL9QX*x~}2*c?yM&3~&A zb~l#S_ZFY?n7K$Mi*`=F%ZHJ-TuR*~#OL79pdjCli!BT(Ww_<&yxQf)pmF7Rvy|wU zq<$ULZydoz$7XuG*P-+Z3QfJ#I-r({A}o>y0tZgx-hr#>lu{%x1dZ4XSZ0bGP2LTj zK_MKV!-BVq6jS*zeisR~>;YNHiFfqyI5ml;;q+lW!<2Z8cy}+Oexr4$;EZ(s2kxC; zj1c4fLD!exCIuC%IJQ0~=8)_#EzmX6!~fXQX=D}9Jc%xp&-pSZgRmSae(zhMit60- z{>$M7NiQ>V)FDc^^I7ipN#B$`1CInb z;q3*R$J!V08>e-`)czx%|wAoX(lZ$ KsC64+BdX?i6E5@yvRr~$6e0gS&&%hz1=0N+ +Dih9JyuTJBFpExS`Zx;X=vsuShZ_;(=R81UE7n|xYMXCbz+mJc+N z+SUhNKMl!a1{oPg)cU#pn{2G^V5i!K203N2B?=ZgyD|q6)ki v4r!1!k0LJ0DmcFc+#FeLa23rTA0}6akCLW499j^IEhIt=r4SnJxA$a8 z`oflSo36dGW@&)?=m`D}XP-Hc`2j*G+pWgoFqv|~>(ylZEnqRxH{E%m4m4Dbd%&Dk z6xur1x9}nDD(Ytxxu~#ihu@l81=H@7!4V_IZ?SMFSh;;m^y|vMs`pyxI@x;rsb_ =&BNSJu9??of9RnFER6Umo$=AA@jlQ!vxZsV>bx(Gqt zhX^6~gX_j7Z>2eBWQ(~RHb@9gYZALW5)RL2x!i4^Qw_Nw`{hg`- l?+I!y^3hw ^!IV% 1)a94@pAOwDsZ@k%n1wEg|`o`*T}?)oo-m@FeB`+<0>>sZ7T99hl+6 zYF606 8Mw;EUsY1ao8zyr8#)tiJDX*-$4aebW|ATt*lfUSCx>z`< zYOn$hEd)mJ*%*RsfphQYSml?uSM!4caqKScElP1yIU#Bjg#Q#wG?UJMZ~D>?wF$kp zFr)mdV0hIywbPcO7E^@vjp=ENTA*-|;*S(jL!G3mYP90Bc6v)gKhl%3!38|Oxs`O~ zoqYBv6FsIU54(K*#n L2Pma70xFDVTlC>li`vK9V- cK4<}a$JD#0dv(@UTbPgj(ZvtZ?MH}iKHwNg2P2 tN1UjTcPD4ShdKs$b&&fmNo2+&YgNYlYS^pAn|6PM#2Iw`z6D{y6 z#d3FZ?A1aMx*}RL*wfR-wm`)Am$A+lNN _*u9>GzQ!uGX9Etlrs_4hZQ zhP_ti)l$2$adR5O4++C k2Y~;E zMg(UaF8=hnO!RCedfft@nJ m+lUv{1ifvU&eXLvj7IE;VylSP7Ga~qoLJ5gkXJ8Hb7v_ESqlFf zB$lap6oF-CXJ0^e0B@Z_;VLHU96rj`)R(N?; $gD>*a4Z zYA$Ml9vYI`@m;`sa|!(_QytQVBtMLOQku=AfgfPxr=+DN@e^eCtl3d|GtW*4MNU-} zVareaAeD6VMz>YX`V6aDA#EW=_z6C zd=l+%jY`E zc#)^W{vEMxX}?AYs@C3&Mu3$1^0;-JU4y;&s|Ax&pOLcLxV$mKNgh{0+FZ`+s?Ys> zDK?Fd&>_gWhg=-#(4b5BRbGdf=rO-Eob2j@ x9>4WHcVaze<4DiEyQQ6U5_Y>}b7^^!wsc+Cx?N7ggHRk&P5>6_aFgbwKhFFl{3t zeX5V*C2^o?+K4IbyE4@4ByD5DFT@MkT;cJ1Nq4Ypw;8G#0CAFfe-<6y!4b}I=shZ? zazX>l)mO~hEQ6O$tmd2f^n%c)m^%u&U3Kpx%pDjvn+l=%Qs!-Mka^h59fCq6RYBFo zR4AyPagfFrr}u%teKwC2{V|$ggodl}ml=G7U9jOL;p^>!pC4;@Zb8-vS9tzAp&|(C zt}_fncZ4&|h1mRTl%p)JA9Y$R1fwaTIt;0t`q2RaI^&|-8wb|yW;ZHX^c(i{D+p +fzoL*Txb~jXPfp^#Z?NMj8V%IF1={~7;qnW<+!$IEQw<_H3eN5_sGW!Nl?@xo? zE5@4jE6j>R2gD0!<$pJt-3#$lL-_f^N|ZpP*8Q|yZ81CILxo4fc*`EdD#$6LC7Fx# zdWVFz^oAJ+e1>2t@3CODp98q7+4){R(^)hRYteS*Ac3!PELUME0U%q}YX+}B@iz >ia64jq=95_+V zT|Fjp&n^$cY^RFYVIu#xD7kai-2fkE4Xx_PTQhSpa2wqgG@K3mtZv1U zyaTK(LWOetz^Nc!QUY+MqeG<3FxJ(7gRj7oY??yIX)0MkQd_xUa{%5GMuDnfp9QO%E6v(DeR#d3Q%hXtBq5PqUP_A=n0fe)2|lP-F-BO_ zEN)&r8XVpN9c~#PG#tGsn={MoSM2uYrL$UeYlrn6UIghGOGG8p1x`8B)QxG61~)6s z4z`U&AuaM7$A*J1gY;6PMr-W+<_p>fWNj9dKCrr-xHaL4c8#0K_0W>K9x3a@@;$IU z?$_;2B>-!Xd PIh`fVRdzk1WBbgypUFKNSwVv3!0B|yaxt5Tct+1qS zbTwJ&bwZqgjy3#O*QM3oOcIuOGMRKH+Cl96^eMgI2zFAUkimM9Hx)@M;wO&?ik1KN zZ+Xp+HcC!TwuM6tJns5qu3e9|O-d@0N-4FJSS@sXSyhy;H)k(QTy-)V-_wW_=7Jqf z=>ALplHIUoU>g`($Cw?-0MF+dc1{o9lX*NBJ(AMm@jD4Fuue^1x{7sO>se0=Nqal@ zThcVUsQ;(>6c1) @sJsucs1EOIT)Q^Zfy(Q7_5JRzUTd zwtPYkpUu*F47MA2(p+!5@1_WzS{C@0x$9Mie-?|9_DLnh$V=d8b?PDd4raO@vY$R+ zQ6R(#J_7Z}tXW`4!{|NxFL4Av$M_)}2Q0r$8cyFlI>oN^Ytf!&%DK)=S&RO({BT?U zLEY-lt)pyAKdn}pm~ecz-$_eKn sP_)#;iXzk0t>M}Um^ !*yNZ-Yb87Ja%U?~QVg_Zgx01Daf zCe{LZFlF}HbSRJq--kq<)9Yz=SW(WIi!Cr8+WRJT=;|Z`H!2~YB{5@xLS(aD G7B;OiSwF9C)npb4qA4-8T1M=-7^^d7q>z1u=0s5{z}p|RyyhamsCm25 zR-eOLc|4;xlASr{$^q&{6?8qRL{!@!|4iwHt4V9V=5H&_6YHWe@(f4x#RoH6^Qn@& z6f_(np=P4|5$cA|zxTiIxwNdjN7Trv&3EUi*4Pd9)TKA6YDY&^UeC-Y;5O-3jp||s zR=a&_%>Ig^^6brZ1!eA5u%B)GB%)^AM+?^8@Np}TxDa4fmbU2K_#F9%K5yR1+DA^Y zZ-y%PxwILnX(^)8{_IA*t2tZ6ZDZ#ns?r?zo@;42w+XWC7TyNXXYrX}b^B6ziwLRR z?d?1d$%a>eKE|9j(Rn?M2~vKv%DP;@!HmMFkMUQI#LrtFV`f*^BH@0q?Zj08-OL-` z`XVfL+uarK_Cgmi#{1>spf&QkK;@})_s{63h0-&xh%rJV@`UAxGtIc)_4Qu4ZI}d_ zc$c%Tf3>vq92Nc*6_;%Ymr@m<&pQ#*DFThg0T63rY{RLr_O^cs?!Y_woRxUsxoigK zDk6(@9@!RY$Q)Wi4A`Td2=Ky*SoCi<83HFvx;oSx8<|t$b8wxL=c|IY6eCS~Qm4-! zIr_&FCy-X|+R8U%3f-w{unRdmAdZqw$x0h7#L>#2IaKSzs(PAsQg3CR%)*4f9&{qL zg2z_OJ$~q7(=)Y3AW;w8V|>GGDb!)2@9&=8E!03D^C~s|Tj-a1e=pvA5YK&b!ABNe z=X7Na*BZ}q;B8c&%{DJ{$fMPXo%!bmeAwR6Q3!Aero>a|7n_WtWS$vygzc**w{3!M z<`WYWS7Xr^KN{@Cqh0XUP>#D{nOCBjh9mGoz24+!n8P6pkp&vOf8B~UHTrjeL)m_d z+~qsBzgLDYaxB7QfaQ(^LUQE@$m5RcyDNC=&{Zs7Rx^Q^uTX&>TDc )GXWx|`SU z#g1&|16Y_W*iPnmwW86@WLr*=n!(6#Lut#ELMQ{yS?$MYW2oV$^M8?2PW3ae9YjN1 z@4`A_f2ssR`)03yX9{y~@S)6<1(Net2@T$3j-+nka{V=#RK}?fnezp3tc3ILU@Wfq zc(<69<8)i$hHVEHjX_YJ8PWfO57o!id~(D^&*N)*M2M}+t9KRcQLjH$k^E @cOqUkk`P)90eGLJkZGkQH^aEAaod;&Oj2B;8br zrDNp)-@s2K%xQV2?4N&jW<&|LiQ9m6IcMdD-?~F^$gSHr-i3lm)ffqtrc?N@Gk3#o zNu>8(?|VcXgAi>-Y>^mKSHowoghw4jZLrcVwdK@zpUNU2l{ihs$@L)98=F?Av`L|v zMzsvqYwDm!zkSGkLz(&4OYDtr58tsR)wv}SA*rsnO;%!0w_*E68pM9}p(e4g7{5r6 zB`9uJAP*6tIvKhKP4x>IE>=#ukVJ6nR-?3twvMa&E$+IkJB$&EsD1UlC$eR33mg|4 zGaXkVZ83>=bTh#OE-CuXfLy9C!2{R&Y28zyl9YCq)%TS)H)!0d7eUzmA2f_G%KY1m z<~#hwLg5X^fp_~Ly m*s_6FDNXbr}C$-6*D1)qwy|6?}|Z9aO2@MGM*O(YjZ zC@7S_7FkU|hgzMY8`Eiog7P=JXo_>k7k#rQaWsgY0gW9kbLm7OEHPcENTK|Ctd}Gx zfV)`Tueve7KJKow+i78zBI|MJ^YhV#&*sfUxTSla1zg9w?0JHyRx%0D)%CQsCH}3t zO$G{Tcg0>kJlmAvfQpn?sdz-9ZstwH*RnMf4hfd4dUlv69b0@!r*=pVWToIgwq9Gr zS89_fL*sH#sK!@M-D2gRyT^XrlO~x|q0Xyjop>ANUF_q>M}V%y{hP{i+5`!S_Y-CN zKiAxCH*S$?Gu*bSHV=iqsj3a@y}t3c!dNsFqgOe+^!Wrim%i?reE_gdHe$5zaIv`G zE0Tunfi0kl275LX8IH~st9~@al>tkSi~*&nGB+SB01%e^t(#Yu=UnzbjhhD~%rY9! z+W{mdH2y#_2QhDskOuUQZ)R27;KxXyrNt Y2@sTXi$p0FZv>L9JPIdz(-ARWiCzgcJat|%lWolYuokgcX?Cqm&FR126xfES1X ze0kN~S89HoeZ{D@CpGqJ7=6-}!y8i;(u7wbCl36W$399*NjV!Oc@;}-x&P+p(Lw8E zOy^TSk1(n4J96W5;3}TQ5J`bdBdcaJ0>+6Qwuh?LsB+bVlBeQ-|5kaK&$Y2;6m5{F z*@anJ2R+hpAwzWo-jhXqZ*+`C-3+TjtY7HwqDiv=vj#xc4ZIN_vl1nd&ILZ z*835mNcH+FhnIM?Ni>mODwtmP6NM~e9oS`zvelXVW0y$lFm&zt7~*Av>PYVO6PpzN zWZ5xCyVUS^9rgd&BsOZMblM*+beB+RL#_FX(z>70k^g0lKELCAzsr4u1=j1|SNhK) z-^J#6mesxwuCm|yEBrF?)~ebBs)5&g2GjF}h{pcM>d9|rzgJ^+-TwzH!+@H8RC9eR zTg1gHP_6pv-yMTzxvxgT|0j6BG&pCl;O9GJU}-5{`YQVuq)vP(K-}P#6;9H=@1Q@$ zZ6cm9q4Emy`*xF^Y2=fyd4b|)j`_kYcv@>=4Zv&2az}Y49lZa>;z#7V=PJD|T>$6$ zG)3@2 _$l}0Culqn-#W?ez04&du%;y!t$k>98r2H5^Y~O=MIfF zbj%EM-x#*NbFC{7Z^O=RZ%5wu2$MhZ`AcB0@S03J(q{cu6dAhThmI%T$}&_*A0#$L z)=T?HCS==PkzYx}`POSmc$YqrUFM9miL24=Q+4ES-jOk_uz$&Cn6;J1T%(|Enc6zD zZ@R3s(rf0-SDMvX`Gs%c&P8asA@(*La;4VA#Mkt``bqm+=sC5BW#$w>LaBK4Xc1Lx zaUvBPMR$)xW*zK`O*m4X_SwO1W~b(Y9-MevH3=Y|#+?yt#5b30`sOb K1ru08)rw% z B>+DDErMKAE1otw<0&{G9p&jIB`)?;3pjb(TQDv$~XWiA_gx?aVd3~bb{l}Z@D zY+P}RwzWgl&jf$B= 1nBhvfwP2WSo*#9bT(#a9HrB^P&D()|Z9Rk}!R CC!PYy5Rd& 6mTCo6A-+Bohby*Arfvkh{cP-QfKNaPuwSxT#!~Z3_n_Co zgd+Q1BKL@~E=TTEERUt8O4i6$4sF^e=)BWO%~%(3M>)vgu_b{0lA+P9_&DovCWFVX zg6ZV;>$MvbdDdgmX!A> Vs(T JUH;jV=3@cNJhF7@C;_qlVR$X0piTCC6P z54y)Op-Sd&+aSkmN!`2r&M%TTxX17+-qGMHL;%{FIDsFn` ch zL1$R((#ab43ckgRE{4RzLe$CqltqmYx*6RFnprMb5WoAv0^Jbc)=y!Uwv-h#QaBRy z|8#ZU@oc?e|8J{Sja1dD)mB?oYPP5mttxHJ4nmFCdzRR-N0r*6HZ^O--kYK}K@dc! z86m_7L7se{=k@#N_jgWS=Q`)y_kCUGzCQ2I`CyhpR%PzcpDeXD{f3vdO!&^a!-|Y2 z>s^i8ez0{0H#pq@k<2wgbd@LRyg|_DG)l8Rksd#aVW^|r`Gu5hx7mrs2K?G=3`I-} z+p)auBRS%1GY($^c>X6{EsHw5jVL^8y)x8@-QrrLJwb`nUVh!Gu$0#^zv;NwNy?9< zOWz%%#a3&F+)3f*NR6)Ar^0l>{0}IY4PdAJ43%T)G2wd`g!_#yXY`(H(}*atmY!bv zBq&mCv97qs_pk;mblvz4y}&I)ehkzC2=rb!c3xm?;b Q+ zPO9+|z-)}_0f)Vg&ZJ9dfG+B>2-K>mvMT?xs1xjdh*e7E6)+IN->YTFELL e4{KhhdpG>M2s{b?!Qa71Y(E88B63~#^CP}o%!V;v=CM6e>?RRO^UDJs z@)WALE5wUG2}&=psT|dN5ANve2=QCD9cBxF+W&duo0$_W4S$afh=b+tVfDVXF+zEk zE+$edxAG~+k#H*R%;Uy~$wIq982=7|s2=9|tNn6o? UT zHF9ov9#q86m)QHNI_RhG=(SK_YymWUCFni;LH91`khYxI^FG-xYWP9h3M}WfhfT;& z?~@I|)efT_PE{~x^d~+C{Otwk(PxeOL*_5aUHQ~ki$gHF-V=&vCLNzuY*-D)E*@<4 z55(%P6tJlTxBErie7vrr===^+yI_h;S)PUOh6o@@bita`Zf+AlbDYY|wq6+~^DX&E z?LY`-mekgJIoN=UF8oX0!FnGc1+nAk-p`ZnJI=fQJQOL}9U@U&HMbdMF8z>>FD28? zZ|pSgC5*qIZ~1n)NppAZ NB(rXKqpc{*i?vnKzg?goA_jZ% z7m-xFI~9{f3A)_6lR!GK0!9$;KVcLDoF$uys(hojbq4v>2l8$}rt2d9(SsDgto& zqPF0J4sn6ikv|$GEZZ hHbCLLA70z>XxBRkT zQ6^2p1>_EuY}%RL<|f#GrF0y=c-3Q3nqwVJPYB#f?@<+r4zIEk4vWwy(LFzC*FBc; zeMGg)qgxwmRbTI0PD^KkF6Bedbl6kivv>hDyGy;j$q>m(7v d4X+-7R|HH2P z6r6fJk`2;zRb@1^!5^nLYn)&az-BJ$vu;h8YiI~i;T@npqKM9-E;=WYft?I= jAja>s96P}E*YLFmgkBf_BS>iITxdRL&zNbt!y(f%jC`|Ygx%6)dp zR$e2YCT6Smn4YZg;n1V1HY5AJIG_HmP*ldXF@+a5>gP|NOP`u)b{2j@1u!nKtanUa z?dUN7L>RJ2@08W>xfLzF|AH_ClMF){RZ{w{RwHrm8=3pctLSG8ia6noMhF p}ld}#>#>EiQd1i*u46*6Bx#ZPzU3yOynFf))W>v4!L9}7-&;gJ& z?^LcX=QDc#wCCrf!mg)?e@@ID8z|l|c|aD00%=A^bTu23THOZlXNrdI+3Py37I=o< z5Z#z#a{d$ZsK>COjE>XslB$(BtYR{R1&3CkuQ& J}!BNvx{WlUlt$H69clEB@=1;0 P}u%e$Y#uMv|lTVTU(b-SYI$$sWK8>KfL> zeE}ye@-(c?J8vShL!>(JwCoL*F&x=?9_0*d{#N>)*n+se!YjKeR?t; IxA2jLY2-I}q! HI5gWocbGZ~y-K&a%Lk(Rg?-o3T=62+N| z0O)N-Pt1kr-rV!$4V3iMLLYFw4UYaDE)_7;?wT`!T+8WS9`{%X?eDh~g@kW7v&!@M z`5mJRcd=FrR}vchc^uC#7@bL2=KWT0W*%OcvBGf(wNv^xGuCLQz+CG}<1WR`o$YQ~ z`6t!l(G)-40C*}_`zBNrOu~BA2*o`Bu^~Em{4t~_Rf$CrxZnfjusU5Rp{|pYoy8AF_oNvNCpMN_m za{AHb?5gXL_YhYBP{6jXZEbFce=zfL)@i0SfJ{7M-^>bG6um+^`hJA2;orLgKuPg1 z`Vb@8bvK_(ZUZ=H=unr#I-5Rp3m#|a%@aB57