Будьте уважні! Це призведе до видалення сторінки "Home".
Der data.HUB ist eine Datenplattform, die aktuell grob zwei Ziele verfolgt und großteils erfüllt:
Der data.HUB besteht darüber hinaus grob gesehen drei Komponenten:
Einige Funktionen sind aktuell noch prototypisch implementiert und müssen u.U. im Zuge einer Weiterentwicklung, v.a. in einem User:innenzentriertem Prozess, noch weiter angepasst werden.
Eine gravierende Einschränkung stellt die aktuelle Implementierung ohne Verschlüsselung der Datenübertragung (kein HTTPS) dar. Das ist dem Umstand geschuldet, dass die aktuellen Sensoren keine Verschlüsselung unterstützen. Es bedeutet aber auch, dass aktuell ein Betrieb mit externen Nutzer:innen nicht empfehlenswert ist.
Die Konfigurationen für die Docker container und docker-compose sind Teil dieses Repositorys.
User:innen können sich unter /user/register registrieren. Die User:innen müssen aber im Anschluss erst freigeschalten werden, bevor sie sich einloggen können. Eine Möglichkeit, per Email das passwort zurückzusetzen gibt es nicht.
Es können zwei User:innen-Rollen für den Administrationsbereich zugewiesen werden:
Es gibt drei Modi, wie Daten für Nutzer:innen oder auch die Öffentlichkeit über Schnittstellen zur Verfügung gestellt werden können. Diese Einstellungen werden über Projekte gesetzt. Jedes Projekt hat außerdem eine:n Projektleiter:in, diese:r Nutzer:in kann immer alle Daten einsehen.
Diese Einschränkungen gelten für alle aktuell implementierte API-Endpunkte, die auf DataSources (Sensoren) oder Datenpunkte (Reading Points) Zugriff bieten. Für z.B. Open Government Data ist dies nicht relevant.
In Ergänzung zur dokumentierten Datenbankstruktur hier noch Ausführungen zur Anwendung der Datenstrukturen
Der Sensorik-Teil des data.HUB beinhaltet eine Reihe an Modellen:
Obwohl aktuell bei DataSource von Geräten/Sensoren die Rede ist: Es ist auch möglich, z.B. Daten des Mobilitätspanels als GeoJSON per REST-API an den data.HUB zu senden. Daher auch der generische Name "Datenquelle".
Die Authentifizierung der REST API für u.a. Sensoren erfolgt über JSON Web Tokens (JWT). Diese Tokens erlauben, ein paar Attribute mit einem "Secret" des Servers zu signieren:
sub ist das subject des JWT, in unserem Fall bietet sich die Sensor-ID an.iss ist der issuer, hier könnten wir den_die User_in des Webservices verwenden, der_die den Token erstellt hat.exp erlaubt, ein Ablaufdatum festzulegen. Das wird aktuell nicht gesetzt, da die Sensorboxen möglichst lange ohne Intervention senden können sollen.iat ist der Ausstellungszeitpunkt. Diesen zu nutzen macht wahrscheinlich zur Nachvollziehbarkeit sinn (wann wurde der Token erstellt?)Mit dem Secret der REST-API signiert und base64-codiert entsteht ein Token der wie folgt aussieht. Ein entsprechendes Interface wird es am Server geben.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Dieser Token muss auf jedem Sensor gespeichert werden, bevor er Daten an die REST API senden kann.
Für jede Anfrage an die REST-API muss dann dieser Token in den Header als Authorization: Bearer geschrieben werden und der Conten
curl
-X POST
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
-d '{"type": "Feature", "geometry": {"type": "Point", "coordinates": [100.0, 0.0]}, "properties": {"Temperature": [24.5, "°C"], "Noise": [100.0, "dB"], "timestamp": "1617140798" }'
https://aml.media.tuwien.ac.at:11312/api/sensordata
Alternativ, da die aktuellen Sensorboxen den Header nicht setzen können, kann der Token auch als Teil der URL gesendet werden:
curl
-X POST
-d '{"type": "Feature", "geometry": {"type": "Point", "coordinates": [100.0, 0.0]}, "properties": {"Temperature": [24.5, "°C"], "Noise": [100.0, "dB"], "timestamp": "1617140798" }'
https://aml.media.tuwien.ac.at:11312/api/sensordata/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Der Server überprüft dann den Token, und liest aus dem Token die Sensor-ID aus und kann somit die Nachricht dem DataSource zuordnen.
Die meisten Endpunkte geben für eingeloggte User:innen mehr Daten Preis. Um das Einloggen zu ermöglichen reicht es, die Person an folgende URL zu schicken: http://aml.media.tuwien.ac.at:11312/user/sign-in?next=https://www.mobillab.wien/path/to/dashboard. Nach dem Login wird die Person zu https://www.mobillab.wien/path/to/dashboard redirected. Wer schon über das Admin-Interface eingeloggt ist, sollte automatisch die sichtbaren Daten angezeigt bekommen.
Wichtig: Aus Sicherheitsgründen werden nur Redirects auf http://www.mobillab.wien/... und https://www.mobillab.wien/... akzeptiert!
/api/sensordata/<token>Dieser Endpunkt nimmt ReadingPoint Daten entgegen. Der Token kann wie oben beschrieben als Teil der URL oder im Header mitgegeben werden. Dabei muss der GeoJSON-Body der Nachricht folgendem Schema folgen:
{
"type": "Feature",
"geometry": {
"type": "<Geometrie-Typ>",
"coordinates": [<Longitude>, <Latitude>]
},
"properties": {
"<Reading name>": [<Reading value>, "<Reading unit>"],
...,
"timestamp": "<POSIX timestamp>"
}
}
D.h. es kann z.B. so aussehen:
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [100.0, 0.0]
},
"properties": {
"Temperature": [24.5, "°C"],
"Noise": [100.0, "dB"],
"Geruch": ["Blumig", ""],
"timestamp": "1617142473"
}
}
Falls ein Gerät keine POSIX timestamp erstellen kann, ist es auch möglich, einen nicht parsbaren dummy-wert (oder emtpy string) zu senden, dann wird die Zeit des Emfpangs am Server als timestamp verwendet.
/api/sensorstatus/<token>Dieser Endpunkt erlaubt es Geräten, Informationen über ihren Status zu senden: Batteriestand in Prozent und Millivolt, ob ein GPS fix erfolgen konnte und ob das Gerät sich herunterfährt und damit offline geht. Der Token kann wie oben beschrieben als Teil der URL oder im Header mitgegeben werden.
Default, wenn alles gut ist, reicht folgende Nachricht aus:
{
"battery": 0.85,
"millivolt": 123.5
}
wenn die batterie niedrig ist als signal, dass die box offline geht (0 fuer false)
{
"battery": 0.05,
"millivolt": 3.5,
"online": 0
}
gleichsam das, falls es kein GPS-signal gibt:
{
"battery": 0.85,
"millivolt": 123.5,
"gps_fix": 0
}
Wenn, wie in der ersten nachricht, keine Einträge fuer gps_fix oder online mitgegeben werden, dann wird das so interpretiert, dass gps da ist und die box auch online ist.
/api/reading_points/Über diesen Endpunkt können alle Datenpunkte/Messungen die zugänglich sind als GeoJSON abgerufen werden (d.h. entweder für den:die User:in oder öffentlich wenn nicht eingeloggt). Ein Beispiel-Resultat ist folgendes:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [16.392097, 48.142757]
},
"properties": {
"Temperature (\u00b0C)": 1.88,
"Timestamp": "2020-12-01 12:52:59.115530"
}
}, {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [16.391411, 48.142502]
},
"properties": {
"Noise (dB)": 35.0,
"Timestamp": "2021-01-20 03:07:14.858159"
}
}, {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [16.391375, 48.142567]
},
"properties": {
"Noise (dB)": 35.0,
"Timestamp": "2020-10-08 00:21:24.705461"
}
}, {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [16.344713, 48.223713]
},
"properties": {
"Temperature (\u00b0C)": 1.56,
"Timestamp": "2020-12-18 21:26:05.633834"
}
}]
}
/api/reading_points/<reading name>Über diesen Pfad können die Datenpunkte nach Reading Name gefiltert werden, d.h. z.B. nur Temperature oder Noise.
/api/datasource/Über diesen Endpunkt kann eine Liste sichtbarer DataSources abgerufen werden. Die Antwort sieht so aus und ist ein Dictionary von DataSource ID und Name:
{
"1": "Sensorbox 5",
"3": "Sensorbox 6",
"5": "Sensorbox 7",
"7": "Sensorbox 1",
"10": "Sensorbox 3",
"11": "Sensorbox 8",
"14": "Sensorbox 4",
"15": "Sensorbox 2",
"16": "Sensorbox 9"
}
/api/datasource/<source_id>Mit der DataSource ID können über diesen Endpunkt alle Daten zu dieser DataSource abgerufen werden, um z.B. ein Dashboard damit zu betreiben:
{
"source_id": 3,
"source_name": "Sensorbox 6",
"description": "+436765163405; CK; v1.0",
"battery_level": null,
"battery_millivolt": null,
"gps_fix": false,
"online": false,
"reading_points": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
16.344734,
48.223747
]
},
"properties": {
"Temperature (°C)": 15.74,
"Timestamp": "2021-03-31 00:04:25.600797"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
16.344734,
48.223747
]
},
"properties": {
"Noise (dB)": 46,
"Timestamp": "2021-03-31 00:04:25.600797"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
16.344734,
48.223747
]
},
"properties": {
"Temperature (°C)": 14.78,
"Timestamp": "2021-03-31 00:24:25.738378"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
16.344734,
48.223747
]
},
"properties": {
"Noise (dB)": 48,
"Timestamp": "2021-03-31 00:24:25.738378"
}
}
]
}
}
/api/datasource/<source_id>?from=<from_date>&to=<to_date>Da die Messpunkte/Reading Points schnell sehr viele werden können ist es auch möglich, per URL-Paramtern die Reading Points der DataSource zu filtern, z.B. http://aml.media.tuwien.ac.at:11312/api/datasource/3?from=2021-03-31&to=2021-04-01. Dabei kann auch nur to oder from gesetzt sein - es müssen nicht unbedingt beide sein.
/api/ogd/api/ogd/<name>Будьте уважні! Це призведе до видалення сторінки "Home".