# API für Umweltmessungen

Die API speichert GPS-verortete Messwerte in einer lokalen SQLite-Datenbank. Sie ist unabhängig von der LabPi-0.29-API unter `/web/backend`.

Basis-URL: `https://www.labpi.de/karte/api.php`

Zusätzlich kann die Kartenoberfläche vorhandene Messreihen direkt aus LabPi COMPare übernehmen. Dieser Import läuft über `POST /karte/compare_import.php` und ist unten separat beschrieben.

## CSV-Schema

Eine Datenzeile entspricht genau einem Messwert. Alle sieben Spalten müssen in der Kopfzeile vorkommen; `unit` und `station_id` dürfen in einzelnen Zeilen leer sein.

| Spalte | Bedeutung | Beispiel |
| --- | --- | --- |
| `timestamp` | ISO 8601 oder Unix-Zeitstempel; ohne Zeitzone wird UTC angenommen | `2026-08-31T10:00:00Z` |
| `latitude` | Breitengrad von −90 bis 90 | `53.1435` |
| `longitude` | Längengrad von −180 bis 180 | `8.2146` |
| `parameter` | Messgröße, maximal 60 Zeichen; Leerzeichen werden zu `_` | `co2`, `temperature`, `humidity`, `ph` |
| `value` | Endliche Zahl; bei Semikolon-CSV ist auch das Dezimalkomma erlaubt | `612` |
| `unit` | Einheit, maximal 24 Zeichen | `ppm`, `°C`, `%`, `pH` |
| `station_id` | Optionale Kennung der Messstation, maximal 80 Zeichen | `labpi-oldenburg` |

Unterstützte Trennzeichen sind Komma, Semikolon und Tabulator. Pro Anfrage sind maximal 5 MB beziehungsweise 10.000 Datenzeilen erlaubt. Doppelte Datensätze werden anhand von Station, Zeitpunkt, Position, Messgröße, Wert und Einheit erkannt und übersprungen.

Beispiel:

```csv
timestamp,latitude,longitude,parameter,value,unit,station_id
2026-08-31T10:00:00Z,53.1435,8.2146,co2,612,ppm,labpi-oldenburg
2026-08-31T10:00:00Z,53.1435,8.2146,temperature,21.8,°C,labpi-oldenburg
```

## CSV hochladen

`POST /karte/api.php` mit `multipart/form-data`; das Dateifeld heißt `file`.

```bash
curl -X POST \
  -F "file=@messwerte.csv" \
  https://www.labpi.de/karte/api.php
```

Erfolgreiche Antwort (`201 Created`):

```json
{
  "ok": true,
  "imported": 2,
  "duplicates": 0,
  "invalid": 0,
  "errors": []
}
```

Ungültige Zeilen werden ausgelassen und mit Zeilennummer gemeldet. Es werden höchstens 20 einzelne Fehlerdetails zurückgegeben. Sind alle Datenzeilen ungültig, antwortet die API mit `422 Unprocessable Content`.

### Optionaler API-Schlüssel

Ist auf dem Server die Umgebungsvariable `LABPI_MAP_API_KEY` gesetzt, müssen Uploads den Schlüssel als Bearer-Token oder `X-API-Key` senden. GET-Abfragen bleiben öffentlich.

```bash
curl -X POST \
  -H "Authorization: Bearer MEIN_SCHLUESSEL" \
  -F "file=@messwerte.csv" \
  https://www.labpi.de/karte/api.php
```

## Messwerte abrufen

`GET /karte/api.php` liefert standardmäßig eine GeoJSON-`FeatureCollection` mit maximal 2.000 Messwerten, absteigend nach Zeitpunkt sortiert.

```bash
curl "https://www.labpi.de/karte/api.php?parameter=co2&limit=500"
```

Filter:

| Parameter | Beschreibung |
| --- | --- |
| `parameter` | Exakte Messgröße, Groß-/Kleinschreibung wird ignoriert |
| `station_id` | Exakte Stationskennung |
| `from` | Frühester Zeitpunkt, ISO 8601 oder Unix-Zeitstempel |
| `to` | Spätester Zeitpunkt, ISO 8601 oder Unix-Zeitstempel |
| `bbox` | Kartenausschnitt als `minLon,minLat,maxLon,maxLat` |
| `limit` | 1 bis 5.000, Standard 2.000 |
| `format` | `geojson` (Standard) oder `csv` |

Beispiel für einen Kartenausschnitt und Zeitraum:

