MP-SS15-01

Aus Verteilte Systeme - Wiki
Wechseln zu: Navigation, Suche
Sensordatenverwaltung am Beispiel von Meeressonden des Helmholtz-Zentrums Geesthacht

Durchgeführt von: Mierswa, Daniel

Organisation

Dieses Wiki dient der Dokumentation für das Master-Projekt im Sommersemester 2015, welches von Daniel Mierswa durchgeführt wird und von Herrn Prof. Dr. Kröger und Kai Beckmann betreut wird. Das Projekt richtet sich nach dem Modulhandbuch für den Studiengang M. Sc. Informatik der Hochschule RheinMain [1]. Die Bearbeitung soll insgesamt rund 450 Stunden dauern und teilt sich in folgende Teilbereiche mit entsprechender Bearbeitungszeit auf:

  • 90h Literaturstudium, Einarbeitungszeit
  • 240h Praktische Tätigkeit (Projekt, inkl. Koordination)
  • 90h Ausarbeitung und Präsentation
  • 30h Vor- und Nacharbeitung (Projekt- und Zeitmanagement)

Der tatsächliche Zeitaufwand wird im Zeitplan festgehalten und stetig aktualisiert. Wie in der Projektbeschreibung beschrieben, wird eine Sensordatenverwaltung entwickelt, die von dem Helmholtz-Zentrum Geesthacht benutzt wird.

Beschreibung des Projekts

Dieses Projekt baut auf ein vorher durchgeführtes Projekt für die HZG auf, welches ebenfalls von Daniel Mierswa durchgeführt wurde. Vor 2 Jahren wurde ein Projekt abgeschlossen, dessen Aufgabenstellung es war, Sensordaten aus dem Meer an einen stationären eingebetteten Rechner zu übertragen. Dabei wurde eine Meeressonde [2] unter Wasser getaucht und mit einem Kabel an einen Embedded System [3] angebunden. Die Sonde überträgt über serielle Kommunikation Daten an den Rechner, welcher ein Programm ausführt, um die Daten zu sammeln und in einer "Round robin"-Datenbank [4] zu speichern. Über die Webservice-Schnittstelle SOS (Sensor Observation Service) [5] werden die Daten angeboten. Das Forschungsinstitut Helmholtz-Zentrum Geesthacht (HZG) [6] nutzt diese Daten dann, um eine eigene lokale Datenbank, nach einer Qualitätskontrolle, mit aufbereiteten Daten zu füllen.

Das Master-Projekt soll die vorhandene Lösung erweitern bzw. anpassen oder erneuern, sofern dies nötig ist. Dabei soll eine Software-Architektur genutzt werden, die klar definierte Schnittstellen hat, um so in der Lage sein zu können, die einzelnen Teilsysteme zu entkoppeln. Vor allem soll es möglich sein neue Sensoren einfach an das System anzubinden und verschiedene Schnittstellen für die Sicht auf die Daten zu verwenden.

Zeitplan

Wie bereits im Kapitel Organisation beschrieben, ist ein Zeitraum zur Bearbeitung vorgesehen. Für dieses Projekt ist ein Teil davon für die interne Präsentation, Dokumentation, Reflexion, Besprechungen und Rückmeldungen an das HZG vorgesehen. Der wesentliche Teil ist für die Analyse, das Entwickeln des Designs, der Umsetzung und das Testen der Software. Im Zeitplan wird festgehalten, wie viel Zeit aufgewendet wurde und welchem Bereich dieser Zeitaufwand zugeordnet wird. Die genaue Auflistung befindet sich auf der Zeitaufwand-Unterseite.

Der Abschluss der Lehrveranstaltung erfolgt am 03.09.2015 mit einer Abnahme an der Hochschule RheinMain. Dazu wird eine Abschluss-Präsentation gehalten und anschließend eine Demonstration der Funktionalität der Software vorgeführt. Am 01.09.2015 muss die Dokumentation im Wiki abgeschlossen sein. Da es durchaus vorkommen kann, dass das Deployment der Software seitens des HZG deutlich hinter dem Ende der Lehrveranstaltung stattfinden kann, können zusätzliche Funktionalität der Software zu einem späteren Zeitpunkt hinzugefügt werden oder Teile optimiert werden. Es ist geplant, zu einem späteren Zeitpunkt eine Abnahme der Software am HZG durchzuführen.

Protokolle für Rücksprachen und Meetings

In der Hochschule findet in der Regel wöchentlich eine Besprechung statt. Mit dem HZG finden gelegentlich Rücksprachen, in Form von Videokonferenzen oder Meetings statt. In diesem Abschnitt werden relevante Einzelheiten aus den Besprechungen protokolliert.

1. Videokonferenz mit dem HZG (20.04.2015)

E-Mail des HZG

Kurze Zeit vor der Konferenz wurde vom HZG (Herrn Breitbach) eine E-Mail an die Beteiligten des Projekts geschickt, in der eine grobe Übersicht über die Anforderungen an die Software, die entwickelt wird, aufgezeigt wurde.

1. Auslesen der Daten aus einer virtuellen seriellen Schnittstelle
2. Speichern der Rohdaten als 10-Minuten Mittelwert, so wie der statistischen Informationen wie
   Min/Max, Zahl der Einzelmessungen, Standardabweichung. Diese Speicherung soll in einer lokalen
   Datenbank erfolgen.
3. Hier eine Ergänzung: Die Daten sollen zusätzlich in voller Auflösung als Datei gespeichert, die jeden Monat neu
   erzeugt wird.
4. Speichern der kalibrierten Daten inklusive Statistik, in der lokalen Datenbank.
5. Bereitstellen aller in der lokalen Datenbank gespeicherten Daten über das SOS Protokoll.
6. Herstellung der SOS Version 2 Kompatibilität
7. Zusätzliche Übertragung der Daten aus der lokalen Datenbank über einen HTTP GET-Aufruf, der an einen
   Server des HZG gesendet wird.
8. Steuerungsmöglichkeiten für das ganze System

Einiges davon kann man von der bisherigen Software übernehmen.
Die Herstellung der Standard Kompatibilität wäre neu und etwas aufwändiger. Außerdem könnte man
diese Software als Basis für das ADCP Projekt besser verwenden.

Basierend auf dieser E-Mail wurden die einzelnen Punkte kurz besprochen.

1.) Die Daten werden mit der seriellen Schnittstelle mit einem entsprechenden Protokoll ausgelesen. Die serielle Schnittstelle kann dabei virtuell sein (Anm.: Im vorhergehendem Projekt waren die Sonden an einem Hub angeschlossen und man konnte auf dem Hub über eine serielle Schnittstelle zugreifen.)

2.) Im Gegensatz zum vorherigen Projekt (Anm.: Speichern von verarbeiteten Werten in sehr kurzen Abständen.) sollen ein Mittelwert der Rohdaten, so wie sie von der Sonde übertragen werden, alle 10 Minuten gespeichert werden. Zusätzlich sollen Zusatzinformationen gespeichert werden (siehe E-Mail).

3.) Über einen vollen Monat hinweg sollen die Rohdaten ebenfalls in voller Auflösung (Anm.: Es wurde der eine Auflösung von 10 Sekunden vorgeschlagen.) in einer zusätzlichen Datei in einem bestimmten Format (Anm.: Vorgeschlagen wurde CSV.) gespeichert werden.

4.) Die kalibrierten Daten (Anm.: Genaue die Daten, die im Projekt, welches bereits für das HZG durchgeführt wurde, gespeichert wurden.) werden ebenfalls mit der gleichen Statistik wie in 2.) in einer Datenbank gespeichert.

5.) Das SOS-Protokoll dient als Schnittstelle zum Zugriff auf die Daten. Dafür werden die Dienste GetObservation, DescribeSensor und GetCapabilities benötigt.

6.) Es soll für den Zugriff über den SOS Webservice (siehe 5.) das SOS-Protokoll 2.0 verwendet werden. Das HZG will in der Lage sein, für (möglicherweise nicht linear zusammenhängende) Zeiträume Blöcke von Daten zu erhalten (Anm.: Filter-Funktionen des Protokolls.).

7.) Zusätzlich zu dem Webservice, soll optional eine URL zur Verfügung stehen, welches entsprechend der Anfrage ein einzelnes Datum liefert. Der Aufbau des Aufrufs wurde noch nicht weiter beschrieben.

8.) Im Gegensatz zu den Steuerungsmöglichkeiten, die es im vorherigen Projekt gab (Anm.: Kalibrierung der Sonde über Hochladen einer Konfigurationsdatei, Netzwerkeinstellungen, Systemlog-Überwachungen, Reboot ...) sollen zunächst nur rudimentäre Steuerungsmöglichkeiten zur Verfügung stehen, da die entwickelte Software auf einem handelsüblichen PC läuft, auf dem sowohl lokal als auch entfernt zugegriffen werden kann.

Anmerkung) Das HZG möchte in Zukunft ein größeres Projekt durchführen (Anm.: ADCP-Projekt). Das Master-Projekt kann als Einstieg in das Projekt dienen oder darin verwendet werden. Daher wird eine Softwarelösung angestrebt, die als Framework dient.

Weitere Anmerkungen zur Konferenz

Das HZG steht im engen Kontakt mit der Firma 52° North [7] (insbesondere Herrn Jirka [8]), die Hilfestellungen oder Anregungen, bei der Verwendung von SOS 2.0 und/oder SensorML geben kann.

Da die anfallende Datenmenge bei den Messungen überschaubar ist, kann eine SQL-Datenbank verwendet werden. Dies hat zum Vorteil, dass es Standard-Abfragesprachen gibt und sie bei Bedarf auch HZG-intern verwendet werden kann. Für die Literaturarbeit im Rahmen des Master-Projekts können verschiedene Datenbanktechnologien zur Speicherung von großen Mengen von Sensordaten betrachtet und auf Merkmale, sowie Vor- und Nachteile gegenüber SQL-Datenbanken untersucht werden.

Da das HZG intern ein Mapping von Sensor-Metadaten auf Climate and Forest Standard-Metadaten [9] durchführt, soll geprüft werden, ob in SensorML eine Möglichkeit besteht, alternative Namen für Sensoren anzugeben.

Es können beliebige vorhandene Softwarelösungen (Bibliotheken, Implementierung, usw.) genutzt werden, solange sie quelloffen sind. Die Software selbst wird mit Java programmiert. Sie wird auf einem Linux-System in einer virtuellen Maschine ausgeführt (Anm.: Der Java-Compiler wird auf dem System zur Verfügung stehen. Es ist also kein Cross-Compiling nötig.).

Es wird ein Treffen beim HZG stattfinden. Das Treffen soll am Freitag, den 29.05.2015 entweder direkt beim HZG oder im Chilehaus Hamburg stattfinden. Bis dahin soll ein Grobentwurf (Anm.: Anlehnung an Pflichtenheft.) entworfen werden. Die genaue Agenda wird noch besprochen.

Das nächste Treffen in der Hochschule Rhein-Main mit den Betreuern des Projekts soll am 28.04., sowie den 19.05., jeweils um 9:30 Uhr stattfinden.

Meeting mit HZG (29.05.2015)

In diesem Meeting wurde das Lastenheft, welches vorher erstellt wurde, besprochen. Es gab eine mündliche Diskussion über die Anforderungen an die Software. Für eine Diskussionsgrundlage für das Meeting wurde das Lastenheft und ein Grobentwurf erstellt. Verschiedene Personen, die im Projekt involviert sind, haben dieses dann im Meeting mit den Beratern und dem Durchführenden diskutiert. Im Anschluss an das Meeting wurde das Lastenheft entsprechend abgeändert und der Entwurf verfeinert. Daraufhin konnte die eigentliche Konzeption beginnen.

2. Videokonferenz mit dem HZG (24.07.2015)

Um einen Überblick über den aktuellen Stand der Software zu gewinnen, gab es eine 2. Videokonferenz. An dieser Videokonferenz nahmen die Berater, Betreuer und der Durchführende des Projekts teil. In dieser Videokonferenz wurden offene Fragen geklärt und der aktuelle Stand des Projekts präsentiert. Insbesondere wurde das Datenmodell überarbeitet, da es dort Unstimmigkeiten bzgl. der Terminologie gab. Diese Überarbeitung war dann die Basis für die Änderungen, die an den DataAccessObjects der 52° North SOS-Implementierung vorgenommen werden mussten. Herr Breitbach gab bekannt, dass es evtl. eine Testumgebung für das Projekt aufgesetzt werden kann, so dass an einer Meeressonde, die in Betrieb ist, Daten abgefangen und dort gespeichert werden können.

Das überarbeitete Datenmodell sorgt dafür, dass im Editor Begriffe und Eingabemasken bearbeitet werden müssen. Der Editor wird in der folgenden Woche fertiggestellt und Herrn Breitbach zugeschickt. Die SOS-Implementierung wird bis spät. Mitte August fertiggestellt sein und kann von Herrn Breitbach getestet werden. Um eine lauffähige SOS-Implementierung anzubieten wird eine virtuelle Maschine in der Hochschule installiert.

Anforderungen

Eine grobe Übersicht über die Anforderungen seitens des HZG wurde in einer E-Mail mitgeteilt. Für das erste Treffen mit dem HZG wird ein Lastenheft erstellt, so dass das HZG dieses mit den eigenen Anforderungen abgleichen kann und somit eine genaue Spezifizierung für die Software geschrieben werden kann.

Produktübersicht

Produktübersicht

Mithilfe der Anforderungen lässt sich eine Produktübersicht darstellen. In der Produktübersicht wird deutlich, wo sich die zu entwickelnde Software befindet. Es gibt vom HZG Meeressonden gibt, die in Küstennähe oder auch weiter entfernt mit einer Reihe von Sensoren Messungen durchführen. Diese Meeressonden sind dann mit einer Station, in der die Laufzeitumgebung der zu entwickelnden Anwendung liegt, über ein Kabel verbunden (dies kann z.B. ein Gebäude am Strand sein). Dort werden die Datenströme der Sonden gebündelt (Multiplexing) und können so auf virtuelle serielle Schnittstellen in der Laufzeitumgebung verteilt werden (z.B. an virtuelle Maschinen). Jeder serielle Port bekommt dann den Datenstrom einer einzelnen Meeressonde.

