From 6f304efb57d0ef31ee059b10806d9a4e988345e0 Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Mon, 14 Jul 2025 11:32:25 +0200 Subject: [PATCH] feat(esphome): Add initial irrigation system configuration This commit introduces the initial ESPHome configuration for the irrigation system. - `irrigation_system.yaml`: ESPHome configuration with Modbus valve control. - `create_secrets.py`: Script to generate `secrets.yaml`. - `secrets.yaml.example`: Example secrets file. - `requirements.txt`: Python dependencies. - `.gitignore`: Standard ESPHome gitignore file. Signed-off-by: Eduard Iten --- software/esphome/.gitignore | 5 ++ software/esphome/create_secrets.py | 55 ++++++++++++ software/esphome/irrigation_system.yaml | 111 ++++++++++++++++++++++++ software/esphome/requirements.txt | 2 + software/esphome/secrets.yaml.example | 4 + 5 files changed, 177 insertions(+) create mode 100644 software/esphome/.gitignore create mode 100755 software/esphome/create_secrets.py create mode 100644 software/esphome/irrigation_system.yaml create mode 100644 software/esphome/requirements.txt create mode 100644 software/esphome/secrets.yaml.example diff --git a/software/esphome/.gitignore b/software/esphome/.gitignore new file mode 100644 index 0000000..d8b4157 --- /dev/null +++ b/software/esphome/.gitignore @@ -0,0 +1,5 @@ +# Gitignore settings for ESPHome +# This is an example and may include too much for your use-case. +# You can modify this file to suit your needs. +/.esphome/ +/secrets.yaml diff --git a/software/esphome/create_secrets.py b/software/esphome/create_secrets.py new file mode 100755 index 0000000..2901973 --- /dev/null +++ b/software/esphome/create_secrets.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import secrets +import string +import os +import base64 +from ruamel.yaml import YAML + +def generate_password(length=32): + """Generate a random password.""" + alphabet = string.ascii_letters + string.digits + return ''.join(secrets.choice(alphabet) for i in range(length)) + +def generate_api_key(): + """Generate a random 32-byte key and base64 encode it.""" + return base64.b64encode(secrets.token_bytes(32)).decode('utf-8') + +SECRETS_FILE = 'secrets.yaml' +# In a real ESPHome project, secrets are often included from a central location +# but for this script, we'll assume it's in the current directory. +# You might need to adjust this path. +secrets_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), SECRETS_FILE) + +yaml = YAML() +yaml.preserve_quotes = True +# To prevent line wrapping +yaml.width = 4096 + +try: + with open(secrets_path, 'r') as f: + secrets_data = yaml.load(f) + if secrets_data is None: + secrets_data = {} +except FileNotFoundError: + print(f"Info: '{SECRETS_FILE}' not found. A new file will be created.") + secrets_data = {} + +# Generate new random passwords +new_api_key = generate_api_key() +new_ota_password = generate_password() + +# Update the dictionary with the new passwords +if 'api_password' in secrets_data: + del secrets_data['api_password'] +secrets_data['api_key'] = new_api_key +secrets_data['ota_password'] = new_ota_password + +# Write the updated dictionary back to the YAML file +with open(secrets_path, 'w') as f: + yaml.dump(secrets_data, f) + +print(f"Successfully updated '{SECRETS_FILE}'.") +print("New values:") +print(f" api_key: {new_api_key}") +print(f" ota_password: {new_ota_password}") \ No newline at end of file diff --git a/software/esphome/irrigation_system.yaml b/software/esphome/irrigation_system.yaml new file mode 100644 index 0000000..571513b --- /dev/null +++ b/software/esphome/irrigation_system.yaml @@ -0,0 +1,111 @@ +esphome: + name: irrigation-system + friendly_name: Bewässerung + +esp32: + board: esp32-c6-devkitm-1 + framework: + type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + fast_connect: true + +api: + encryption: + key: !secret api_key + +ota: + platform: esphome + password: !secret ota_password + +logger: + +web_server: + +# UART-Bus für Modbus +uart: + id: uart_bus + tx_pin: GPIO1 + rx_pin: GPIO2 + baud_rate: 9600 + stop_bits: 1 + parity: NONE + +# Modbus-Komponente (der Hub) +modbus: + - id: modbus1 + uart_id: uart_bus + +modbus_controller: + - id: valve_device + address: 0x01 + modbus_id: modbus1 + +number: + - platform: modbus_controller + modbus_controller_id: valve_device + id: valve_controller_command + name: "Valve Control" + address: 0x01 + value_type: U_WORD + # min_value: 0 + # max_value: 2 + # step: 1 + +globals: + - id: my_valve_is_open + type: bool + restore_value: false + initial_value: 'true' + +valve: + - platform: template + name: "Modbus Ventil" + id: my_modbus_valve + + # Lambda, um den aktuellen Zustand zu bestimmen + # Liest den Zustand aus der globalen Variable + lambda: |- + return id(my_valve_is_open); + + # Aktion beim Drücken auf "Öffnen" + open_action: + - number.set: + id: valve_controller_command + value: 1 + - globals.set: + id: my_valve_is_open + value: 'true' + + # Aktion beim Drücken auf "Schliessen" + close_action: + - number.set: + id: valve_controller_command + value: 2 + - globals.set: + id: my_valve_is_open + value: 'false' + + # (Optional) Aktion beim Drücken auf "Stopp" + stop_action: + - number.set: + id: valve_controller_command + value: 0 + +sensor: +- platform: modbus_controller + modbus_controller_id: valve_device + name: "Supply Voltage" + register_type: read + device_class: voltage + entity_category: diagnostic + accuracy_decimals: 2 + filters: + - lambda: |- + return x / 1000.0; + address: 0x00F5 + unit_of_measurement: "V" + value_type: U_WORD + diff --git a/software/esphome/requirements.txt b/software/esphome/requirements.txt new file mode 100644 index 0000000..1994f4e --- /dev/null +++ b/software/esphome/requirements.txt @@ -0,0 +1,2 @@ +ruamel.yaml +esphome diff --git a/software/esphome/secrets.yaml.example b/software/esphome/secrets.yaml.example new file mode 100644 index 0000000..165698b --- /dev/null +++ b/software/esphome/secrets.yaml.example @@ -0,0 +1,4 @@ +wifi_ssid: 'PUT YOUR WIFI SSID HERE' +wifi_password: 'PUT YOUR WIFI PASSWORD HERE' +api_key: 'PUT YOUR KEY HERE OR USE create_secrets.py' +ota_password: 'PUT YOUR KEY HERE OR USE create_secrets.py'