# SensorAPI - API Dokumentation ## Übersicht Die SensorAPI ist eine REST-API zur Abfrage von Umweltsensordaten (Lärm, Feinstaub, Temperatur, Radioaktivität). Sie unterstützt sowohl InfluxDB 1.8 (InfluxQL) als auch InfluxDB 2.0 (Flux) sowie MongoDB für Metadaten. **Version:** 1.4.1 **Basis-URL:** `http://:/api/` --- ## Technologie-Stack - **Backend:** Node.js mit Express.js - **Datenbanken:** - InfluxDB 1.8/2.0 (Zeitreihendaten) - MongoDB (Sensor-Metadaten und -Eigenschaften) - **Sprachen:** JavaScript (ES6 Module) - **Key Dependencies:** axios, luxon, i18next, dotenv --- ## Unterstützte Sensortypen | Typ | Beschreibung | Messgrößen | |-----|--------------|------------| | `noise` | Lärmsensoren | LA_max, LA_min, LA_eq, E10tel_eq | | `pm` | Feinstaubsensoren | P1, P2, P0 | | `thp` | Temperatur/Luftfeuchte/Druck | temperature, humidity, pressure | | `radioactivity` | Radioaktivitätssensoren | counts_per_minute | --- ## API Endpunkte Alle Endpunkte folgen dem Schema: `GET /api/?` ### 1. **getsensordata** Hauptendpunkt zum Abrufen von Sensordaten. Leitet je nach Sensortyp an spezialisierte Handler weiter. **Endpunkt:** `/api/getsensordata` **Pflichtparameter:** - `sensorid` (int) - Eindeutige Sensor-ID **Optionale Parameter (abhängig vom Sensortyp):** #### Für Lärmsensoren (`noise`): - `data` (string, default: 'live') - Art der Daten - `span` (int, default: 1) - Zeitspanne in Tagen - `daystart` (bool, default: null) - Start um 00:00:00 Uhr - `peak` (int, default: 70) - Schwellenwert für Lärmspitzen in dB - `since` (date, default: '1900-01-01T00:00:00Z') - Startdatum - `datetime` (date, default: null) - Spezifisches Datum/Zeit - `long` (bool, default: false) - Erweiterte Ausgabe - `sort` (int, default: 1) - Sortierung (1=aufsteigend, -1=absteigend) - `csv` (bool, default: false) - CSV-Ausgabe - `out` (string, default: '') - Ausgabeformat #### Für Radioaktivitätssensoren (`radioactivity`): - `what` (string, default: 'day') - Art der Aggregation - `span` (int, default: 1) - Zeitspanne in Tagen - `avg` (int, default: 1) - Mittelwert-Intervall - `moving` (bool, default: false) - Gleitender Mittelwert **Beispiel:** ``` GET /api/getsensordata?sensorid=12345&span=7&peak=75 ``` **Antwort:** ```json { "err": null, "values": [ { "_time": "2025-11-04T10:00:00.000Z", "DNMS_noise_LA_max": 78.5, "DNMS_noise_LA_min": 45.2, "DNMS_noise_LA_eq": 65.3, "E10tel_eq": 72777980.45 } ] } ``` --- ### 2. **getactdata** Abrufen aktueller/historischer Rohdaten eines Sensors. **Endpunkt:** `/api/getactdata` **Parameter:** - `sensorid` (int) - Sensor-ID - `span` (int, optional) - Zeitspanne in Tagen - `datetime` (date, optional) - Startdatum - `sort` (int, optional) - Sortierung **Beispiel:** ``` GET /api/getactdata?sensorid=12345&span=1 ``` **Antwort:** ```json { "err": null, "values": [ { "_time": "2025-11-04T10:00:00.000Z", "DNMS_noise_LA_max": 78.62, "DNMS_noise_LA_min": 47.36, "DNMS_noise_LA_eq": null, "E10tel_eq": 72777980.45 } ] } ``` --- ### 3. **getavgdata** Abrufen von Durchschnittswerten mit konfigurierbarem Zeitfenster. **Endpunkt:** `/api/getavgdata` **Pflichtparameter:** - `sensorid` (int) - Sensor-ID **Optionale Parameter:** - `span` (int, default: 1) - Zeitspanne in Tagen - `datetime` (date, default: null) - Startdatum - `avg` (int, default: 10) - Mittelwert-Intervall in Minuten - `moving` (bool, default: true) - Gleitender Mittelwert **Beispiel:** ``` GET /api/getavgdata?sensorid=12345&span=7&avg=60&moving=true ``` **Antwort:** ```json { "data": { "start": "2025-10-28T10:00:00Z", "span": 7, "avg": 60, "moving": true, "count": 168, "values": [...] }, "err": null } ``` --- ### 4. **getlongavg** Langzeit-Durchschnittswerte über einen längeren Zeitraum. **Endpunkt:** `/api/getlongavg` **Pflichtparameter:** - `sensorid` (int) - Sensor-ID **Optionale Parameter:** - `span` (int, default: 2) - Zeitspanne in Tagen **Beispiel:** ``` GET /api/getlongavg?sensorid=12345&span=30 ``` **Antwort:** ```json { "data": { "span": 30, "values": [ { "_stop": "2025-11-04T00:00:00.000Z", "LA_max": 75.3, "LA_min": 42.1, "LA_eq": 63.8 } ] }, "err": null } ``` --- ### 5. **getoneproperty** Abrufen der Eigenschaften eines Sensors (Metadaten, Standort, etc.). **Endpunkt:** `/api/getoneproperty` **Pflichtparameter:** - `sensorid` (int) - Sensor-ID **Beispiel:** ``` GET /api/getoneproperty?sensorid=12345 ``` **Antwort:** ```json { "err": null, "props": { "_id": 12345, "name": [{"name": "Hauptstraße"}], "type": "noise", "location": [{ "id": "loc_123", "loc": { "type": "Point", "coordinates": [9.123, 48.456] }, "indoor": false }], "othersensors": [ {"name": "PM Sensor", "sid": 12346} ] } } ``` --- ### 6. **getmapdata** Abrufen von Sensordaten für Kartendarstellung mit geografischer Filterung. **Endpunkt:** `/api/getmapdata` **Pflichtparameter:** - `type` (string) - Sensortyp (noise, pm, thp, radioactivity) **Optionale Parameter (einer muss angegeben werden):** - `box` (string) - Begrenzungsbox: "west,south,east,north" - `poly` (JSON-Array) - Polygon-Koordinaten - `center` (Array) - Mittelpunkt [lng, lat] - `distance` (int, default: 10) - Radius in km (nur mit `center`) **Beispiel:** ``` GET /api/getmapdata?type=noise&box=9.0,48.0,9.5,48.5 ``` **Antwort:** ```json { "err": null, "options": { "lastdate": "2025-11-04T10:30:00.000Z", "count": 25, "data": "map" }, "values": [ { "location": [9.123, 48.456], "id": 12345, "name": "Hauptstraße", "indoor": false, "lastseen": "2025-11-04T10:25:00.000Z", "value": 75.3, "weeks": 0 } ] } ``` **Wert-Kodierung:** - `value >= 0`: Aktueller Messwert - `value = -1`: Daten älter als 2 Stunden - `value = -2`: Daten älter als 7 Tage - `value = -3`: Daten älter als 30 Tage - `value = -4`: Daten älter als 365 Tage - `value = -5`: Keine Daten vorhanden --- ### 7. **getaddress** Geocoding: Koordinaten aus Adresse ermitteln. **Endpunkt:** `/api/getaddress` **Parameter:** - `address` (string) - Adresse **Beispiel:** ``` GET /api/getaddress?address=Hauptstraße+10,+Stuttgart ``` --- ### 8. **getcitycoords** Koordinaten einer Stadt abrufen. **Endpunkt:** `/api/getcitycoords` **Parameter:** - `city` (string) - Stadtname **Beispiel:** ``` GET /api/getcitycoords?city=Stuttgart ``` --- ### 9. **getakwdata** Abrufen von Atomkraftwerks-Daten (spezialisiert). **Endpunkt:** `/api/getakwdata` --- ## Zeitformat-Konvertierung Die API akzeptiert verschiedene Zeitformate: ### InfluxDB 2.0 (Flux) Format: ``` start: -7d stop: now() ``` ### InfluxDB 1.8 (InfluxQL) Format: ``` now() - 7d now() ``` ### Absolute Zeitangaben (ISO 8601): ``` 2025-11-04T10:00:00.000Z ``` **Wichtig:** Bei der Verwendung von ISO-Zeitstempeln mit InfluxDB 1.8 werden diese automatisch in Anführungszeichen gesetzt. --- ## Fehlerbehandlung Alle Endpunkte geben Fehler im folgenden Format zurück: ```json { "err": "ERROR_CODE", "values": [] } ``` **Häufige Fehlercodes:** - `NODATA` - Keine Daten gefunden - `SYNTAXURL` - Ungültige Query-Syntax - `NOPROPSREAD` - Eigenschaften konnten nicht gelesen werden - `NOPROPSFOUND` - Keine Eigenschaften gefunden - `CMNDUNKNOWN` - Unbekannter Befehl --- ## Spezielle Berechnungen für Lärmdaten ### Logarithmische Mittelwertbildung Für Dezibel-Werte (LA_max) wird eine korrekte logarithmische Mittelwertbildung durchgeführt: 1. **Konvertierung zu linear:** `E10tel = 10^(LA_max/10)` 2. **Arithmetischer Mittelwert:** `mean_E10tel = sum(E10tel) / count` 3. **Rückkonvertierung zu dB:** `n_AVG = 10 * log10(mean_E10tel)` ### Peak-Zählung Bei `getlongavg` mit `long=true` werden Lärmspitzen über einem Schwellenwert gezählt: ```json { "_time": "2025-11-04T12:00:00.000Z", "peakcount": 13, "n_AVG": 78.51, "count": 18 } ``` --- ## Datenbank-Konfiguration ### Umgebungsvariablen (.env) ```bash # InfluxDB 1.8 INFLUXHOST=localhost INFLUXPORT=8086 INFLUXUSER=username INFLUXPASS=password INFLUXDB=sensor_data # InfluxDB 2.0 INFLUXTOKEN=your_token_here INFLUXDATABUCKET=sensor_data INFLUXORG=citysensor # MongoDB MONGOHOST=localhost MONGOPORT=27017 MONGODB=sensordb # Datenbank-Auswahl DBASE=mongo # oder 'influx' ``` --- ## Ausgabeformate ### JSON (Standard) Alle Endpunkte geben standardmäßig JSON zurück. ### CSV (Optional) Bei einigen Endpunkten kann `csv=true` übergeben werden: ``` GET /api/getsensordata?sensorid=12345&csv=true ``` --- ## Paginierung Die API verwendet keine explizite Paginierung. Große Datenmengen sollten über `span` und `datetime` Parameter zeitlich eingeschränkt werden. --- ## Rate Limiting Aktuell ist kein Rate Limiting implementiert. Dies sollte auf Proxy/Load-Balancer-Ebene erfolgen. --- ## Beispiel-Workflows ### Workflow 1: Karte mit Lärmsensoren anzeigen 1. Sensoren in Gebiet abrufen: ``` GET /api/getmapdata?type=noise&box=9.0,48.0,9.5,48.5 ``` 2. Details für einen Sensor abrufen: ``` GET /api/getoneproperty?sensorid=12345 ``` 3. Historische Daten abrufen: ``` GET /api/getactdata?sensorid=12345&span=7 ``` ### Workflow 2: Lärmstatistik über eine Woche 1. Durchschnittswerte mit Lärmspitzen: ``` GET /api/getsensordata?sensorid=12345&span=7&peak=70&long=true ``` 2. Ergebnis analysieren: ```json { "values": [ { "_time": "2025-11-04T00:00:00.000Z", "peakcount": 13, "n_AVG": 78.51, "count": 1440, "LA_max_log_avg": 78.51 } ] } ``` --- ## Internationalisierung Die API unterstützt mehrere Sprachen über i18next: - Deutsch (de) - Englisch (en) Fehlermeldungen werden automatisch in der gewünschten Sprache zurückgegeben. --- ## Sicherheit ### API-Key-Authentifizierung Die API unterstützt API-Key-Authentifizierung für programmatischen Zugriff. #### Aktivierung 1. **API-Keys generieren:** ```bash node generate-apikey.js 3 ``` 2. **In .env konfigurieren:** ```bash API_AUTH_REQUIRED=true API_KEYS=key1,key2,key3 ``` 3. **Server neu starten** #### Verwendung API-Keys können auf zwei Arten übergeben werden: **Option 1: HTTP-Header (empfohlen)** ```bash curl -H "X-API-Key: your-api-key-here" \ "http://localhost:3000/api/getactdata?sensorid=12345" ``` **Option 2: Query-Parameter** ```bash curl "http://localhost:3000/api/getactdata?sensorid=12345&apikey=your-api-key-here" ``` #### Beispiel mit JavaScript/Node.js ```javascript import axios from 'axios' const API_KEY = 'your-api-key-here' const BASE_URL = 'http://localhost:3000/api' // Mit Header const response = await axios.get(`${BASE_URL}/getactdata`, { params: { sensorid: 12345 }, headers: { 'X-API-Key': API_KEY } }) // Mit Query-Parameter const response2 = await axios.get(`${BASE_URL}/getactdata`, { params: { sensorid: 12345, apikey: API_KEY } }) ``` #### Beispiel mit Python ```python import requests API_KEY = 'your-api-key-here' BASE_URL = 'http://localhost:3000/api' # Mit Header headers = {'X-API-Key': API_KEY} response = requests.get(f'{BASE_URL}/getactdata', params={'sensorid': 12345}, headers=headers) # Mit Query-Parameter response2 = requests.get(f'{BASE_URL}/getactdata', params={'sensorid': 12345, 'apikey': API_KEY}) ``` #### Fehlermeldungen **401 Unauthorized - Kein API-Key angegeben:** ```json { "err": "UNAUTHORIZED", "message": "API key required. Provide X-API-Key header or apikey query parameter." } ``` **403 Forbidden - Ungültiger API-Key:** ```json { "err": "FORBIDDEN", "message": "Invalid API key" } ``` #### Best Practices - **Niemals API-Keys im Code committen** - verwenden Sie Umgebungsvariablen - **Verschiedene Keys für verschiedene Clients** - ermöglicht granulare Kontrolle - **Keys regelmäßig rotieren** - besonders nach Mitarbeiterabgängen - **HTTPS verwenden** - schützt Keys bei Übertragung - **Keys sicher speichern** - z.B. in Secret Management Systemen - **Logging aktivieren** - überwachen Sie API-Zugriffe ### Weitere Sicherheitsmaßnahmen Für Produktionsumgebungen sollten zusätzlich implementiert werden: - **HTTPS erzwungen** - verhindert Man-in-the-Middle-Angriffe - **CORS-Regeln konfiguriert** - beschränkt Browser-Zugriffe - **Rate Limiting aktiviert** - schützt vor Missbrauch - **IP-Whitelisting** - zusätzliche Zugriffskontrolle - **Request-Logging** - Audit-Trail für Compliance --- ## Support und Weiterentwicklung Für Fragen, Bugs oder Feature-Requests siehe die Projekt-Repository-Dokumentation. **Version History:** - 1.4.1: Unterstützung für InfluxDB 1.8 mit InfluxQL, logarithmische Mittelwertbildung für Lärmdaten