# VENTT Export Agent

Logt automatisch in op het Airios Cloud portal (manage.connect2myhome.eu),
detecteert alle bridges/devices op het account, start een export per bridge,
wacht tot deze klaar is, downloadt de ZIP en zet de CSV's om naar een nette,
leesbare vorm (juiste kolomnamen + gefixte getalnotatie).

## 1. Eenmalige installatie

Open Terminal en ga naar de map waarin je dit project hebt gezet, bijv.:

```bash
cd ~/Documents/ventt_agent
```

Maak een virtuele omgeving en installeer de dependencies:

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Maak je eigen `.env` bestand met inloggegevens:

```bash
cp .env.example .env
nano .env   # of open in een editor, vul USERNAME en PASSWORD in
```

**Belangrijk:** `.env` staat in `.gitignore` en mag nooit gedeeld worden.

## 2. Eenmalig handmatig testen

Voordat je het automatiseert, eerst 1x handmatig draaien om te checken of
alles werkt:

```bash
source .venv/bin/activate
python3 ventt_export_agent.py
```

Je ziet live logging in de terminal, en dezelfde info staat in
`data/logs/2026-06-25.log` (datum van vandaag). Bij succes vind je de
verwerkte CSV's in `data/processed/2026-06-25/`.

Veelvoorkomende foutmeldingen en wat ze betekenen:

| Foutmelding | Betekenis |
|---|---|
| `.env bestand niet gevonden` | Je hebt stap 1 (cp .env.example .env) nog niet gedaan |
| `Login lijkt mislukt` | Gebruikersnaam/wachtwoord klopt niet in `.env` |
| `Kon geen link naar de user-detailpagina vinden` | Portal-layout is gewijzigd, even melden zodat het script aangepast kan worden |
| `Export-job ... is mislukt met status ERROR/TIMEOUT` | Portal-probleem, meestal de volgende dag vanzelf weer goed |
| `Export-job ... duurde te lang` | Server was trager dan verwacht (>4 min), kun je het script gewoon opnieuw starten |

## 3. Automatisch elke dag laten draaien (macOS launchd)

macOS gebruikt `launchd` in plaats van cron — werkt ook na slaapstand/herstart.

1. Open `nl.ventt.export-agent.plist` in een teksteditor en vervang **alle**
   `__SCRIPT_PATH__` door het volledige pad naar deze map, bijvoorbeeld:
   `/Users/robbert/Documents/ventt_agent`

   Snelle manier via Terminal (pas het pad aan):
   ```bash
   SCRIPT_PATH="/Users/robbert/Documents/ventt_agent"
   sed -i '' "s|__SCRIPT_PATH__|$SCRIPT_PATH|g" nl.ventt.export-agent.plist
   ```

2. Kopieer het bestand naar de juiste launchd-map:
   ```bash
   cp nl.ventt.export-agent.plist ~/Library/LaunchAgents/
   ```

3. Activeer de job:
   ```bash
   launchctl load ~/Library/LaunchAgents/nl.ventt.export-agent.plist
   ```

   Vanaf nu draait het script elke dag automatisch om **07:00**.

### Handige launchd-commando's

```bash
# Direct een keer handmatig triggeren (voor test, los van het schema)
launchctl start nl.ventt.export-agent

# Job uitschakelen
launchctl unload ~/Library/LaunchAgents/nl.ventt.export-agent.plist

# Tijd aanpassen: bewerk het plist-bestand (Hour/Minute), daarna opnieuw laden
launchctl unload ~/Library/LaunchAgents/nl.ventt.export-agent.plist
launchctl load ~/Library/LaunchAgents/nl.ventt.export-agent.plist
```

**Let op:** je MacBook moet aan staan en niet in slaapstand om 07:00 (wel mag
het scherm vergrendeld zijn). Staat de Mac uit, dan draait de taak simpelweg
niet die dag — er is geen automatische "inhaalslag", dus check af en toe het
logbestand.

## 4. Dashboard

Na elke succesvolle run wordt automatisch een dashboard gegenereerd:

```
data/processed/2026-06-25/dashboard.html
```

Dit is een **op zichzelf staand HTML-bestand** (geen server nodig) met:
- Een dropdown boven aan om te wisselen tussen ventilatie-units
- Gegroepeerde grafieken: temperaturen, flow/ventilatie, sturing/PWM, klimaat
- Eén gezamenlijke tijdas per unit: zoomen/pannen op één grafiek beweegt alle
  grafieken van die unit synchroon mee
- Een status/events-tabel voor Fault Status en Ventilation Mode

Dubbelklik het bestand om het in je browser te openen. Het bestand bevat alle
data van die dag ingebakken (typisch 1-2 MB per unit), dus je kunt het ook
gewoon mailen, delen of archiveren zonder dat er iets anders bij hoort.

Als je het dashboard-uiterlijk wilt aanpassen, bewerk je
`dashboard_template/dashboard_template.html` — dit bestand moet in dezelfde
map blijven staan als `ventt_export_agent.py`, want het script gebruikt het
als basis voor elke gegenereerde dashboard.html.

## 5. Upload naar server (optioneel)

Als `VENTT_SCP_HOST` en `VENTT_SCP_ROOT_DIR` zijn ingevuld in `.env`, uploadt
het script na elke run automatisch alle bestanden van die dag naar een
server via `scp`/`ssh`. Dit veronderstelt dat de hostnaam/alias al werkt
zonder wachtwoord-prompt (dus al in je `~/.ssh/config` staat met user en key).

Resulterende structuur op de server:

```
{VENTT_SCP_ROOT_DIR}/{datum}/
  index.html              <- het dashboard, direct als webpagina te openen
  raw/
    {bridge-id}.zip
    {bridge-id}/{device-id}.csv
  processed/
    {device-id}.csv
```

Als de upload faalt (bijv. server tijdelijk onbereikbaar), wordt dit gelogd
maar stopt het script niet — de lokale data en het lokale dashboard blijven
gewoon beschikbaar, en de volgende dag wordt opnieuw geprobeerd te uploaden.

Laat `VENTT_SCP_HOST`/`VENTT_SCP_ROOT_DIR` leeg of verwijder de regels uit
`.env` om uploaden volledig over te slaan.

## 6. Output structuur

```
data/
  raw/
    2026-06-25/
      {bridge-id}.zip              <- ongewijzigde download (audit trail)
      {bridge-id}/
        {device-id}.csv            <- uitgepakte originele CSV
  processed/
    2026-06-25/
      {device-id}.csv              <- opgeschoond: juiste kolomnamen + getallen
      dashboard.html                <- kant-en-klaar dashboard voor die dag
  logs/
    2026-06-25.log                 <- 1 logbestand per dag
```

Open `data/processed/{datum}/dashboard.html` in je browser om de data van die
dag te bekijken.

## 7. Onderhoud / als het portal verandert

Dit script werkt door specifieke HTML-elementen van het portal te herkennen
(CSRF-tokens, device-checkboxes, job-status JSON). Als Airios/connect2myhome
hun portal-layout ooit aanpast, kan het script breken. De logmeldingen
vertellen dan vrij precies welk onderdeel niet meer matcht.
