From e8abbfea3fda20a7aa99cdaef7497bcfae60afe6 Mon Sep 17 00:00:00 2001 From: Claus Dethlefsen Date: Mon, 25 May 2026 09:41:59 +0200 Subject: [PATCH] Vanding: automationer, datetime-input, shell_command, save-defaults script + mealie --- include/automations/vanding.yaml | 9 +- include/input/datetime/vanding.yaml | 28 ++++++ include/shell_commands/vanding.yaml | 1 + python_scripts/save_vanding_defaults.py | 114 ++++++++++++++++++++++++ www/mealie.json | 2 +- 5 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 include/input/datetime/vanding.yaml create mode 100644 include/shell_commands/vanding.yaml create mode 100644 python_scripts/save_vanding_defaults.py diff --git a/include/automations/vanding.yaml b/include/automations/vanding.yaml index aa53d8b..a87a901 100644 --- a/include/automations/vanding.yaml +++ b/include/automations/vanding.yaml @@ -1,21 +1,21 @@ - alias: 'Vanding morgen kl. 06' trigger: platform: time - at: '06:00:00' + at: input_datetime.vanding_morgen_tid action: - service: script.vanding_hojbed_skiftevis - alias: 'Vanding aften kl. 22' trigger: platform: time - at: '22:00:00' + at: input_datetime.vanding_aften_tid action: - service: script.vanding_hojbed_skiftevis - alias: 'Vanding sikkerhedsstop morgen kl. 8' trigger: platform: time - at: '08:00:00' + at: input_datetime.vanding_sikkerhedsstop_morgen action: - service: script.turn_off data: @@ -30,7 +30,7 @@ - alias: 'Vanding sikkerhedsstop nat kl. 23' trigger: platform: time - at: '23:00:00' + at: input_datetime.vanding_sikkerhedsstop_nat action: - service: script.turn_off data: @@ -41,3 +41,4 @@ - switch.hojbed_1 - switch.hojbed_2 - switch.drivhus_drypvanding + diff --git a/include/input/datetime/vanding.yaml b/include/input/datetime/vanding.yaml new file mode 100644 index 0000000..563bf98 --- /dev/null +++ b/include/input/datetime/vanding.yaml @@ -0,0 +1,28 @@ +# Vandingstidspunkter – initial-værdier overskrives af 'Gem defaults'-knap +vanding_morgen_tid: + name: Vanding – morgen start + has_date: false + has_time: true + initial: "04:00:00" + icon: mdi:weather-sunrise + +vanding_aften_tid: + name: Vanding – aften start + has_date: false + has_time: true + initial: "21:00:00" + icon: mdi:weather-sunset + +vanding_sikkerhedsstop_morgen: + name: Vanding – sikkerhedsstop morgen + has_date: false + has_time: true + initial: "09:00:00" + icon: mdi:alarm-off + +vanding_sikkerhedsstop_nat: + name: Vanding – sikkerhedsstop nat + has_date: false + has_time: true + initial: "23:59:00" + icon: mdi:alarm-off diff --git a/include/shell_commands/vanding.yaml b/include/shell_commands/vanding.yaml new file mode 100644 index 0000000..4877059 --- /dev/null +++ b/include/shell_commands/vanding.yaml @@ -0,0 +1 @@ +vanding_save_defaults: "python3 /config/python_scripts/save_vanding_defaults.py" diff --git a/python_scripts/save_vanding_defaults.py b/python_scripts/save_vanding_defaults.py new file mode 100644 index 0000000..b495431 --- /dev/null +++ b/python_scripts/save_vanding_defaults.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +""" +Gem nuværende vandingsindstillinger som nye 'initial' standardværdier i YAML-filerne. +Efter dette script køres vil næste HA-genstart bruge de gemte værdier. + +Køres inde i homeassistant Docker-containeren via shell_command. +""" +import re +import json +import urllib.request + +DATETIME_FILE = "/config/include/input/datetime/vanding.yaml" +NUMBER_FILE = "/config/include/input/number/vanding.yaml" +SECRETS_FILE = "/config/secrets.yaml" +HA_URL = "http://localhost:8123" + +DATETIME_ENTITIES = [ + "vanding_morgen_tid", + "vanding_aften_tid", + "vanding_sikkerhedsstop_morgen", + "vanding_sikkerhedsstop_nat", +] + +NUMBER_ENTITIES = [ + "vanding_varighed_smart", + "vanding_varighed_hojbed_1", + "vanding_varighed_hojbed_2", + "vanding_varighed_hojbed_3", +] + + +def get_token(): + with open(SECRETS_FILE) as f: + for line in f: + if line.startswith("ha_token:"): + return line.split(":", 1)[1].strip() + raise ValueError("ha_token ikke fundet i secrets.yaml") + + +def get_states(token): + req = urllib.request.Request( + f"{HA_URL}/api/states", + headers={"Authorization": f"Bearer {token}"}, + ) + with urllib.request.urlopen(req, timeout=10) as resp: + return {d["entity_id"]: d["state"] for d in json.loads(resp.read())} + + +def update_initial(content, entity_name, new_value): + """Erstat initial-værdien for en given entity i YAML-indholdet.""" + pattern = rf"(^{re.escape(entity_name)}:\n(?: [^\n]*\n)*? initial: )\S+" + new_content, count = re.subn( + pattern, rf'\g<1>"{new_value}"', content, flags=re.MULTILINE, count=1 + ) + if count == 0: + print(f" ADVARSEL: {entity_name} ikke fundet i YAML") + return new_content + + +def main(): + token = get_token() + states = get_states(token) + saved = [] + + # Gem input_datetime tider + with open(DATETIME_FILE) as f: + dt_content = f.read() + + for name in DATETIME_ENTITIES: + entity_id = f"input_datetime.{name}" + state = states.get(entity_id) + if state in (None, "unavailable", "unknown"): + print(f" SPRING OVER {entity_id}: {state}") + continue + # HA returnerer HH:MM:SS for input_datetime (time only) + dt_content = update_initial(dt_content, name, state) + saved.append(f"{entity_id} = {state}") + + with open(DATETIME_FILE, "w") as f: + f.write(dt_content) + + # Gem input_number værdier + with open(NUMBER_FILE) as f: + num_content = f.read() + + for name in NUMBER_ENTITIES: + entity_id = f"input_number.{name}" + state = states.get(entity_id) + if state in (None, "unavailable", "unknown"): + print(f" SPRING OVER {entity_id}: {state}") + continue + val = float(state) + val_str = str(int(val)) if val == int(val) else str(val) + # input_number initial er uden anførselstegn + pattern = rf"(^{re.escape(name)}:\n(?: [^\n]*\n)*? initial: )\S+" + num_content, count = re.subn( + pattern, rf"\g<1>{val_str}", num_content, flags=re.MULTILINE, count=1 + ) + if count == 0: + print(f" ADVARSEL: {name} ikke fundet i YAML") + else: + saved.append(f"{entity_id} = {val_str}") + + with open(NUMBER_FILE, "w") as f: + f.write(num_content) + + print(f"Gemt {len(saved)} standardværdier") + for line in saved: + print(f" {line}") + + +if __name__ == "__main__": + main() + diff --git a/www/mealie.json b/www/mealie.json index 53f24df..6b98c03 100644 --- a/www/mealie.json +++ b/www/mealie.json @@ -1 +1 @@ -{"count": 7, "items": [{"date": "2026-05-29", "recipe": {"name": "Laks med sesam og citron", "slug": "laks-med-sesam-og-citron"}}, {"date": "2026-05-30", "recipe": {"name": "Hjemmelavet laksesushi", "slug": "hjemmelavet-laksesushi"}}, {"date": "2026-05-28", "recipe": {"name": "One Pot Pasta med chorizo", "slug": "one-pot-pasta-med-chorizo"}}, {"date": "2026-05-27", "recipe": {"name": "Rester fra mandag (Bolognese)", "slug": ""}}, {"date": "2026-05-26", "recipe": {"name": "Rester fra s\u00f8ndag (Kylling i sennepssauce)", "slug": ""}}, {"date": "2026-05-25", "recipe": {"name": "Spaghetti Bolognese - pasta med k\u00f8dsovs", "slug": "spaghetti-bolognese-pasta-med-kodsovs"}}, {"date": "2026-05-24", "recipe": {"name": "Kylling i cremet sennepssauce", "slug": "kylling-i-cremet-sennepssauce"}}]} \ No newline at end of file +{"count": 7, "items": [{"date": "2026-05-29", "recipe": {"name": "Laks med sesam og citron", "slug": "laks-med-sesam-og-citron"}}, {"date": "2026-05-31", "recipe": {"name": "Marry Me Chicken", "slug": "marry-me-chicken"}}, {"date": "2026-05-30", "recipe": {"name": "Hjemmelavet laksesushi", "slug": "hjemmelavet-laksesushi"}}, {"date": "2026-05-28", "recipe": {"name": "One Pot Pasta med chorizo", "slug": "one-pot-pasta-med-chorizo"}}, {"date": "2026-05-27", "recipe": {"name": "Rester fra mandag (Bolognese)", "slug": ""}}, {"date": "2026-05-26", "recipe": {"name": "Rester fra s\u00f8ndag (Kylling i sennepssauce)", "slug": ""}}, {"date": "2026-05-25", "recipe": {"name": "Spaghetti Bolognese - pasta med k\u00f8dsovs", "slug": "spaghetti-bolognese-pasta-med-kodsovs"}}]} \ No newline at end of file