Die Anwendung, die zu entwickeln ist, wird im folgenden DVSM (Datenverwaltung von Sensor-Messwerten) genannt. Die DVSM verbindet sich dann im Collector mit einem seriellen Endpunkt der virtuellen Maschine und kann dann den Datenstrom einer Meeressonde lesen. Anhand der Konfiguration (Datenbank-Einträge), weiß die DVSM, wie der Datenstrom zu dekodieren ist und erhält aus dem Datenstrom Rohwerte der Sensoren. Mit Formeln werden die Rohwerte in kalibrierte Werte umgewandelt. Die Formeln selbst werden in Code formuliert, der von den eigentlichen Programmen ausgegrenzt wird, da dieser vom HZG selbst geschrieben wird und dann mit einem Compiler übersetzt wird. Dieser übersetzte Code muss dann von der DVSM eingebunden werden und vom Collector aufgerufen werden.

Anwendungsfälle und Produktfunktionen

Im Meeting mit dem HZG wurden Anwendungsfälle diskutiert und daraus Minimalanforderungen an die DVSM herausgearbeitet. Das Lastenheft wurde im Anschluss an das Meeting fertiggestellt. Bei der Auflistung der Funktionen im Lastenheft wurden Funktionen in Gruppen eingeteilt. Anhand der Produktfunktionen konnte man ableiten, was analysiert werden muss, um die Software zu entwickeln. Es folgt ein Auszug der Produktfunktionen:

  • Verbindungen verwalten
    • [LF0110] Nutzung einer seriellen Verbindung
    • [LF0120] Konfiguration der seriellen Verbindung mit Datei
    • [LF0130] Erneuter Aufbau der Verbindung bei Abbruch
    • [LF0140] Kommunikation mit einer oder mehreren Meeressonden
  • Daten einlesen
    • [LF0210] Verarbeiten von Datenströmen aus Meeressonden
    • [LF0220] Implementierung der Übertragungsprotokolle der Meeressonden
    • [LF0230] Keine Verarbeitung bei Verbindungs- oder Verarbeitungsfehler
  • Daten verarbeiten
    • [LF0310] Rohdaten aus Datenstrom extrahieren
    • [LF0320] Rohdaten kalibrieren
  • Daten speichern
    • [LF0410] Kalibrierten Daten in lokaler DB speichern
    • [LF0420] Rohdaten in lokaler DB speichern
    • [LF0420] Feinstmögliche Auflösung für die Daten in LF0410 und LF0420
    • [LF0440] Rohdaten werden zusätzlich in CSV Datei gepeichert
    • [LF0441] Nach einem Monat wird die CSV Datei (LF0440) erneuert
  • Daten bereitstellen
    • [LF0510] Rohdaten und kalibrierte Daten über SOS 2.0 anbieten
    • [LF0511] Dokument-Validierung
    • [LF052*,LF053*,LF054*,LF055*,LF056*] GetObservation für Rohdaten und kalibrierte Daten
    • [LF0570] DescribeSensor für Anforderungen der Metadaten
    • [LF0580] GetCapabilities für Abfrage der SOS-Implementierung
    • [LF0590] Übertragung der kalibrierten Daten mit Statistiken über HTTP-GET an HZG
  • System konfigurieren, überwachen und neustarten
    • [LF0610] Direkte Eingriffe in der Laufzeitumgebung zur Konfiguration
    • [LF0620] Metadaten der Meeressonden über GUI pflegen
    • [LF0630] Kalibrierung der Sensoren der Meeressonden über GUI
    • [LF0640] Statusmeldungen in System-Log
    • [LF0650] Reagieren auf externe Ereignisse, die das System neustarten
    • [LF0660] Konfigurierbares Zeitintervall für GetObservation (LF05**)


Analyse

Die Software unterteilt sich in 4 Bereiche:

  • Einlesen, Verarbeiten und Speichern der Daten
  • Übertragen der Daten inklusive Statistiken über HTTP GET
  • Anbieten der Daten über SOS
  • Editieren der Metadaten

Die Komponenten, die diese Bereiche abdecken, werden im folgenden Collector, Sender, SOS und Editor genannt.

Daten der Messsensoren auslesen, verarbeiten und speichern

Im Vorgängerprojekt wurde das Auslesen und Verarbeiten der Messsensoren in einer Collector-Komponente zusammengefasst. Diese wurde in einem C daemon realisiert und kann hier nicht wieder verwendet werden, da das Projekt in Java realisiert wird. Der Collector muss sich mit der seriellen Schnittstelle verbinden und die Daten der Messsensoren kontinuierlich auslesen. Ist dann ein valides Datum angefallen, so muss geprüft werden, welcher Sensor der Sonde dieses Datum geschickt hat und speichert dieses Datum (Rohwert) zusammen mit einem Zeitstempel ab. Diese Rohwerte sind Integers und dimensionslos. Sie werden deshalb mit einer Verarbeitungsvorschrift (Formel) in einen Messwert (mit entsprechender Einheit) umgewandelt. Die Formeln werden in den Handbüchern der Messsensoren beschrieben. In diesem Formeln werden in der Regel Kalibrierungskonstanten benutzt, die sich über lange Zeit aufgrund der Eigenschaften der Sensoren ändern können. Es muss eine Lösung entwickelt werden, die es erlaubt, diese Konstanten zu ändern und verwenden, ohne den Quellcode neu zu übersetzen. Der Collector ist eine Komponente, die schreibend auf die Laufzeitumgebung wirkt, und muss deshalb entsprechende Status- und insbesondere Fehlermeldung leicht erkennbar machen.

Abrufen von Rohwerten

Die Meeressonde übermittelt Daten über die serielle Schnittstelle. Das Projekt soll in Java realisiert werden. Für Java gibt es mehrere Bibliotheken, die es ermöglichen, Daten über die serielle Schnittstelle auszulesen. Zwei häufig benutzte OpenSource-Bibliotheken (LGPL lizenziert) sind unter anderem:

  • RXTX [10]
  • Java Simple Serial Connector [11]

Beide Bibliotheken abstrahieren die vom Betriebssystem abhängigen Treiber in entsprechenden dynamisch ladbaren Bibliotheken, die bereits in einem Java-Archiv vorhanden sind. Die API der beiden Bibliotheken unterscheiden sich minimal. Da auf Standard Ubuntu- und Debian-Installationen RXTX als Paket angeboten wird, wurde diese Bibliothek verwendet.

Der Datenstrom der Meeressonde enthält ein Muster. Anhand diesem Muster ist es möglich zu prüfen, wo ein Datum beginnt und wo es aufhört. In der Anleitung einer Meeressonde werden diese Muster z.B. HIHILOW, LOWHILOW, usw. genannt. Um ein Datum zu extrahieren, müssen die jeweils letzten Bits von einem Bytestrom aus 3 Bytes ausgelesen werden. Das HIHILOW-Protokoll hat wahrscheinlich dann ein korrektes Datum, wenn ein Byte mit dem 1-Bit endet, das folgende ebenfalls und das letzte mit 0 endet. Ob das Datum tatsächlich korrekt ist, hängt davon ab, ob die Daten korrekt übertragen werden. In den ersten 5 Bits des letzten Bytes ist die Adresse kodiert. Die übrigen 16 Bit kodieren das eigentliche Integer-Datum (Rohwert). Der vorzeichenlose Wertebereich für eine Adresse ist demnach 0-254 und für ein Rohwert 0-65535. Anhand der Adresse kann im Handbuch der Sonde nachgeschaut werden, welcher Sensor diesen Wert liefert.

Verarbeitung der Rohwerte in Messwerte

Die Rohwerte der Messsensoren müssen nach dem Auslesen so verarbeitet werden, dass Messwerte entstehen. Die Formeln, die aus dem Handbuch der Sonde entnommen werden können, enthalten in der Regel einfache mathematische Operationen:

return (((((koeffizient5) *

     rohwert + koeffizient4) *
     rohwert + koeffizient3) *
     rohwert + koeffizient2) *
     rohwert + koeffizient1)

Die Koeffizienten sind Fließkommazahlen, wodurch das Resultat der Operation ein Fließkomma-Messwert ist. Sie liegen in einem Kalibrierungsdokument digital und ausgedruckt der Meeressonde bei. Damit man den Quellcode nicht neu kompilieren muss, sobald man die Koeffizienten ändert, könnte man die Formeln in der Datenbank ablegen und die Evaluation zur Laufzeit vornehmen, sobald ein Rohwert anfällt. Diese Formel wäre dann in einem Format, welches zur Laufzeit von einem Evaluator interpretiert wird. Ebenfalls wäre es möglich, nur die Formel-Werte (Koeffizienten) aus der Datenbank auszulesen und diese dann als Methoden-Parameter an vorgefertigte Methoden in kompilierten Klassen zu übergeben. Die Klassennamen für die entsprechende Formel ist dann in der Datenbank abzulegen. Die Klassen werden dann vom Collector zur Laufzeit geladen. Eine weitere Alternative für dieses Szenario ist das Schreiben von Templates, die dann mit den entsprechenden Werten für die Formel befüllt werden und "just in time" kompiliert und vom Collector verwendet werden. Ein Vorteil diesre Alternative ist, dass man die Klassen und Methoden nicht mehr selbst schreiben und kompilieren muss und diesen Teil damit vom Betreuer der Software abstrahiert. Hier gälte es zu untersuchen, wie Compiler-Fehler bekannt gemacht werden und ob weitere Zugriffsrechte für die Applikation benötigt werden. Es wird für die Konzeption die Alternative verwendet, die die Formeln in Methoden ausgrenzt. Für eine Weiterentwicklung kann dann eine Erweiterung auf Templates angestrebt werden.

Weiterhin müssen Statistiken generiert werden. Eine Möglichkeit, die Statistiken für den Messzeitraum zu ermitteln, ist die Nutzung der Funktionen des DBMS (PostgreSQL). Mit entsprechend komplexen Queries (Joins und PostgreSQL-Windows) kann PostgreSQL alle angeforderten Werte in einer Abfrage realisieren. Da die Statistiken jedoch in der Datenbank hinterlegt werden, kann auf die Verwendung der Funktionen verzichtet werden und stattdessen die Generierung der Statistiken direkt im Collector durchgeführt werden. Dazu kann das DescriptiveStatistics-Modul der Apache Commons Math3 Bibliothek [12] verwendet werden.

Speichern der Messwerte

Im vorherigen Projekt wurde eine "round robin"-Datenbank verwendet. Das Arbeiten mit dieser Datenbank hat sich am Ende eher als problematisch dargestellt. Die Administration der Datenbank musste in der Laufzeitumgebung selbst vorgenommen werden und die angebotene Funktionalität war oft unzureichend. Für dieses Projekt wird eine SQL-Datenbank genutzt, da diese gängier ist und die Administration und Wartung von Betreuern der Software mit einer Reihe von Software und einer standardisierten Abfragesprache möglich ist. Es wird PostgreSQL eingesetzt, da bei der Recherche festgestellt wurde, dass dieses DBMS in Anwendungen im Bereich Sensordaten, häufig verwendet wird.

Es gilt zunächst zu prüfen, welchen Speicherbedarf die Daten benötigen. Dies ist abhängig davon, welches DBMS verwendet wird und wie die Daten modelliert werden. Wie oft ein Rohwert eines einzigen Sensors im Datenstrom erscheint, hängt vom Sensor selbst ab.

Ein Beispiel: In einem Datenstrom einer Meeressonde, der im Jahre 2013 aufgezeichnet wurde, wurden ungefähr 4-6 Messwerte pro Sekunde übertragen.

Dies hat zur Folge, dass auf einen Zeitraum von einem Jahr ungefähr 157680000 Rohwerte für einen Sensor übertragen werden. Da alle Rohwerte und Messwerte in vollster Auflösung gespeichert werden, sollte der Overhead durch zusätzlichen Daten beim Speichern eines Roh- und Messwertes vermieden werden. PostgreSQL benötigt im Schnitt durch verschiedene Zusatzdaten in einer Zeile pro Messwert ~55 Byte und pro Rohwert ~50 Byte. Diese Zeile enthält einen Primary Key (8 Byte), den Messwert (8 Byte für einen Messwert, 4 Byte für einen Rohwert) und einen Zeitstempel (8 Byte). Demnach müsste der optimale Bedarf einer Zeile maximal 24 Byte sein (kein Padding). Der weitere Overhead von ~30 Byte ist spezifisch für PostgreSQL und kann nicht verringert werden. Hinzu kommt, dass statistischen Daten (Minimum, Maximum, Standardabweichung, Median und Durchschnitt) auch in der Datenbank gespeichert werden sollen. Diese Daten fallen jedoch nur einmal in einem bestimmten Zeitfenster (z.B. alle 10 Minuten) an und haben sehr geringe Auswirkungen auf den Speicherbedarf und werden somit nicht in die folgende Berechnung mit einbezogen. Der Speicherbedarf der CSV-Dateien hängt davon ab, wie viele Ziffern im Messwert relevant sind bzw. wie die Fließkommazahl repräsentiert wird, da die Daten als Zeichenketten gespeichert werden. Die CSV-Datei speichert den Zeitstempel und danach das Datum. Im Header der Datei wird beschrieben, welcher Sensor an welcher Sonde diese Daten generiert hat. In einem Test-Durchlauf wurde ermittelt, dass die größte CSV-Datei für eine Zeile ungefähr 40 Byte und die kleinste (für Rohwerte) 20 Byte Speicherbedarf benötigt.

Der minimale Speicherbedarf für Daten einer Meeressonde mit 10 Sensoren in einem Jahr würde sich also wie folgt berechnen:

  157680000 (Werte pro Sensor) * 10 (Sensoren) * 55 Byte (Messwert)
+ 157680000 (Werte pro Sensor) * 10 (Sensoren) * 50 Byte (Rohwert)
= ~154 GB
  157680000 (Werte pro Sensor) * 10 (Sensoren) * 40 Byte (CSV-Datei für Messwerte)
+ 157680000 (Werte pro Sensor) * 10 (Sensoren) * 20 Byte (CSV-Datei für Rohwerte)
= ~88 GB
----------
  242 GB

