Developer Guide

Architecture, contributing guidelines, and development setup

Architecture

System design and component overview

Learn →

Contributing

How to contribute to EOS Connect

Contribute →

Testing

Running and writing tests

Test →

Dev Setup

Setting up development environment

Setup →

Architecture Overview

System Components

eos_connect.py

Main application entry point and orchestration

config.py

Configuration loading and validation

interfaces/

Data source and control interfaces

web/

Web dashboard (HTML/CSS/JS)

Core Interfaces

Interface Purpose File
Base Control Core control state management base_control.py
Battery Interface Battery data retrieval and management battery_interface.py
PV Interface Solar forecast retrieval pv_interface.py
Price Interface Electricity price forecasts price_interface.py
Load Interface Household load data load_interface.py
Inverter (Fronius) Inverter control and monitoring inverter_fronius_v2.py
EVCC Interface EV charging control evcc_interface.py
MQTT Interface MQTT publishing and subscription mqtt_interface.py
Optimization Interface EOS/EVopt communication optimization_interface.py

Data Flow

1. Main Loop (every refresh_time minutes)
   ├─ Fetch battery SOC (battery_interface)
   ├─ Fetch PV forecast (pv_interface)
   ├─ Fetch price forecast (price_interface)
   ├─ Fetch load data (load_interface)
   ├─ Build optimization request
   ├─ Send to EOS/EVopt (optimization_interface)
   ├─ Process optimization response
   ├─ Update controls (base_control)
   ├─ Execute inverter commands (inverter_interface)
   ├─ Update EVCC (evcc_interface)
   ├─ Publish to MQTT (mqtt_interface)
   └─ Serve via web API

Contributing

Branch Strategy

Branch Type Purpose Naming
main Stable, tagged releases only -
develop Integration branch (PR target) -
feature New functionality feature/<desc> or feature/<issue>-<desc>
bugfix Fix for develop bugfix/<issue>-<desc>
hotfix Urgent production fix hotfix/<issue>-<desc>
issue GitHub auto-created issue-<number>-<desc>

Contribution Workflow

# 1. Update local
git fetch origin
git switch develop
git pull --ff-only

# 2. Create feature branch
git switch -c feature/better-forecast

# 3. Code + test + document
# - Write code
# - Add/update tests
# - Update docs (README / CONFIG_README / MQTT if behavior changes)

# 4. Format and lint
black .
pylint src/

# 5. Run tests
pytest tests/

# 6. Rebase before PR
git fetch origin
git rebase origin/develop

# 7. Push
git push -u origin feature/better-forecast

# 8. Create PR targeting develop
# - Link relevant issues (Closes #123)
# - Provide clear description

Code Quality Requirements

  • Formatting: Use Black for all Python files
  • Linting: Pylint score ≥9.0
  • Testing: Add/update tests for logic changes
  • Documentation: Update relevant docs

Commit Message Format (Conventional Commits)

feat: add battery forecast smoothing
fix: correct negative PV handling
docs: update MQTT topic table
test: add tests for price calculation
refactor: simplify config loading
chore: update dependencies
VS Code Tip: Install the Black Formatter extension for automatic formatting on save.

Testing

Test Structure

Tests are organized to mirror the source structure:

tests/
├── test_control_states.py
└── interfaces/
    ├── test_base_control.py
    ├── test_battery_interface.py
    ├── test_inverter_fronius_v2.py
    ├── test_load_interface.py
    ├── test_optimization_interface.py
    ├── test_price_interface.py
    ├── test_pv_interface.py
    └── optimization_backends/
        └── test_optimization_backend_eos.py

Running Tests

# Run all tests
pytest tests/

# Run specific test file
pytest tests/interfaces/test_battery_interface.py

# Run with coverage
pytest --cov=src tests/

# Run with verbose output
pytest -v tests/

Writing Tests

Test File Naming

  • Place in tests/ directory
  • Mirror source structure
  • Name as test_<module>.py

Example Test

import pytest
from src.interfaces.battery_interface import BatteryInterface

def test_battery_soc_calculation():
    """Test SOC calculation with known values"""
    battery = BatteryInterface(capacity_wh=10000)
    battery.set_soc(0.75)
    
    assert battery.get_remaining_wh() == 7500
    assert battery.get_soc() == 0.75

def test_battery_temperature_protection():
    """Test temperature-based power reduction"""
    battery = BatteryInterface(
        capacity_wh=10000,
        max_charge_power_w=5000,
        temperature_sensor="sensor.temp"
    )
    
    # Cold temperature should reduce power
    power = battery.calculate_max_charge_power(
        soc=0.50, 
        temperature=-5
    )
    assert power < 500  # Should be ~5-7.5% of max

Test Configuration

Configure pytest in pytest.ini:

[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*

Development Setup

Prerequisites

  • Python 3.11 or higher
  • Git
  • pip
  • (Optional) VS Code with Python extension

Setup Steps

# 1. Clone repository
git clone https://github.com/ohAnd/EOS_connect.git
cd EOS_connect

# 2. Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# 3. Install dependencies
pip install -r requirements.txt

# 4. Install development dependencies
pip install black pylint pytest pytest-cov

# 5. Copy and edit config
cp src/config.yaml.example src/config.yaml
# Edit src/config.yaml with your settings

# 6. Run EOS Connect
python src/eos_connect.py

VS Code Configuration

Recommended .vscode/settings.json:

{
  "python.defaultInterpreterPath": "./venv/bin/python",
  "python.linting.enabled": true,
  "python.linting.pylintEnabled": true,
  "python.linting.pylintArgs": ["--rcfile=.pylintrc"],
  "python.formatting.provider": "black",
  "[python]": {
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.organizeImports": true
    }
  },
  "python.testing.pytestEnabled": true,
  "python.testing.pytestArgs": ["tests"]
}

Environment Variables

For development, you can override config with environment variables:

# Linux/Mac
export EOS_CONNECT_LOG_LEVEL=debug
export EOS_CONNECT_PORT=8081

# Windows
set EOS_CONNECT_LOG_LEVEL=debug
set EOS_CONNECT_PORT=8081

Project Structure

EOS_connect/
├── src/
│   ├── eos_connect.py         # Main application
│   ├── config.py              # Configuration management
│   ├── config.yaml            # User configuration
│   ├── constants.py           # Constants and enums
│   ├── log_handler.py         # Logging setup
│   ├── version.py             # Version information
│   ├── interfaces/            # Data interfaces
│   │   ├── base_control.py
│   │   ├── battery_interface.py
│   │   ├── evcc_interface.py
│   │   ├── inverter_fronius_v2.py
│   │   ├── load_interface.py
│   │   ├── mqtt_interface.py
│   │   ├── optimization_interface.py
│   │   ├── price_interface.py
│   │   └── pv_interface.py
│   ├── web/                   # Web dashboard
│   │   ├── index.html
│   │   ├── css/
│   │   └── js/
│   └── json/                  # JSON schemas and examples
├── tests/                     # Test suite
├── docs/                      # Documentation (GitHub Pages)
├── docker-compose.yml         # Docker deployment
├── Dockerfile                 # Docker image
├── requirements.txt           # Python dependencies
├── pytest.ini                 # Pytest configuration
├── README.md                  # Project overview
├── CONTRIBUTING.md            # Contribution guidelines
└── LICENSE                    # MIT License

Resources

Documentation

Related Projects

Tools

Get Involved!

We welcome contributions of all kinds:

Report Bugs

Open an issue with detailed reproduction steps

Suggest Features

Share your ideas in GitHub Discussions

Improve Docs

Documentation PRs are always welcome!

Submit PRs

Follow the contribution workflow and submit your changes