diff --git a/README.md b/README.md index 12f659e..e9a032b 100644 --- a/README.md +++ b/README.md @@ -59,14 +59,14 @@ This project is in its early stages and is actively being developed and enhanced ### Base -EOS Connect is a self-running system that periodically collects: +**EOS Connect** is a self-running system that periodically collects: - Local energy consumption data. - PV solar forecasts for the next 48 hours. - Upcoming energy prices. Using this data, a request is sent to EOS, which creates a model predicting the energy needs based on different energy sources and loads (grid, battery, PV). -EOS Connect waits for the response from EOS (e.g., ~2 min 15 sec for a full 48-hour prediction on a Raspberry Pi 5). After receiving the response, it is analyzed to extract the necessary values. +**EOS Connect** waits for the response from EOS (e.g., ~2 min 15 sec for a full 48-hour prediction on a Raspberry Pi 5). After receiving the response, it is analyzed to extract the necessary values. Finally, the system sets up the inverter based on the following states: - `MODE_CHARGE_FROM_GRID` with a specific target charging power (based on your configuration). @@ -103,11 +103,15 @@ Energy price forecasts are retrieved from the chosen source (TIBBER or AKKUDOKTO ## Webpage Example +The dashbaord of **EOS connect** is available at `http://localhost:8081`. + ![webpage screenshot](doc/screenshot.PNG) ## Configuration -Configuration is described here [CONFIG_README](src/CONFIG_README.md) +With the first start of **EOS connect** a default `config.yaml` will be generated in the `\src` folder. For full documentation for the different entries go to [CONFIG_README](src/CONFIG_README.md) + +*Note: With the default config and a valid EOS server IP/DNS name entry ('eos -> server') - **EOS connect** should be running out of the box with some static defaults as a start point for a step-by-step commissioning.* ## Useful Information diff --git a/doc/screenshot.PNG b/doc/screenshot.PNG index ce4e6e7..26fca08 100644 Binary files a/doc/screenshot.PNG and b/doc/screenshot.PNG differ diff --git a/src/CONFIG_README.md b/src/CONFIG_README.md index 9c20420..561d412 100644 --- a/src/CONFIG_README.md +++ b/src/CONFIG_README.md @@ -1,153 +1,106 @@ # Configuration Guide -This document provides an overview of the configuration settings for the application. The configuration settings are stored in a `config.yaml` file. -A default config file will be created with the first start, if there is no config.yaml in folder 'src'. +This document provides an overview of the configuration settings for the application. The configuration settings are stored in a `config.yaml` file. +A default config file will be created with the first start, if there is no `config.yaml` in the `src` folder. + +--- ## Configuration Sections -### Load Configuration +### **Load Configuration** -- **load.source**: Data source for load power. Possible values: `openhab`, `homeassistant`, `default` (default will using a primitive static consumption scheme). -- **load.url**: URL for openhab (e.g. ip:8080) or homeassistant (e.g. ip:8123) -- **load.load_sensor**: item / entity name for load power data (openhab item/ homeassistant sensor) - HINT: for Home Assistant expected as persisted negative values -- **load.car_charge_load_sensor**: item / entity for wallbox power data -- **load.access_token**: access token for homeassistant (optional) +- **`load.source`**: + Data source for load power. Possible values: `openhab`, `homeassistant`, `default` (default will use a primitive static consumption scheme). -### EOS Server Configuration +- **`load.url`**: + URL for OpenHAB (e.g., `http://:8080`) or Home Assistant (e.g., `http://:8123`). -- **eos.server**: EOS server address. -- **eos.port**: port for EOS server. -- **timeout**: timeout for EOS optimize request in seconds +- **`load.load_sensor`**: + Item/entity name for load power data (OpenHAB item/Home Assistant sensor). + Must be in watts. + **Hint**: For Home Assistant, negative values are expected for persisted data. -### Electricity Price Configuration +- **`load.car_charge_load_sensor`**: + Item/entity name for wallbox power data. + Must be in watts or kilowatts (automatically checked). -- **price.source**: Data source for electricity price. Possible values: `tibber`, `akkudoktor`. -- **price.token**: Token for electricity price. -- **price.feed_in_price**: Feed-in price for the grid in €/kWh -- **price.negative_price_switch**: Switch for handling negative electricity prices (e.g., no payment if negative stock price). select "True" for limit the feed-in price to 0 if there is a negative stock price in this hour or "False" to ignore this specific handling and use only the feed-in price as constant +- **`load.access_token`**: + Access token for Home Assistant (optional). -### Battery Configuration -- **battery.source**: Data source for battery SOC. Possible values: openhab, homeassistant, default (static data). -- **battery.url**: URL for openhab (e.g. ip:8080) or homeassistant (e.g. ip:8123) -- **battery.soc_sensor**: item / entity name for soc_sensor (openhab item/ homeassistant sensor) -- **battery.access_token**: access token for homeassistant (optional) -- -- **battery.capacity_wh**: Battery capacity in Wh. -- **battery.charge_efficiency**: Efficiency for charging the battery. -- **battery.discharge_efficiency**: Efficiency for discharging the battery. -- **battery.max_charge_power_w**: Maximum charging power in W. -- **battery.min_soc_percentage**: Minimum state of charge percentage. -- **battery.max_soc_percentage**: Maximum state of charge percentage. +--- -### PV Forecast Configuration +### **EOS Server Configuration** -The `pv_forecast` section allows you to define multiple PV forecast entries, each distinguished by a user-given name. Below is an example of a default PV forecast configuration: +- **`eos.server`**: + EOS server address (e.g., `192.168.1.94`). -```yaml -pv_forecast: - - name: default - lat: 47.5 - lon: 8.5 - azimuth: 10.0 - tilt: 30.0 - power: 4600 - powerInverter: 5000 - inverterEfficiency: 0.9 - horizont: "10,20,10,15" -``` +- **`eos.port`**: + Port for the EOS server. Default: `8503`. -ATTENTION (2025-04-05): incompatible change from +- **`timeout`**: + Timeout for EOS optimization requests, in seconds. Default: `180`. -```yaml -pv_forecast: - default: - lat: 47.5 -``` -to -```yaml -pv_forecast: - - name: default - lat: 47.5 -``` +--- -Each PV forecast entry can have the following parameters: +### **Electricity Price Configuration** -*hint: check also for details https://api.akkudoktor.net/#/pv%20generation%20calculation/getForecast* +- **`price.source`**: + Data source for electricity prices. Possible values: `tibber`, `default` (default uses akkudoktor API). -- **lat**: Latitude for PV forecast @ Akkudoktor API. -- **lon**: Longitude for PV forecast @ Akkudoktor API. -- **azimuth**: Azimuth for PV forecast @ Akkudoktor API. -- **tilt**: Tilt for PV forecast @ Akkudoktor API. -- **power**: Power for PV forecast @ Akkudoktor API. -- **powerInverter**: Power Inverter for PV forecast @ Akkudoktor API. -- **inverterEfficiency**: Inverter Efficiency for PV forecast @ Akkudoktor API. -- **horizont**: optionial - Horizont to calculate shading up to 360 values to describe shading situation for your PV. +- **`price.token`**: + Token for accessing electricity price data. -Feel free to add more PV forecast entries under the pv_forecast section by providing a unique name for each entry. +- **`price.feed_in_price`**: + Feed-in price for the grid, in €/kWh. -### Inverter Configuration Settings +- **`price.negative_price_switch`**: + Switch for handling negative electricity prices. + - `True`: Limits the feed-in price to `0` if there is a negative stock price for the hour. + - `False`: Ignores negative stock prices and uses the constant feed-in price. -- **inverter.type**: fronius_gen24 or default -- **inverter.address**: address of the inverter - e.g. 192.168.1.12 -- **inverter.user**: username in local portal e.g. customer (inverter local webpage login data - be aware: website Customer vs. customer in this level) -- **inverter.password**: password for local portal -- **inverter.max_grid_charge_rate**: e.g. 5000 in Watts -- **inverter.max_pv_charge_rate**: e.g. 5000 in Watts -- **inverter.max_bat_discharge_rate**: e.g. 5000 in Watts +--- -### EVCC Configuration Settings -- **evcc.url**: url to EVCC instance e.g. htpp://192.168.0.1:7070 +### **Battery Configuration** -### Other Configuration Settings +- **`battery.source`**: + Data source for battery SOC (State of Charge). Possible values: `openhab`, `homeassistant`, `default` (static data). -**refresh_time**: Default refresh time in minutes. +- **`battery.url`**: + URL for OpenHAB (e.g., `http://:8080`) or Home Assistant (e.g., `http://:8123`). -**time_zone**: Default time zone. +- **`battery.soc_sensor`**: + Item/entity name for the SOC sensor (OpenHAB item/Home Assistant sensor). -**eos_connect_web_port**: Default port for EOS connect server. +- **`battery.access_token`**: + Access token for Home Assistant (optional). -**log_level**: loglevel: debug, info, warning, error. +- **`battery.capacity_wh`**: + Total capacity of the battery, in watt-hours (Wh). -## Notes -Ensure that the config.yaml file is located in the same directory as the application. +- **`battery.charge_efficiency`**: + Efficiency of charging the battery, as a decimal value between `0` and `1`. -If the configuration file does not exist, the application will create one with default values and prompt you to restart the server after configuring the settings. +- **`battery.discharge_efficiency`**: + Efficiency of discharging the battery, as a decimal value between `0` and `1`. -## Full Config Example +- **`battery.max_charge_power_w`**: + Maximum charging power for the battery, in watts (W). -```yaml -load: - source: default # Data source for load power - openhab, homeassistant, default (static data) - url: http://:8080 # URL for openhab (e.g. ip:8080) or homeassistant (e.g. ip:8123) - load_sensor: sensor.load_power # item / entity name for load power data (openhab item/ homeassitant sensor) - car_charge_load_sensor: sensor.car_charge_load_sensor # item / entity for wallbox power data - access_token: 123456abcd # access token for homeassistant (optional) +- **`battery.min_soc_percentage`**: + Minimum state of charge for the battery, as a percentage. -eos: - server: # EOS server address - port: 8503 # port for EOS server - timeout: 180 # timeout for EOS optimize request in seconds +- **`battery.max_soc_percentage`**: + Maximum state of charge for the battery, as a percentage. -price: - source: tibber # Data source for electricity price - token: tibberBearerToken # Token for electricity price - feed_in_price: 0 # Feed-in price for the grid in €/kWh - negative_price_switch: False # Switch for handling negative electricity prices - True / False +--- -battery: - source: default # Data source for battery SOC - openhab, homeassistant, default (static data) - url: http://:8080 # URL for openhab (e.g. ip:8080) or homeassistant (e.g. ip:8123) - load.load_sensor: sensor.battery_soc - load.access_token: 123456abcd # access token for homeassistant (optional) - capacity_wh: 11059 # Battery capacity in Wh - charge_efficiency: 0.88 # Efficiency for charging the battery - discharge_efficiency: 0.88 # Efficiency for discharging the battery - max_charge_power_w: 5000 # Maximum charging power in W - min_soc_percentage: 5 # Minimum state of charge percentage - max_soc_percentage: 100 # Maximum state of charge percentage +### **PV Forecast Configuration** + +The `pv_forecast` section allows you to define multiple PV forecast entries, each distinguished by a user-given name. Below is an example of a default PV forecast configuration: +```yaml pv_forecast: - - name: roof_west + - name: myPvInstallation1 # User-defined identifier for the PV installation, must be unique if you use multiple installations lat: 47.5 # Latitude for PV forecast @ Akkudoktor API lon: 8.5 # Longitude for PV forecast @ Akkudoktor API azimuth: 90.0 # Azimuth for PV forecast @ Akkudoktor API @@ -155,31 +108,154 @@ pv_forecast: power: 4600 # Power for PV forecast @ Akkudoktor API powerInverter: 5000 # Power Inverter for PV forecast @ Akkudoktor API inverterEfficiency: 0.9 # Inverter Efficiency for PV forecast @ Akkudoktor API - horizont: "10,20,10,15" # Horizont to calculate shading up to 360 values to describe shading situation for your PV - - name: garden_south - lat: 47.5 # Latitude for PV forecast @ Akkudoktor API - lon: 8.5 # Longitude for PV forecast @ Akkudoktor API - azimuth: 0.0 # Azimuth for PV forecast @ Akkudoktor API - tilt: 45.0 # Tilt for PV forecast @ Akkudoktor API - power: 860 # Power for PV forecast @ Akkudoktor API - powerInverter: 800 # Power Inverter for PV forecast @ Akkudoktor API - inverterEfficiency: 0.9 # Inverter Efficiency for PV forecast @ Akkudoktor API - horizont: "" # Horizont to calculate shading up to 360 values to describe shading situation for your PV + horizont: 10,20,10,15 # Horizont to calculate shading up to 360 values to describe shading situation for your PV. +``` -inverter: - type: fronius_gen24 # default or fronius_gen24 - default disables the controlling - address: # address of the inverter - e.g. 192.168.1.12 - user: customer # username in local portal e.g. customer - password: abc123 # password for local portal - max_grid_charge_rate: 5000 # in Watts - max_pv_charge_rate: 5000 # in Watts - max_bat_discharge_rate: 5000 # in Watts +#### **Parameters** +- **`name`**: + A user-defined identifier for the PV installation. Must be unique if you use multiple installations. + +- **`lat`**: + Latitude for the PV forecast. + +- **`lon`**: + Longitude for the PV forecast. + +- **`azimuth`**: + Azimuth angle for the PV forecast. + +- **`tilt`**: + Tilt angle for the PV forecast. + +- **`power`**: + The power of the PV installation, in watts (W). + +- **`powerInverter`**: + The power of the inverter, in watts (W). + +- **`inverterEfficiency`**: + The efficiency of the inverter, as a decimal value between `0` and `1`. +- **`horizont`**: + (Optional) A list of up to 360 values describing the shading situation for the PV installation. + +--- + +### **Inverter Configuration** + +- **`inverter.type`**: + Specifies the type of inverter. Possible values: + - `fronius_gen24`: Use the Fronius Gen24 inverter. + - `default`: Disable inverter control (only display the target state). + +- **`inverter.address`**: + The IP address of the inverter. + +- **`inverter.user`**: + The username for the inverter's local portal. + +- **`inverter.password`**: + The password for the inverter's local portal. + +- **`inverter.max_grid_charge_rate`**: + The maximum grid charge rate, in watts (W). + +- **`inverter.max_pv_charge_rate`**: + The maximum PV charge rate, in watts (W). + +- **`inverter.max_bat_discharge_rate`**: + The maximum battery discharge rate, in watts (W). + +--- + +### **EVCC Configuration** + +- **`evcc.url`**: + The URL for the EVCC instance (e.g., `http://:7070`). + +--- + +### **Other Configuration Settings** + +- **`refresh_time`**: + Default refresh time for the application, in minutes. + +- **`time_zone`**: + Default time zone for the application. + +- **`eos_connect_web_port`**: + Default port for the EOS Connect server. + +- **`log_level`**: + Log level for the application. Possible values: `debug`, `info`, `warning`, `error`. + +--- + +## Notes + +- Ensure that the `config.yaml` file is located in the same directory as the application. +- If the configuration file does not exist, the application will create one with default values and prompt you to restart the server after configuring the settings. + +## Full Config Example (will be generated at first startup) + +```yaml +# Load configuration +load: + source: default # Data source for load power - openhab, homeassistant, default (using a static load profile) + url: http://homeassistant:8123 # URL for openhab or homeassistant (e.g. http://openhab:7070 or http://homeassistant:8123) + load_sensor: Load_Power # item / entity for load power data in watts + car_charge_load_sensor: Wallbox_Power # item / entity for wallbox power data in watts or kilowatts + access_token: abc123 # access token for homeassistant (optional) +# EOS server configuration +eos: + server: 192.168.1.94 # EOS server address + port: 8503 # port for EOS server - default: 8503 + timeout: 180 # timeout for EOS optimize request in seconds - default: 180 +# Electricity price configuration +price: + source: default # data source for electricity price tibber, default (default uses akkudoktor) + token: tibberBearerToken # Token for electricity price + feed_in_price: 0.0 # feed in price for the grid in €/kWh + negative_price_switch: false # switch for no payment if negative stock price is given +# battery configuration +battery: + source: default # Data source for battery soc - openhab, homeassistant, default + url: http://homeassistant:8123 # URL for openhab or homeassistant (e.g. http://openhab:7070 or http://homeassistant:8123) + soc_sensor: battery_SOC # item / entity for battery SOC data in [0..1] + access_token: abc123 # access token for homeassistant (optional) + capacity_wh: 11059 # battery capacity in Wh + charge_efficiency: 0.88 # efficiency for charging the battery in [0..1] + discharge_efficiency: 0.88 # efficiency for discharging the battery in [0..1] + max_charge_power_w: 5000 # max charging power in W + min_soc_percentage: 5 # URL for battery soc in % + max_soc_percentage: 100 # URL for battery soc in % +# List of PV forecast configurations. Add multiple entries as needed. +# See Akkudoktor API (https://api.akkudoktor.net/#/pv%20generation%20calculation/getForecast) for more details. +pv_forecast: + - name: myPvInstallation1 # User-defined identifier for the PV installation, have to be unique if you use more installations + lat: 47.5 # Latitude for PV forecast @ Akkudoktor API + lon: 8.5 # Longitude for PV forecast @ Akkudoktor API + azimuth: 90.0 # Azimuth for PV forecast @ Akkudoktor API + tilt: 30.0 # Tilt for PV forecast @ Akkudoktor API + power: 4600 # Power for PV forecast @ Akkudoktor API + powerInverter: 5000 # Power Inverter for PV forecast @ Akkudoktor API + inverterEfficiency: 0.9 # Inverter Efficiency for PV forecast @ Akkudoktor API + horizont: 10,20,10,15 # Horizont to calculate shading up to 360 values to describe shading situation for your PV. +# Inverter configuration +inverter: + type: default # Type of inverter - fronius_gen24, default (default will disable inverter control - only displaying the target state) - preset: default + address: 192.168.1.12 # Address of the inverter + user: customer # Username for the inverter + password: abc123 # Password for the inverter + max_grid_charge_rate: 5000 # Max grid charge rate in W - default: 5000 + max_pv_charge_rate: 5000 # Max PV charge rate in W - default: 5000 + max_bat_discharge_rate: 5000 # Max battery discharge rate in W (currently not used) - default: 5000 +# EVCC configuration evcc: - url: http://:7070 # URL to your evcc installation + url: http://yourEVCCserver:7070 # URL for EVCC server - default: http://yourEVCCserver:7070 +refresh_time: 3 # Default refresh time of EOS connect in minutes - default: 3 +time_zone: Europe/Berlin # Default time zone - default: Europe/Berlin +eos_connect_web_port: 8081 # Default port for EOS connect server - default: 8081 +log_level: info # Log level for the application : debug, info, warning, error - default: info -refresh_time: 3 # Default refresh time in minutes -time_zone: Europe/Berlin # Default time zone -eos_connect_web_port: 8081 # Default port for EOS connect server -log_level: info # loglevel: debug, info, warning, error ``` \ No newline at end of file diff --git a/src/config.py b/src/config.py index b612d94..2af02c8 100644 --- a/src/config.py +++ b/src/config.py @@ -42,7 +42,7 @@ def create_default_config(self): "load": CommentedMap( { "source": "default", # data source for load power - "url": "http://:8080", # URL for openhab or homeassistant + "url": "http://homeassistant:8123", # URL for openhab or homeassistant "load_sensor": "Load_Power", # item / entity for load power data "car_charge_load_sensor": "Wallbox_Power", # item / entity wallbox power "access_token": "abc123", # access token for homeassistant @@ -50,7 +50,7 @@ def create_default_config(self): ), "eos": CommentedMap( { - "server": "192.168.1.94", # Default EOS server address + "server": "192.168.100.100", # Default EOS server address "port": 8503, # Default port for EOS server "timeout": 180, # Default timeout for EOS optimize request } @@ -59,14 +59,14 @@ def create_default_config(self): { "source": "default", "token": "tibberBearerToken", # token for electricity price - "feed_in_price": 0.0, # feed in price for the grid + "feed_in_price": 0.0, # feed in price for the grid "negative_price_switch": False, # switch for negative price } ), "battery": CommentedMap( { "source": "default", # data source for battery soc - "url": "http://:8080", # URL for openhab or homeassistant + "url": "http://homeassistant:8123", # URL for openhab or homeassistant "soc_sensor": "battery_SOC", # item / entity for battery SOC data "access_token": "abc123", # access token for homeassistant "capacity_wh": 11059, @@ -80,14 +80,14 @@ def create_default_config(self): "pv_forecast": [ CommentedMap( { - "name": "", # Placeholder for user-defined + "name": "myPvInstallation1", # Placeholder for user-defined # configuration name "lat": 47.5, # Latitude for PV forecast @ Akkudoktor API "lon": 8.5, # Longitude for PV forecast @ Akkudoktor API "azimuth": 90.0, # Azimuth for PV forecast @ Akkudoktor API "tilt": 30.0, # Tilt for PV forecast @ Akkudoktor API "power": 4600, # Power of PV system in Wp - "powerInverter": 5000, # Inverter Power + "powerInverter": 5000, # Inverter Power "inverterEfficiency": 0.9, # Inverter Efficiency for # PV forecast @ Akkudoktor API "horizont": "10,20,10,15", # Horizont to calculate shading @@ -96,21 +96,20 @@ def create_default_config(self): ], "inverter": CommentedMap( { - "type": "fronius_gen24", + "type": "default", "address": "192.168.1.12", "user": "customer", "password": "abc123", "max_grid_charge_rate": 5000, "max_pv_charge_rate": 5000, - "max_bat_discharge_rate": 5000 + "max_bat_discharge_rate": 5000, } ), "evcc": CommentedMap( { - "url": "http://:7070", # URL for EVCC server + "url": "http://yourEVCCserver:7070", # URL for EVCC server } ), - "refresh_time": 3, # Default refresh time in minutes "time_zone": "Europe/Berlin", # Add default time zone "eos_connect_web_port": 8081, # Default port for EOS connect server @@ -119,160 +118,174 @@ def create_default_config(self): ) # load configuration config.yaml_set_comment_before_after_key("load", before="Load configuration") - config["load"].yaml_set_comment_before_after_key( - "source", before="Data source for load power - openhab, homeassistant, default" + config["load"].yaml_add_eol_comment( + "Data source for load power - openhab, homeassistant,"+ + " default (using a static load profile)", + "source", ) - config["load"].yaml_set_comment_before_after_key( - "url", before="URL for openhab or homeassistant" + config["load"].yaml_add_eol_comment( + "URL for openhab or homeassistant"+ + " (e.g. http://openhab:7070 or http://homeassistant:8123)", + "url", ) - config["load"].yaml_set_comment_before_after_key( - "load_sensor", before="item / entity for load power data" + config["load"].yaml_add_eol_comment( + "item / entity for load power data in watts", "load_sensor" ) - config["load"].yaml_set_comment_before_after_key( - "car_charge_load_sensor", before="item / entity for wallbox power data" + config["load"].yaml_add_eol_comment( + "item / entity for wallbox power data in watts or kilowatts", + "car_charge_load_sensor", ) - config["load"].yaml_set_comment_before_after_key( - "access_token", before="access token for homeassistant (optional)" + config["load"].yaml_add_eol_comment( + "access token for homeassistant (optional)", "access_token" ) # eos configuration config.yaml_set_comment_before_after_key( "eos", before="EOS server configuration" ) - config["eos"].yaml_set_comment_before_after_key( - "server", before="EOS server address" - ) - config["eos"].yaml_set_comment_before_after_key( - "port", before="port for EOS server - default: 8503" + config["eos"].yaml_add_eol_comment("EOS server address", "server") + config["eos"].yaml_add_eol_comment( + "port for EOS server - default: 8503", "port" ) - config["eos"].yaml_set_comment_before_after_key( - "timeout", before="timeout for EOS optimize request in seconds - default: 180" + config["eos"].yaml_add_eol_comment( + "timeout for EOS optimize request in seconds - default: 180", "timeout" ) # price configuration config.yaml_set_comment_before_after_key( "price", before="Electricity price configuration" ) - config["price"].yaml_set_comment_before_after_key( - "source", before="data source for electricity price tibber, default (akkudoktor)" + config["price"].yaml_add_eol_comment( + "data source for electricity price tibber, default (default uses akkudoktor)", + "source", ) - config["price"].yaml_set_comment_before_after_key( - "token", before="Token for electricity price" + config["price"].yaml_add_eol_comment("Token for electricity price", "token") + config["price"].yaml_add_eol_comment( + "feed in price for the grid in €/kWh", "feed_in_price" ) - config["price"].yaml_set_comment_before_after_key( - "feed_in_price", before="feed in price for the grid" - ) - config["price"].yaml_set_comment_before_after_key( - "negative_price_switch", before="switch for no payment if negative stock price" + config["price"].yaml_add_eol_comment( + "switch for no payment if negative stock price is given", + "negative_price_switch", ) # battery configuration - config.yaml_set_comment_before_after_key("battery", before="battery configuration") - config["battery"].yaml_set_comment_before_after_key( - "source", before="Data source for battery soc - openhab, homeassistant, default" + config.yaml_set_comment_before_after_key( + "battery", before="battery configuration" ) - config["battery"].yaml_set_comment_before_after_key( - "url", before="URL for openhab or homeassistant" + config["battery"].yaml_add_eol_comment( + "Data source for battery soc - openhab, homeassistant, default", "source" ) - config["battery"].yaml_set_comment_before_after_key( - "soc_sensor", before="item / entity for battery SOC data" + config["battery"].yaml_add_eol_comment( + "URL for openhab or homeassistant"+ + " (e.g. http://openhab:7070 or http://homeassistant:8123)", + "url", ) - config["battery"].yaml_set_comment_before_after_key( - "access_token", before="access token for homeassistant (optional)" + config["battery"].yaml_add_eol_comment( + "item / entity for battery SOC data in [0..1]", "soc_sensor" ) - config["battery"].yaml_set_comment_before_after_key( - "capacity_wh", before="battery cpaacity in Wh" + config["battery"].yaml_add_eol_comment( + "access token for homeassistant (optional)", "access_token" ) - config["battery"].yaml_set_comment_before_after_key( - "charge_efficiency", before="efficiency for charging the battery" + config["battery"].yaml_add_eol_comment("battery capacity in Wh", "capacity_wh") + config["battery"].yaml_add_eol_comment( + "efficiency for charging the battery in [0..1]", "charge_efficiency" ) - config["battery"].yaml_set_comment_before_after_key( - "discharge_efficiency", before="efficiency for discharging the battery" + config["battery"].yaml_add_eol_comment( + "efficiency for discharging the battery in [0..1]", "discharge_efficiency" ) - config["battery"].yaml_set_comment_before_after_key( - "max_charge_power_w", before="max charging power in W" + config["battery"].yaml_add_eol_comment( + "max charging power in W", "max_charge_power_w" ) - config["battery"].yaml_set_comment_before_after_key( - "min_soc_percentage", before="URL for battery soc" + config["battery"].yaml_add_eol_comment( + "URL for battery soc in %", "min_soc_percentage" ) - config["battery"].yaml_set_comment_before_after_key( - "max_soc_percentage", before="URL for battery soc" + config["battery"].yaml_add_eol_comment( + "URL for battery soc in %", "max_soc_percentage" ) # pv forecast configuration config.yaml_set_comment_before_after_key( - "pv_forecast", before="List of PV forecast configurations."+ - " Add multiple entries as needed." + "pv_forecast", + before="List of PV forecast configurations." + + " Add multiple entries as needed.\nSee Akkudoktor API " + + "(https://api.akkudoktor.net/#/pv%20generation%20calculation/getForecast) " + + "for more details.", ) for index, pv_config in enumerate(config["pv_forecast"]): - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "lat", before="Latitude for PV forecast @ Akkudoktor API" + config["pv_forecast"][index].yaml_add_eol_comment( + "User-defined identifier for the PV installation," + + " have to be unique if you use more installations", + "name", ) - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "lon", before="Longitude for PV forecast @ Akkudoktor API" + config["pv_forecast"][index].yaml_add_eol_comment( + "Latitude for PV forecast @ Akkudoktor API", "lat" ) - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "azimuth", before="Azimuth for PV forecast @ Akkudoktor API" + config["pv_forecast"][index].yaml_add_eol_comment( + "Longitude for PV forecast @ Akkudoktor API", "lon" ) - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "tilt", before="Tilt for PV forecast @ Akkudoktor API" + config["pv_forecast"][index].yaml_add_eol_comment( + "Azimuth for PV forecast @ Akkudoktor API", "azimuth" ) - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "power", before="Power for PV forecast @ Akkudoktor API" + config["pv_forecast"][index].yaml_add_eol_comment( + "Tilt for PV forecast @ Akkudoktor API", "tilt" ) - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "powerInverter", before="Power Inverter for PV forecast @ Akkudoktor API" + config["pv_forecast"][index].yaml_add_eol_comment( + "Power for PV forecast @ Akkudoktor API", "power" ) - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "inverterEfficiency", before="Inverter Efficiency for PV forecast @ Akkudoktor API" + config["pv_forecast"][index].yaml_add_eol_comment( + "Power Inverter for PV forecast @ Akkudoktor API", "powerInverter" ) - config["pv_forecast"][index].yaml_set_comment_before_after_key( - "horizont", before="Horizont to calculate shading up to 360 values to describe" + - " shading situation for your PV." + config["pv_forecast"][index].yaml_add_eol_comment( + "Inverter Efficiency for PV forecast @ Akkudoktor API", + "inverterEfficiency", + ) + config["pv_forecast"][index].yaml_add_eol_comment( + "Horizont to calculate shading up to 360 values"+ + " to describe shading situation for your PV.", + "horizont", ) # inverter configuration config.yaml_set_comment_before_after_key( "inverter", before="Inverter configuration" ) - config["inverter"].yaml_set_comment_before_after_key( - "type", before="Type of inverter - fronius_gen24, fronius_solar_api" - ) - config["inverter"].yaml_set_comment_before_after_key( - "address", before="Address of the inverter" - ) - config["inverter"].yaml_set_comment_before_after_key( - "user", before="Username for the inverter" - ) - config["inverter"].yaml_set_comment_before_after_key( - "password", before="Password for the inverter" + config["inverter"].yaml_add_eol_comment( + "Type of inverter - fronius_gen24, default (default will disable inverter control -"+ + " only displaying the target state) - preset: default", + "type", ) - config["inverter"].yaml_set_comment_before_after_key( - "max_grid_charge_rate", before="Max grid charge rate in W" + config["inverter"].yaml_add_eol_comment("Address of the inverter", "address") + config["inverter"].yaml_add_eol_comment("Username for the inverter", "user") + config["inverter"].yaml_add_eol_comment("Password for the inverter", "password") + config["inverter"].yaml_add_eol_comment( + "Max grid charge rate in W - default: 5000", "max_grid_charge_rate" ) - config["inverter"].yaml_set_comment_before_after_key( - "max_pv_charge_rate", before="Max PV charge rate in W" + config["inverter"].yaml_add_eol_comment( + "Max PV charge rate in W - default: 5000", "max_pv_charge_rate" ) - config["inverter"].yaml_set_comment_before_after_key( - "max_bat_discharge_rate", before="Max battery discharge rate in W" + config["inverter"].yaml_add_eol_comment( + "Max battery discharge rate in W (currently not used) - default: 5000", + "max_bat_discharge_rate", ) # evcc configuration - config.yaml_set_comment_before_after_key( - "evcc", before="EVCC configuration" - ) - config["evcc"].yaml_set_comment_before_after_key( - "url", before="URL for EVCC server" + config.yaml_set_comment_before_after_key("evcc", before="EVCC configuration") + config["evcc"].yaml_add_eol_comment( + "URL for EVCC server - default: http://yourEVCCserver:7070", + "url", ) # refresh time configuration - config.yaml_set_comment_before_after_key( - "refresh_time", before="Default refresh time in minutes" + config.yaml_add_eol_comment( + "Default refresh time of EOS connect in minutes - default: 3", + "refresh_time", ) # time zone configuration - config.yaml_set_comment_before_after_key( - "time_zone", before="Default time zone" + config.yaml_add_eol_comment( + "Default time zone - default: Europe/Berlin", "time_zone" ) # eos connect web port configuration - config.yaml_set_comment_before_after_key( - "eos_connect_web_port", before="Default port for EOS connect server" + config.yaml_add_eol_comment( + "Default port for EOS connect server - default: 8081", + "eos_connect_web_port", ) # loglevel configuration - config.yaml_set_comment_before_after_key( - "log_level", before="Log level for the application : debug, info, warning, error" + config.yaml_add_eol_comment( + "Log level for the application : debug, info, warning, error - default: info", + "log_level", ) return config @@ -312,7 +325,11 @@ def check_eos_timeout_and_refreshtime(self): if eos_timeout_seconds > refresh_time_seconds: logger.error( - ("[Config] EOS timeout (%s s) is greater than the refresh time (%s s)." - " Please adjust the settings."), eos_timeout_seconds, refresh_time_seconds + ( + "[Config] EOS timeout (%s s) is greater than the refresh time (%s s)." + " Please adjust the settings." + ), + eos_timeout_seconds, + refresh_time_seconds, ) sys.exit(0) diff --git a/src/interfaces/eos_interface.py b/src/interfaces/eos_interface.py index 189417e..8c20c13 100644 --- a/src/interfaces/eos_interface.py +++ b/src/interfaces/eos_interface.py @@ -149,7 +149,9 @@ def eos_set_optimize_request(self, payload, timeout=180): logger.error("[EOS] OPTIMIZE Request timed out after %s seconds", timeout) return {"error": "Request timed out - trying again with next run"} except requests.exceptions.RequestException as e: - logger.error("[EOS] OPTIMIZE Request failed: %s - response: %s", e, response) + logger.error( + "[EOS] OPTIMIZE Request failed: %s - response: %s", e, response + ) return {"error": str(e)} def examine_response_to_control_data(self, optimized_response_in): @@ -347,7 +349,6 @@ def __retrieve_eos_version(self): """ try: response = requests.get(self.base_url + "/v1/health", timeout=10) - # response = requests.get(self.base_url + "/v1/config", timeout=10) response.raise_for_status() eos_version = response.json().get("status") if eos_version == "alive": @@ -365,8 +366,21 @@ def __retrieve_eos_version(self): "[EOS] HTTP error occurred while getting EOS version: %s", e ) return None + except requests.exceptions.ConnectTimeout: + logger.error( + "[EOS] Failed to get EOS version - Server not reachable:"+ + " Connection to %s timed out", + self.base_url, + ) + return "Server not reachable" + except requests.exceptions.ConnectionError as e: + logger.error( + "[EOS] Failed to get EOS version - Server not reachable: Connection error: %s", + e, + ) + return "Server not reachable" except requests.exceptions.RequestException as e: - logger.error("[EOS] Failed to get EOS version: %s", e) + logger.error("[EOS] Failed to get EOS version - Error: %s", e) return None except json.JSONDecodeError as e: logger.error("[EOS] Failed to decode EOS version response: %s", e) diff --git a/src/interfaces/evcc_interface.py b/src/interfaces/evcc_interface.py index 9e57bed..534fd94 100644 --- a/src/interfaces/evcc_interface.py +++ b/src/interfaces/evcc_interface.py @@ -93,6 +93,9 @@ def start_update_service(self): """ Starts the background thread to periodically update the charging state. """ + if self.url == "http://yourEVCCserver:7070": + logger.warning("[EVCC] Update service not started. URL is not set.") + return if self._update_thread is None or not self._update_thread.is_alive(): self._stop_event.clear() self._update_thread = threading.Thread( @@ -133,7 +136,7 @@ def __request_charging_state(self): """ Fetches the EVCC state from the API and returns the charging state. """ - data = self.fetch_evcc_state_via_api() + data = self.__fetch_evcc_state_via_api() if not data or not isinstance(data.get("result", {}).get("loadpoints"), list): logger.error("[EVCC] Invalid or missing loadpoints in the response.") return None @@ -172,7 +175,7 @@ def __request_charging_state(self): return charging_state, charging_mode - def fetch_evcc_state_via_api(self): + def __fetch_evcc_state_via_api(self): """ Fetches the state of the EVCC (Electric Vehicle Charging Controller) via its API. diff --git a/src/version.py b/src/version.py index cff05f8..f390837 100644 --- a/src/version.py +++ b/src/version.py @@ -1 +1 @@ -__version__ = 'snapshot-v0.1.6' +__version__ = 'develop-v0.1.36' diff --git a/src/web/index.html b/src/web/index.html index e33c3e3..5221225 100644 --- a/src/web/index.html +++ b/src/web/index.html @@ -10,37 +10,56 @@ - + -
-
+
+

EOS connect

-

Waiting for first data...

-

...

-
+

loading ... +

+

+ ...

+
+
-
EOS connect: v00.00.00
+
+ EOS connect version: v00.00.00
-