```text
GET /karte/api.php?bbox=7.5,52.8,9.0,53.7&from=2026-08-01T00:00:00Z&to=2026-09-01T00:00:00Z
```

CSV-Export:

```bash
curl -o umweltmessungen.csv \
  "https://www.labpi.de/karte/api.php?format=csv&parameter=temperature"
```

## Statuscodes

| Status | Bedeutung |
| --- | --- |
| `200` | Abruf erfolgreich |
| `201` | Upload verarbeitet |
| `400` | Anfrage oder Filter ungültig |
| `401` | API-Schlüssel fehlt oder ist ungültig |
| `413` | Datei oder Zeilenzahl zu groß |
| `415` | Keine CSV-Datei |
| `422` | CSV-Schema oder alle Datenzeilen ungültig |
| `429` | Zu viele COMPare-Prüfversuche |
| `503` | COMPare-Datenbank vorübergehend nicht erreichbar |
| `500` | Interner Serverfehler |

## COMPare-Messungen importieren

In der Kartenoberfläche öffnet die Schaltfläche **COMPare-Import** einen geführten Import:

1. Messung-ID und COMPare-Passwort eingeben.
2. Erkannte Gruppen und Messreihen kontrollieren.
3. Fehlende GPS-Positionen sowie Startdatum und -uhrzeit ergänzen.
4. Festlegen, ob die X-Werte Zeitversätze darstellen oder ein gleichmäßiges Messintervall verwendet werden soll.
5. Vorgeschlagene Messgrößen und Einheiten bei Bedarf anpassen und importieren.

GPS-Position und Zeitangaben werden je COMPare-Gruppe verwaltet. Eine Standardposition kann auf alle Gruppen angewendet und anschließend gruppenweise überschrieben werden. Der in COMPare vorhandene Datensatz-Zeitstempel wird nur als Vorschlag für die Startzeit verwendet und sollte vor dem Import geprüft werden.

### Zweistufige Importschnittstelle

Die Schnittstelle ist für die Kartenoberfläche gedacht. Im ersten Schritt werden die COMPare-Zugangsdaten geprüft:

```http
POST /karte/compare_import.php
Content-Type: application/json

{
  "action": "preview",
  "measurement_id": 123,
  "password": "COMPARE-PASSWORT"
}
```

Bei Erfolg liefert die API eine zeitlich begrenzte Importkennung und ausschließlich Metadaten der Gruppen und Messreihen. Das Passwort wird weder zurückgegeben noch in der Karten-Datenbank oder Importsitzung gespeichert. Die Vorschau ist 20 Minuten gültig.

Im zweiten Schritt sendet die Oberfläche die ergänzten Angaben zusammen mit der Importkennung:

```json
{
  "action": "commit",
  "token": "ZEITLICH-BEGRENZTE-IMPORTKENNUNG",
  "station_id": "compare-123",
  "default_latitude": 53.1435,
  "default_longitude": 8.2146,
  "groups": [
    {
      "id": "g42",
      "latitude": "",
      "longitude": "",
      "start_time": "2026-09-02T10:00:00Z",
      "time_mode": "x_axis",
      "time_unit": "s",
      "interval_seconds": 1,
      "series": [
        {
          "id": "r42_y1",
          "enabled": true,
          "parameter": "temperature",
          "unit": "°C"
        }
      ]
    }
  ]
}
```

`time_mode` akzeptiert `x_axis` oder `interval`. Für `x_axis` stehen die Zeiteinheiten `ms`, `s`, `min` und `h` zur Verfügung. Bei `interval` muss `interval_seconds` größer als null sein. Pro Import werden höchstens 50.000 Messwerte verarbeitet. Die Importkennung ist an die Browsersitzung gebunden und nach einem erfolgreichen Import nicht erneut verwendbar.

Zusätzlich zu den normalen Messfeldern speichert die Karten-Datenbank bei COMPare-Importen Quelltyp, COMPare-Referenz, Gruppenname und ursprünglichen X-Wert. Das COMPare-Passwort gehört ausdrücklich nicht dazu.

## Serverkonfiguration

Die API benötigt PHP 8.1 oder neuer mit `PDO_SQLite`. Standardmäßig liegt die Datenbank unter `karte/data/measurements.sqlite`; der Ordner ist über Apache gesperrt. Mit `LABPI_MAP_DB_PATH` kann ein Pfad außerhalb des Webroots konfiguriert werden. Für den produktiven Betrieb wird außerdem ein `LABPI_MAP_API_KEY` empfohlen.