Da die Ziel-Laufzeitumgebungen in der Regel mit Festplatten von einer Kapazität weit über diesem Wert ausgestattet sind, erzeugt das Speichern der Daten keine weiteren Probleme.

Der Speicherort der CSV-Datei wird in der Konfigurationsdatei des Systems festgelegt. Der Aufbau der CSV-Datei ist hard-kodiert. Für einen zukünftigen Ausbau der Software könnte hier ein Template verwenden werden, welches dann mit den Daten aus der Datenbank befüllt wird. Trifft ein Datum ein, welches in einer CSV-Datei gespeichert werden muss, so wird geprüft, in welchem Monat sich die Laufzeitumgebung befindet. Dann wird die Datei namens "<Speicherort>/<Sensor name>_<ObservedPropertyInstance name>_<Month>.csv" geöffnet. In dieser Datei wird nur der Zeitstempel und das Datum gespeichert. Läuft der Collector über eine Monatsgrenze hinweg, so wird eine neue Datei erstellt, sobald ein Datum eintrifft, welches nicht mit dem Monat übereinstimmt, für welchen die CSV-Datei geöffnet wurde.

In objektorientierten Programmiersprachen ist es üblich, die Objekte aus den Datenbank-Tabellen abzuleiten und zu befüllen. Das Hibernate-Framework wird verwendet, um dies automatisiert zu ermöglichen. Im Programmcode kann man Java-Objekte benutzen, die vom Hibernate-Framework aus den Tabellen des DBMS generiert werden und umgekehrt die Daten in das DBMS persistieren. Das Hibernate-Framework bietet Sessions an, die wie Caches agieren. Man speichert die Daten in einem Cache, bis sie auf das Speichermedium übertragen werden. Dies kann entweder durch das Beenden einer Transaktion passieren, in einem Intervall oder manuell. Da bei der Speicherung eine hohe Anzahl von Messwerten in geringen Zeitabständen erwartet wird, ist das Nutzen von Transaktionen mit einem starken Overhead verbunden und würde so die Performance stark beeinträchtigen. Stattdessen werden die Sessions, in einem Zeitintervall Sekunden-Zeitintervall, manuell auf das Speichermedium übertragen (geflushed). Damit beschränkt sich der Datenverlust bei einem I/O-Fehler auf maximal dieses Zeitintervall.

Übertragung der kalibrierten Daten mit Statistiken

Es werden Statistiken für Messwerte, die in einem bestimmten Zeitfenster erfasst werden, generiert. Diese Statistiken werden an einen Webserver mit einem HTTP GET-Aufruf gesendet. Die Werte werden im Query-String hinterlegt. Es wird der kleinste/größte Messwert, sowie Median/Mittelwert, Standardabweichung und die Anzahl der Messwerte in diesem Zeitraum übertragen. Ebenfalls muss ein Zeitstempel in einem bestimmten Format übertragen werden. Dazu kann entweder der letzte erhobene Messwert oder die aktuelle Systemzeit der Laufzeitumgebung verwendet werden. Beim Abfangen des HTTP GET-Aufrufs auf der Empfängerseite wird geprüft, ob für diesen Zeitstempel bereits Daten eingetragen wurden und weist neue Daten ab, falls der Zeitstempel nicht aktueller ist. Da für den Aufruf evtl. eine Authentifizierung (Basic Auth) notwendig ist oder die Laufzeitumgebung einen Proxy benutzt, sollten diese unterstützt werden.

OGC-Standards

Die SOS- und SensorML-Standards werden vom Open Geospatial Consortium (OGC) veröffentlicht und ähneln anderen XML-Standards, in denen zunächst die Datenmodelle anhand von UML-Diagrammen beschrieben werden und dann eine XML-Abbildung vorgestellt wird. Es gibt in den OGC-Standards sehr viele Kreuzverweise auf andere Standards, die ähnliche Aufgabengebiete abdecken. Folglich werden nur relevante Teile des Standards aufgezeigt und speziell jene Details herausgearbeitet, die für die Anforderungen benötigt werden.

Sensor Model Language (SensorML)

Beschreibung

Für die Beschreibung der Sensoren, sowie der akzeptierten Eingaben und produzierten Ausgaben der Sensoren, die im Projekt unterstützt werden, kann eine bereits zur Verfügung stehende Modellierungssprache benutzt werden. SensorML [13] ist ein Standard des Open Geospatial Consortium (OGC), um Messungen, sowie Prozesse und Komponenten, die daran beteiligt sind, zu beschreiben. Der Standard existiert in 2 Versionen, Version 2.0 [14] und Version 1.0 [15]. Für SensorML 1.0 gibt es ein Corrigendum, wodurch ein weiterer Sub-Standard SensorML 1.0.1 spezifiziert wird [16]. Es wird im Standard zunächst ein konzeptionelles Modell mittels UML beschrieben. Es können folgende wesentliche beteiligte Elemente beschrieben werden:

  • Komponente
  • System
  • Prozess
  • Prozesskette

Alle Komponenten werden als abstrakte Prozesse modelliert, die Eingaben erhalten und unter Verwendung von Algorithmen, die mit einer Methode und festgesetzten Werten definiert werden, Ausgaben generieren. Anhand des UML-Modells sind automatisch XML-Schemata generiert, die dieses Modell umsetzen. Die Schemata [17] stehen zur Validierung zur Verfügung. Die XML-Kodierung dient der eindeutigen Syntax, die von verschiedenen Rechensystemen benutzt werden kann.

SensorML kann zwar zwischen Komponenten und Systemen unterscheiden, legt sich aber nicht fest, was genau ein System oder eine Komponente ist. Demnach gibt es mehrere Sichtweisen auf die Modellierung (z.B. einer Meeressonde):

  • Sonde (PhysicalSystem), Messsensor der Sonde (Komponente)
  • Sonde (Komponente), Messsensor der Sonde (Eigenschaft)

Für eigene Anwendungsfälle sind Erweiterungen an bestimmten Stellen in der XML-Instanz vorgesehen. Es wird in einer Instanz auf folgende Ontologien verwiesen:

  • General sensor community [18]
  • OGC [19]
  • Semantic Web for Earth and Environmental Terminology (SWEET) [20]
  • Marine Metadata Interoperability (MMI) [21]

Beispiele (Ausschnitte)

Es folgen einige Beispiele, die Ausschnitte aus XML-Instanzen zeigen, die der SensorML 2.0 Spezifikation genügen.

Ein Auszug aus dem Beispiel zur Beschreibung einer Wetterstation mit SensorML 2.0 [22]:

[...]
    <sml:inputs>
        <sml:InputList>
            <sml:input name="temperature">
                <sml:ObservableProperty definition="http://sweet.jpl.nasa.gov/2.3/propTemperature.owl#Temperature"/>
            </sml:input>
            <sml:input name="wind">
                <sml:ObservableProperty definition="http://sweet.jpl.nasa.gov/2.3/phenAtmoWind.owl#Wind"/>
            </sml:input>
        </sml:InputList>
    </sml:inputs>
[...]
   <sml:outputs>
      <sml:OutputList>
         <sml:output name="weather">
            <swe:DataRecord>
               <swe:field name="temperature">
                  <swe:Quantity definition="http://sensorml.com/ont/swe/property/AtmosphericTemperature">
                     <swe:label>Air Temperature</swe:label>
                     <swe:uom code="cel"/>
                  </swe:Quantity>
               </swe:field>
               <swe:field name="wind_chill">
                  <swe:Quantity definition="http://sensorml.com/ont/swe/property/WindChillFactor">
                     <swe:label>Wind Chill Factor</swe:label>
                     <swe:uom code="cel"/>
                  </swe:Quantity>
               </swe:field>
               <swe:field name="wind_speed">
                  <swe:Quantity definition="http://sensorml.com/ont/swe/property/WindSpeed">
                     <swe:label>Wind Speed</swe:label>
                     <swe:uom code="km/h"/>
                  </swe:Quantity>
               </swe:field>
               <swe:field name="wind_direction">
                  <swe:Quantity definition="http://sensorml.com/ont/swe/property/WindDirection">
                     <swe:label>Wind Direction</swe:label>
                     <swe:uom code="deg"/>
                  </swe:Quantity>
               </swe:field>
            </swe:DataRecord>
         </sml:output>
      </sml:OutputList>
   </sml:outputs>
[...]
   <sml:components>
      <sml:ComponentList>
         <sml:component name="thermometer" xlink:title="urn:davis:sensors:7817"
            xlink:href="http://www.sensorml.com/sensorML-2.0/examples/xml/Davis_7817.xml"/>
         <sml:component name="anemometer" xlink:title="urn:davis:sensors:barometer_internal"
            xlink:href="http://www.sensorml.com/sensorML-2.0/examples/xml/Davis_7911.xml"/>
          <sml:component name="windchill" xlink:title="urn:ogc:process:windchill-02"
            xlink:href="http://www.sensorml.com/sensorML-2.0/examples/xml/windchill-02.xml"/>
      </sml:ComponentList>
   </sml:components>
[...]
   <sml:connections>
      <sml:ConnectionList>
         <!-- connection between thermometer's output and system's temperature output -->
         <sml:connection>
            <sml:Link>
               <sml:source ref="components/thermometer/outputs/temperature"/>
               <sml:destination ref="outputs/weather/temperature"/>
            </sml:Link>
         </sml:connection>
[...]
      </sml:ConnectionList>
   </sml:connections>
[...]

Ein Auszug aus dem Beispiel zur Beschreibung eines einzelnen Sensors in SensorML 2.0 [23]:

[...]
   <sml:outputs>
      <sml:OutputList>
         <sml:output name="temp">
            <sml:DataInterface>
               <sml:data>
                  <swe:DataStream>
                      <!-- describe output -->
                     <swe:elementType name="temperature">
                         <swe:Quantity
                                definition="http://mmisw.org/ont/cf/parameter/air_temperature">
                             <swe:uom code="Cel"/>
                         </swe:Quantity>
                     </swe:elementType>
 
                     <!-- simple text encoding  -->
                     <swe:encoding>
                        <swe:TextEncoding tokenSeparator="," blockSeparator=" "/>
                     </swe:encoding>
                      
                     <!-- reference the values at a RESTful resource -->
                     <!-- returns latest measurement or continues to send new values through open http pipe -->
                     <swe:values xlink:href="http://myServer.com:4563/sensor/02080"/>
 
                  </swe:DataStream>
               </sml:data>
             </sml:DataInterface>
         </sml:output>
      </sml:OutputList>
   </sml:outputs>
[...]
   <sml:position>
      <gml:Point gml:id="stationLocation" srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
         <gml:coordinates>47.8 88.56</gml:coordinates>
      </gml:Point>
   </sml:position>
[...]

Die URL in swe:values liefert dann einen Block von Daten.

Sensor Observation Service (SOS)

SOS [24] ist ein weiterer Standard (so wie SensorML) aus der Familie des OGC Sensor Web Enablement framework (SWE). In diesem Standard wird eine Schnittstelle definiert, die einen standardisierten Zugriff auf Beschreibungen und Messwerte von Sensoren ermöglicht. Es existieren 2 Versionen, Version 1.0 [25] und Version 2.0 [26]. Der Standard in Version 2.0 ist nicht abwärtskompatibel zur Version 1.0. Für die Kodierung der Sensor-Messwerte wird der OGC Observations & Measurements Standard [27] benutzt. Der Standard liegt derzeit in Version 2.0 [28] vor. Im Abschnitt SensorML wird der Standard beschrieben, der zur Kodierung der Beschreibungsdaten für Sensoren genutzt wird.

Im Standard wird zusätzlich ein SOAP- und HTTP KVP (Key/Value Pair)- Binding für einen WebService beschrieben. Die generierten XML-Schemata aus den konzeptuellen Modellen des Standards können jedoch auch für eigene bzw. zukünftige Bindings mit REST(ful) oder POX (Plain Old XML) over HTTP verwendet werden.

Den Kern der SOS-Funktionalität bieten die folgenden 3 Operationen:

  • GetCapabilities
    • Stellt Zugriff auf Metadaten und detaillierte Informationen über die Operationen eines SOS-Servers bereit.
      • Der Aufruf wird in Kapitel 7 der OGC Web Services Common Specification [29] definiert
      • Die Antwort enthält einen Datentyp Capabilities, welcher vom Datentyp OWS Common OWSServiceMetadata (Kapitel 7.4.2 der gleichen Spezifikation) abgeleitet wird und im SOS 2.0 Standard entsprechend erweitert wird.
  • DescribeSensor
    • Für das Abfragen der Metadaten von Sensoren oder Systemen des SOS-Servers.
      • Die gesamte Operation wird in Kapitel 11 des OpenGIS SWE Service Model [30] definiert.
      • Zusätzlich verlangt SOS, dass der Wert des service Parameter die Zeichenkette "SOS" und der Wert des version Parameter die Zeichenkette "2.0.0" ist.
  • GetObservation
    • Stellt Zugriff auf Aufzeichnung der Systeme bereit und erlaubt räumliche, themenbasiert und zeitliche Filterung.
      • Der Aufruf enthält einen Datentyp GetObservation, welcher vom Datentyp SWES Common ExtensibleRequest [31]) abgeleitet wird und im SOS 2.0 Standard entsprechend erweitert wird.
      • Die Antwort soll entsprechend des responseFormat Parameters zurückgeliefert werden. Falls kein solcher Parameter im Aufruf existiert, wird standardmäßig ein Datentyp aus Geographic Information - Observation and measurements O & M 2.0 [32] zurückgeliefert.

Der Standard stellt Erweiterungen zur Verfügung, darunter weitere Operationen, Unterstützung für Transaktionen und Alternativen zur Abfrage und dem Hinzufügen von Messwerten. Die Operation zum Hinzufügen von Daten über die SOS-Schnittstelle wird nicht benötigt, da die Messdaten über eine andere Schnittstelle direkt in die Datenbank eingetragen werden. Ebenso sind die anderen Erweiterungen für das Projekt nicht weiter relevant und werden deshalb nicht weiter betrachtet.

Im Standard werden Beispiele für den Aufbau der Kernoperationen im SOAP Binding gezeigt:

  • GetCapabilities
  • DescribeSensor
