~/blog/homewizard-pvoutput.md
< cd ..

HomeWizard naar PVOutput: Real-time Solar Data met Docker

HomeWizard naar PVOutput: Real-time Solar Data met Docker

Als eigenaar van zonnepanelen wil je natuurlijk precies weten hoeveel energie je opwekt en verbruikt. PVOutput.org is een geweldige (gratis) dienst om je zonne-energie data te delen en te vergelijken met andere installaties wereldwijd. Maar hoe krijg je je data van je HomeWizard meters naar PVOutput?

Ik heb een complete Docker container oplossing gebouwd die automatisch data van HomeWizard apparaten uitleest en doorstuurt naar PVOutput. Het mooie: inclusief een live webinterface met grafieken!

Dashboard Screenshot

Linkje naar mijn Github repo waar je de code kan vinden: Github

Link naar PVOutput pagina.

Op moment van schrijven is heb ik nog geen zonnepanelen. Ik verwacht deze in de loop van april 2026 te kunnen te kunnen uitlezen met mijn script. Ik zal naar verwachting 2 Kwh meters aansluiten voor twee verschillende zonnepananelen arrays. 11 panelen op zuid-oost. En nog eens 8 panelen op zuid-west.

Waarom deze oplossing?

HomeWizard heeft geweldige apparaten voor het monitoren van je energieverbruik en opwekking:

  • P1 meter - meet je totale stroomverbruik en teruglevering aan het net
  • kWh meter(s) - meet de productie van je zonnepanelen (zelfs meerdere omvormers!)

Het probleem? Deze apparaten praten niet direct met PVOutput. Je zou dit handmatig kunnen doen, maar dat is omslachtig en niet real-time.

De Oplossing: Een Docker Container

Ik heb een Python applicatie gebouwd die:

  1. Elk interval (bijv. elke 5 minuten) data ophaalt van je HomeWizard apparaten
  2. De data omzet naar het PVOutput formaat
  3. Automatisch naar PVOutput stuurt
  4. Een mooie webinterface biedt om alles te monitoren

Technische Stack

# Core dependencies
fastapi==0.109.0        # Web framework voor de dashboard en API
uvicorn==0.27.0         # ASGI server
httpx==0.26.0           # Async HTTP client voor API calls
pyyaml==6.0.1           # Config management
jinja2==3.1.2           # Template engine voor dashboard

De applicatie is volledig asynchroon gebouwd met FastAPI, wat zorgt voor efficiënte I/O operaties bij het ophalen van data van meerdere bronnen.

Features die het Verschil Maken

1. Meerdere kWh Meters Ondersteuning

Heb je meerdere omvormers? Geen probleem! De applicatie ondersteunt meerdere kWh meters en combineert automatisch de data:

# In app/homewizard.py
@staticmethod
def combine_kwh_data(kwh_data_list: List[Dict]) -> Dict:
    """Combineer data van meerdere kWh meters"""
    valid_data = [d for d in kwh_data_list if d]

    combined = {
        'total_power_export_kwh': sum(d.get('total_power_export_kwh', 0) for d in valid_data),
        'active_power_w': sum(d.get('active_power_w', 0) for d in valid_data),
        'timestamp': datetime.now().isoformat(),
        'meters': valid_data,  # Bewaar individuele meter data
        'meter_count': len(valid_data)
    }

    return combined

2. Voltage Reporting

De P1 meter meet het voltage per fase. De applicatie berekent automatisch het gemiddelde en stuurt dit naar PVOutput (v6 parameter):

# Voltage extraction from P1 meter
voltage_l1 = data.get('voltage_sag_l1_v')
voltage_l2 = data.get('voltage_sag_l2_v')
voltage_l3 = data.get('voltage_sag_l3_v')

# Bereken gemiddelde van beschikbare fases
voltages = [v for v in [voltage_l1, voltage_l2, voltage_l3]
            if v is not None and v > 0]
voltage_avg = sum(voltages) / len(voltages) if voltages else None

3. Weather Data Integratie

Een unieke feature: automatische weather conditions naar PVOutput! De applicatie gebruikt de gratis Open-Meteo API om temperatuur en weersomstandigheden op te halen:

