substitutions: # ----------------------- # Geräte-Identifikation # ----------------------- device_name: bewaesserung device_friendly_name: "Bewässerung" # ----------------------- # Friendly Names # ----------------------- sensor1_name: "Feuchtigkeit Sensor 1" sensor2_name: "Feuchtigkeit Sensor 2" sensor3_name: "Feuchtigkeit Sensor 3" sensor4_name: "Feuchtigkeit Sensor 4" pumpe1_name: "Pumpe 1" pumpe2_name: "Pumpe 2" pumpe3_name: "Pumpe 3" pumpe4_name: "Pumpe 4" wasserschwimmer_name: "Wassertank Schwimmer" # ----------------------- # Anzahl aktiver Pumpen # ----------------------- anzahl_pumpen: "4" # 1-4: wie viele Pumpen verwendet werden # ----------------------- # Timing (Fix) # ----------------------- # Pause zwischen Pumpen im Auto-Modus pause_zwischen_pumpen: "2s" # Sensor Update Intervall sensor_update_interval: "10s" # ----------------------- # Standardwerte (Für Number / in HA änderbar) # ----------------------- # Schwellwerte für Sensoren (in Volt) # Kapazitive Sensoren: Hoher Wert = trocken (ca. 2V), niedriger Wert = feucht (ca. 0,6V) # Schwellwert bei ca. 1,5V = bewässern wenn trockener als dieser Wert initial_threshold_sensor1: "1.5" initial_threshold_sensor2: "1.5" initial_threshold_sensor3: "1.5" initial_threshold_sensor4: "1.5" # Pumpendauer für Auto-Modus (Sekunden) initial_pumpen_dauer_auto: "10" # Pumpendauer bei Set-Button Kurzdruck (Sekunden) initial_pumpen_dauer_set: "5" # Max. Laufzeit pro Pumpe (Timeout in Sekunden) initial_max_laufzeit: "60" # Auto-Modus Prüfintervall (Sekunden) initial_auto_intervall: "300" # 5 Minuten # ----------------------- # Sicherheit & Netzwerk # ----------------------- wifi_ssid: !secret wifi_ssid wifi_password: !secret wifi_password ap_ssid: "Bewaesserung Fallback" ap_password: !secret ap_password api_encryption_key: !secret api_encryption_key ota_password: !secret ota_password # ----------------------- # I2C Adressen # ----------------------- mcp23017_address: "0x20" ads1115_address: "0x48" # ----------------------- # Hardware GPIO Pins # ----------------------- # I2C Bus sda_pin: GPIO4 scl_pin: GPIO5 # Buttons pin_mode_button: GPIO14 pin_set_button: GPIO16 # ----------------------- # MCP23017 Pin-Mapping # ----------------------- # Wasserschwimmer pin_wasserschwimmer: "7" # Pumpen (MOSFETs) pin_pumpe1: "8" pin_pumpe2: "9" pin_pumpe3: "10" pin_pumpe4: "11" # ----------------------- # Konfiguration ENDE # ----------------------- esphome: name: ${device_name} friendly_name: ${device_friendly_name} comment: "Automatische Bewässerung mit 4 Bodenfeuchtesensoren und 4 Pumpen" project: name: "smarthomeyourself.bewaesserung" version: "1.0.0" esp8266: board: esp01_1m logger: level: INFO api: encryption: key: ${api_encryption_key} # ⚠️ WICHTIG für autonomen Betrieb (ohne Home Assistant): # Wenn die API nicht mit einem Client verbunden werden soll, # muss der reboot_timeout auf 0s gesetzt werden, sonst startet # das Gerät nach 15min automatisch neu! # Für autonomen Betrieb auskommentieren: # reboot_timeout: 0s ota: - platform: esphome password: ${ota_password} # ⚠️ OPTIONAL: Web-Interface für autonomen Betrieb # Ermöglicht lokalen Zugriff auf Sensoren/Schalter ohne Home Assistant # Auskommentieren um Web-Interface zu aktivieren: # web_server: # port: 80 # # Auth ist optional - für ungeschützten Zugriff weglassen: # auth: # username: admin # password: !secret web_server_password # In secrets.yaml definieren wifi: ssid: ${wifi_ssid} password: ${wifi_password} min_auth_mode: WPA2 # ⚠️ WICHTIG für autonomen Betrieb (ohne WiFi): # Wenn kein WiFi verfügbar ist, startet das Gerät nach 15min neu. # Für Betrieb ohne WiFi (nur Access Point) auskommentieren: # reboot_timeout: 0s ap: ssid: ${ap_ssid} password: ${ap_password} captive_portal: # I2C Bus i2c: sda: ${sda_pin} scl: ${scl_pin} id: i2c_component scan: true # 16x Binary GPIO Portexpander mcp23017: - id: mcp1 address: ${mcp23017_address} # 4x Analog Input Portexpander ads1115: - address: ${ads1115_address} id: ads1 # Globale Variablen globals: # Aktuelle Pumpe für Set-Button (1-4) - id: current_pump type: int restore_value: true initial_value: '1' # ============================================================================ # SWITCHES # ============================================================================ # Interne GPIO Switches (nicht für HA freigegeben) # Werden nur über Template Switches mit Sicherheitsprüfung gesteuert switch: - platform: gpio id: pumpe1_gpio internal: true restore_mode: ALWAYS_OFF pin: mcp23xxx: mcp1 number: ${pin_pumpe1} mode: OUTPUT - platform: gpio id: pumpe2_gpio internal: true restore_mode: ALWAYS_OFF pin: mcp23xxx: mcp1 number: ${pin_pumpe2} mode: OUTPUT - platform: gpio id: pumpe3_gpio internal: true restore_mode: ALWAYS_OFF pin: mcp23xxx: mcp1 number: ${pin_pumpe3} mode: OUTPUT - platform: gpio id: pumpe4_gpio internal: true restore_mode: ALWAYS_OFF pin: mcp23xxx: mcp1 number: ${pin_pumpe4} mode: OUTPUT # Template Switches mit Sicherheitsprüfung (für HA freigegeben) # Prüfen Wasserstand + Interlock vor Einschalten - platform: template name: ${pumpe1_name} id: pumpe1 icon: "mdi:water-pump" optimistic: false turn_on_action: - script.execute: pumpe1_an turn_off_action: - script.execute: pumpe1_aus lambda: |- return id(pumpe1_gpio).state; - platform: template name: ${pumpe2_name} id: pumpe2 icon: "mdi:water-pump" optimistic: false turn_on_action: - script.execute: pumpe2_an turn_off_action: - script.execute: pumpe2_aus lambda: |- return id(pumpe2_gpio).state; - platform: template name: ${pumpe3_name} id: pumpe3 icon: "mdi:water-pump" optimistic: false turn_on_action: - script.execute: pumpe3_an turn_off_action: - script.execute: pumpe3_aus lambda: |- return id(pumpe3_gpio).state; - platform: template name: ${pumpe4_name} id: pumpe4 icon: "mdi:water-pump" optimistic: false turn_on_action: - script.execute: pumpe4_an turn_off_action: - script.execute: pumpe4_aus lambda: |- return id(pumpe4_gpio).state; # Gain Messbereich (±V) Auflösung (in µV) # 6.144 ±0.256 V 7.8125 # 4.096 ±0.512 V 15.625 # 2.048 ±1.024 V 31.25 # 1.024 ±2.048 V 62.5 # 0.512 ±4.096 V 125 # 0.256 ±6.144 V 250 sensor: # ═══════════════════════════════════════════════════════════════════════ # Bodenfeuchtesensoren (ADS1115 4x 16-Bit Analog Inputs) # ═══════════════════════════════════════════════════════════════════════ # Gain 6.144 = ±6.144V Messbereich (unterstützt 3.3V und 5V Sensoren) # # ⚙️ WICHTIG: Jumper J6 auf der PCB (Sensor-Spannungswahl): # - Pin 1-2: Sensoren mit 3.3V versorgen → Messbereich 0-3.3V # - Pin 2-3 (Standard): Sensoren mit 5V versorgen → Messbereich 0-5V # ═══════════════════════════════════════════════════════════════════════ - platform: ads1115 ads1115_id: ads1 gain: 6.144 multiplexer: 'A0_GND' name: ${sensor1_name} id: feuchtigkeit1 update_interval: ${sensor_update_interval} unit_of_measurement: "V" accuracy_decimals: 3 device_class: voltage state_class: measurement filters: - sliding_window_moving_average: window_size: 5 send_every: 1 - platform: ads1115 ads1115_id: ads1 gain: 6.144 multiplexer: 'A1_GND' name: ${sensor2_name} id: feuchtigkeit2 update_interval: ${sensor_update_interval} unit_of_measurement: "V" accuracy_decimals: 3 device_class: voltage state_class: measurement filters: - sliding_window_moving_average: window_size: 5 send_every: 1 - platform: ads1115 ads1115_id: ads1 gain: 6.144 multiplexer: 'A2_GND' name: ${sensor3_name} id: feuchtigkeit3 update_interval: ${sensor_update_interval} unit_of_measurement: "V" accuracy_decimals: 3 device_class: voltage state_class: measurement filters: - sliding_window_moving_average: window_size: 5 send_every: 1 - platform: ads1115 ads1115_id: ads1 gain: 6.144 multiplexer: 'A3_GND' name: ${sensor4_name} id: feuchtigkeit4 update_interval: ${sensor_update_interval} unit_of_measurement: "V" accuracy_decimals: 3 device_class: voltage state_class: measurement filters: - sliding_window_moving_average: window_size: 5 send_every: 1 # WiFi Signal - platform: wifi_signal name: "WiFi Signal" update_interval: 60s # Uptime - platform: uptime name: "Uptime" update_interval: 60s # ============================================================================ # BINARY SENSOREN # ============================================================================ binary_sensor: # Wassertank Schwimmer (Füllstand-Sensor) # ON = Wasser verfügbar, OFF = Tank leer - platform: gpio name: ${wasserschwimmer_name} id: wasserstand device_class: moisture pin: mcp23xxx: mcp1 number: ${pin_wasserschwimmer} mode: INPUT_PULLUP inverted: true filters: - delayed_on: 100ms - delayed_off: 100ms on_press: then: - logger.log: "✅ Wassertank: VOLL" # Wenn im Notaus-Modus: Automatisch zurück zu Auto - if: condition: lambda: |- std::string mode = id(betriebsmodus).current_option(); return mode == "Notaus"; then: - select.set: id: betriebsmodus option: "Auto" - logger.log: "✅ Notaus beendet - Wechsel zu Auto-Modus" on_release: then: - script.execute: notaus - logger.log: format: "🚨 NOTAUS: Wassertank LEER!" level: ERROR # Mode-Button (Betriebsmodus wechseln: Auto ↔ Manuell) # Hardware-Pullup (R7 10k) auf PCB vorhanden # Sperre: Deaktiviert bei leerem Wassertank - platform: gpio name: "Mode-Button" id: mode_button pin: number: ${pin_mode_button} mode: INPUT inverted: true filters: - delayed_on: 50ms - delayed_off: 50ms on_press: - if: condition: binary_sensor.is_on: wasserstand then: - script.execute: switch_mode else: - logger.log: format: "🚫 Mode-Button gesperrt - Wassertank leer!" level: WARN # Set-Button (Pumpen manuell aktivieren) # Hardware-Pullup (R11 10k) auf PCB vorhanden # Kurzdruck (<500ms): nächste Pumpe für X Sekunden # Langdruck (>1s): Pumpe aktivieren solange gedrückt - platform: gpio name: "Set-Button" id: set_button pin: number: ${pin_set_button} mode: INPUT inverted: true filters: - delayed_on: 50ms - delayed_off: 50ms # Kurzdruck: < 500ms on_click: min_length: 50ms max_length: 500ms then: - script.execute: set_button_short # Langdruck: > 1s, aktiviert Pumpe solange gedrückt on_multi_click: - timing: - ON for at least 1s then: - script.execute: set_button_long # Status - platform: status name: "Status" # Unbenutzte MCP23017 GPIOs neutralisieren - platform: gpio name: "GPA0" pin: { mcp23xxx: mcp1, number: 0, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPA1" pin: { mcp23xxx: mcp1, number: 1, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPA2" pin: { mcp23xxx: mcp1, number: 2, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPA3" pin: { mcp23xxx: mcp1, number: 3, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPA4" pin: { mcp23xxx: mcp1, number: 4, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPA5" pin: { mcp23xxx: mcp1, number: 5, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPA6" pin: { mcp23xxx: mcp1, number: 6, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPB4" pin: { mcp23xxx: mcp1, number: 12, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPB5" pin: { mcp23xxx: mcp1, number: 13, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPB6" pin: { mcp23xxx: mcp1, number: 14, mode: INPUT_PULLUP } internal: true - platform: gpio name: "GPB7" pin: { mcp23xxx: mcp1, number: 15, mode: INPUT_PULLUP } internal: true # ============================================================================ # TEXT SENSOREN # ============================================================================ text_sensor: - platform: version name: "ESPHome Version" hide_timestamp: true - platform: wifi_info ip_address: name: "IP Adresse" ssid: name: "SSID" mac_address: name: "MAC Adresse" # ============================================================================ # NUMBER INPUTS (konfigurierbare Werte) # ============================================================================ number: # Schwellwerte für Bodenfeuchtesensoren (in Volt) - platform: template name: "Schwellwert Sensor 1" id: threshold_sensor1 icon: "mdi:water-percent" unit_of_measurement: "V" mode: box min_value: 0.0 max_value: 6.0 step: 0.1 initial_value: ${initial_threshold_sensor1} optimistic: true restore_value: true - platform: template name: "Schwellwert Sensor 2" id: threshold_sensor2 icon: "mdi:water-percent" unit_of_measurement: "V" mode: box min_value: 0.0 max_value: 6.0 step: 0.1 initial_value: ${initial_threshold_sensor2} optimistic: true restore_value: true - platform: template name: "Schwellwert Sensor 3" id: threshold_sensor3 icon: "mdi:water-percent" unit_of_measurement: "V" mode: box min_value: 0.0 max_value: 6.0 step: 0.1 initial_value: ${initial_threshold_sensor3} optimistic: true restore_value: true - platform: template name: "Schwellwert Sensor 4" id: threshold_sensor4 icon: "mdi:water-percent" unit_of_measurement: "V" mode: box min_value: 0.0 max_value: 6.0 step: 0.1 initial_value: ${initial_threshold_sensor4} optimistic: true restore_value: true # Pumpendauer für Auto-Modus - platform: template name: "Pumpendauer (Auto-Modus)" id: pumpen_dauer_auto icon: "mdi:timer" unit_of_measurement: "s" mode: box min_value: 1 max_value: 60 step: 1 initial_value: ${initial_pumpen_dauer_auto} optimistic: true restore_value: true # Pumpendauer bei Set-Button Kurzdruck - platform: template name: "Pumpendauer (Set-Button)" id: pumpen_dauer_set icon: "mdi:timer" unit_of_measurement: "s" mode: box min_value: 1 max_value: 30 step: 1 initial_value: ${initial_pumpen_dauer_set} optimistic: true restore_value: true # Max. Laufzeit (Timeout) - platform: template name: "Max. Laufzeit (Timeout)" id: max_laufzeit icon: "mdi:timer-alert" unit_of_measurement: "s" mode: box min_value: 10 max_value: 300 step: 5 initial_value: ${initial_max_laufzeit} optimistic: true restore_value: true # Auto-Modus Prüfintervall - platform: template name: "Auto-Modus Intervall" id: auto_intervall icon: "mdi:clock-outline" unit_of_measurement: "s" mode: box min_value: 60 max_value: 3600 step: 60 initial_value: ${initial_auto_intervall} optimistic: true restore_value: true # ============================================================================ # SELECT (Betriebsmodus) # ============================================================================ select: - platform: template name: "Betriebsmodus" id: betriebsmodus icon: "mdi:cog" options: - "Manuell" - "Auto" - "Notaus" initial_option: "Auto" optimistic: true restore_value: true on_value: then: - logger.log: format: "Betriebsmodus gewechselt: %s" args: ['x.c_str()'] # Bei Wechsel zu Notaus: Alle Pumpen ausschalten - if: condition: lambda: return x == "Notaus"; then: - switch.turn_off: pumpe1_gpio - switch.turn_off: pumpe2_gpio - switch.turn_off: pumpe3_gpio - switch.turn_off: pumpe4_gpio - logger.log: format: "🚨 NOTAUS aktiviert - Alle Pumpen gestoppt" level: WARN # ============================================================================ # BUTTONS # ============================================================================ button: # Mode-Button (virtuell für HA) # Sperre: Deaktiviert bei leerem Wassertank - platform: template name: "Mode-Button" icon: "mdi:format-list-bulleted" on_press: - if: condition: binary_sensor.is_on: wasserstand then: - script.execute: switch_mode else: - logger.log: format: "🚫 Mode-Button gesperrt - Wassertank leer!" level: WARN # Set-Button (virtuell für HA) - platform: template name: "Set-Button" icon: "mdi:rotate-right" on_press: - script.execute: set_button_short # Notaus Button - platform: template name: "🚨 NOTAUS" icon: "mdi:alert-octagon" on_press: then: - script.execute: notaus - logger.log: format: "🚨 NOTAUS manuell ausgelöst!" level: WARN # Neustart - platform: restart name: "Neustart" icon: "mdi:restart" # ============================================================================ # INTERVAL (Automatik-Steuerung) # ============================================================================ interval: # Automatik-Steuerung (prüft Sensoren und bewässert bei Bedarf) - interval: 60s then: - script.execute: automatik_steuerung # ============================================================================ # SCRIPTS # ============================================================================ script: # =================================== # NOTAUS - Modus auf Notaus setzen # =================================== - id: notaus mode: restart then: - select.set: id: betriebsmodus option: "Notaus" - logger.log: format: "🚨 NOTAUS aktiviert!" level: ERROR # =================================== # INTERLOCK - Andere Pumpen abschalten # =================================== - id: interlock_off parameters: except_pump: int then: - lambda: |- if (except_pump != 1) id(pumpe1_gpio).turn_off(); if (except_pump != 2) id(pumpe2_gpio).turn_off(); if (except_pump != 3) id(pumpe3_gpio).turn_off(); if (except_pump != 4) id(pumpe4_gpio).turn_off(); # =================================== # PUMPEN AN/AUS mit Sicherheitsprüfung # =================================== # Pumpe 1 - id: pumpe1_an mode: restart then: - if: condition: and: - binary_sensor.is_on: wasserstand - lambda: |- std::string mode = id(betriebsmodus).current_option(); return mode != "Notaus"; then: - script.execute: id: interlock_off except_pump: 1 - switch.turn_on: pumpe1_gpio - logger.log: "💧 Pumpe 1 EIN" else: - logger.log: format: "🚨 Pumpe 1 BLOCKIERT - Kein Wasser oder Notaus aktiv!" level: ERROR - id: pumpe1_aus then: - switch.turn_off: pumpe1_gpio - logger.log: "⚫ Pumpe 1 AUS" # Pumpe 2 - id: pumpe2_an mode: restart then: - if: condition: and: - binary_sensor.is_on: wasserstand - lambda: |- std::string mode = id(betriebsmodus).current_option(); return mode != "Notaus"; then: - script.execute: id: interlock_off except_pump: 2 - switch.turn_on: pumpe2_gpio - logger.log: "💧 Pumpe 2 EIN" else: - logger.log: format: "🚨 Pumpe 2 BLOCKIERT - Kein Wasser oder Notaus aktiv!" level: ERROR - id: pumpe2_aus then: - switch.turn_off: pumpe2_gpio - logger.log: "⚫ Pumpe 2 AUS" # Pumpe 3 - id: pumpe3_an mode: restart then: - if: condition: and: - binary_sensor.is_on: wasserstand - lambda: |- std::string mode = id(betriebsmodus).current_option(); return mode != "Notaus"; then: - script.execute: id: interlock_off except_pump: 3 - switch.turn_on: pumpe3_gpio - logger.log: "💧 Pumpe 3 EIN" else: - logger.log: format: "🚨 Pumpe 3 BLOCKIERT - Kein Wasser oder Notaus aktiv!" level: ERROR - id: pumpe3_aus then: - switch.turn_off: pumpe3_gpio - logger.log: "⚫ Pumpe 3 AUS" # Pumpe 4 - id: pumpe4_an mode: restart then: - if: condition: and: - binary_sensor.is_on: wasserstand - lambda: |- std::string mode = id(betriebsmodus).current_option(); return mode != "Notaus"; then: - script.execute: id: interlock_off except_pump: 4 - switch.turn_on: pumpe4_gpio - logger.log: "💧 Pumpe 4 EIN" else: - logger.log: format: "🚨 Pumpe 4 BLOCKIERT - Kein Wasser oder Notaus aktiv!" level: ERROR - id: pumpe4_aus then: - switch.turn_off: pumpe4_gpio - logger.log: "⚫ Pumpe 4 AUS" # =================================== # PUMPEN mit Timeout-Steuerung # =================================== # Pumpe für bestimmte Zeit aktivieren (mit Timeout-Schutz) - id: pumpe_timed mode: queued max_runs: 4 parameters: pump_nr: int duration: int then: - lambda: |- int max_time = (int)id(max_laufzeit).state; int actual_duration = (duration > max_time) ? max_time : duration; ESP_LOGI("pumpe", "Aktiviere Pumpe %d für %ds (Max: %ds)", pump_nr, actual_duration, max_time); // Pumpe einschalten if (pump_nr == 1) id(pumpe1_an).execute(); else if (pump_nr == 2) id(pumpe2_an).execute(); else if (pump_nr == 3) id(pumpe3_an).execute(); else if (pump_nr == 4) id(pumpe4_an).execute(); # Non-blocking delay - delay: !lambda "return duration * 1000;" - lambda: |- // Pumpe ausschalten if (pump_nr == 1) id(pumpe1_aus).execute(); else if (pump_nr == 2) id(pumpe2_aus).execute(); else if (pump_nr == 3) id(pumpe3_aus).execute(); else if (pump_nr == 4) id(pumpe4_aus).execute(); # =================================== # MODE-BUTTON: Betriebsmodus wechseln # =================================== - id: switch_mode then: - lambda: |- std::string current = id(betriebsmodus).current_option(); std::string new_mode; // Nur zwischen Auto und Manuell wechseln (Notaus separat) if (current == "Manuell" || current == "Notaus") { new_mode = "Auto"; } else { new_mode = "Manuell"; } id(betriebsmodus).publish_state(new_mode); ESP_LOGI("mode", "Betriebsmodus: %s → %s", current.c_str(), new_mode.c_str()); # =================================== # SET-BUTTON: Kurzdruck # =================================== - id: set_button_short mode: single then: - lambda: |- int anzahl = ${anzahl_pumpen}; // Nächste Pumpe id(current_pump)++; if (id(current_pump) > anzahl) { id(current_pump) = 1; } ESP_LOGI("set_button", "🔄 Wechsel zu Pumpe %d", id(current_pump)); - script.execute: id: pumpe_timed pump_nr: !lambda "return id(current_pump);" duration: !lambda "return (int)id(pumpen_dauer_set).state;" # =================================== # SET-BUTTON: Langdruck (solange gedrückt) # =================================== - id: set_button_long mode: restart then: - logger.log: format: "⏳ Pumpe %d aktiviert (solange gedrückt)" args: ['id(current_pump)'] - lambda: |- int pump = id(current_pump); if (pump == 1) id(pumpe1_an).execute(); else if (pump == 2) id(pumpe2_an).execute(); else if (pump == 3) id(pumpe3_an).execute(); else if (pump == 4) id(pumpe4_an).execute(); # Warte bis Button losgelassen oder Timeout erreicht (non-blocking) - wait_until: timeout: !lambda "return (int)id(max_laufzeit).state * 1000;" condition: binary_sensor.is_off: set_button # Timeout-Warnung falls erreicht - if: condition: binary_sensor.is_on: set_button then: - logger.log: format: "⚠️ Timeout erreicht - Pumpe wird gestoppt" level: WARN # Button wurde losgelassen oder Timeout → Pumpe ausschalten - lambda: |- int pump = id(current_pump); if (pump == 1) id(pumpe1_aus).execute(); else if (pump == 2) id(pumpe2_aus).execute(); else if (pump == 3) id(pumpe3_aus).execute(); else if (pump == 4) id(pumpe4_aus).execute(); - logger.log: "✅ Set-Button losgelassen / Pumpe gestoppt" # =================================== # AUTOMATIK-STEUERUNG # =================================== - id: automatik_steuerung mode: single then: # Nur im Auto-Modus und nach Intervall ausführen - if: condition: lambda: |- // Nur im Auto-Modus std::string mode = id(betriebsmodus).current_option(); if (mode != "Auto") { return false; } // Prüfe Intervall static unsigned long last_check = 0; unsigned long now = millis(); unsigned long interval = (unsigned long)id(auto_intervall).state * 1000; if (now - last_check < interval) { return false; } last_check = now; return true; then: - logger.log: "═══════════════════════════════════" - logger.log: "🔍 Automatik-Prüfung gestartet" # Prüfe Wasserstand - if: condition: binary_sensor.is_off: wasserstand then: - logger.log: format: "⚠️ Kein Wasser im Tank - Abbruch" level: WARN - script.stop: automatik_steuerung # Sensor 1 prüfen - script.execute: auto_check_sensor_1 - delay: ${pause_zwischen_pumpen} # Sensor 2 prüfen - script.execute: auto_check_sensor_2 - delay: ${pause_zwischen_pumpen} # Sensor 3 prüfen (wenn aktiviert) - if: condition: lambda: return ${anzahl_pumpen} >= 3; then: - script.execute: auto_check_sensor_3 - delay: ${pause_zwischen_pumpen} # Sensor 4 prüfen (wenn aktiviert) - if: condition: lambda: return ${anzahl_pumpen} >= 4; then: - script.execute: auto_check_sensor_4 - logger.log: "✅ Automatik-Prüfung abgeschlossen" - logger.log: "═══════════════════════════════════" # =================================== # AUTOMATIK: Einzelne Sensor-Checks # =================================== # Sensor 1 - id: auto_check_sensor_1 mode: single then: - lambda: |- float sensor_value = id(feuchtigkeit1).state; float threshold = id(threshold_sensor1).state; ESP_LOGI("auto", "📊 Sensor 1: %.3fV (Schwelle: %.2fV)", sensor_value, threshold); if (isnan(sensor_value)) { ESP_LOGW("auto", "⚠️ Sensor 1: Fehler/NaN - KEINE Bewässerung!"); return; } // Kapazitive Sensoren: Hoher Wert = trocken, niedriger Wert = feucht if (sensor_value > threshold) { ESP_LOGI("auto", "💧 Sensor 1: %.3fV > %.2fV → ZU TROCKEN, bewässere!", sensor_value, threshold); id(pumpe_timed).execute(1, (int)id(pumpen_dauer_auto).state); } else { ESP_LOGI("auto", "✅ Sensor 1: %.3fV ≤ %.2fV - ausreichend feucht", sensor_value, threshold); } # Sensor 2 - id: auto_check_sensor_2 mode: single then: - lambda: |- float sensor_value = id(feuchtigkeit2).state; float threshold = id(threshold_sensor2).state; ESP_LOGI("auto", "📊 Sensor 2: %.3fV (Schwelle: %.2fV)", sensor_value, threshold); if (isnan(sensor_value)) { ESP_LOGW("auto", "⚠️ Sensor 2: Fehler/NaN - KEINE Bewässerung!"); return; } // Kapazitive Sensoren: Hoher Wert = trocken, niedriger Wert = feucht if (sensor_value > threshold) { ESP_LOGI("auto", "💧 Sensor 2: %.3fV > %.2fV → ZU TROCKEN, bewässere!", sensor_value, threshold); id(pumpe_timed).execute(2, (int)id(pumpen_dauer_auto).state); } else { ESP_LOGI("auto", "✅ Sensor 2: %.3fV ≤ %.2fV - ausreichend feucht", sensor_value, threshold); } # Sensor 3 - id: auto_check_sensor_3 mode: single then: - lambda: |- float sensor_value = id(feuchtigkeit3).state; float threshold = id(threshold_sensor3).state; ESP_LOGI("auto", "📊 Sensor 3: %.3fV (Schwelle: %.2fV)", sensor_value, threshold); if (isnan(sensor_value)) { ESP_LOGW("auto", "⚠️ Sensor 3: Fehler/NaN - KEINE Bewässerung!"); return; } // Kapazitive Sensoren: Hoher Wert = trocken, niedriger Wert = feucht if (sensor_value > threshold) { ESP_LOGI("auto", "💧 Sensor 3: %.3fV > %.2fV → ZU TROCKEN, bewässere!", sensor_value, threshold); id(pumpe_timed).execute(3, (int)id(pumpen_dauer_auto).state); } else { ESP_LOGI("auto", "✅ Sensor 3: %.3fV ≤ %.2fV - ausreichend feucht", sensor_value, threshold); } # Sensor 4 - id: auto_check_sensor_4 mode: single then: - lambda: |- float sensor_value = id(feuchtigkeit4).state; float threshold = id(threshold_sensor4).state; ESP_LOGI("auto", "📊 Sensor 4: %.3fV (Schwelle: %.2fV)", sensor_value, threshold); if (isnan(sensor_value)) { ESP_LOGW("auto", "⚠️ Sensor 4: Fehler/NaN - KEINE Bewässerung!"); return; } // Kapazitive Sensoren: Hoher Wert = trocken, niedriger Wert = feucht if (sensor_value > threshold) { ESP_LOGI("auto", "💧 Sensor 4: %.3fV > %.2fV → ZU TROCKEN, bewässere!", sensor_value, threshold); id(pumpe_timed).execute(4, (int)id(pumpen_dauer_auto).state); } else { ESP_LOGI("auto", "✅ Sensor 4: %.3fV ≤ %.2fV - ausreichend feucht", sensor_value, threshold); } # ============================================================================ # IDEEN / MÖGLICHE ERWEITERUNGEN # ============================================================================ # # Diese Features könnten in Zukunft ergänzt werden: # # 1. Bewässerungs-Zeitfenster: # - Bewässerung nur zwischen bestimmten Uhrzeiten erlauben # - z.B. nur zwischen 06:00 - 22:00 Uhr (nicht nachts) # - Benötigt: time component (SNTP), 4x Number (von_stunde, von_minute, bis_stunde, bis_minute) # - Implementierung: Prüfung in automatik_steuerung Script # # 2. Pause-Funktion: # - Auto-Bewässerung für X Stunden pausieren # - Nützlich nach manuellem Gießen oder bei Regen # - Benötigt: Number (Pause-Dauer in Stunden), Button (Pause aktivieren) # - Implementierung: Timestamp speichern, in automatik_steuerung prüfen # # ============================================================================