M-Bus Gateway
← Tilbage til blog
· lejerportal· selvaflæsning· EU EED· artikel 9d· fjernaflæsning· månedlige data· BEK 563· wM-Bus· IoT

Lejer-selvaflæsning og EU EED 2027 månedlige data

Lejer-selvaflæsning via portal: EU EED 2023/1791 artikel 9d krav, mobil aflæsningsindberetning, valideringsregler mod automatisk fjernaflæsning, konfliktresolution og platform-implementering.

Af M-Bus Gateway

EU EED 2023/1791 artikel 9d kræver at lejere kan tilgå eget forbrug månedligt fra 2027. Selvaflæsningsportalen er brobyggeren til ejendomme uden fuldt fjernaflæsning.


EU EED artikel 9d — månedlige data til lejere

EU EED 2023/1791 artikel 9d (gælder fra 2027):

Hvad lejere har ret til:
  → Månedlig forbrugsdata (faktisk eller estimeret)
  → Sammenligning med forrige periode
  → Sammenligning med gennemsnitslejer i ejendommen (anonymiseret)
  → Graddage-normaliseret forbrug for klimakorrektion
  → CO2-intensitet for opvarmningskilden

Hvem er forpligtet:
  → Udlejere med fjernaflæsbare målere: Platform-automatik
  → Udlejere med manuelle aflæsninger: Selvaflæsningsportal

Sanktioner (DK — forventet implementering):
  → Manglende efterlevelse: Huslejenævn kan pålægge udlejer
  → EU-Kommissionen: Kan indlede traktatbrudssag mod DK

Platform-compliance:
  → Fjernaflæsning (wM-Bus): Automatisk månedlige data ✅
  → Selvaflæsning: Lejer-portal med månedlig indberetning
  → Begge kanaler: Lejer-dashboard med historik og sammenligning

Selvaflæsningsportal — brugerflow

Lejer-selvaflæsningsflow (EU EED 2027 compliant):

1. Udlejer aktiverer selvaflæsning for ejendom
   → Property.self_reading_enabled = True
   → Udlejer definerer aflæsningsvindue (f.eks. 25.–31. i måneden)

2. Lejer modtager SMS/email-påmindelse
   → "Husk at aflæse din måler inden 31. maj"
   → Link til lejer-portal (magic link eller password)

3. Lejer indberetter via mobil:
   → Fotograferer måler-display
   → Indtaster aflæsning manuelt
   → System validerer mod forrige aflæsning + forventet forbrug

4. Validering:
   → Under minimumsgrænse: "Lavere end forrige måned — korrekt?"
   → Over maksimum: "Usædvanlig høj — bekræft venligst"
   → Foto påkrævet ved afvigelse > 50% fra forventet

5. Konfliktresolution (selvaflæsning vs. fjernaflæsning):
   → Fjernaflæsning altid prioriteret (MID-certificeret)
   → Selvaflæsning bruges kun ved manglende fjernaflæsning
   → Afregning markerer tydeligt: "Faktisk aflæsning" vs. "Selvaflæsning"

API endpoint — indberetning

# server/src/readings/self_reading_router.py
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form
from sqlmodel import Session
from datetime import datetime, date
from decimal import Decimal
from server.src.auth.deps import get_current_user

router = APIRouter(prefix="/api/v1/self-readings", tags=["self-readings"])


@router.post("/")
async def submit_self_reading(
    meter_installation_id: str = Form(...),
    reading_value: Decimal = Form(...),
    reading_date: date = Form(...),
    photo: UploadFile | None = File(None),
    current_user=Depends(get_current_user),
    db=Depends(get_db),
) -> dict:
    """
    Lejer indberetter manuel aflæsning.
    Valideres mod seneste automatiske aflæsning og historisk forbrug.
    """
    # Verificer at lejer ejer denne installation
    installation = await _verify_tenant_installation(
        meter_installation_id, current_user, db
    )

    # Validér mod forventet forbrug
    validation = await _validate_reading(
        meter_installation_id, reading_value, reading_date, db
    )
    if validation["status"] == "rejected":
        raise HTTPException(
            status_code=422,
            detail=f"Aflæsning afvist: {validation['reason']}",
        )

    # Gem fotos i Hetzner Object Storage hvis medfølger
    photo_key = None
    if photo:
        photo_key = await _upload_reading_photo(
            photo, meter_installation_id, reading_date
        )

    # Gem selvaflæsning
    reading = await _save_self_reading(
        meter_installation_id=meter_installation_id,
        value_kwh=reading_value,
        timestamp=datetime.combine(reading_date, datetime.min.time()),
        source="self_reading",
        photo_s3_key=photo_key,
        submitted_by=current_user.id,
        db=db,
    )

    return {
        "reading_id": str(reading.id),
        "status": validation["status"],    # "accepted" eller "warning"
        "validation_message": validation.get("message"),
        "photo_uploaded": photo_key is not None,
    }

