Compare commits

..

4 Commits

Author SHA1 Message Date
claus 5a9db0b8c2 improve(automation): increase reliability of tesla charging control
- Change mode to restart to prevent skipped runs
- Replace failsafe template trigger with time_pattern
- Add plugged-in condition to avoid unnecessary switching
- Add explicit deadline validation condition

Result:
- More reliable execution of charging logic
- Prevents missed failsafe activation
- Reduces unnecessary charger toggling
2026-03-17 06:18:50 +01:00
claus dde5ff292a fix(template): correct and simplify tesla_charge_now logic
- Convert tesla_charge_now to binary_sensor
- Replace strptime with as_timestamp for robust time parsing
- Fix hour alignment (remove 15-min slot mismatch)
- Implement proper deadline filtering using timestamps
- Simplify template to minimal, readable logic

Result:
- Accurate identification of cheapest charging hours
- Eliminates false negatives in charge scheduling
2026-03-17 06:18:27 +01:00
claus bed93b148f Get rid of warnings in the log 2026-03-16 21:03:57 +01:00
claus da931bbca6 Make startup happy 2026-03-16 19:38:07 +01:00
7 changed files with 39 additions and 54 deletions
+2 -3
View File
@@ -2,9 +2,8 @@
trigger: trigger:
platform: state platform: state
entity_id: binary_sensor.indkorsel_sensor_motion entity_id: binary_sensor.indkorsel_sensor_motion
to: 'on' condition: to: 'on'
- condition: template actions:
value_template: "{{ states('input_number.ai_gemini_calls_today') | int < 20 }}" actions:
- action: script.overvaagning - action: script.overvaagning
metadata: {} metadata: {}
data: {} data: {}
-9
View File
@@ -1,9 +0,0 @@
- alias: Reset AI Gemini Calls Daily
trigger:
platform: time
at: '00:00:00'
action:
- service: input_number.set_value
data:
entity_id: input_number.ai_gemini_calls_today
value: 0
@@ -1,12 +1,15 @@
- alias: Tesla failsafe charge - alias: Tesla failsafe charge
trigger: trigger:
- platform: template - platform: time_pattern
minutes: "/5"
condition:
- condition: template
value_template: > value_template: >
{% set deadline_ts = as_timestamp(states('input_datetime.tesla_charge_deadline')) %} {% set deadline_ts = as_timestamp(states('input_datetime.tesla_charge_deadline')) %}
{% set now_ts = as_timestamp(now()) %} {% set now_ts = as_timestamp(now()) %}
{{ (deadline_ts - now_ts) <= 3600 }} # 1 time = 3600 sekunder {{ (deadline_ts - now_ts) <= 3600 }}
condition:
- condition: numeric_state - condition: numeric_state
entity_id: sensor.tesla_kwh_needed entity_id: sensor.tesla_kwh_needed
above: 0 above: 0
@@ -2,8 +2,8 @@
trigger: trigger:
- platform: template - platform: template
value_template: > value_template: >
{{ states('sensor.snowywhite_battery')|float >= {{ (states('sensor.snowywhite_battery') | default(0)) | float >=
states('number.snowywhite_charge_limit')|float }} (states('number.snowywhite_charge_limit') | default(100)) | float }}
action: action:
- service: switch.turn_off - service: switch.turn_off
-7
View File
@@ -1,7 +0,0 @@
ai_gemini_calls_today:
name: AI Gemini Calls Today
min: 0
max: 50
step: 1
mode: box
unit_of_measurement: calls
+3 -6
View File
@@ -43,14 +43,11 @@ overvaagning:
eller stationære objekter. Hvis der ikke er nogen synlig årsag til eller stationære objekter. Hvis der ikke er nogen synlig årsag til
bevægelsen, svar blot med 'Ingen åbenlys bevægelse detekteret.' Hold bevægelsen, svar blot med 'Ingen åbenlys bevægelse detekteret.' Hold
beskeden kort og underholdende som en notifikation på Apple! beskeden kort og underholdende som en notifikation på Apple!
images: filenames:
- /config/www/indkorsel_snapshot.jpg - /config/www/indkorsel_snapshot.jpg
response_variable: generated_content response_variable: generated_content
action: ai_task.generate_data action: google_generative_ai_conversation.generate_content
- service: input_number.set_value - if:
data:
entity_id: input_number.ai_gemini_calls_today
value: "{{ states('input_number.ai_gemini_calls_today') | int + 1 }}"
- condition: template - condition: template
value_template: "{{ 'No Obvious Motion Detected.' in generated_content.text }}" value_template: "{{ 'No Obvious Motion Detected.' in generated_content.text }}"
then: then:
+18 -16
View File
@@ -1,27 +1,29 @@
platform: template binary_sensor:
sensors:
- name: tesla_charge_now - name: tesla_charge_now
state: > state: >
{% set deadline = states('input_datetime.tesla_charge_deadline') %} {% set deadline_raw = states('input_datetime.tesla_charge_deadline') %}
{% set hours_needed = states('sensor.tesla_charge_hours_needed')|float(0)|round(0,'ceil') %} {% set deadline_ts = as_timestamp(deadline_raw) if deadline_raw not in ['unknown','unavailable',''] else none %}
{% set prices = state_attr('sensor.energidataservice','today') + state_attr('sensor.energidataservice','tomorrow') %}
{% set valid = [] %}
{# Filtrer kun timer før deadline #} {% set hours_needed = states('sensor.tesla_charge_hours_needed') | float(0) | round(0, 'ceil') %}
{% set prices = (state_attr('sensor.energidataservice','today') or [])
+ (state_attr('sensor.energidataservice','tomorrow') or []) %}
{# Filter valid price entries and apply deadline #}
{% set valid = [] %}
{% for p in prices %} {% for p in prices %}
{% set slot_time = as_timestamp(strptime(p.hour,'%Y-%m-%dT%H:%M:%S')) %} {% if p.hour is defined and p.hour %}
{% if slot_time <= as_timestamp(deadline) %} {% set ts = as_timestamp(p.hour) %}
{% if not deadline_ts or ts <= deadline_ts %}
{% set valid = valid + [p] %} {% set valid = valid + [p] %}
{% endif %} {% endif %}
{% endif %}
{% endfor %} {% endfor %}
{# Sorter efter pris #} {# Pick cheapest hours #}
{% set sorted = valid | sort(attribute='price') %} {% set cheapest = (valid | sort(attribute='price'))[:hours_needed] %}
{# Vælg de billigste slots der dækker ladetiden #} {# Current hour #}
{% set cheapest = sorted[:hours_needed] %} {% set now_slot = now().replace(minute=0, second=0, microsecond=0).isoformat() %}
{# Tjek om nuværende slot er i listen #}
{% set now_slot = now().replace(minute=(now().minute//15)*15, second=0, microsecond=0).isoformat() %}
{{ cheapest | selectattr('hour','equalto',now_slot) | list | count > 0 }} {{ cheapest | selectattr('hour','equalto',now_slot) | list | count > 0 }}