AutomationDataset/CJDumbleton/CJDumbleton_automations.yaml

169 lines
7.3 KiB
YAML

- alias: PV clipping - Forecast clipped PV for next 24 hours
description: 'Calculates forecast clipped PV for day = sum of 5 minute predbat.pv_energy forecasts
> inverter limit.
Change the variables to suit your set-up. Adjust the tuning_factor to optimise
battery availability. The tuning factor is designed to account for spikey solar
due to intermittent clouds and how aggressive you want to be with making room
in the battery - the lower the value, the more room it will make.'
triggers:
- event: sunrise
offset: 0
trigger: sun
conditions: []
actions:
- variables:
tuning_factor: 0.9
inverter_limit_kW: 5
inverter_limit: '{{ inverter_limit_kW / 12 }}'
- metadata: {}
data:
value: "{% set pv_clipped = namespace(value=0.0) %} {% set pv_prev\
\ = namespace(value=0.0) %} {% set pv_cur = namespace(value=0.0) %}\
\ {% if state_attr('predbat.pv_energy', 'results') %}\n {%- for five_min_period\
\ in state_attr('predbat.pv_energy', 'results') -%}\n {% if loop.index0\
\ == 0 %}\n {%- set pv_prev.value = state_attr('predbat.pv_energy', 'results')[five_min_period]\
\ | float -%}\n {% else %}\n {%- set pv_cur.value = state_attr('predbat.pv_energy',\
\ 'results')[five_min_period] | float -%}\n {% set tuned_clipped = (pv_cur.value\
\ - pv_prev.value) / tuning_factor %}\n {% if tuned_clipped > inverter_limit\
\ %}\n {%- set pv_clipped.value = pv_clipped.value + tuned_clipped\
\ - inverter_limit -%}\n {% endif %}\n {%- set pv_prev.value = pv_cur.value\
\ -%}\n {% endif %}\n {# Only look at the next 24 hours (each loop is\
\ 5 minutes) #}\n {% if loop.index0 == 288 %}\n {% break %}\n {%\
\ endif %}\n {%- endfor -%} \n{% endif %} {{ pv_clipped.value }}\n"
target:
entity_id: input_number.pv_clipped_in_next_24_hours
action: input_number.set_value
mode: single
- alias: PV clipping - make room in battery at sunrise
description: "Make room in battery at sunrise if PV clipping is forecast in the\
\ next 24 hours \nAdjust the variables to suit your set-up. The sunrise_to_clipping_hours\
\ variable is the number of hours from sunrise to when your set-up is first at\
\ risk of clipping. Round up to the nearest half-hour eg 3.5\nIf any clipping\
\ is predicted, the automation sets the first 30-min export for (sunrise_to_clipping_hours\
\ - 0.5) hours after sunrise. Then backfills towards sunrise with appropriate\
\ force export and freeze export slots. Assumes a straight-line increase in export\
\ capacity being taken up by solar export from sunrise to clipping start. And\
\ a corresponding decrease in availability for battery export. Does not account\
\ for load."
triggers:
- event: sunrise
offset: '120'
trigger: sun
conditions:
- condition: numeric_state
entity_id: predbat.rates
above: 0
- condition: template
value_template: '{{ states(''input_number.pv_clipped_in_next_24_hours'') | float
> 0 }}
'
actions:
- variables:
inverter_limit: 5
bat_capacity_max: 9.5
bat_discharge_max: 3.6
sunrise_to_clipping_hours: 4
slots: '{{ (sunrise_to_clipping_hours * 2) | int }}'
soc: '{{ states(''predbat.soc_kw_h0'') | float }}'
- repeat:
sequence:
- if:
- condition: template
value_template: '{{ states(''input_number.pv_clipped_in_next_24_hours'')
| float > 0 }}'
then:
- metadata: {}
data:
option: '{% set t = utcnow().strftime("%s") | int %} {# Round up
the time to nearest half-hour #} {# Set 30-min export for offset
seconds after sunrise #} {% set offset = (slots - repeat.index) *
1800 %} {{ (t - (t % 1800) + offset) | timestamp_custom("%H:%M:%S")
}}
'
target:
entity_id: select.predbat_manual_export
action: select.select_option
- action: input_number.set_value
metadata: {}
data:
value: "{# Assume straight line climb in solar export from 0 to inverter_limit\
\ over sunrise_to_clipping_hours. #} {% set solar_export = (slots\
\ - repeat.index) * (inverter_limit / slots) %} {% set available_export_capacity\
\ = inverter_limit - solar_export %} {# How much battery can be\
\ exported in 30-min period? #} {% set battery_export = min(bat_discharge_max,\
\ available_export_capacity) / 2 %} {# If the battery isn't full,\
\ we already have some spare capacity for clipping. #} {% set clipping\
\ = namespace(value=states('input_number.pv_clipped_in_next_24_hours')\
\ | float) %} {% if repeat.index == 1 %}\n {%- set clipping.value\
\ = clipping.value - (bat_capacity_max - soc) -%}\n{% endif %} {# We\
\ don't need to export more than the current battery SOC. #} {% set\
\ excess = min(soc, clipping.value) %} {{ max(excess - battery_export,\
\ 0) }}\n"
target:
entity_id: input_number.pv_clipped_in_next_24_hours
else:
- metadata: {}
data:
option: '{% set t = utcnow().strftime("%s") | int %} {# Round up
the time to nearest half-hour #} {# Set 30-min freeze charge for
offset seconds after sunrise #} {% set offset = (slots - repeat.index)
* 1800 %} {{ (t - (t % 1800) + offset) | timestamp_custom("%H:%M:%S")
}}
'
target:
entity_id: select.predbat_manual_freeze_export
action: select.select_option
- delay:
hours: 0
minutes: 0
seconds: 1
milliseconds: 0
count: '{{ slots }}'
mode: single
- alias: PV clipping - PV goes above inverter limit
description: Set predbat force manual export for this 30-min period. (Replace geserial
with your GE inverter serial number. Replace 5000 with your hybrid inverter limit
in Watts.)
triggers:
- entity_id:
- sensor.givtcp_geserial_pv_power
above: 5000
trigger: numeric_state
- minutes: '1'
trigger: time_pattern
- minutes: '31'
trigger: time_pattern
conditions:
- condition: sun
before: sunset
after: sunrise
- condition: numeric_state
entity_id: predbat.rates
above: 0
- condition: template
value_template: "{# Check this half-hour is not already set to force export #}\
\ \n{% set t = utcnow().strftime(\"%s\") | int %} \n{% set half_hour = (t -\
\ (t % 1800 )) | timestamp_custom(\"%H:%M:%S\") %}\n{{ half_hour not in states('select.predbat_manual_export')\
\ }}"
- condition: numeric_state
entity_id: sensor.givtcp_geserial_pv_power
above: 5000
- condition: numeric_state
entity_id: predbat.soc_kw_h0
above: 1
actions:
- metadata: {}
data:
option: '{# Round down the time to nearest half-hour #} {% set t = utcnow().strftime("%s")
| int %} {{ (t - (t % 1800 )) | timestamp_custom("%H:%M:%S") }}
'
target:
entity_id: select.predbat_manual_export
action: select.select_option
mode: single