<swes:DescribeSensorResponse
  xmlns:swes="http://www.opengis.net/swes/2.0"
  xmlns:sml="http://www.opengis.net/sensorML/1.0.1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <swes:procedureDescriptionFormat>http://www.opengis.net/sensorML/1.0.1</swes:procedureDescriptionFormat>
  <swes:description>
    <swes:SensorDescription>
      <swes:data>
        <sml:Component>
          <!-- details omitted for brevity -->
        </sml:Component>
      </swes:data>
    </swes:SensorDescription>
  </swes:description>
</swes:DescribeSensorResponse>
  • GetObservation (mit Parametern: observedProperty und temporalFilter)

SOS

Für das Anbieten der Daten über das SOS-Protokoll wurde geprüft, ob eine eigene Implementierung notwendig ist oder eine vorhandene Implementierung benutzt werden kann. Eine eigene minimale Implementierung des SOS-Protokolls wurde bereits im vorherigen Projekt mit Python entwickelt. Diese bietet die 3 geforderten Kern-Operationen an und lieferte XML-Dokumente für das SOS-Protokoll 1.0 zurück. Für dieses Projekt müsste die Implementierung nach Java portiert werden und auf das SOS-Protokoll 2.0 angepasst werden. Die Firma 52°-North stellt eine Implementierung [37] bereit, welche verschiedene Bindings (Key/Value Pairs, SOAP, POX, JSON) anbietet und SOS-Protokoll in der Version 1.0 und 2.0 unterstützt. Falls diese Implementierung genutzt werden soll, muss untersucht werden, ob Änderungen nötig sind, um die Anforderungen an das Projekt zu erfüllen.

52° North SOS

Die SOS-Implementierung wird als Java-Web-Servlet eingebunden. Nach erfolgreicher Einrichtung (Datenbank-Parameter und Server-Konfiguration) ist die Implementierung benutzbar. Man kann Daten über die Operationen InsertSensor und InsertObservation in die SOS-Datenbank einpflegen, sobald man in den Einstellungen das "SOS 2.0 Transactional Profile" aktiviert hat. Da in dem Anwendungsfall in diesem Projekt sehr viele Daten in sehr kurzen Zeitabständen anfallen, ist das Einfügen von Daten über HTTP-POST nicht optimal, da die Aufrufe entsprechend viel Zeit benötigen. Als Alternative ist es möglich, über den SOS Importer[38] Daten direkt über die API der Implementierung einzupflegen. Der SOS Importer liest eine CSV-Datei ein, worin Metadaten und Daten aufgelistet sind. Diese Alternative ist deutlich performanter sein, da der Collector ganze Datenblöcke in eine CSV-Datei exportieren kann und diese dann mit dem SOS Importer eingelesen werden. Noch performanter wird das Einpflegen, wenn die API der SOS-Implementierung direkt genutzt werden kann. Auf Anfrage an einen der 52° North-Entwickler stellte sich jedoch heraus, dass die API sich im ständigen Wandel befindet und nicht für externe Verwendung gedacht ist. Eine weitere Alternative, um die Daten zu erhalten, bietet sich an, indem man die Daten komplett unabhängig von der SOS-Implementierung pflegt und die SOS-Implementierung die Daten nur read-only nutzt.

Das 52° North SOS hat eine Mehrschichten-Architektur (External/Internal Representation und Data Source Representation) und bietet ein vollständiges SOS Datenmodell [39] an, welches für SOS-2.0 entwickelt wurde. Werden die Daten komplett unabhängig gepflegt, müssen Modifikationen an der Implementierung vorgenommen werden, so dass die separat gepflegten Daten verwendet werden können. Unter anderem müssen die DataAccessObjects (DAO) in der Implementierung angepasst werden.

Ein weiterer Vorteil der Nutzung dieser Implementierung ist, dass sie stets die XML-Dokumente validiert, die ausgeliefert werden. Damit hat man bereits eine Anforderung abgedeckt ohne selbst einen Validator zu entwickeln oder einzubinden. Die Implementierung bietet weitere im SOS-Protokoll spezifizierte Operationen, die nicht gefordert sind, jedoch vielleicht in einer späteren Weiterentwicklung der Software nützlich sein können.

Datenmodell

Aufgrund der Häufigkeit der Messwerte kann das SOS-Datenmodell [39], welches von 52° North in ihrer Implementierung benutzt wird, nicht verwendet werden. Das Datenmodell ist nicht für sehr viele Messwerte geeignet, da eine Messung als SOS Observation gespeichert werden muss und dies den Speicherbedarf und die Komplexität der Daten zu stark beeinflussen würde. Stattdessen wird ein eigenes Datenmodell entwickelt. In der SOS-Implementierung muss dann auf diesem Datenmodell gearbeitet werden und das SOS-Datenmodell dynamisch zur Laufzeit erzeugt werden. Ein statischer Teil (Metadaten) wird an einem zentralen Punkt im System konfiguriert und zusammen mit den Messdaten bei einer Abfrage an das SOS zur Laufzeit zusammengefügt.

Das verwendete Datenmodell

Das Datenmodell ist sehr einfach gehalten, so dass es bei Bedarf (Optimierung, Erweiterung des SOS, usw.) angepasst werden kann. Zunächst werden Meeressonden beschrieben (Im Datenmodell: Sensor). Der Begriff Sensor wurde aufgrund der SOS-Terminologie gewählt. Eine Meeressonde kann als aktiv markiert werden (sie sendet Daten über die serielle Schnittstelle) und wird dann vom Collector ausgelesen. Der Name wird statisch hinterlegt und wird mit "procedure" an die SOS-Operation DescribeSensor oder GetObservation übergeben. Das Gerät ist der Name der seriellen Schnittstelle (Auf Linux z.B. /dev/ttyXYZ).

Meeressonden koppeln mehrere ObservedProperty-Instanzen. Eine ObservedProperty-Instanz ist die Zusammenfassung von Daten, die notwendig sind, um einen Messwert über SOS anzubieten. Wird über eine Adresse ein Rohwert geliefert, so werden alle ObservedProperty-Instanzen überprüft, die für diese Adresse gespeichert sind. Zu jeder Instanz wird die entsprechende Beschreibung untersucht, in welcher die Formel in Form einer Klasse) und die Einheit hinterlegt werden. Diese Formeln werden mit dem Rohwert und den aktuellen Koeffizienten aufgerufen, um einen Messwert zu generieren. Diese Werte werden in den Tabellen RawValue und CalculatedValue gespeichert. Ebenfalls muss für die Unterscheidung zwischen Intervall (Werte mit Statistiken) und voller Auflösung (Werte ohne Statistiken, so wie sie von der Meeressonde übertragen wurden) jeweils eine ObservedProperty-Instanz angelegt werden. Der Name einer ObservedProperty-Instanz wird statisch hinterlegt und muss als "observedProperty" in der SOS-Operation GetObservation mit angegeben werden.

Einpflegen der Metadaten

Zur Bearbeitung der Metadaten und Konfiguration der Sensoren und Meeressonden wird ein Editor entwickelt. Als Alternative wurde im 1. Meeting vorgeschlagen, die Datenbankeinträge direkt über Administrationsoberflächen für das DBMS (für PostgreSQL zum Beispiel pgadmin3) zu modifizieren. Allerdings sollte man auch in der Lage sein, die Methoden der Formel-Klassen zu editieren, die auf dem Dateisystem hinterlegt sind. Ein Vorteil des Editors ist, dass vom benutzten DBMS abstrahiert wird und ein Betreuer der Laufzeitumgebung keine großen Kentnisse bzgl. DB-Administration haben muss. Die Eingabemasken des Editors sollen, wo möglich, die Eingaben validieren, bevor sie in der Datenbank hinterlegt werden.

Die notwendige Funktionen soll der Editor auf jeden Fall anbieten:

  • Einstellen der Koeffizienten der Sensoren, die an der Messung beteiligt sind
  • Zuordnung der Sensoren zu den jeweiligen Adressen im Datenstrom
  • Festlegen von Start- und Endzeitpunkt, für den die Koeffizienten gültig sind

Der Editor wird als separate Java-Anwendung entwickelt und ist in der Lage, sich auf entfernte Datenbanken zu verbinden. Dadurch ist man in der Lage, die Datenbank in der Laufzeitumgebung von PCs an Arbeitsplätzen aus zu administrieren. Ein Handbuch oder eine Kurzanleitung, die aus dem Editor aus erreichbar ist, gibt Hinweise, wie der Editor zu bedienen ist und welche Auswirkungen entsprechende Änderungen haben. Die GUI-Komponenten werden mit Swing/AWT realisiert. Die Anwendung soll hinreichend komplex und spezifisch sein, um dem Anwender ein für die wichtigen Anwendungsfälle entsprechende einfaches Arbeitsumfeld zu schaffen.

Designentscheidungen

Der Collector, das SOS und der Sender werden in Servlets realisiert. Die 52° North SOS-Implementierung wird bereits als Servlet realisiert, die Entscheidung das SOS und den Collector ebenfalls in einem Servlet zu realisieren, wurde getroffen, da sie somit in der Lage sind separat als Dienst zu arbeiten, jedoch trotzdem die gleichen Logdateien verwenden. Damit kann man an zentraler Stelle Fehler- und Statusmeldungen der drei Komponenten einsehen und entsprechend reagieren. Ein Servlet Container startet dann die Dienste in den Servlets und beendet sie, sobald von außen ein Ereignis eintritt, welches ein Beenden veranlassen würde. Ein weiterer Vorteil der Entwicklung in einem Servlet ist, dass Zugriffsrechte einfach über den Servlet Container für die entsprechenden Java-Anwendungen zentral reguliert werden können.

Die Konfiguration der Software geschieht in der Regel in der Laufzeitumgebung selbst. Da die Anwendung auf einem Standard-Linux PC eingesetzt wird, kann eine Remote Desktop Application genutzt werden, um dieses zu administrieren. Das Konfigurieren geschieht durch das Ändern entsprechender Dateien oder Datenbankeinträge, die dann von der Anwendung an entsprechender Stelle ausgelesen werden.

Konzept

Gesamtarchitektur

Konfiguration

Der Servlet Container konfiguriert die Laufzeit-Eigenschaften der Servlets. Diese Konfiguration ist abhängig vom Container und wird über Remote Administration (SSH, TeamViewer) vorgenommen. Alle Konfigurationsparameter für die Komponenten, werden in einer XML-Datei vorgenommen. Die Komponenten brauchen also eine Möglichkeit, die XML-Datei zu Beginn einzulesen und die entsprechenden Parameter herauszufiltern. Die XML-Datei enthält ebenfalls einen Abschnitt für globale Konfiguration (derzeit nur Datenbankeigenschaften). Für jede Komponente wird ein XML-Tag verwendet, worin dann spezifische konfiguriert wird.

Für das Abstrahieren des XML-Dokuments wird eine Klasse geschrieben, die das XML-Dokument verarbeitet. Darin werden die einzelnen Blöcke (Tags) in entsprechenden Methoden abstrahiert, wobei die Tags auf Methodennamen abgebildet werden und die Werte als Rückgabewerte abgebildet werden.

Collector

Architektur des Collectors
Sequenzdiagramm Collector-Thread
Sequenzdiagramm Handler-Thread

Damit ein Dienst in einem Servlet realisiert werden kann, muss eigentlich gegen das Prinzip eines Servlets gearbeitet werden. Ein Servlet wird im Prinzip nur dann aufgerufen, sobald ein Request an den Server stattfindet, der auf das Servlet abgebildet ist. Eine Möglichkeit, einen Dienst in einem Servlet zu realisieren, ist über die Nutzung eines Singletons. Dieses wird bei dem ersten Request erstellet und startet einen Worker Thread, der die jeweilige Dienst-Funktion erbringt. Tomcat bietet jedoch einen Listener Interface (ServletContextListener), welches implementiert werden kann, um einmalige Aktionen durchzuführen, bevor ein Servlet überhaupt kontaktiert wird. In diesem ServletContextListener wird die Methode contextInitialized überschrieben, um die XML-Konfiguration auszulesen und den Collector-Dienst zu starten. Die contextDestroyed-Methode wird überschrieben, um Resourcen freizugeben und die Threads sauber zu beenden. Kann ein Thread nicht enden, so wird dieser früher oder später von Tomcat beendet und eine Warnung im Log ausgegeben. Der Collector bezieht zunächst eine Liste von Meeressonden aus der Datenbank, die aktiv markiert sind. Für jeder dieser Meeressonden wird dann ein Handler (separater Thread) gestartet.

In diesem Handler wird ein Communicator gestartet, der für das Lesen der seriellen Schnittstelle eingesetzt wird. Der Communicator stellt ein InputStream zur Verfügung, der das Datenübertragungsprotokoll der Meeressonde abstrahiert und eine Schnittstelle zum Erfassen des Rohwertes anbietet. Da der Collector auf Verbindungs- und I/O-Fehler reagieren muss, wird weiterhin ein Task gestartet, der, falls ein Fehler auftritt, den Handler neu startet. Dies wird jedoch nur in einem festen Zeitintervall probiert, da davon ausgegangen werden kann, dass ein Verbindungs- oder Lesefehler nicht unmittelbar behoben ist und somit nicht zu viele Fehlermeldungen hintereinander generiert werden.

Jede ObservedProperty-Instanz der Sonde, wird in einem Mapping (Adresse -> Instanz) gespeichert, um einen schnellen Zugriff zu ermöglichen. Weiterhin wird jede Formel-Klasse der ObservedProperty-Instanz geladen und ebenfalls in einem Mapping gespeichert. Jeder Handler öffnet seine eigene Hibernate-Session und besitzt weiterhin ein Flag, welches signalisiert, dass die Session geflushed werden muss. Der Collector-Thread startet eine Task, die in einem konfigurierbaren Intervall das Flag im Handler setzt und somit dem Handler mitteilt die Session zu flushen. Deshalb muss dieses Flag vor gleichzeitigem Zugriff geschützt sein.

