Mittwoch, 7. Juli 2010

UbiSense-Probleme und ihre Lösung

Für unseren Prototyp haben wir uns vorerst für die Ortung via UbiSense entschlossen. Da der UbiSense-Server am Lehrstuhl schon fertig aufbereitete Positionsdaten im XML-Format versendet, gibt es in diesem Fall nämlich angenehm wenige Störfaktoren auf unserer Seite. Das einzige Problem ist es nun, an die Daten heranzukommen.

Die Kommunikation läuft folgendermaßen ab:
1) Zunächst muss man ein UbiSense-Endgerät beim Server auf seine IP-Addresse registrieren, damit man die Daten überhaupt erst einmal zugesendet bekommt.
2) Danach fängt der Server an, UDP-Pakete mit den XML-Daten auf einem bestimmten Port zu senden. Diese müssen empfangen und interpretiert werden.

Der erste Punkt ist relativ schnell in Processing geschrieben, wenn man die mitgelieferte Network-Library nutzt:

import processing.net.*;

Client ctrlMsg;
String ubisenseId = "020-000-024-100";

void setup()
{
    size(200,200);
    ctrlMsg = new Client(this, "137.226.56.44", 3501);
    ctrlMsg.write("register " + ubisenseId + " " + ctrlMsg.ip());
}


Nun gilt es allerdings, Daten auf dem UDP-Port zu empfangen und zu parsen. Der Empfang war das erste Problem. Zunächst mal wunderten wir uns, dass wir die Daten zwar im Terminal anschauen konnten, es uns aber nicht möglich war, mit Processing an die Daten zu kommen. Wie wir später herausgefunden haben, spricht Processing von Hause aus kein UDP und konnte damit auch nichts mit den eintreffenden Paketen anfangen.
Zum Glück gibt es eine Library, die grundlegende UDP-Funktionalitäten zur Verfügung stellt. Also schon einmal ein Problem weniger. Als nächstes müssen die XML-Daten geparsed werden. Natürlich könnte man jetzt eine Library fürs Parsen von XML-Daten hernehmen oder gar selbst implementieren, aber weil die zu parsenden Daten ja doch relativ speziell sind, haben wir uns nun doch für reguläre Ausdrücke entschieden (es ist einfach unglaublich viel einfacher). Das ganze (Empfang von Daten und Parsen) sieht in Processing dann so aus:

import hypermedia.net.*;

UDP udp;
String[] posData = new String[4];

void setup()
{
    udp = new UDP(this, 3501);
    udp.listen(true);
}

void receive(byte[] data)
{
    String inputString = new String(data);  
    String[] id = match(inputString, "id=\"([^\"]*)\"");
    String[] posX = match(inputString, "posX=\"([^\"]*)\"");
    String[] posY = match(inputString, "posY=\"([^\"]*)\"");
    String[] posZ = match(inputString, "posZ=\"([^\"]*)\"");
    posData[0] = id[1];
    posData[1] = posX[1];
    posData[2] = posY[1];
    posData[3] = posZ[1];
}



In posData stehen nun also die aktuellen Positionsdaten.

Der nächste Schritt ist jetzt, den ganzen Kram auch am UbiSense-Server zu testen. Es funktioniert zwar mit einem Testprogramm, dass ähnliche Botschaften auf einen UDP-Port sendet, aber man weiß ja nie.

Ein weiteres Ziel: Die XBee-Module dazu bewegen, wieder mit uns zu sprechen. Wenn sie sich dazu dann mal entschließen sollten, können wir die restliche Kommunikation fertig machen. Im Grunde muss der Arduino ja jetzt nur noch per XBee alle paar Sekunden die aktuelle Position anfragen und von Processing zugeschickt bekommen. Dazu aber dann später mehr, jetzt naht das Halbfinale und ich habe keine Lust mehr, noch länger vorm Rechner zu sitzen ;)

Keine Kommentare:

Kommentar veröffentlichen