# In app/weather.py
class OpenMeteoClient:
    """Weather client voor Open-Meteo API (geen authenticatie vereist)"""

    async def get_weather(self) -> Dict:
        # Check cache eerst (15 min TTL)
        cached_data = self.cache.get(self.latitude, self.longitude)
        if cached_data:
            return cached_data

        # Haal fresh data op
        async with httpx.AsyncClient(timeout=10.0) as client:
            response = await client.get(
                self.base_url,
                params={
                    'latitude': self.latitude,
                    'longitude': self.longitude,
                    'current': 'temperature_2m,weather_code'
                }
            )
            # ... process and cache

De WMO weather codes worden automatisch gemapped naar PVOutput condities:

@staticmethod
def wmo_to_pvoutput_condition(wmo_code: int) -> str:
    """Map WMO weather code naar PVOutput condition string"""
    if wmo_code == 0 or wmo_code == 1:
        return "Fine"
    elif wmo_code == 2:
        return "Partly Cloudy"
    elif wmo_code == 3:
        return "Cloudy"
    elif 51 <= wmo_code <= 67:  # Drizzle and rain
        return "Showers"
    elif 71 <= wmo_code <= 77:  # Snow
        return "Snow"
    elif wmo_code >= 95:  # Thunderstorm
        return "Storm"
    # ... etc

4. Smart Data Management

De applicatie houdt dagelijkse totalen bij voor PVOutput. Dit is cruciaal omdat PVOutput cumulatieve waarden per dag verwacht:

# In app/data_manager.py
def get_daily_totals(self) -> Dict:
    """Bereken totalen voor vandaag (voor PVOutput)"""
    self._check_and_reset_daily_values()

    totals = {
        'energy_generation_wh': 0,
        'energy_consumption_wh': 0,
        'energy_import_wh': 0,
        'energy_export_wh': 0
    }

    # Bereken opwekking: huidige waarde - start waarde van vandaag
    if self.latest_kwh_data:
        current_kwh = self.latest_kwh_data['total_power_export_kwh']
        start_kwh = self.daily_start_values.get('kwh_export_kwh', current_kwh)
        totals['energy_generation_wh'] = int((current_kwh - start_kwh) * 1000)

    # ... berekening voor import/export
    return totals

5. PVOutput API Integratie

De PVOutput client stuurt alle relevante data:

# In app/pvoutput.py
async def add_status(
    self,
    energy_generation: Optional[int] = None,      # v1: Totaal opgewekt vandaag (Wh)
    power_generation: Optional[int] = None,       # v2: Actueel opgewekt (W)
    energy_consumption: Optional[int] = None,     # v3: Totaal verbruikt vandaag (Wh)
    power_consumption: Optional[int] = None,      # v4: Actueel verbruik (W)
    temperature: Optional[float] = None,          # v5: Temperatuur (°C)
    voltage: Optional[float] = None,              # v6: Voltage (V)
    condition: Optional[str] = None               # cd: Weather condition
) -> bool:
    """Voeg status toe aan PVOutput"""
    params = {
        'd': datetime.now().strftime('%Y%m%d'),
        't': datetime.now().strftime('%H:%M')
    }

    # Voeg alle beschikbare parameters toe
    if energy_generation is not None:
        params['v1'] = int(energy_generation)
    # ... etc

    response = await client.post(
        f"{self.base_url}/addstatus.jsp",
        headers=self._get_headers(),
        data=params
    )

Configuratie

De configuratie is simpel via een YAML bestand:

# HomeWizard P1 Meter configuratie
homewizard_p1:
  host: "192.168.1.100"
  enabled: true

# HomeWizard kWh Meters - ondersteuning voor meerdere!
homewizard_kwh_meters:
  - name: "Omvormer 1"
    host: "192.168.1.101"
    enabled: true
  - name: "Omvormer 2"
    host: "192.168.1.102"
    enabled: true

# PVOutput configuratie
pvoutput:
  api_key: "jouw-api-key"
  system_id: "jouw-system-id"

# Weather data (optioneel)
weather:
  enabled: true
  latitude: 52.3676
  longitude: 4.9041
  cache_duration_minutes: 15