Liefert der Communicator einen Rohwert, so wird die anhand der Adresse in dem Mapping (Adresse -> Instanz) die dazugehörige Instanz gesucht. Sollte ein Datum erschienen sein, für das keine Instanz in der Datenbank vorhanden ist, wird eine Warnmeldung geloggt. Ist eine Instanz vorhanden, so wird die Methode der entsprechenden Formel-Klasse mit den Koeffizieiten der ObservedProperty-Instanz aufgerufen und ein Messwert generiert. Ist die ObservedProperty-Instanz für ein Intervall konfiguriert (benötigt Statistiken), so wird dieser Wert in das DescriptiveStatistics-Array der Apache Commons Math3 Library eingefügt. Ist das konfigurierbare Zeitintervall zum Erheben der Statistiken abgelaufen, wird die API des Arrays verwendet, um die benötigten Statistiken zu generieren. Diese werden dann in der Datenbank hinterlegt. Ist die ObservedProperty-Instanz nicht für ein Intervall konfiguriert (benötigt volle Auflösung) wird das Datum einfach in der Session gespeichert. Zusätzlich wird für diese Instanz geprüft, ob eine CSV-Datei zur Speicherung des Wertes für diesen Monat bereits geöffnet ist. Falls nicht wird geprüft, in welchem Monat sich die Laufzeitumgebung befindet und eine CSV-Datei für diesen Monat generiert. Das Datum wird in die Datei geschrieben (siehe Analyse: ein Speichern des Datums auf dem Speichermedium ist erst sicher bei einem Flush erfolgt, welches in einem separaten Task realisiert wird).

Als zusätzliches Feature wird im Collector ein WebLog-Handler installiert. Dieser WebLog-Handler wird vom Logging Framework zusätzlich zum normalen SystemLog-Handler verwendet. Mit einem HTTP GET-Request an /log kann die Ausgabe des Collectors betrachtet werden. Das hat den Vorteil, dass der Betreuer der Laufzeitumgebung sich nicht erst zur Maschine verbinden muss, um festzustellen, ob der Collector noch ausgeführt wird. Es sollte gelegentlich aufgerufen werden, da der WebLog sonst Speicher benutzt, der für andere Zwecke genutzt werden kann.

Sender

Die Sender-Komponente ist nahezu identisch aufgebaut wie der Collector. Es wird wieder ein ServletContextListener implementiert, der für die Initialisierung des Dienstes (Threads) zuständig ist. Der Sender Thread startet ein Future, welches alle 10 Minuten versucht, neue Daten zu senden. Für alle ObservedProperty-Instanzen, welche für Intervall-Messwerte hinterlegt wurden, wird in der Datenbank gefragt, ob es neue Werte zwischen der letzte Abfrage (initial: Startzeitpunkt des Senders) und dem jetzigen Zeitpunkt gibt. Diese Werte werdenn dann in einem Query-String nach einem Template geformt, welches in der XML-Konfiguration hinterlegt ist. Zusammen mit den optionalen Basic Auth Informationen in der XML-Konfiguration, wird ein HTTP GET-Aufruf gebaut und an den entfernten WebServer abgesendet. Ist ein Aufruf fehlgeschlagen, so wird der aktuelle Zeitstempel nicht gespeichert, so dass beim nächsten Aufruf (10 Minuten später) die Daten, die nicht gesendet wurden, erneut aufgegriffen werden.

Editor

Das erste Feature, welches im Editor umgesetzt wurde, ist das Bearbeiten aller Meeressonden (Sensors). Durch die Menüpunkte Edit->Create/Edit/List sensor(s), öffnen sich entweder Dialoge, Eingabemasken oder Tabellen. Je nach Aufgabe auch eine Kombination dieser GUI-Komponenten. Ähnlich verhält es sich, wenn man ObservedPropertyInstances, ObservedProperty Classes und CalibrationSets editieren möchte. Die folgenden Funktionen werden vom Editor angeboten:

  • Erstellen von Meeressonden (in der Regel nur eine pro Station, also pro Deployment der Software)
  • Darin: Erstellen von ObservedPropertyInstances (Adresse, Auswahl der Description, Name, jeweils Selektion für "Ist ein Rohwert" und "Ist ein Intervall-Wert")
  • Bearbeiten einer Meeressonden
  • Darin: ObservedPropertyInstances direkt über eine Tabelle editieren, aktives CalibrationSet und dessen Koeffizienten werden direkt mitangezeigt)
  • Weiter darin: Löschen der ObservedPropertyInstances und Auswählen/Editieren des CalibrationSets
  • Auflistung der Meeressonden und direkte Bearbeitung der Parameter in einer Tabelle
  • Erstellen von ObservedPropertyDescriptions (Name, Auswahl der Java Klasse für die Formel, Einheit, Metadaten)
  • Bearbeiten einer ObservedPropertyDescription (gleicher Aufbau wie zuvor)
  • Auflistung aller ObservedPropertyDescriptions (direkte Bearbeitung der Informationen [keine Metadaten] über Tabelle)
  • Erstellen von CalibrationSets (Eingabe der Koeffizienten, Auswahl des gültigen Start- und Endzeitpunkts über Kalender-Popup, zugehörige Instanz)
  • Bearbeiten eines CalibrationSets (gleicher Aufbau wie zuvor)
  • Auflistung aller CalibrationSets (direkte Bearbeitung über Tabelle)
  • Erstellen von ObservedProperty Class (Name, Textfeld für Klassen-Editor [read only Kopf, nur die Methoden sind editierbar], direktes On The Fly-Compiling über Knopfdruck)
  • Bearbeiten einer ObservedProperty Class (gleicher Aufbau wie zuvor)
  • Auflistung aller ObservedProperty Classes (nur Namen, dafür Extra-Funktionalität: Kompilieren aller Klassen mit einem Knopfdruck, Ausgabe-Fenster wird durch Compiler-Meldungen in einem Thread befüllt)
  • Auflistung der Roh- und Messwerte (read only)

Diese Liste ist deutlich länger als jene, die in den Anforderungen gestellt wurde. Das resultiert daraus, dass es während der Entwicklung immer mehr "praktische Tätigkeiten" gefunden haben, die man im Editor realisieren kann. Dadurch, dass der Editor sehr mächtig ist und bis zum Ende hin erweitert wurde, wurde ein Konzept nie fertiggestellt. Stattdessen wurden die sehr modular gehaltenen GUI-Komponenten je nach Bedarf leicht abgeändert und wiederverwendet.

Grundsätzlich wurde viel Wert darauf gelegt, wiederverwendbare Komponenten (Checkboxes, Eingabefelder, usw. abgebildet auf Datenbank-Elemente) zu entwickeln. Jedoch blieb es an manchen Stellen nicht aus, Teile zu duplizieren und zu modifizieren. Es wurde ebenfalls viel Wert darauf gelegt, eine Eingabe direkt zu validieren, bevor sie an die Datenbank gesendet wird. Die Fehlerbehandlung (Fehleingaben, Datenbank-Fehler, usw.) stellte sich prinzipiell als schwierig heraus, da es für gewisse Fälle Fallback-Mechanismen geben muss. Zum Beispiel muss, wenn eine Java Formel-Klasse umbenannt wird, auf dem Dateisystem eine Umbenennung stattfinden. Schlägt diese fehl, sollte die alte Klasse davon unberührt bleiben. Ein weiteres Problem war das Verwenden von Threads beim Kompilieren der Java-Klassen und gleichzeitiger Ausgabe der Compiler-Meldungen in einem Popup. Die Funktionalität wurde dennoch angeboten, so dass der Anwender nicht erst auf das Dateisystem zugreifen, die Datei editieren und kompilieren muss, sondern mit einem Programm die Datei editieren und kompilieren kann ohne extra Software zu installieren. Durch die Angabe der Datenbank-Einstellungen in der XML-Datei ist der Editor ebenfalls in der Lage, Datenbestände in anderen Laufzeitumgebungen zu editieren.

Implementierung

Die Komponenten wurden in jeweiligen Eclipse-Projekten realisiert. Für die Servlet-Komponenten Sender und Collector wurde ein Dynamic Web Project in Eclipse [40] angelegt. Der Editor wurde als einfaches Java-Projekt in Eclipse entwickelt.

Als Servlet Container dient Apache Tomcat [41] in der Version 7.0. Die folgenden Pakete werden auf einer Standard Debian 8.1 Linux-Installation benötigt, um alle Komponenten auszuführen:

  • openjdk-7-jdk
  • tomcat7
  • postgis
  • sqlite
  • libswingx-java
  • libcommons-math3-java
  • librxtx-java
  • libpostgresql-jdbc-java
  • libopencsv-java
  • ant

Da die Komponenten auf "headless machines" ausgeführt werden, wurden aus Eclipse heraus Apache Ant Buildfiles [42] generiert und danach bearbeitet. Diese Buildfiles sind so angepasst, dass sie auf der VM der Hochschule RheinMain (Test-Umgebung) benutzt werden können.

Es muss ebenfalls das Hibernate Framework in der Version 4.* [43] heruntergeladen und entpackt werden. Der Pfad zum Framework muss in den Projekt-Eigenschaften in Eclipse bzw. in den Ant Buildfiles angepasst werden.

Common

Das Common-Projekt umfasst Funktionalität, die für jede Komponente benötigt wird, und wird deshalb als separate Bibliothek (Java Archive) entwickelt. Die folgende Funktionalität wird bereitgestellt:

  • Abstrahieren der XML-Konfiguration als Objekt
  • Bereitstellen der von Hibernate generierten Java Objekte
  • Base Java Interface für die Repräsentation für Roh- und Messwerte

In den Projekten der Komponenten muss diese Bibliothek stets (beim Übersetzen als auch zur Laufzeit) eingebunden werden.

Es ist üblich, die Datenbank-Einstellungen für Servlets im Tomcat-Kontext zu konfigurieren. Dazu wird im JNDI (Java Naming and Directory Interface) die Datenbank bekannt gemacht, die dann von anderen Komponenten genutzt wird. Da der Editor aber nicht in einem Servlet ausgeführt wird, jedoch ebenfalls die Datenbank-Anbindung benötigt, hätte die Konfiguration der Datenbank an zwei Stellen durchgeführt werden müssen. Stattdessen wurden die Datenbank-Anbindung in der XML-Datei konfiguriert und programmatisch dem Hibernate Framework zugänglich gemacht.

Damit die Konfiguration zur Laufzeit eingelesen werden kann, muss der Pfad der Common-Bibliothek bekannt gemacht werden. Dies geschieht über die Java System Property "hzg.home". In diesem Verzeichnis wird der Pfad "hzg/configuration.xml" als Dateipfad zur Konfigurationsdatei gewählt. Die System Property kann in einem normalen Java Aufruf über den "-D" Command Line Switch oder in Tomcat7 in der Datei "catalina.properties" festgelegt werden.

Einbinden von Hibernate

Hibernate bietet eine API, mit der es möglich ist, aus Datenbank-Queries Java-Objekte zu generieren. Dazu muss Hibernate bekannt gemacht werden, wie Objekteigenschaften auf Datenbankebene abgebildet werden. Ein Beispiel aus einer Konfigurationsdatei für ein Hibernate Java-Objekt:

 <hibernate-mapping>
         <class name="de.hzg.measurement.Sensor" table="sensors">
                 <id name="id" column="id">
                         <generator class="native">
                                 <param name="sequence">sensors_id_seq</param>
                         </generator>
                 </id>
                 <property name="active">
                         <column name="active" not-null="true" />
                 </property>
 [...]

Das Java-Objekt muss dann ein Attribut "active" und "id" haben und für diese Attribute Getter und Setter (getActive, setId, usw.). Um eine Anfrage an die Datenbank zu generieren, kann man nun entweder JPA benutzen (Java Persistence) oder die Hibernate Query Language. Je nach Unterstützung und Komplexität kann man aber beliebig zwischen den beiden Varianten wählen. Der einfache Aufruf FROM Sensor gibt eine Liste alle Java-Objekte zurück, die mit den Daten aus der Tabelle "sensors" befüllt sind.

Da es während der Entwicklung kaum Fälle gab, wo man einzelne Datenbank-Werte, statt Objekte benötigte, war die Einarbeitung und die zusätzliche Abhängigkeit durch die enorme Zeitersparnis bei der Implementierung gerechtfertigt.

SOS

Das SOS-Protokoll wird mit der Implementierung von 52° North angeboten. Die Implementierung muss so angepasst werden, dass sie das Datenmodell benutzen kann. Dazu müssen die DataAccessObjects und der Hibernate Layer komplett ausgetauscht werden. Ein großes Problem, welches es zu lösen galt, war, in der Implementierung herauszufinden, an welchen Stellen in der Implementierung welche Daten in einem Objekt erwartet werden. Ob Fehler beim Abrufen der Objekte aus der Datenbank aufgetreten sind, wurde an manchen Stellen mit einer Prüfung "Referenz != NULL" vorgenommen, an anderen Stellen wurde geprüft, ob eine leere Liste vorliegt, oder ähnliches. Bei der Bearbeitung der DAOs wurden insgesamt auch herausgefunden, dass die Implementierung inkomsistente Objekte erlaubt. Ein Teil der Probleme konnte gelöst werden, in dem man im Datenmodell prüft, welche Tabellenspalten nicht NULL sein dürfen, bzw. wie die Constraints aussehen. Im folgenden wird gezeigt, wie z.B. das ObservationConstellationsDAO angepasst wurde. Dieses DAO ist dafür verantwortlich, aus der Daten für eine Observation zusammenzufassen. Originalcode:

        Criteria criteria = session.createCriteria(ObservationConstellation.class)
          .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
          .add(Restrictions.eq(ObservationConstellation.DELETED, false));
        criteria.createCriteria(ObservationConstellation.PROCEDURE)
         .add(Restrictions.eq(Procedure.IDENTIFIER, procedure));
        criteria.createCriteria(ObservationConstellation.OBSERVABLE_PROPERTY)
         .add(Restrictions.eq(ObservableProperty.IDENTIFIER, observableProperty));
        return criteria.list();