Valideringslogik

# server/src/readings/validation.py
from decimal import Decimal
from datetime import date
from sqlalchemy import text


async def _validate_reading(
    meter_installation_id: str,
    value: Decimal,
    reading_date: date,
    db,
) -> dict:
    """
    Validér selvaflæsning mod historisk forbrug.
    Returns: {"status": "accepted"|"warning"|"rejected", "reason": str}
    """
    # Hent seneste 3 faktiske aflæsninger
    result = await db.execute(
        text("""
            SELECT value_kwh, timestamp
            FROM readings
            WHERE meter_installation_id = :mi_id
                AND source != 'self_reading'
            ORDER BY timestamp DESC
            LIMIT 3
        """),
        {"mi_id": meter_installation_id},
    )
    recent = result.fetchall()

    if not recent:
        return {"status": "accepted", "message": "Ingen historik — aflæsning accepteret"}

    latest = recent[0]
    latest_value = Decimal(str(latest.value_kwh))

    # Afvisning: Aflæsning lavere end seneste (tæller aldrig bagud)
    if value < latest_value:
        return {
            "status": "rejected",
            "reason": f"Aflæsning ({value}) lavere end seneste ({latest_value:.1f}). Målertæller kan ikke gå baglæns.",
        }

    # Beregn forventet dagsforbrug fra historik
    if len(recent) >= 2:
        days_between = (recent[0].timestamp - recent[1].timestamp).days or 1
        delta = Decimal(str(recent[0].value_kwh)) - Decimal(str(recent[1].value_kwh))
        daily_rate = delta / Decimal(days_between)

        days_since_last = (reading_date - latest.timestamp.date()).days or 1
        expected = latest_value + daily_rate * Decimal(days_since_last)
        deviation = abs(value - expected) / expected if expected > 0 else Decimal("0")

        if deviation > Decimal("0.5"):    # > 50% afvigelse
            return {
                "status": "warning",
                "message": f"Aflæsning afviger {deviation:.0%} fra forventet ({expected:.1f}). Foto påkrævet.",
                "requires_photo": True,
            }

    return {"status": "accepted", "message": "Aflæsning accepteret"}

Lejer-dashboard — EU EED 2027 månedsoverblik

Lejer-portal EU EED 2027 compliant:

Månedsoverblik (ArticLe 9d data):
  ┌─────────────────────────────────────────────┐
  │  Dit forbrug — maj 2026                      │
  │                                              │
  │  Varme:     234 kWh   (forrige md: 198 kWh) │
  │  Vand:      3,2 m³    (forrige md: 2,9 m³)  │
  │                                              │
  │  Sammenlignet med gennemsnit i ejendommen:  │
  │  Du bruger 12% MINDRE end gennemsnittet     │
  │                                              │
  │  Klimakorrigeret (graddage):                │
  │  Normaliseret: 218 kWh (maj er varm)        │
  │                                              │
  │  CO2: 23 kg (fjernvarme: 98 g/kWh)          │
  └─────────────────────────────────────────────┘

Historik (12 måneder):
  [BarChart: månedligt forbrug + gennemsnitslinje]

Datatype-indikator:
  🔵 Automatisk aflæsning (wM-Bus)
  🟡 Selvaflæsning (dig)
  ⚪ Estimeret (§ 13)

Årsafregning:
  → Link til seneste PDF-afregning
  → Indsigelsesformular (6-ugers frist)

Konklusion

EU EED 2023/1791 artikel 9d kræver månedlige forbrugsdata til lejere fra 2027. For ejendomme med wM-Bus fjernaflæsning leverer platformen dette automatisk. For manuelle ejendomme er selvaflæsningsportalen svaret — lejer fotograferer og indberetter, systemet validerer mod historisk forbrug og prioriterer altid fjernaflæsning ved konflikt. Valideringslogik afviser umulige aflæsninger (bagudgående tæller) og flagger usædvanlige afvigelser med fotokrav. Lejer-dashboardet viser månedsoverblik, klimakorrektion og CO2-intensitet — fuldt EU EED 2027 compliant.

Se EU 2027 fjernaflæsning lovkrav eller hvad kan lejer se guide.