diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index ba934c0c..ee93f611 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -20,9 +20,7 @@ jobs: - name: Install dependencies run: | - sudo apt install -y libmariadb3 libmariadb-dev python -m pip install --upgrade pip - pip install -r requirements.txt pip install -r requirements-dev.txt - name: Run Pytest diff --git a/.gitignore b/.gitignore index 5863b08e..a911327f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ docs/ data/ +cache/ +output/ # Default ignore folders and files for VS Code, Python diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e4fbc3d4..229d33be 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ To make collaboration easier, we require pull requests to pass code style and un Our code style checks use [`pre-commit`](https://pre-commit.com). ```bash -pip install -r requirements.txt +pip install -r requirements-dev.txt ``` To run formatting automatically before every commit: @@ -36,7 +36,7 @@ pre-commit install Or run them manually: ```bash -pre-commit --all +pre-commit run --all-files ``` ### Tests diff --git a/Dockerfile b/Dockerfile index dbbb1d25..87ebca6f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,23 +3,33 @@ FROM python:${PYTHON_VERSION}-slim LABEL source="https://github.com/Akkudoktor-EOS/EOS" -EXPOSE 5000 +ENV VIRTUAL_ENV="/opt/venv" +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" +ENV MPLCONFIGDIR="/tmp/mplconfigdir" +ENV EOS_DIR="/opt/eos" +ENV EOS_CACHE_DIR="${EOS_DIR}/cache" +ENV EOS_OUTPUT_DIR="${EOS_DIR}/output" -WORKDIR /opt/eos +WORKDIR ${EOS_DIR} -COPY . . +RUN adduser --system --group --no-create-home eos \ + && mkdir -p "${MPLCONFIGDIR}" \ + && chown eos "${MPLCONFIGDIR}" \ + && mkdir -p "${EOS_CACHE_DIR}" \ + && chown eos "${EOS_CACHE_DIR}" \ + && mkdir -p "${EOS_OUTPUT_DIR}" \ + && chown eos "${EOS_OUTPUT_DIR}" -ARG APT_OPTS="--yes --auto-remove --no-install-recommends --no-install-suggests" +COPY requirements.txt . -RUN DEBIAN_FRONTEND=noninteractive \ - apt-get update \ - && apt-get install ${APT_OPTS} gcc libhdf5-dev libmariadb-dev pkg-config mariadb-common libmariadb3 \ - && rm -rf /var/lib/apt/lists/* \ - && pip install --no-cache-dir -r requirements.txt \ - && pip install --no-cache-dir build \ - && pip install --no-cache-dir -e . \ - && apt remove ${APT_OPTS} gcc libhdf5-dev libmariadb-dev pkg-config +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install -r requirements.txt +COPY src . + +USER eos ENTRYPOINT [] -CMD ["python", "-m", "akkudoktoreos.flask_server"] +CMD ["python", "-m", "akkudoktoreosserver.flask_server"] + +VOLUME ["${MPLCONFIGDIR}", "${EOS_CACHE_DIR}", "${EOS_OUTPUT_DIR}"] diff --git a/Makefile b/Makefile index 82df14b5..17865c74 100644 --- a/Makefile +++ b/Makefile @@ -71,4 +71,7 @@ test: # Run entire setup on docker docker-run: - @docker compose up + @docker compose up --remove-orphans + +docker-build: + @docker compose build diff --git a/README-DE.md b/README-DE.md index a3bde4cc..8a757888 100644 --- a/README-DE.md +++ b/README-DE.md @@ -67,14 +67,6 @@ source .venv/bin/activate (wenn zsh verwendet wird, vor allem MacOS-Nutzende). -Sollte `pip install` die mariadb-Abhängigkeit nicht installieren können, -dann helfen folgende Kommandos: - -* Debian/Ubuntu: `sudo apt-get install -y libmariadb-dev` -* Macos/Homebrew: `brew install mariadb-connector-c` - -gefolgt von einem erneuten `pip install -r requirements.txt`. - ## Nutzung Einstellungen in `config.py` anpassen. diff --git a/README.md b/README.md index 45422a31..282fde3d 100644 --- a/README.md +++ b/README.md @@ -63,13 +63,6 @@ source .venv/bin/activate ``` (if using zsh, primarily for MacOS users). -If `pip install` fails to install the mariadb dependency, the following commands may help: - -* Debian/Ubuntu: `sudo apt-get install -y libmariadb-dev` -* MacOS/Homebrew: `brew install mariadb-connector-c` - -Followed by a renewed `pip install -r requirements.txt`. - ## Usage Adjust `config.py`. diff --git a/docker-compose.yaml b/docker-compose.yaml index 34650d40..cdc5ad61 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -5,28 +5,18 @@ networks: services: eos: image: 'akkudoktor/eos:${EOS_VERSION}' + read_only: true build: context: . dockerfile: 'Dockerfile' args: PYTHON_VERSION: '${PYTHON_VERSION}' - depends_on: - - 'mariadb' init: true environment: FLASK_RUN_PORT: '${EOS_PORT}' networks: - 'eos' + volumes: + - ./src/akkudoktoreos/config.py:/opt/eos/akkudoktoreos/config.py:ro ports: - '${EOS_PORT}:${EOS_PORT}' - mariadb: - image: 'mariadb:${MARIADB_VERSION}-jammy' - environment: - MARIADB_ROOT_PASSWORD: '${MARIADB_ROOT_PASSWORD}' - MARIADB_DATABASE: '${MARIADB_DATABASE}' - MARIADB_USER: '${MARIADB_USER}' - MARIADB_PASSWORD: '${MARIADB_PASSWORD}' - networks: - - 'eos' - volumes: - - ./data/mariadb:/var/lib/mysql diff --git a/requirements-dev.txt b/requirements-dev.txt index b47030fb..af8093e5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,4 @@ -build==1.2.2.post1 +-r requirements.txt pytest==8.3.3 -pytest-xprocess==1.0.2 -requests==2.32.3 +pytest-cov==5.0.0 pre-commit diff --git a/requirements.txt b/requirements.txt index dfa8727b..fd82718f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,7 @@ numpy==2.1.2 -mariadb==1.1.10 matplotlib==3.9.2 flask==3.0.3 scikit-learn==1.5.2 deap==1.4.1 -joblib==1.4.2 requests==2.32.3 -pytest==8.3.3 -pytest-cov==5.0.0 pandas==2.2.3 diff --git a/src/akkudoktoreos/config.py b/src/akkudoktoreos/config.py index 109c3b0e..9a1ee37f 100644 --- a/src/akkudoktoreos/config.py +++ b/src/akkudoktoreos/config.py @@ -1,5 +1,7 @@ from datetime import datetime, timedelta +output_dir = "output" + prediction_hours = 48 optimization_hours = 24 strafe = 10 diff --git a/src/akkudoktoreos/visualize.py b/src/akkudoktoreos/visualize.py index 727cce4a..81e59f61 100644 --- a/src/akkudoktoreos/visualize.py +++ b/src/akkudoktoreos/visualize.py @@ -1,4 +1,5 @@ import datetime +import os # Set the backend for matplotlib to Agg import matplotlib @@ -7,6 +8,7 @@ from matplotlib.backends.backend_pdf import PdfPages from akkudoktoreos.class_sommerzeit import ist_dst_wechsel +from akkudoktoreos.config import output_dir matplotlib.use("Agg") @@ -28,7 +30,10 @@ def visualisiere_ergebnisse( ##################### # 24-hour visualization ##################### - with PdfPages(filename) as pdf: + if not os.path.exists(output_dir): + os.makedirs(output_dir) + output_file = os.path.join(output_dir, filename) + with PdfPages(output_file) as pdf: # Load and PV generation plt.figure(figsize=(14, 14)) plt.subplot(3, 3, 1) diff --git a/src/akkudoktoreosserver/flask_server.py b/src/akkudoktoreosserver/flask_server.py index c97373fd..58347030 100755 --- a/src/akkudoktoreosserver/flask_server.py +++ b/src/akkudoktoreosserver/flask_server.py @@ -18,7 +18,12 @@ from akkudoktoreos.class_optimize import optimization_problem from akkudoktoreos.class_pv_forecast import PVForecast from akkudoktoreos.class_strompreis import HourlyElectricityPriceForecast -from akkudoktoreos.config import get_start_enddate, optimization_hours, prediction_hours +from akkudoktoreos.config import ( + get_start_enddate, + optimization_hours, + output_dir, + prediction_hours, +) app = Flask(__name__) @@ -255,11 +260,11 @@ def flask_optimize(): return jsonify(result) # Return optimization results as JSON -@app.route("/visualisierungsergebnisse.pdf") +@app.route("/visualization_results.pdf") def get_pdf(): # Endpoint to serve the generated PDF with visualization results return send_from_directory( - "", "visualisierungsergebnisse.pdf" + os.path.abspath(output_dir), "visualization_results.pdf" ) # Adjust the directory if needed