Dieser Programmcode liest über das Hibernate Framework Werte aus der Datenbank und befüllt so das Objekt ObservationConstellation. Da man im Datenmodell, welches im Projekt genutzt wird, jedoch keine ObservationConstellation vorfindet, muss der Programmcode abgeändert werden:

 final SOSConfiguration sosConfiguration = SosContextListener.hzgSOSConfiguration;
 
 if (!procedure.startsWith(sosConfiguration.getProcedureIdentifierPrefix())) {
     return Collections.emptyList();
 }
 
 if (!observableProperty.startsWith(sosConfiguration.getObservablePropertyIdentifierPrefix())) {
     return Collections.emptyList();
 }
 
 final Criteria criteria = session.createCriteria(ObservedPropertyInstance.class);
 final Criteria sensorCriteria = criteria.createCriteria("sensor");
 final String instanceName = observableProperty.substring(sosConfiguration.getObservablePropertyIdentifierPrefix().length());
 final String sensorName = procedure.substring(sosConfiguration.getProcedureIdentifierPrefix().length());
 
 criteria.add(Restrictions.eq("name", instanceName));
 sensorCriteria.add(Restrictions.eq("name", sensorName));
 
 final List<ObservedPropertyInstance> results = criteria.list();
 final List<ObservationConstellation> obsConsts = Lists.newArrayListWithCapacity(results.size());
 
 for (final ObservedPropertyInstance observedPropertyInstance: results) {
     obsConsts.add(createObservationConstellation(observedPropertyInstance, session));
 }
 
 return obsConsts;

In der Implementierung wird zunächst geprüft, ob die übergebenen Werte an die Methode korrekt sind. Dann wird eine Abfrage zur Datenbank generiert und zusätzlich Werte aus der XML-Konfiguration mit einbezogen. Die zurückgelieferten ObservationConstellations werden dann in weiteren Ebenen der Implementierung wiederverwendet und sind dynamich generierte Daten zur Laufzeit.

Da die Änderung der Implementierung rund ~7000 LOC beinhaltet, wird nicht im Detail weiter darauf eingegangen. Das obige Beispiel soll nur die prinzipielle Vorgehensweise erläutern.

Für alle Schreibzugriffe auf die Laufzeitumgebung (Bsp.: InsertSensor, InsertObservation) werden derzeit Exceptions generiert, da diese noch nicht implementiert sind. Die Daten-Bereitstellung für das SOS geschieht über die XML-Konfiguration, den Messdaten aus dem Collector und den Metadaten, die über den Editor gepflegt werden.

Kompilieren und Starten der Anwendungen

Die empfohlene Vorgehensweise die Servlet-Komponenten und den Editor zu übersetzen ist das Verwenden des Ant Buildsystems. Der Befehl "ant build" im entsprechenden Projektverzeichnis übersetzt das entsprechende Projekt. Durch den Befehl "ant package" für Collector und Sender, kann ein Web Archive erzeugt werden, dass von Tomcat deployed werden kann. Mit "ant -Dhzg.home=<Speicherort zur hzg/configuration.xml> Editor" kann der Editor gestartet werden. Der Editor gibt zu beginn (Initialisierung von Hibernate) Statusmeldungen auf der Standard-Ausgabe aus, so ist es ratsam das Programm in jedem Fall über die Konsole zu starten, da sonst evtl. auftretende Fehler nicht gesehen werden und der Editor nicht gestartet werden kann.

Die SOS-Implementierung wird nicht mit Ant Buildfiles generiert, sondern mit Apache Maven [44]. Die originale Implementierung von 52° North bietet dieses Buildsystem an und wurde nur an wenigen Stellen verändert, um die Common Bibliothek mit einzubinden. Der Übersetzungsprozess wird mit mvn package angestoßen, allerdings muss noch -Dmaven.test.skip=true angehängt werden, da die Testcases mit dem neuen Datenmodell noch nicht durchgeführt wurden. Es wird ein WAR-File generiert, welches ebenfalls im Tomcat deployed werden kann.

Quellcode

Der aktuelle Code befindet für die Komponenten befindet sich im SVN Repository der Hochschule RheinMain [45] der Hochschule RheinMain. Die einzelnen Verzeichnisse "HZG *" können in Eclipse als Projekte importiert werden. Der Quellcode für die SOS-Implementierung befindet sich im github repository des Projektdurchführenden [46]. Für die Bewertung ist der Stand am 01.09.2015 ausschlaggebend, welcher zusätzlich im SVN Repository, wo sich die Komponenten befinden, als SOS.zip beigelegt wurde.

Tests und Testumgebung

Zum jetzigen Zeitpunkt ist es leider nicht möglich, die Daten einer Sonde in Echtzeit aufzunehmen und zu verarbeiten. Als Datenbestand wird eine Datei verwendet, die während der Entwicklung des Vorgängerprojekts aufgezeichnet wurde. Diese Datei enthält einen aufgezeichneten Datenstrom einer typähnlichen Meeressonde für den Zeitraum von einem Tag. Für das Testen des Senders wurde seitens des HZG eine Account eingerichtet, mit dem man Daten zum HZG senden darf. Der Sender, Collector und das SOS wurde auf einer VM in der Hochschule RheinMain deployed und kann mittels Port-Forwarding von der HZG getestet werden. Im folgenden wird beschrieben, wie die einzelnen Komponenten getestet wurden.

Collector

Damit die Daten aus der Datei an eine serielle Schnittstelle übermittelt werden, wurde ein Python-Programm geschrieben. Dieses läuft ununterbrochen und beginnt die Datei erneut einzulesen, wenn sie komplett ausgelesen wurde. Dadurch ist es möglich eine Meeressonde an einer seriellen Schnittstelle zu emulieren. Zunächst wurde sichergestellt, das sich der Collector nach Verbindungs- und Lesefehler erneut mit der seriellen Schnittstelle nach einem bestimmten Zeitintervall verbindet. Die Fehler wurden durch Beendigung des Python-Programms erzeugt.

Die Datenströme können vom Collector erfolgreich in Adresse/Daten-Paare dekodiert werden. Im Datenstrom sind Messwerte von Temperatur-, Druck- und Spannungssensoren. Diese Sensoren sind vom Typ P und N (Herstellerbezeichnung). Die Formeln, Adressen und Koeffizienten wurden aus dem Vorgängerprojekt übernommen. Nachdem die Sensor-Klassen geschrieben wurden und auf dem Dateisystem abgelegt wurden, wurde geprüft, ob der Collector in der Lage ist die empfangenen Rohdaten in Messdaten umzuwandeln und beide Daten als Intervall und in voller Auflösung zu speichern. Dazu mussten ObservedPropertyInstances angelegt werden (Pressure_Full, Pressure_10mins, Pressure_Raw_Full, Pressure_Raw_10mins, usw.). Der Test wurde erfolgreich durchgeführt.

Sender

Der Sender funktioniert logischerweise nur dann, wenn die Laufzeitumgebung den eingestellten Server in der XML-Konfiguration erreichen kann. Da in der VM der Hochschule ein Proxy vorgeschaltet ist, müssen in der Tomcat-Konfiguration (catalina.properties) die Proxy-Einstellungen vorgenommen werden:

 http.proxyHost=proxy.cs.hs-rm.de
 http.proxyPort=8080
 https.proxyHost=proxy.cs.hs-rm.de
 https.proxyPort=8080

Da das HZG in der Testumgebung derzeit nur eine festgelegte observedProperty (test) und station (testenv) empfangen kann, wird im derzeitigen Code hardkodiert, welche observedProperty aus den gespeicherten Daten für diese Zwecke genutzt wird. Dies muss geändert werden, sobald die Software in der echten Umgebung eingesetzt wird. Zunächst wurde erfolgreich geprüft, ob der HTTP GET-Aufruf überhaupt vom HZG empfangen werden kann (Status Code 2**). Dann wurde erfolgreich geprüft, dass der Sender einen erneuten Aufruf mit den gleichen Daten zu einem späteren Zeitpunkt sendet, falls der HTTP Status Code nicht 2** ist oder ein anderer Fehler auftritt. Mittels einer Plot-Oberfläche, die man am HZG Webserver aufrufen kann, wurde verifiziert, dass das HZG die empfangenen Daten speichern kann.

Editor

Für die Editor-Testläufe wurden verschiedene Kombinationen von Eingaben und Folgeaktionen getestet. Eine Tabelle mit einem Auszug der Testfälle soll verdeutlichen, wie die Funktionen getestet wurden.

SOS

Die SOS-Implementierung wird anhand der Aufrufe getestet, die das HZG für gewöhnlich ausführt, da eine Vielzahl von Falsch-Aufrufen möglich ist bzw. beliebige Kombination von Query-Parameter hinzugefügt und weggelassen werden können. Mit Hilfe der ausgelieferten XML-Dokumente die folgend beschrieben werden, wird ebenfalls erklärt, wie diese Daten generiert wurden. Es wird nur der relevante Teil der XML-Dokumente gezeigt:

 <?xml version="1.0" encoding="UTF-8"?>
 <sos:Capabilities xmlns:sos="http://www.opengis.net/sos/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ows="http://www.opengis.net/ ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:swes="http://www.opengis.net/swes/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" version="2.0.0" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd http://www.opengis.net/swes/2.0 http://schemas.opengis.net/swes/2.0/swes.xsd http://www.opengis.net/sos/2.0 http://schemas.opengis.net/sos/2.0/sosGetCapabilities.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsAll.xsd">
  <ows:ServiceIdentification>
    <ows:Title xml:lang="eng">COSYNA SOS</ows:Title>
    <ows:Abstract xml:lang="eng">COSYNA - Data Access for the Sensor Web</ows:Abstract>
    <ows:ServiceType>OGC:SOS</ows:ServiceType>
    <ows:ServiceTypeVersion>1.0.0</ows:ServiceTypeVersion>
    <ows:ServiceTypeVersion>2.0.0</ows:ServiceTypeVersion>
    <ows:Profile>http://www.opengis.net/extension/SOSDO/1.0/observationDeletion</ows:Profile>
    [...]
   </ows:ServiceIdentification>
   <ows:ServiceProvider>
    <ows:ProviderName>HZG</ows:ProviderName>
    <ows:ProviderSite xlink:href="http://www.hzg.de"/>
    <ows:ServiceContact>
    [...]
    </ows:ServiceContact>
    [...]
    <ows:Operation name="DescribeSensor">
      <ows:DCP>
        <ows:HTTP>
          <ows:Get xlink:href="http://eta-ori.net:8888/service/kvp?">
            <ows:Constraint name="Content-Type">
              <ows:AllowedValues>
                <ows:Value>application/x-kvp</ows:Value>
              </ows:AllowedValues>
            </ows:Constraint>
          </ows:Get>
          [...]
          <ows:Post xlink:href="http://eta-ori.net:8888/service/pox">
            <ows:Constraint name="Content-Type">
              <ows:AllowedValues>
                <ows:Value>application/xml</ows:Value>
                <ows:Value>text/xml</ows:Value>
              </ows:AllowedValues>
            </ows:Constraint>
          </ows:Post>
      [...]
      <ows:Parameter name="procedure">
        <ows:AllowedValues>
          <ows:Value>http://www.hzg.de/sos/procedure/FakeCTDHelgoland</ows:Value>
        </ows:AllowedValues>
      </ows:Parameter>
      <ows:Parameter name="procedureDescriptionFormat">
        <ows:AllowedValues>
          <ows:Value>http://www.opengis.net/sensorML/1.0.1</ows:Value>
          <ows:Value>http://www.opengis.net/sensorml/2.0</ows:Value>
          <ows:Value>http://www.opengis.net/waterml/2.0/observationProcess</ows:Value>
        </ows:AllowedValues>
      </ows:Parameter>
      <ows:Parameter name="validTime">
        <ows:AnyValue/>
      </ows:Parameter>
    </ows:Operation>
    <ows:Operation name="GetObservation">
      [...]
      <ows:Parameter name="observedProperty">
        <ows:AllowedValues>
          <ows:Value>http://www.hzg.de/sos/observedProperty/Pressure_10mins</ows:Value>
          <ows:Value>http://www.hzg.de/sos/observedProperty/Pressure_10mins_Raw</ows:Value>
          <ows:Value>http://www.hzg.de/sos/observedProperty/Pressure_Full</ows:Value>
          [...]
       <ows:Parameter name="offering">
        <ows:AllowedValues>
          <ows:Value>http://www.hzg.de/sos/offering/BoknisEck1</ows:Value>
        </ows:AllowedValues>