# Update interval (minimum 300 sec voor gratis account)
update_interval: 300

Installatie in 3 Stappen

1. Clone en Configureer

git clone https://github.com/jeroen-klaver/Homewizard-to-PVOutput.git
cd Homewizard-to-PVOutput
cp config/config.example.yaml config/config.yaml
# Bewerk config.yaml met je eigen instellingen

2. Start de Container

docker-compose up -d

3. Open het Dashboard

Ga naar http://localhost:8080 en zie je data in real-time!

Webinterface Features

De webinterface biedt:

  • Real-time overview van opwekking, verbruik en grid import/export
  • Dagelijkse totalen - hoeveel heb je vandaag opgewekt/verbruikt?
  • Individuele meter weergave - zie elk van je omvormers afzonderlijk
  • Live grafieken met historische data van het laatste uur
  • PVOutput status - zie of je data succesvol wordt verzonden
  • Configuratie management - pas instellingen aan via de web UI

REST API

De container biedt ook een complete REST API:

# Status ophalen
GET /api/status

# Nieuwste data
GET /api/data/latest

# Historische data (laatste uur)
GET /api/data/history?hours=1

# Statistieken
GET /api/data/statistics

# Weather data
GET /api/weather/current

# Forceer directe update
POST /api/update-now

Performance & Reliability

Caching

Weather data wordt gecached voor 15 minuten, wat het aantal API calls met 97% reduceert en zorgt voor snelle response tijden.

Error Handling

De applicatie heeft graceful degradation:

  • Als weather API faalt, gaat de solar data upload gewoon door
  • Bij netwerk problemen gebruikt het expired cache als fallback
  • Configuratie validatie voorkomt runtime errors

Async Architecture

Volledig asynchroon gebouwd met asyncio en httpx:

async def collect_and_send_data():
    """Verzamel data van HomeWizard en stuur naar PVOutput"""

    # Parallel data collection mogelijk
    p1_data = await p1_client.get_data()
    kwh_data = await kwh_client.get_data()
    weather_data = await weather_client.get_weather()

    # Converteer en verstuur
    pvoutput_data = PVOutputDataConverter.convert_to_pvoutput(
        p1_data, kwh_data, daily_totals, weather_data
    )
    await pvoutput_client.add_status(**pvoutput_data)

Project Structuur

.
├── app/
│   ├── static/          # CSS en JavaScript voor dashboard
│   ├── templates/       # Jinja2 templates
│   ├── config.py        # Configuratie management
│   ├── homewizard.py    # HomeWizard API client
│   ├── pvoutput.py      # PVOutput API client
│   ├── weather.py       # Weather integratie
│   ├── data_manager.py  # Data opslag en berekeningen
│   └── main.py          # FastAPI applicatie
├── config/
│   └── config.yaml      # Configuratie bestand
├── Dockerfile           # Container definitie
└── docker-compose.yml   # Orchestration

Wat Maakt Dit Project Bijzonder?

  1. Complete oplossing - Van data ophalen tot visualisatie in één package
  2. Meerdere meters - Ideaal voor installaties met meerdere omvormers
  3. Weather integratie - Uniek: automatisch weather conditions naar PVOutput
  4. Voltage monitoring - Extra inzicht in je netwerk kwaliteit
  5. Docker-based - Draait overal, geen dependency hell
  6. Open Source - Volledig vrij te gebruiken en aan te passen

Toekomstige Uitbreidingen

Ideeën voor de toekomst:

  • Notificaties bij afwijkingen (bijv. omvormer offline)
  • Langere historie opslag (database integratie)
  • Meer gedetailleerde grafieken en analyses
  • Support voor andere smart meter types
  • MQTT integratie voor home automation systemen

Conclusie

Met deze Docker container krijg je een professionele oplossing om je HomeWizard data automatisch naar PVOutput te sturen. De combinatie van meerdere meters support, weather data en een mooie webinterface maakt het een complete monitoring oplossing voor je zonnepanelen installatie.

Alle code is open source en beschikbaar op GitHub. Pull requests zijn welkom!


Draai je deze oplossing ook? Laat het me weten! Voor vragen of suggesties kun je een issue openen op GitHub.