Dieses Capability-Dokument beschreibt, welche Operationen und Profile diese SOS-Implementierung unterstützt. Die einzelnen Operationen können in der Administrationsoberfläche der SOS-Implementierung beliebig ein- oder ausgeschaltet werden. Werte die in <ows:Value> von <ows:AllowedValues> der <ows:Parameter> geben an, welche Query-Parameter akzeptiert werden. Da ebenfalls <ows:Post> definiert ist, kann der komplette Request auch in einem XML-Dokument über HTTP POST abgesendet werden. Dies ist dann nötig, wenn die Query-Parameter zu lang für einen GET Request werden. Sämtliche Prefixes (Bsp.: http://www.hzg.de/sos/observedProperty) werden in der XML-Konfiguration hinterlegt:

        <sos>
                <identifier_prefix>http://www.hzg.de/sos</identifier_prefix>
                <procedures>
                        <identifier_prefix>procedure</identifier_prefix>
                </procedures>
                <offering>
                        <identifier_prefix>offering</identifier_prefix>
                        <name>BoknisEck1</name>
                </offering>

Der vollständige Identifier (welcher bei der Abfrage z.B. verwendet werden kann) bildet sich dann aus dem statischen Teil der XML-Konfiguration und den Daten aus der Datenbank.

Die Metadaten des Messsystems können mit DescribeSensor abgerufen werden. Als Parameter muss der Name der Meeressonde im Query-Parameter procedure übergeben werden (Datenmodell: Sensor). Beispiel:

wget 'http://eta-ori.net:8888/sos/service?service=SOS&version=2.0.0& \
request=DescribeSensor&procedure=http://www.hzg.de/sos/procedure/FakeCTDHelgoland'

Der Aufruf schlägt fehl:

?xml version="1.0" encoding="UTF-8"?>
<ows:ExceptionReport xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsAll.xsd">
  <ows:Exception exceptionCode="MissingParameterValue" locator="procedureDescriptionFormat">
    <ows:ExceptionText>The value for the parameter 'procedureDescriptionFormat' is missing in the request!</ows:ExceptionText>
  </ows:Exception>

Es ist weiterhin notwendig, das procedureDescriptionFormat (z.B. SensorML 2.0) mit zu übergeben. Die SOS-Implementierung kann prinzipiell alle von SOS unterstützen Formate ausgeben, jedoch wird in der Implementierung hardkodiert SensorML 2.0 generiert. Der folgende Aufruf mit der dazugehörigen Antwort beschreibt die Metadaten in SensorML 2.0:

wget 'http://eta-ori.net:8888/sos/service?service=SOS&version=2.0.0& \
request=DescribeSensor&procedure=http://www.hzg.de/sos/procedure/FakeCTDHelgoland& \
procedureDescriptionFormat=http://www.opengis.net/sensorml/2.0'
<?xml version="1.0" encoding="UTF-8"?>
<swes:DescribeSensorResponse xmlns:swes="http://www.opengis.net/swes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www
.opengis.net/gml/3.2" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:xlink="http://www.w3.org/1999/x
link" xsi:schemaLocation="http://www.opengis.net/swes/2.0 http://schemas.opengis.net/swes/2.0/swesDescribeSensor.xsd http://www.isotc211.org/2005/gco
 http://schemas.opengis.net/iso/19139/20070417/gco/gco.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd http://www.iso
tc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd http://www.opengis.net/sensorml/2.0 http://schemas.opengis.net/sensorML/
2.0/sensorML.xsd">
  <swes:procedureDescriptionFormat>http://www.opengis.net/sensorml/2.0</swes:procedureDescriptionFormat>
  <swes:description>
    <swes:SensorDescription>
      <swes:validTime>
        <gml:TimePeriod gml:id="tp_CEFFF0FD3721DB69D6F00CD6EC09E3D219788C75">
          <gml:beginPosition>2015-01-01T00:00:00.000Z</gml:beginPosition>
          <gml:endPosition>2016-01-01T00:00:00.000Z</gml:endPosition>
        </gml:TimePeriod>
      </swes:validTime>
      <swes:data>
        <sml:PhysicalSystem xmlns:sml="http://www.opengis.net/sensorml/2.0" xmlns:swe="http://www.opengis.net/swe/2.0" gml:id="ps_750FFFB6D28F6D8AFD1
AC983517D12BCA9C1404F">
          <gml:identifier codeSpace="uniqueID">http://www.hzg.de/sos/procedure/FakeCTDHelgoland</gml:identifier>
          <gml:name codeSpace="eng">FakeCTDHelgoland</gml:name>
          <sml:keywords>
            <sml:KeywordList>
              <sml:keyword>http://www.hzg.de/sos/observedProperty/Pressure_Full</sml:keyword>
              <sml:keyword>http://www.hzg.de/sos/offering/BoknisEck1</sml:keyword>
              <sml:keyword>http://www.hzg.de/sos/observedProperty/Pressure_10mins</sml:keyword>
              <sml:keyword>http://www.hzg.de/sos/procedure/FakeCTDHelgoland</sml:keyword>
              <sml:keyword>http://www.hzg.de/sos/observedProperty/Temperature_10mins_Raw</sml:keyword>
              <sml:keyword>http://www.hzg.de/sos/observedProperty/Temperature_Full_Raw</sml:keyword>
           [...]

Wie zu sehen ist, wird die Meeressonde in SensorML 2.0 als PhysicalSystem modelliert. Es war zunächst geplant, die Metadaten der einzelnen Messsensoren als Zusatz-Feature ebenfalls in das Datenmodell mit einzubeziehen. In einer Diskussion auf der Mailingliste der Firma 52° North [47] stellte sich heraus, dass die Einbettung von PhysicalCompoennt (Messsensor) in einem PhysicalSystem (Meeressonde) derzeit nicht funktioniert. Ein Commit zur Behebenung des Fehlers erschien erst relativ spät, so dass keine Zeit mehr übrig blieb das Datenmodell und das System entsprechend anzupassen. Für zukünftige Versionen dieser Software, kann hier, falls vom HZG erwünscht, weiter gearbeitet werden.

Das PhysicalSystem zeigt, in welchem Zeitintervall dieses gültig ist (hardkodiert: das derzeitige Jahr der Laufzeitumgebung) und welche Keywords mit dem PhysicalSystem verbunden werden (z.B. observed properties). Eine Anforderung des HZG war es, die Kalibrierungs-Koeffizienten im SensorML 2.0-Dokument sichtbar zu machen. Dies wurde realisiert, indem ein eigenes Datum in <sml:outputs> definiert wurde:

          <sml:outputs>
            <sml:OutputList>
              <sml:output name="output_0">
                <swe:DataRecord definition="output data record 0">
                  <swe:field name="calibration_set_0">
                    <swe:DataRecord xmlns:ns="http://www.opengis.net/swe/2.0">
                      <ns:field name="parameter_1">
                        <swe:Text>
                          <ns:value>-9.82973</ns:value>
                        </swe:Text>
                      </ns:field>
                      <ns:field name="parameter_2">
                        <swe:Text>
                          <ns:value>0.0033478</ns:value>
                        </swe:Text>
                      </ns:field>
                      [...]
                      <ns:field name="valid_start">
                        <swe:Text>
                          <ns:value>2015-07-28T00:00Z</ns:value>
                        </swe:Text>
                      </ns:field>
                      <ns:field name="valid_end">
                        <swe:Text>
                          <ns:value>2016-07-28T08:28Z</ns:value>
                        </swe:Text>
                      </ns:field>
                    </swe:DataRecord>
                  </swe:field>
                  <swe:field name="unit">
                    <swe:Text xmlns:ns="http://www.opengis.net/swe/2.0">
                      <ns:value>dbar</ns:value>
                    </swe:Text>
                  </swe:field>
                  <swe:field name="identifier">
                    <swe:Text xmlns:ns="http://www.opengis.net/swe/2.0">
                      <ns:value>http://www.hzg.de/sos/observedProperty/Pressure_Full</ns:value>
                    </swe:Text>
                  </swe:field>
                </swe:DataRecord>

Anhand dieser Auflistung wird deutlich, welche Koeffizienten in welchem Zeitraum für welche observedProperty gültig sind. Es ist vorgesehen, dass in einer weiteren Version zusätzliche Metadaten übertragen werden. Im Datenmodell ist dafür ein Textfeld metadata für jede ObservedPropertyDescription vorgesehen. Eine Verbindung zwischen diesem Textfeld und der Ausgabe des XML-Dokuments besteht bisher noch nicht. Das Datum mit den Koeffizienten, Zeiträumen, Einheit und dem Name der ObservedPropertyInstance wird in der SOS-Implementierung hardkodiert.

Die eigentlichen Messwerte werden mit der SOS Operation GetObservation angefordert. Um einen gültigen Aufruf zu generieren, muss zumindest der Query-Parameter procedure (also die Meeressonde) mitgeliefert werden. Wird kein Zeit-Intervall oder eine observed Property festgelegt, so wird für alle observed properties der komplette Datenbestand zurückgeliefert. Dies stellt sich als Problem dar, da das XML-Dokument im Arbeitsspeicher generiert wird und unter Umständen deutlich zu groß wird, als dass es vom Webserver verarbeitet werden kann. Die SOS-Implementierung bietet als zusätzliches Feature das Streaming von Werten an. Damit ist es möglich ein XML-Envelope zum Client zu schicken und die Daten über Streaming in den Envelope einzubetten. Ein Nachteil dieser Methode ist, dass die XML-Dokumente nicht mehr von der Implementierung validiert werden können. Der zeitliche Rahmen des Projekts hat nicht ausgereicht, um dieses Feature zu unterstützen. Es ist jedoch im weiteren Verlauf der Anstellung mit dem HZG geplant, diese Funktionalität noch umzusetzen. Da schon bereits beim Anfordern der Daten (durch Hibernate) eine Java VM Out of memory Exceptions generiert, wird diese gefangen, die Hibernate Session verworfen und eine XML-Exception zurückgegeben. Das Fangen von Out of memory Exceptions ist Bad practice und nur eine Notlösung bis das Streaming implementiert wurde, da es sonst beim Testen evtl. nötig ist, die Tomcat-Instanz neuzustarten. Damit für die derzeitige Test-Umgebung möglichst viel Speicher genutzt werden kann, wird in der Tomcat-Konfiguration (CATALINA_OPTS="$CATALINA_OPTS -Xmx3052m" hinzugefügt. Beispiel einer XML-Exception, falls zu viele Daten angefordert werden:

<?xml version="1.0" encoding="UTF-8"?>
<ows:ExceptionReport xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0.0" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsAll.xsd">
  <ows:Exception exceptionCode="ResponseExceedsSizeLimit">
    <ows:ExceptionText>The observation response is to big for the maximal heap size of 129761280 Byte of the virtual machine! Please either refine your getObservation request to reduce the number of observations in the response or ask the administrator of this SOS to increase the maximum heap size of the virtual machine!</ows:ExceptionText>
  </ows:Exception>
</ows:ExceptionReport>

Durch das Hinzufügen eines Zeit-Intervalls (temporalFilter) kann die Datenmenge deutlich reduziert werden. Die folgenden Beispiele zeigen den erfolgreichen Abruf von Daten (für Roh- und Messwerte und einem Messwert in einem Intervall):

wget 'http://eta-ori.net:8888/sos/service?service=SOS&version=2.0.0& \
request=GetObservation&procedure=http://www.hzg.de/sos/procedure/FakeCTDHelgoland& \
namespaces=xmlns(om,http://www.opengis.net/om/2.0)& \
temporalFilter=om:resultTime,2015-08-27T17:00:00.000%2B00:00/2015-08-27T18:00:00.000%2B00:00& \
observedProperty=http://www.hzg.de/sos/observedProperty/Voltage_Full'
[...]
<sos:observationData>
    <om:OM_Observation gml:id="o_0">
      <om:type xlink:href="http://www.opengis.net/def/observationType/OGC-OM/2.0/OM_SWEArrayObservation"/>
      <om:phenomenonTime>
        <gml:TimePeriod gml:id="phenomenonTime_0">
          <gml:beginPosition>2015-08-27T17:00:00.126Z</gml:beginPosition>
          <gml:endPosition>2015-08-27T17:59:59.998Z</gml:endPosition>
        </gml:TimePeriod>
      </om:phenomenonTime>
      <om:resultTime>
        <gml:TimeInstant gml:id="ti_79124C97652F290471578B0D9218469D83407F04">
          <gml:timePosition>2015-08-27T17:59:59.998Z</gml:timePosition>
        </gml:TimeInstant>
      </om:resultTime>
      <om:procedure xlink:href="http://www.hzg.de/sos/procedure/FakeCTDHelgoland"/>
      <om:observedProperty xlink:href="http://www.hzg.de/sos/observedProperty/Voltage_Full"/>
      <om:featureOfInterest xlink:href="http://www.hzg.de/sos/featureOfInterest/BoknisEck" xlink:title="BoknisEck"/>
      <om:result xmlns:ns="http://www.opengis.net/swe/2.0" xsi:type="ns:DataArrayPropertyType">
        <ns:DataArray>
          <ns:elementCount>
            <ns:Count>
              <ns:value>17741</ns:value>
            </ns:Count>
          </ns:elementCount>
          <ns:elementType name="Components">
            <ns:DataRecord>
              <ns:field name="value">
                <ns:Quantity>
                  <ns:uom code="Volt"/>
                </ns:Quantity>
              </ns:field>
            </ns:DataRecord>
          </ns:elementType>
          <ns:encoding>
            <ns:TextEncoding blockSeparator="@@" decimalSeparator="." tokenSeparator=","/>
          </ns:encoding>
          <ns:values>11.991655672999999@@11.991655672999999@@11.990651078999997@@...</ns:values>
 [...]

Es wird zwischen phenomenonTime und resultTime unterschieden. Die phenomenonTime sagt aus, wann die Messung durchgeführt wurde (wann etwas angeschaut wurde) und die resultTime sagt aus, wann das Messergebnis verfügbar ist. Aufgrund der Änderungen am Datenmodell, die zuvor beschrieben wurden, ist eine SOS Observation nicht gleichbedeutend mit einer einzelnen Messung eines Messsensors der Meeeressonde, sondern eine dynamisch erzeugte Observation bedingt durch die Parameter. Als resultTime (TimeInstant) wird die letzte phenomenonTime (TimePeriod) verwendet. In <om:result> wird der Datentyp der Observation festgelegt. Zusammen mit <ns:enoding> kann dann der String in <ns:values> interpretiert werden.

wget 'http://eta-ori.net:8888/sos/service?service=SOS&version=2.0.0& \
request=GetObservation&procedure=http://www.hzg.de/sos/procedure/FakeCTDHelgoland& \
namespaces=xmlns(om,http://www.opengis.net/om/2.0)& \
temporalFilter=om:resultTime,2015-08-27T17:00:00.000%2B00:00/2015-08-27T18:00:00.000%2B00:00& \
observedProperty=http://www.hzg.de/sos/observedProperty/Voltage_Full_Raw'
[...]
      <om:result xmlns:ns="http://www.opengis.net/swe/2.0" xsi:type="ns:DataArrayPropertyType">
        <ns:DataArray>
          <ns:elementCount>
            <ns:Count>
              <ns:value>17741</ns:value>
            </ns:Count>
          </ns:elementCount>
          <ns:elementType name="Components">
            <ns:DataRecord>
              <ns:field name="value">
                <ns:Quantity>
                  <ns:uom xlink:href="http://www.opengis.net/def/nil/OGC/0/unknown"/>
                </ns:Quantity>
              </ns:field>
            </ns:DataRecord>
          </ns:elementType>
          <ns:encoding>
            <ns:TextEncoding blockSeparator="@@" decimalSeparator="." tokenSeparator=","/>
          </ns:encoding>
          <ns:values>55009@@55009@@55007@@55009@@55009@@55009@@...
[...]

Der Unterschied zwischen einer _Raw observed property und einer "non-raw" property ist das Fehlen der Einheit im zurückgegebenen Datentypen.

wget 'http://eta-ori.net:8888/sos/service?service=SOS&version=2.0.0& \
request=GetObservation&procedure=http://www.hzg.de/sos/procedure/FakeCTDHelgoland& \
namespaces=xmlns(om,http://www.opengis.net/om/2.0)& \
temporalFilter=om:resultTime,2015-08-27T17:00:00.000%2B00:00/2015-08-27T18:00:00.000%2B00:00& \
observedProperty=http://www.hzg.de/sos/observedProperty/Voltage_10mins'
[...[
      <om:result xmlns:ns="http://www.opengis.net/swe/2.0" xsi:type="ns:DataArrayPropertyType">
        <ns:DataArray>
          <ns:elementCount>
            <ns:Count>
              <ns:value>6</ns:value>
            </ns:Count>
          </ns:elementCount>
          <ns:elementType name="Components">
            <ns:DataRecord>
              <ns:field name="average">
                <ns:Quantity>
                  <ns:uom code="Volt"/>
                </ns:Quantity>
              </ns:field>
              <ns:field name="min">
                <ns:Quantity>
                  <ns:uom code="Volt"/>
                </ns:Quantity>
              </ns:field>
              <ns:field name="max">
                <ns:Quantity>
                  <ns:uom code="Volt"/>
                </ns:Quantity>
              </ns:field>
              <ns:field name="median">
                <ns:Quantity>
                  <ns:uom code="Volt"/>
                </ns:Quantity>
              </ns:field>
              <ns:field name="stddev">
                <ns:Quantity>
                  <ns:uom code="Volt"/>
                </ns:Quantity>
              </ns:field>
            </ns:DataRecord>
          </ns:elementType>
          <ns:encoding>
            <ns:TextEncoding blockSeparator="@@" decimalSeparator="." tokenSeparator=","/>
          </ns:encoding>
          <ns:values>11.98846550416246,11.881150332999999,11.992660266999996,11.991655672999999,0.015039071046842432@@

Der Unterschied zwischen einer observed property für Intervall-Werte und Werte in voller Auflösung ist der Informationsgehalt der Daten und dem Datentyp im XML-Dokument (average, max, min, usw.).

Fazit

Das Master-Projekt ist aus Sicht des Durchführenden erfolgreich verlaufen. Es werden weitere Arbeiten notwendig sein, da die Test-Umgebung einer realen Umgebung mit Meeressonden nur ähnelt. Da keine Dokumentation über die eingesetzte Meeressonde und derer Sensoren zur Verfügung steht, muss ein zufriedenstellender Projektabschluss aus Sicht des HZG zu einem späteren Zeitpunkt stattfinden. Im folgenden werden die erreichten Ergebnisse in Bezug auf die Anforderungen des HZG und der Lernziele aufgelistet. Abschließend gibt es einen Ausblick darüber, welche Arbeiten noch im Zeitraum der Anstellung am HZG erreicht durchgeführt werden und was im weiteren Verlauf an der Software verbessert oder hinzugefügt werden kann.

Ergebnisse

Das Master-Projekt wurde nicht ganz im Zeitrahmen absolviert, da es während die Implementierung des SOS und Editors sehr viel Zeit beansprucht hat. Es gab während der Bearbeitung verschiedene Meetings mit dem HZG, so dass sichergestellt ist, dass die Software den Anforderungen des HZG genügt. Die Anforderung die im Lastenheft im 1. Meeting präsentiert wurden sind alle erfüllt. Die nicht-funktionalen Anforderungen sollten seitens des HZG überprüft werden, sobald eine reale Testumgebung zur Verfügung steht. Die Sensordatenverwaltung ist ein Framework mit dem Kern "Collector" und "Editor". Dieser Teil ist so generisch wie möglich realisiert worden, so dass rein theoretisch nicht nur das HZG diesen Teil verwenden kann. Derzeit ist der Collector in der Lage Datenströme von Sea & Sun Technologie Sensoren zu verarbeiten. Sollten andere Sensoren verwendet werden, so entfallen unter Umständen die Rohwerte und man speichert nur noch Messwerte. Die Observed Property Instances können weiterhin verwendet werden.

Der Editor arbeitet komplett losgelöst von HZG-Metadaten, da bisher nur ein Metadaten-Textfeld für Sensoren angeboten wird, welches aber noch nicht von der SOS-Implementierung verarbeitet wird. Der Teil der Sensor-Metadaten ist sehr wahrscheinlich spezifisch für das jeweilige Institut, welches die Software nutzen würde und müsste jeweils angepasst werden.

Der Sender ist spezifisch für die HZG implementiert worden. Es ist sehr unwahrscheinlich, dass dieser für andere Anwender der Sensordatenverwaltung wiederverwendbar ist.

Die Anbindung der Daten für SOS-Implementierung arbeitet nur lesend auf den Daten. Derzeitig wird in der SOS-Implementierung der Rückgabewert für die Operation DescribeSensor fest einprogrammiert. Der Rückgabewert kodiert die Koeffizienten für die Kalibrierung der Sensoren. Abgesehen von diesem Teil sind die SOS-Metadaten komplett über die Administrationsoberfläche der 52° North SOS-Implementierung einstellbar. Der Rest der SOS-Metadaten wird aus der XML-Datei gelesen. Mit wenig Anpassungen kann diese SOS-Implementierung auch generisch gemacht werden und wiederverwendet werden.

Erfahrung

Durch die Bearbeitung des Projekts wurden zusätzliche Erfahrungen gesammelt oder Wissen vertieft:

  • Korrektes Erstellen von Lastenheften (wurde in bisherigen Lehrveranstaltungen nie als zusammenhängendes geschrieben)
  • Implementierung von Servlets
  • Optimierung von Datenbank-Abfragen
  • Lesen von XML-Standards
  • Validierung von XML-Dokumenten mit XML-Schemata
  • Verwendung von Data Access Objects generiert durch Hibernate Framework
  • Einordnung von SOS/SensorML im Sensor Web Enablement (SWE) und die Zusammenhänge kennenlernen

Ausblick

Da die Software aus dem Projekt erst zu einem späteren Zeitpunkt komplett getestet werden kann, muss zu einem späteren Zeitpunkt die Software weiterentwickelt werden. Bis zu einem Deployment können weitere Verbesserungen und Features realisiert werden.

Der Collector ist derzeit nur in der Lage ein bestimmtes Datenübertragungs-Protokoll einer Sonde zu dekodieren. Bei einem Deployment muss geprüft werden, ob der Teil des Collectors, welcher den Datenstorm dekodiert angepasst werden muss. Falls sich die Datenübertragungs-Protokolle der Meeressonden ähneln, kann das Dekodieren des Protokolls ausgelagert werden. Es ist zum Beispiel Möglich ebenfalls Klassen zu implementieren (ähnlich die Formel-Klassen) um die Datenströme zu dekodieren.

Der Collector kann derzeit nur P und N Sensoren von Sea & Sun durch Formel-Klassen in Messwerte umwandeln. Für die Implementierung von weiteren Formel-Klassen müssen die Handbücher der Sensoren bei einem Deployment untersucht werden. Es wurde vom HZG vorgeschlagen, schon weitere Formel-Klassen zu schreiben, die die Sensor-Typen aus dem vorherigen Projekt unterstützen. Da diese allerdings nicht getestet werden können (nicht in der Datenstrom-Datei vorhanden), wurde darauf verzichtet.

Der Sender kann derzeit nur eine observed property an das HZG senden. Das HZG hat eine Test-Umgebung eingerichtet, worin Werte gespeichert werden können. In der Sender-Implementierung wurde eine beliebige observed property ausgewählt (anhand einer ID aus der Datenbank), welche zur HZG gesendet wird. Diese Auswahl muss aufgehoben werden, so dass alle observed properties zum HZG übertragen werden. Weiterhin überträgt der Sender mit count Query-Parameter nicht die genaue Anzahl der gesammelten Werte aus einem Zeitraum sondern 1. Dies muss noch bis zum Ablauf des Vertrags, durch Verwendung einer 2. Datenbankabfrage pro observed property, implementiert werden.

Im Editor können zwar Metadaten für Sensoren hinterlegt werden, jedoch werden diese nicht von der SOS-Implementierung verarbeitet. Derzeitig wird die Zusammensetzung eines Teils des XML-Dokuments aus der DescribeSensor Antwort in der Implementierung fest einprogrammiert. Dort werden derzeit die Kalibrierungs-Koeffizienten und Namen der observed properties eingebettet. Die Zusammenhänge zwischen dem Metadaten-Feld der Sensoren und dem XML-Dokument müssen noch geklärt werden. Da das HZG eine die Metadaten aus einer eigenen Datenbank bezieht, ist es evtl. möglich, anhand diese Metadaten in das Textfeld zu kopieren und daraus die relevanten zu extrahieren und für SensorML 2.0 neu zu kodieren. Das HZG betrachtet bisher die Metadaten einer kompletten Meeressonde. Das derzeitige Datenmodell sieht nicht vor, dass Meeressonden mit dem Editor beschrieben werden können. Die Metadaten setzen sich aus den kompletten Metadaten der Sensoren einer Meeressonde zusammen. Durch diese Möglichkeit ist eine höhere Flexibilität und Wiederverwendbarkeit bei der Beschreibung gegeben.

Bei der Konzeption wurde bereits erwähnt, dass in einem Meeting vorgeschlagen wurde, den Collector und Sender nicht als Servlet zu implementieren. Dies widerspricht zumindest das 1. Meeting, indem vorgeschlagen wurde, alles in einer Tomcat-Instanz zu deployen, damit ein einheitlicher Systemlog und eine zentrale Administration möglich ist. In einer zukünftigen Version kann der Collector und Sender als eigenständige Java-Anwendung implementiert werden, die dann vom Servlet gestartet wird. Durch diese Realisierung sind beide Alternativen möglich.

Der Editor kann zur vollständigen Administrationsoberfläche aufgerüstet werden. Derzeitig ist der Editor in der Lage auf Datenbank auf anderen Laufzeitumgebungen zuzugreifen. Mit einem Server/Client-Prinzip können weitere Informationen von Collector, Sender und SOS übertragen werden. Dadurch dass der Editor als zentrale Administrationsoberfläche dienen würde, müsste man sich nur zur Wartung im Fehlerfall (oder Abrufen der CSV-Dateien) mit der Laufzeitumgebung durch Nutzten von Remote Desktop Applications verbinden.

Es sollte weiterhin untersucht werden, ob die Datenbank mit zusätzlichen Constraints ausgestattet werden können, um das Datenmodell robuster zu gestalten. Die Optimierung der Datenbank-Anfragen ist ebenfalls sinnvoll. Beim Ausführen verschiedener Tests bzgl. der SOS-Implementierung wurde die Dauer für ein Abfrage von Daten in einer Woche auf einem Datenbestand von einem Jahr untersucht. Es wurden ca. 35 Sekunden benötigt. Durch ein Hinzufügen eines Indexes über die Zeitstempel-Spalte konnte die Dauer der kompletten Anfrage auf unter 1 Sekunde gesenkt werden. Sobald die SOS-Implementierung auf einem realen Datenbestand arbeitet sollte mit verschiedenen Aufrufen geprüft werden, ob noch Optimierungen vorgenommen werden müssen.

Ein Teil der Arbeiten kann noch während der Anstellung am HZG durchgeführt werden. In Rücksprache mit Herrn Breitbach sollte geklärt werden, was noch während des Arbeitsverhältnisses zu tun ist. Der Durchführende des Projekts hat sich bereit erklärt, auch nach der Anstellung weiterhin die Software zu erweitern, für das HZG zu optimieren und bei dem Deployment anwesend zu sein.

Als Abschluss sollte nach dem Deployment und den erfolgreichen Tests ein Gesamt-Abschluss am HZG erfolgen. Daran teilnehmen sollten die Teilnehmer des 1. Meetings teilnehmen mit denen die Anforderungen durchgesprochen wurden.

Quellen und Verweise

  1. [1] Modulhandbuch für den Studiengang M. Sc. Informatik der Hochschule RheinMain
  2. [2] Meeressonde der Firma Sea & Sun Technologies
  3. [3] PAC 4000 Embedded PC
  4. [4] rrdtool round robin database
  5. [5] Sensor Observation Service
  6. [6] Helmholtz-Zentrum Geesthacht
  7. [7] 52° North
  8. [8] Kontaktformular Herr Jirka (52° North)
  9. [9] Offizielle CF (Climate and Forecast) Standard-Metadaten für Messsysteme
  10. [10]RXTX
  11. [11] Java Simple Serial Connector
  12. [12] DescriptiveStatistics der Apache Commons Math3 Bibliothek
  13. [13] SensorML-Dokumente
  14. [14] SensorML 2.0
  15. [15] SensorML 1.0
  16. [16] SensorML 1.0.1 Corrigendum
  17. [17] SensorML-XML-Schemata
  18. [18] Ontology Repository: General Sensor Community
  19. [19] Ontology Repository: Open Geospatial Consortium
  20. [20] Ontology Repository: Semantic Web for Earth and Environmental Terminology (SWEET)
  21. [21] Ontology Repository: Marine Metadata Interoperability
  22. [22] Beschreibung einer Wetterstation mit SensorML 2.0
  23. [23] Beschreibung eines einzelnen Sensors in SensorML 2.0
  24. [24] SOS-Dokumente
  25. [25] SOS 1.0 (OpenGIS)
  26. [26] SOS 2.0 (OGC)
  27. [27] OGC Observations & Measurements Standard-Dokumente
  28. [28] VOGC Observations & Measurements Standard 2.0
  29. [29] OGC Web Services Common Specification
  30. [30] OpenGIS SWE Service Model
  31. [31] OpenGIS SWE Service Model
  32. [32] Geographic Information - Observation and Measurements 2.0
  33. [33] SOS 2.0 GetCapabilities Request
  34. [34] SOS 2.0 GetCapabilities Response
  35. [35] SOS 2.0 GetObservation Request
  36. [36] SOS 2.0 GetObservation Response
  37. [37] 52° North SOS-Implementierung
  38. [38] 52° North SOS Importer
  39. 39,0 39,1 [39] 52° North SOS Database Model
  40. [40] Eclipse for Java EE Developers
  41. [41] Apache Tomcat
  42. [42] Apache Ant Buildsystem
  43. [43] Hibernate Framework Downloads
  44. [44] Apache Maven Buildsystem
  45. [45] Sourcecode der Software des Projekts im SVN Repository der Hochschule RheinMain
  46. [46] Fork der 52° North SOS-Implementierung im github repository des Projektdurchführenden
  47. [47] 52° North Mailinglist Problems using embedded PhysicalComponent