Fernsteuerung eines Modellfahrzeugs durch zwei Android-Smartphones Remote control of a model vehicle by using two Android-powered mobile phones

Größe: px
Ab Seite anzeigen:

Download "Fernsteuerung eines Modellfahrzeugs durch zwei Android-Smartphones Remote control of a model vehicle by using two Android-powered mobile phones"

Transkript

1 Fakultät Elektrotechnik & Informatik Bachelor-Thesis Fernsteuerung eines Modellfahrzeugs durch zwei Android-Smartphones Remote control of a model vehicle by using two Android-powered mobile phones Sven Nobis 17. Juli 2012 Betreut durch Prof. Dr. rer. nat. Ulrich Breymann Prof. Dr.-Ing. Heiko Mosemann Zusammenfassung: Ziel der Bachelor-Thesis ist es, ein ferngesteuertes Modellfahrzeug zu entwickeln. Dafür sollten zwei Android-Smartphones genutzt werden. Eines der Smartphones ist auf dem Modellfahrzeug befestigt und steuert die Motoren an. Es ist mit dem zweiten über WLAN oder Mobilfunk verbunden. Mit Hilfe des zweiten Smartphones kann der Benutzer das Fahrzeug aus der Ferne steuern. Durch die Nutzung der Smartphones sollten unter anderem das Kamerabild und die Position des Fahrzeugs übertragen werden. Ein versionierbares Protokoll sollte spätere Erweiterungen möglich machen. Die beschriebenen Ziele der Thesis konnten alle zufriedenstellend umgesetzt werden.

2 Erklärung Hiermit versichere ich, dass ich die vorliegende Arbeit selbstständig gefertigt habe und die angegebenen Quellen und Hilfsmittel in einem vollständigen Verzeichnis enthalten sind. Alle Stellen der Arbeit, die aus anderen Werken dem Wortlaut oder dem Sinne nach entnommen sind, gegebenenfalls auch aus elektronischen Medien, wurden eindeutig unter Angabe der Quellen als Entlehnung gekennzeichnet. Außer den genannten wurden keine Hilfsmittel verwendet. Bremen, den 17. Juli 2012 Ort, Datum Unterschrift

3 Ich möchte mich bei meinen Kollegen in der Commerz Systems und bei meiner Familie für die Unterstütztung bei dieser Arbeit bedanken. Legende Quellenangaben sind im Text in eckigen Klammern mit einem Verweis auf den Eintrag im Literaturverzeichnis dargestellt. Gegebenenfalls enhält die Angabe noch die Seitezahl bzw. den Abschnitt in der Quelle. Zitate sind eingerückt, von Anführungszeichen umfasst und mit einer Quellenangabe versehen. Bezeichner für Symbole, wie Klassennamen, Methodennamen oder Feldnamen, sind durch nichtproportionale Schrift erkennbar. Methoden sind durch die Klammern hinter dem Methodnamen erkennbar. Der Übersichtlichkeit halber werden die Parameter größtenteils weggelassen. Dies wird durch... gekennzeichnet. Beispiel: methodenname(...)

4 Inhaltsverzeichnis 1 Einführung 6 2 Anforderungen Funktionale Anforderungen Schnittstelle zwischen Mikrocontroller und Smartphone Schnittstelle zwischen den beiden Smartphones Grenzen, Einschränkungen und Nicht-Ziele Systementwurf 10 4 Subsystementwurf Hardware ADK-kompatibles Entwicklungsboard Fahrgestell mit Motoren Schaltung zur Ansteuerung der Motoren Dreh und schwenkbare Halterung für das Smartphone Batterie zur Energieversorgung mitmessschaltung Schaltung zur Messung der verbleibenden Leistung Übersicht der Bauteile und Kosten Beschreibung der Schnittstellen Schnittstelle zwischen den beiden Smartphones Nachrichten zum Client Nachrichten zum Host Übertragung des Kamerabilds Schnittstelle zwischen Mikrocontroller und Smartphone Befehle an den Mikrocontroller Antworten vom Mikrocontroller Fehlercodes des Mikrocontrollers Subsystementwurf: Software auf dem Mikrocontroller Externe Bibliotheken Architektur Paket AndroidRCCar Paket AndroidRCReferenceCar Ablauf der Methode loop() Subsystementwurf: Software für das Smartphone Softwareentwicklung für Android Gesamtarchitektur Externe Bibliotheken Paket communication Verbindungsaufbau zum Client Paket accessorycommunication Architektur Ablauf der Verarbeitung eines Befehls Sven Nobis Seite 4 von 110

5 7.5.3 Verbindungsaufbau zum Mikrocontroller Paket logic Abstrakte Logik Client Logik Host Logik Paket framework DependencyContainer Factory Paket services Paket presentation und controller im Host Paket presentation im Client Sonstige Pakete Benutzeroberfläche Host Client Realisierung Hardware Software Benutzeroberfläche Komponententest Testziel Testwerkzeuge Werkzeuge für den Test der Smartphone-Software Werkzeuge für den Test der Mikrocontroller-Software Testumgebung Smartphone-Software Mikrocontroller-Software Testfälle Software für das Smartphone: Common Software für das Smartphone: Host Software für das Smartphone: Client Software auf dem Mikrocontroller Systemtest Testziel Testumgebung Testfälle Fazit und Ausblick 103 Tabellenverzeichnis 104 Abbildungsverzeichnis 106 Literatur 108 Sven Nobis Seite 5 von 110

6 1 Einführung Gängige ferngesteuerte Modellfahrzeuge sind darauf ausgelegt, dass eine Person das Fahrzeug aus der Nähe fernsteuert. Zum einen ist Sichtkontakt zum Fahrzeug für eine sinnvolle Nutzung nötig und zum anderen ist auch die Reichweite des Funkmoduls beschränkt. Möchte man diese Einschränkung aufheben oder das Modellfahrzeug gar autonom fahren lassen, so wird weitere Hardware benötigt. Eine Lösung wäre es, die Steuersignale und das Bild einer Kamera über das Internet zu übertragen. Zur weiteren Unterstüzung oder für die autonome Steuerung könnten unter anderem das Satellitennavigationssystem GPS, ein Beschleunigungssensor oder ein digitaler Kompass eingesetzt werden. Die Kosten für diese Hardware wären dann jedoch weitaus höher als für das ursprüngliche Modellfahrzeug. Moderne Smartphones bringen in der Regel die aufgezählten Hardwaremodule schon mit und liefern dazu auch eine gute Plattform zur Nutzung dieser. Eine sehr verbreitete Plattform ist das freie und von vielen Herstellern genutzte Betriebsystem Android. Ziel der Bachelor-Thesis ist es, unter Nutzung der beschriebenen Möglichkeiten zweier Android- Smartphones, ein ferngesteuertes Modellfahrzeug zu entwickeln. Durch die Nutzungen der beiden Smartphones sollen die Anschaffungskosten für die weitere Hardware gering sein. Sven Nobis Seite 6 von 110

7 2 Anforderungen Wie in der Einführung bereits erwähnt, sollen zwei Android-Smartphones genutzt werden, um ein fernsteuerbares Fahrzeug zu realisieren. Dabei soll eins der Geräte dem Benutzer zur Fernsteuerung dienen und mit dem zweiten Gerät über TCP/IP kommunizieren. Das zweite Gerät ist auf dem Fahrzeug befestigt. Es verarbeitet die empfangenen Steuerbefehle und sendet die Daten der Sensoren zurück. Zur Ansteuerung der Motoren oder anderer Aktoren und Sensoren auf dem Fahrzeug soll ein Mikrocontroller eingesetzt werden. Die Kommunikation zwischen dem Android Smartphone und dem Mikrocontroller soll über das von Android angebotene Android Open Accessory Development Kit (ADK) realisiert werden. Dabei werden die beiden Geräte mittels des Universal Serial Bus (USB) verbunden. Die Abbildung 1 zeigt den beschriebenen Aufbau des Gesamtsystems grafisch. Microcontroller Abbildung 1: Aufbau des Systems 2.1 Funktionale Anforderungen An das zu entwickelnde System werden die folgenden funktionalen Anforderungen gestellt: Möglichkeiten der Fernsteuerung Fahrtrichtungen: Vorwärts, Rückwärts, Halt Regelbare Geschwindigkeit Lenken nach Links und Rechts Drehen und Schwenken des Smartphones und somit der Kamera auf dem Fahrzeug im Bereich von je 180 (siehe Abbildung 2 auf der nächsten Seite) Übertragung vom Smartphone des Fahrzeugs und Anzeige auf der Fernsteuerung Bild der Kamera Position des Fahrzeugs Sven Nobis Seite 7 von 110

8 Als Entfernung zur eigener Position (z.b. 500 m nördlich ) Optional auf Karte Blickrichtung (Himmelsrichtung) Ungefähre verbleibende Akkuleistung des Fahrzeugs Geht die Verbindung vom Smartphone zum Mikrocontroller oder zum anderen Smartphone verloren, so soll das Fahrzeug stoppen ~180 Mobiltelefon Fahrzeug ~180 Kamera Mobiltelefon Abbildung 2: Rotationsbereich der Kamera (bzw. des Smartphones) 2.2 Schnittstelle zwischen Mikrocontroller und Smartphone Wie in Abschnitt 2 auf der vorherigen Seite beschrieben, soll die Kommunikation über USB mittels des ADK umgesetzt werden. Dabei soll ein Protokoll entwickelt werden, welches erweiterbar ( versioniert) ist und den Austausch des Fahrzeugs inklusive Mikrocontroller erlaubt. So soll der Mikrocontroller mitteilen können, welche Version vom Protokoll er implementiert hat und welche Funktionen er unterstützt. Die Mindestanforderung an ein Fahrzeug ist, dass es lenkbar ist, stoppen und vorwärtsfahren kann. Sven Nobis Seite 8 von 110

9 2.3 Schnittstelle zwischen den beiden Smartphones Ebenso wie bei der Schnittstelle zwischen dem Mikrocontroller und Android, muss zwischen den beiden Android-Smartphones ein Protokoll entwickelt werden. Dieses soll ebenfalls erweiterbar sein und die unterstützten Funktionen des Fahrzeug übertragen können. Die Übertragung des Kamera-Bildes und der Position soll abschaltbar sein. 2.4 Grenzen, Einschränkungen und Nicht-Ziele In folgender Auflistung wird darauf eingegangen, was in der Bachelor-Thesis nicht betrachtet wird und was als Vorraussetzung angesehen wird. Kommunikation zwischen den beiden Smartphones Eine ausreichende Bandbreite wird vorrausgesetzt. Es wird davon ausgegangen, dass eine direkte Kommunikation möglich ist; sich die Smartphones also im gleichen Netz befinden. Mögliche Probleme z.b. durch Network Address Translation werden nicht betrachtet. Protokolle In den Schnittstellen werden nur für das Projekt relevante Funktionen definiert. Mögliche weitere Funktionen, wie z.b. die Übertragung von weiteren Sensordaten, werden in den Protokollen nicht definiert. Echtzeitverhalten ist keine Anforderung an das System, d.h. die maximale Reaktionszeit bei der Steuerung und die maximale Verzögerung des Videosignals sind nicht vorgegeben. Sven Nobis Seite 9 von 110

10 3 Systementwurf Anhand der gestellten Anforderungen (Abschnitt 2 auf Seite 7) wird im folgendenen das System entworfen. Das System kann in drei Subsysteme aufgeteilt werden: Hardware, Software für den Mikrocontroller und Software für die beiden Smartphones. Außerdem müssen die beiden Schnittstellen entworfen werden. Die Abbildung 3 zeigt das System mit den Subsystemen und Schnittstellen grafisch. Das Subsystem Hardware wird im Abschnitt 4 auf der nächsten Seite beschrieben. In diesem wird darauf eingegangen, wie das Fahrzeug aufgebaut werden soll und welche Komponenten benötigt werden. Danach folgen die beiden Schnittstellenbeschreibungen im Abschnitt 5 auf Seite 23: Die Schnittstelle zwischen den beiden Smartphones (Schnittstelle 1 in Abbildung 3), sowie die Schnittstelle zwischen dem Mikrocontroller und dem Smartphone auf dem Fahrzeug (Schnittstelle 2). Danach folgt der Subsystementwurf für die Software des Mikrocontrollers (Abschnitt 6 auf Seite 40) und der Software für das Android-Smartphone (Abschnitt 7 auf Seite 45). Subsystem Hardware Subsystem: Smartphone Software Schnittstelle 1: Subsystem: Smartphone Software Schnittstelle 2: Subsystem: Mikrocontroller Software Abbildung 3: Aufbau des Systems Sven Nobis Seite 10 von 110

11 4 Subsystementwurf Hardware In diesem Kapitel wird der Aufbau der Hardware beschrieben. Dabei wurde die Hardware des Fahrzeug in fünf Komponenten unterteilt, die in den folgenden Abschnitten betrachtet werden: ADK-kompatibles Entwicklungsboard Fahrgestell mit Motoren Schaltung zur Ansteuerung der Motoren Dreh und schwenkbare Halterung für das Smartphone Batterie zur Energieversorgung mitmessschaltung Im Anschluss daran werden alle benötigten Bauteile aufgelistet und die Kosten angegeben. 4.1 ADK-kompatibles Entwicklungsboard Die Anforderungen geben vor, dass die Kommunikation mittels des ADK umgesetzt werden soll. Dabei muss ein ADK-kompatibles Entwicklungsboard ausgewählt werden. Es handelt sich in der Regel um ein Entwicklungsboard, welches neben einen Mikrocontroller auch einen USB-Host- Controller verbaut hat. Der Mikrocontroller kann mittels dieses Controllers wie ein normaler Computer USB-Geräte verwenden. Der Accessory Development Kit 2011 Guide [1] bietet eine (unvollständige) Liste der kompatiblen Entwicklungsboards an. DasArduino ADK (Abbildung 4 auf der nächsten Seite) zählt zu den bekanntesten ADK-kompatiblen Boards und wird direkt von der Firma Arduino hergestellt. Diese betreut die sehr verbreitete und quelloffene Arduino-Plattform. Dazu entwickelt sie die ebenfalls quelloffenen Boards. Das Board bietet zudem eine Vielzahl an Schnittstellen. Diese Gründe waren ausschlaggebend, um in diesem Projekt eingesetzt zu werden. Auf dem Arduino ADK ist ein ATmega2560 verbaut. Dieser ist ein 8-bit AVR Mikrocontroller von Atmel mit 8 KB RAM und 16 MHz Takt. Der ATmega2560 ist über ein serielles Interface verbunden mit dem USB-Host-Controller MAX3421E von Maxim Integrated Products [7]. Dieser ermöglicht die Kommunikation mit dem Smartphone. Sven Nobis Seite 11 von 110

12 Abbildung 4: Arduino ADK Board [7] 4.2 Fahrgestell mit Motoren Das Fahrgestell des Fahrzeugs muss ausreichend Platz für die Komponenten bieten. Außerdem dürfen dabei die anderen Komponenten nicht den Sichtbereich der Kamera des Smartphones beinträchtigen. Die Auswahl fiel hier auf die 4WD Mobile Plattform von DFRobot (siehe Abbildung 5 auf der nächsten Seite). Das Fahrgestell bringt pro Rad einen Motor mit und bietet Platz für die Komponenten auf drei Ebenen. Anhand der Maße in der Spezifikation (siehe unten) und der Abbildung, sollen die Koponenten wie folgt platziert werden: Obere Ebene: Eine Halterung für das Smartphone und die Batterie Mittlere Ebene: Mikrocontroller und Motor-Ansteuerung Untere Ebene: Motoren und Schaltung zur Messung der verbleibenden Leistung; (ggf. Batterie) Die Beschreibung auf der Webseite des Herstellers liefert folgende Spezifikationen [32]: Specification 4WD Mobile platform Motors: 3-12V DC Speed: 90cm/s Dimensions: 200mm x 170mm x 105mm Motor Specification Gear Ratio: 1:120 No-load speed(3v): 100RPM No-load speed(6v): 200RPM No-load current(3v): 60mA No-load current(6v): 71mA Stall current(3v): 260mA Stall current(6v): 470mA Sven Nobis Seite 12 von 110

13 Abbildung 5: DFRobot 4WD Mobile Platform [32] Torgue (3V): 1.2Kgcm Torque (6V): 1.92Kgcm Size: 55mm x 48.3mm x 23mm Weight: 45g Es wird also eine Motor-Ansteuerung benötigt, die vier Gleichstrommotoren mit einer Maximallast von 470 ma pro Motor bei ca. 6 V ansteuern kann. 4.3 Schaltung zur Ansteuerung der Motoren Für die Motor-Ansteuerung wurde das Motor Shield von ladyada.net (siehe Abbildung 6 auf der nächsten Seite) gewählt. Die Platine ist mit Arduino kompatibel und auch dafür getestet. So lässt es sich, wie die meisten sogenannten Arduino Shields, direkt auf das Arduino ADK Board stecken. Außerdem ist das Design der Platine offen (Open Source), so dass es von verschiedenen Herstellern erworben werden kann [19]. Auf dem Shield sind zwei L293D-ICs verbaut. Ein L293D beinhaltet vier Halb-H-Brücken Treiber, mit denen sich zwei Gleichstrommotoren bidirektional betreiben lassen. Es können also alle vier Motoren einzeln angesteuert werden. Dabei steht jedem Motor ein maximaler Strom von 600 ma zur Verfügung, damit außreichend um die volle Leistung der Motoren zu nutzen. Der c t-artikel Spielgefährten - Roboter für Löter, Simulator für Soft-Werker von 2006 erläutert die Funktionweise der H-Brückenschaltung sehr treffend [16, S. 134]: Eine H-Brücke verbindet die Gleichstrommotoren direkt mit der Batteriespannung, die TTL-Pegel des Mikrocontrollers liefern nur die Steuersignale. Da die Laufrichtung Sven Nobis Seite 13 von 110

14 Abbildung 6: Motor Shield von ladyada.net [19] von der Polung abhängt, benötigt jeder Motor vier Schalter [...]. Dennoch ergeben nur drei Konstellationen Sinn, alle anderen führen zum Kurzschluss: Sind zwei sich diagonal gegenüberstehende Schalter geschlossen und alle anderen offen, so dreht sich der Motor rechts- oder linksherum je nach Polung. Öffnet man mindestens drei Schalter, steht der Motor still. Der Baustein L293D [...] erwartet pro Motor die Drehrichtung auf zwei Pins einmal invertiert und einmal direkt sowie ein Enable- Signal. Nur wenn dieses auf High steht, schaltet er den Motor an. Speist man diesen Eingang mit einem PWM-Signal (Pulsweitenmodulation), so lässt sich auch die Drehgeschwindigkeit regeln. Ein PWM-Signal besteht aus einem Rechteck mit fester Grundfrequenz. Man verschiebt nur die Anteile der Low- und High-Pegel. Soll der Motor auf voller Geschwindigkeit laufen, so wird t low null und das Signal ist die ganze Zeit high. Zum Deaktivieren des Motors setzt man t h igh gleich null. Für eine mittlere Geschwindigkeit können beide Zeiten identisch sein. Es gilt dabei immer: t low + t high = 1/f P W M = konstant. Da die Gleichstrommotoren träge sind, reagieren sie nur auf den zeitlichen Mittelwert der Spannung. Dieser ergibt sich zu: V eff = V In t high /(t high + t low ) Die Abbildung 7 auf Seite 16 zeigt den Schaltplan des Motor Shield. In der Mitte und rechts sind die L293D-Treiber zu sehen; auf der linken Seite das Mapping zum Arduino (hier ein Arduino Duemilanove; Portbelegung ist jedoch gleich). Die Pins zur Drehrichtung werden nicht direkt zum Arduino geleitet sondern über einen 74HC595-IC gesetzt. Mittels eines seriellen 8-bit- Signals können dort 8 parallele Ausgänge am IC geschaltet werden [27]. Dadurch ist es möglich, die Drehrichtung aller vier Motoren mit nur 4 Pins zu schalten, anstatt der sonst 8 benötigten Pins. An die in Abbildung 6 auf der linken und rechten Seite sichtbaren Anschlussleiste werden die Sven Nobis Seite 14 von 110

15 Motoren angeschlossenen. Die Anschlüsse sind von M1 bis M4 beschriftet und sollen wie folgt mit den Motoren verbunden werden: M1 Hinten links (PWM2A) M2 Hinten rechts (PWM2B) M3 Vorne rechts (PWM0A) M4 Vorne links (PWM0B) Die Werte in den Klammern referenzieren sich auf die Benennung des Enable-Pins im Schaltplan (Abbildung 7 auf der nächsten Seite). Die Belegung wurde so gewählt, dass die Anschlüsse jeweils an der Stelle positioniert sind, an dem der Motor liegt. Vorraussetzung dafür ist, dass derarduino ADK mit dem USB-Anschluss zur Rückseite eingebaut wird. Sven Nobis Seite 15 von 110

16 Abbildung 7: Schaltplan des Motor Shield von ladyada.net [19] Sven Nobis Seite 16 von 110

17 4.4 Dreh und schwenkbare Halterung für das Smartphone Soll das Bild der Kamera drehbar und schwenkbar durch den entfernten Benutzer sein, so müssen Motoren zum Einsatz kommen, die das gesamte Smartphone drehen oder schwenken können. Dabei reicht es nicht aus, dass sich die Motoren nur dehen lassen. Sodern sie müssen sich auch zu einer bestimmten Position drehen lassen. Außerdem muss die Kraft ausreichen, um das Gerät zu drehen und danach an der Position zu halten. Im Modellbau werden für ähnliche Aufgaben oft Servos eingesetzt. Jürgen Plate beschreibt in seinem Buch Linux Hardware Hackz diese folgendermaßen [28, S.237]: Servos ( Rudermaschinen ) aus dem Modellbaubereich sind trotz der Betriebsspannung von 5 Volt besonders kräftige Antriebe. Ihr hohes Drehmoment wird durch ein Üntersetzungsgetriebe erreicht. Ein Servoantrieb besteht aus einem Motor, einem auf der Achse angebrachten Positions- oder Winkelsensor (im einfachsten Fall ist das ein Potentiometer) und einer Regelelektronik mit Sollwert-Eingang. Diese vergleicht den eingegebenen Sollwert mit dem Istwert des Sensors. Stimmen beide nicht überein, so lässt die Regelung den Motor zu der Position laufen, bei der Istwert und Sollwert gleich sind. Diese elektronische Motorsteuerung ermöglicht nicht nur ein sehr feinfühliges und genaues Stellen des Antriebs in eine bestimmte Position, sie sorgt auch für ein kräftiges Gegenmoment gegen Rückstellversuche der Last und hält damit die gewünschte Position. Anhand der eben beschriebenen Eigenschaften lässt sich folgern, dass zwei Servos ideal geeignet sind. So lassen sie sich auch direkt mit der Spannungsversorgung des Arduino betreiben und auch sehr einfach ansteuern (siehe Abschnitt auf Seite 42). Der Hersteller Dagu bietet dazu das Pan/Tilt-Kit in Abbildung 8 an. Dieses beinhaltet zwei kleine Servos mit Befestigungsteilen, so dass sich daraus eine Dreh- und Schwenkbare Plattform ergibt. Die Servos lassen sich in einem Bereich von 170 drehen und können an das Motor Shield angeschlossen werden. Dieses bietet zwei Anschlüsse für Servos (links oben in Abbildung 6 auf Seite 14). Die Belegung der Anschlüsse lässt sich dem Schaltplan in Abbildung 7 auf der vorherigen Seite entnehmen (ebenfalls links oben). Die Befestigung des Smartphones kann über Klett-Kabelbinder oder ähnliches erfolgen. Abbildung 8: Sensor pan/tilt kit [10] Sven Nobis Seite 17 von 110

18 Bachelor-Thesis 17. Juli Batterie zur Energieversorgung mitmessschaltung Das Arduino ADK kann mit einer Eingangsspannung von 6 bis 20V arbeiten. Jedoch wird empfohlen das Board im Bereich von 7 bis 12 V zu betreiben. Wird weniger als 7 V geliefert, kann es sein, dass der 5V-Pin weniger als 5V liefert. Wird dass Board mit mehr als 12V betrieben, kann das Spannungsreglermodul u berhitzen und das Board scha digen [7, Abschn. Power ]. Laut Angaben des Herstellers beno tigt das Board eine Stromversorgung von 1,5 A. Dabei fallen 750 ma fu r den Mikrocontroller und das Smartphone ab und maximal 750 ma fu r die angeschlossenen Aktoren und Sensoren [7, Abschn. Power ]. Damit werden zu einem die Servo-Motoren betrieben und zum anderen die Logik der Motor-Ansteuerung. Neben dem Board beno tigen noch die Antriebsmotoren Strom. Diese werden u ber einen weiteren VCC -Pin der Motor-Ansteuerung versorgt. Laut Datenblatt, des verwendeten L293D-Treibers, arbeitet die Motor-Ansteuerung bei 4,5 V bis 36 V, die Motoren von 3 bis 12 V. Die Spitzenlast kann bei 1,2 A pro Kanal liegen. Die Normallast bei 600 ma [31, S. 1]. Somit muss die Batterie eine Spitzenlast von 4 1, 2 A + 1, 5 A = 6, 3 A liefern ko nnen. Ausgewa hlt wurde ein 2-Zellen Modellbau Lithium-Polymer-Akkumulator, wie in Abbildung 9 dargestellt. Die auch LiPo gennanten Akkumulatoren werden im Modellbau fast ausschließlich eingesetzt, da sie sehr hohe Stro me liefern ko nnen und auch nach vielen Ladevorga ngen kaum messbar an Leistung verlieren. So ist die Spitzenlast von 6, 3 A kein Problem fu r den Akku. So kann z.b. der Akku in der Abbildung 9 dauerhaft 55 A liefern (bis er leer ist). Jede Zelle hat eine Nennspannung von 3,7 V. Bei zwei Zellen, in Reihe geschaltet, liegt die Nennspannung bei 7,4 V. Die Ladeschlussspannung pro Zelle betra gt 4,22 V. Die Spannungen liegen also innerhalb des empfohlenen Arbeitsbereichs des Mikrocontrollers und der Motoren. Eine Zelle sollte nicht unter 3 Volt entladen werden, da sie sonst irreperabel bescha digt wird. Empfohlen wird es, den Akku zu laden, sobald die Zellspannung unter 3,3 V sinkt [11, Abschn. Grundlagen ] [22]. Abbildung 9: Ein 2-Zellen Lithium-Polymer-Akkumulator fu r den Modellbau Schaltung zur Messung der verbleibenden Leistung Zum Schutz der Batterie muss also einemessschaltung entworfen werden, mit die der Mikrocontroller die Zellspannungen der beiden Zellen messen kann. Sobald die Spannung einer Zelle unter 3,3 V fa llt, muss er die Arbeit einstellen und dem Nutzer mitteilen ko nnen, dass die Batterie geladen werden muss. Bei gleichma ßigen Entladung der beiden Zellen, wu rde das bedeuten, dass Sven Nobis Seite 18 von 110

19 die Spannung beider Zellen dann bei 6,6 V liegt. Da der Mikrocontroller nicht unter 7 V betrieben werden sollte, ist es sinnvoll zu prüfen, ob der Grenzwert nicht schon bei 3,5 V gesetzt wird. Über den Balancer-Stecker (weißer Stecker in Abbildung 9 auf der vorherigen Seite) können die Spannungen der einzelnen Zellen des Akkus abgegriffen werden. Die drei Adern sind im Normalfall wie folgt belegt: Minuspol (Schwarz), Pluspol Zelle 1 (Gelb), Pluspol Zelle 2 (Rot). Der Mikrocontroller kann über die analogen Eingänge Spannungen von 0 V bis zur Referenzspannung von 5 V messen. Der Pluspol der Zelle 1 kann also direkt gemessen werden. Da die Zellen in Reihe geschaltet sind, messen wir zwischen dem Pluspol von Zelle 2 bis zum Minuspol beide Zellen. Da die Spannung beider Zellen über 5 V liegt, muss die Spannung zuerst mit einem Spannungsteiler geteilt werden. Dazu werden zwei 100kΩ Widerstände in Reihe geschaltet und die Spannung vor dem zweiten Widerstand abgegriffen. Dadurch erhält man genau die Hälfte der Spannung beider Zellen. Dies lässt sich durch die Gleichung (1) bis Gleichung (5) beweisen [20, S. 31]. I = I = U 2 R 2 = U ges = U ges (1) R ges R 1 + R 2 U 2 R 2 (2) U ges R 1 + R 2 (3) R 2 U 2 = U ges R 1 + R 2 (4) U 2 = 100kΩ U ges 100kΩ + 100kΩ = 1 2 U Ges (5) Die Abbildung 10 auf der nächsten Seite zeigt den Schaltplan zur Messung der Batteriespannung. (Die Pins auf der linken Seite werden an den Mikrocontroller angeschlossenen.) Der Spannungsteiler wird durch die Widerstände R 1 und R 2 realisiert. Außerdem ist je ein Optokoppler vom Typ LTV 827 hinter den Batterie Pins (V Bat 2Cell und V Bat 1Cell ) geschaltet. Dieser schaltet (durch den Enable-Pin) mittels einer Leuchtdiode eine Fotodiode. Ist die Leuchtdiode nicht geschaltet, isoliert sich die Fotodiode. Dies soll verhindern, dass beim ausgeschalteten Mikrocontroller ein, wenn auch nur sehr kleiner, Strom fließt. Ein Optokoppler wurde für diese Aufgabe gewählt, weil das Schaltpotential von dem Messpotential galvanisch getrennt ist. Es findet also keine Beeinflussung des zu messenden Spannungspotentials durch den zwischengeschalteten Optokoppler statt, wie es bei einem Transistor der Fall wäre [28, S. 201f]. Zwischem den Enable-Pin und den beiden Optokopplern muss je ein Vorwiderstand (R 3 und R 4 ) geschaltet werden. Dieser berechnet sich aus der Eingangsspannung U 0 = 5 V, der typischen Diodenspannung von U F = 1, 2 V und dem Nennstrom von I F = 20 ma. Die Eingangsspannung ist durch den Mikrocontroller gegeben und die letzten beiden Werte durch das Datenblatt des LTV 827 [24, S. 9]. Die Berechnung des Vorwiderstands erfolgt in Gleichung (7) auf der nächsten Seite. Der zu wählende Widerstand sollte mindestens so groß wie der berechnete Wert sein. Ist der Widerstand zu klein, so erhöht sich die Spannung an der Sendediode (U F ) und kann bei einem Sven Nobis Seite 19 von 110

20 Analog In 0 (2Cell) R3 220Ω Enable (IO-Pin 40) V_Bat_2Cell R4 220Ω LTV-1 LTV-827 R1 100kΩ R2 100kΩ V_Bat_1Cell GND Analog In 1 (1Cell) R2 100kΩ Abbildung 10: Schaltplan zur Messung der Batteriespannung zu hohen Wert (hier > 1, 4 V [24, S. 9]) die Diode zerstören. Da die Größe 190Ω ungebräuchlich ist, wird ein 220Ω Widerstand eingesetzt. U 0 = R 3;4 I F + U F (6) R 3;4 = U 0 U F 5 V 1, 2 V = = 190Ω I F 20 ma (7) Da für die Messung der Spannung kein hoher Strom fließen muss, wurden sehr hohe Widerstände beim Spannungsteiler und der zweiten Messleitung gewählt (100kΩ). Die Schaltung soll auf einer Streifenrasterplatine aufgelötet werden. Der Entwurf der Platine ist in Abbildung 11 dargestellt. Die kupfernen Linien sind durchkontaktiert. Unter den Widerständen und dem Optokoppler muss die Verbindung unterbrochen werden. Die blauen Linien stellen den Schaltdraht dar und die schwarzen Kästchen eine Stiftleiste. Analog In 0 (2Cell) Analog In 1 (1Cell) Enable (IO-Pin 40) V_Bat_2Cell V_Bat_1Cell GND Abbildung 11: Entwurf der Platine zur Messung der Batteriespannung Sven Nobis Seite 20 von 110

21 4.6 Übersicht der Bauteile und Kosten In der Einführung wird beschrieben, dass die Anschaffungskosten für die Hardware ohne Smartphone gering ausfallen sollten. Die Tabelle 1 listet daher alle benötigten Bauteile der beschriebenen Hardware auf und den Preis zum Zeitpunkt des Kaufs. Dabei ist die Auflistung nach den Komponenten gruppiert. Gehört mehr als ein Bauteil zu einer Komponente, wird eine Zwischensumme dazu angegeben. Kleinteile und die Beschaffungskosten (z.b. Versandkosten) werden als Pauschale angegeben. In den Anforderungen wird zusätzlich definiert, dass ein Fahrzeug nicht alle Funktionen implementieren muss. Außerdem wurde für das Projekt Hardware ausgewählt, die möglichst angemessen für die Entwicklung sind (z.b. Aufladbarer Akku oder das Arduino ADK). In Tabelle Tabelle 2 auf der nächsten Seite wurde deshalb noch eine Bauteilliste für ein minimales Fahrzeug aufgestellt. Die Kosten wurden dafür am 11. Juli 2012 ermittelt. So sollte ein kleinerer Mikrocontroller (Arduino Nano) mit einem ADK-kompatiblen USB-Host-Shield und ein kleineres Fahrgestell aussreichend sein. Auch die Batterie kann gegen kostengünstigere Einweg-AA-Batterien ohnemessschaltung ausgetauscht werden. Tabelle 1: Kosten für den beschriebenen Bausatz Bezeichnung Stück Betrag ADK-kompatibles Entwicklungsboard Arduino Mega ADK 1 58,31 AC Fahrgestell mit Motoren DFRobot 4WD Mobile Platform 1 39,00 AC Schaltung zur Ansteuerung der Motoren Motor Drive Shield L293D 1 12,50 AC Dreh und schwenkbare Halterung für das Smartphone Dagu Pan/Tilt Kit mit Servomotoren 1 13,90 AC Hama Klett-Kabelbinder 6 3,87 AC Zwischensumme: 17,77 AC Batterie zur Energieversorgung mitmessschaltung Turnigy Lipo Akku 2200mAh 2S 7,4V 25C-35C 1 17,50 AC Streifenrasterplatine, Hartpapier, 50x100mm 1 0,50 AC Metallschichtwiderstände (3x 100kΩ, 2x 220Ω) 5 0,50 AC Optokoppler LTV ,31 AC Feinsicherung, Picofuse, flink, 7,0A 1 0,32 AC Zwischensumme: 19,13 AC Sonstiges CA-101D Micro USB Data Cable 1 2,18 AC Kleinteilepauschale (div. Kabel, Stecker, Schrumpfschlauch) - 4,00 AC Beschaffungskostenpauschale - 8,00 AC Zwischensumme: 14,18 AC Summe: 160,89 AC Sven Nobis Seite 21 von 110

22 Tabelle 2: Kosten für den minimalen Bausatz/kostengünstigste Variante Bezeichnung Stück Betrag ADK-kompatibles Entwicklungsboard Arduino Nano V3.0 kompatibler Mikrocontroller 1 12,19 AC DFRobot USB Host Shield 1 16,60 AC Zwischensumme: 28,79 AC Fahrgestell mit Motoren Dagu Magician Robot Chassis 1 17,50 AC Schaltung zur Ansteuerung der Motoren SainSmart L293D Motor Drive Shield 1 9,49 AC Halterung für das Smartphone Hama Klett-Kabelbinder 6 3,87 AC Batterie zur Energieversorgung 4xAA Battery Holder 1 1,10 AC AA-Batterie 7 2,00 AC Zwischensumme: 3,10 AC Sonstiges Kleinteilepauschale 1 4,00 AC Beschaffungskostenpauschale 1 4,00 AC Zwischensumme: 8,00 AC Summe: 70,75 AC Sven Nobis Seite 22 von 110

23 5 Beschreibung der Schnittstellen In den folgenden beiden Abschnitten werden die zwei Schnittstellen beschrieben. 5.1 Schnittstelle zwischen den beiden Smartphones Für die Kommunikation zwischen den beiden Smartphones muss ein eigenes Übertragungsprotokoll über TCP/IP realisiert werden. Dabei nimmt das Smartphone auf dem Fahrzeug die Rolle des Servers ein (im folgenden Host gennant). Der Host wartet standardmäßig auf Port 4253 auf die Verbindung eines Clients. Nachdem Verbindungsaufbau können die beiden Geräte bidirektional Nachrichten austauschen. Als Datenformat kommt die JavaScript Object Notation (JSON) zum Einsatz. Aufgrund seines kompakten Formats eignet es sich gut für den Einsatz auf mobilen Geräten. Dabei wird pro Nachricht ein JSON-Objekt gesendet. Jede Nachricht hat einen Typ, der durch die angegeben wird. Das Listing 1 zeigt beispielhaft einen Auschnitt mit zwei Nachrichten. { } { } Listing 1: Beispiel zum : TurnCarMessage, r o t a t i o n : 0. : AdjustSpeedMessage, speed : 1. 0 Die Abbildung 12 auf der nächsten Seite zeigt den Ablauf, wenn sich ein Client mit dem Host verbunden hat. Bevor ein Client die Steuerung des Fahrzeugs übernehmen kann, wird eine einfache Authentifizierung durchgeführt. Dabei überträgt der Host zuerst mit der Protokoll- Versionsnummer eine zufällige Zeichenfolge, auch Salt genannt (2). Der Client bildet dann aus dem Passwort und dem Salt einen SHA-1-Hashwert und sendet diesen zum Host (3). Dieser bildet ebenfalls den Hashwert und vergleicht diesen mit dem Empfangenen. Dies soll verhindern, dass das Passwort abgehört werden kann. Ansonsten erfolgt die Übertragung im Klartext. Nach erfolgreicher Authentifizierung überträgt der Host die Funktionen, die vom Fahrzeug unterstützt werden (6). Danach ist die Initialisierung abgeschlossen und der Client kann Fahrbefehle senden. Sven Nobis Seite 23 von 110

24 Host Client 1: Verbindung ist hergestellt 2: GreetingMessage(version, authsalt) 3: AuthenticationMessage(passwordHash) alt [Passwort falsch] 4: AuthenticationFailedMessage(reason) 5: Schließe Verbindung [Passwort korrekt] 6: FeatureMessage([...]) 7: Initialisierung abgeschlossen Abbildung 12: Initialisierung der Verbindung Nachrichten zum Client In den Tabellen 3 bis 8 (Seite 26) wird beschrieben, welche Nachrichten der Client zum Host senden kann. Neben einer Beschreibung, werden die Vorbedingungen angegeben, die erfüllt sein müssen, damit die Nachricht gesendet werden darf. Unter Eigenschaften wird beschrieben, welche zusätzlichen Informationen in der Nachricht mitgesendet werden. Dabei wird zuerst der (Java- )Datentyp, dann der Name und danach eine Beschreibung angegeben. GreetingMessage Beschreibung Vorbedingungen Eigenschaften Tabelle 3: Begrüßungs-Nachricht Der Host begrüßt den Client. Client hat sich gerade verbunden; d.h. es wurde noch keine Nachricht gesendet. int version: Version des Prokolls, welches der Host implementiert hat String authsalt: Eine zufällige Zeichenfolge, die verwendet wird um das Passwort zu verschlüsseln. Sven Nobis Seite 24 von 110

25 FeatureMessage Beschreibung Vorbedingungen Eigenschaften Tabelle 4: Funktions-Nachricht Enthält alle vom Fahrzeug und Host unterstützten bzw. aktivierten Funktionen. Client ist authentifiziert. FeatureMessage wurde noch nicht gesendet. boolean camera: Wird die Übertragung des Kamerabildes unterstützt? Maximale mögliche Drehung der Kamera in Grad... float camerapanmin:...nach links. float camerapanmax:...nach rechts. float cameratiltmin:...nach unten. float cameratiltmax:...nach oben. Für die vier Kamera-Werte gilt: Mögliche Wert sind Wenn die Drehung bzw. Schwenkung nicht untersützt wird, enhalten die beiden Werte 0. boolean adjustablespeed: Ist die Geschwindigkeit anpassbar? Wenn nicht, dann wird nur eine konstante Geschwindigkeit unterstützt. boolean drivebackward: Wird Rückwärtsfahren unterstützt? boolean location: Kann die geografische Position des Fahrzeugs (Längengrad, Breitengrad und Höhe) abgerufen werden? boolean bearing: Kann die Fahrtrichtung des Fahrzeugs abgerufen werden? boolean speed: Kann die Geschwindigkeit des Fahrzeugs abgerufen werden? boolean batterypower: Kann der Batterie-Ladestand abgerufen werden? Tabelle 5: Kamera-Verbindungs-Parameter-Nachricht CameraConnectionParameterMessage Beschreibung Stream des Kamerabilds ist bereit. Nachricht enthält die Verbindungsparameter, aus dem die URI zum Stream erstellt werden kann. Vorbedingungen FeatureMessage (siehe Tabelle 4) wurde gesendet. Antwort auf CameraConnectionParameterMessage (siehe Tabelle 5). Eigenschaften int port: TCP/IP-Port auf dem der Stream aufgerufen werden kann. String scheme: URI-Scheme (z.b. rtsp) String path: Pfad zum Stream, ohne / prefix (z.b. video/camera.mp4) Sven Nobis Seite 25 von 110

26 LocationMessage Beschreibung Vorbedingungen Eigenschaften Tabelle 6: Ortungs-Nachricht Nachricht enthält Informationen über die Position des Fahrzeugs inklusive Bewegung. Die Eigenschaften sind kompatibel zur Android Klasse Location. Senden der Nachricht wurde über eine SetUpCyclicUpdateMessage (siehe Tabelle 11 auf Seite 28) aktiviert. double latitude: Breitengrad in dem sich das Fahrzeug befindet. double longitude: Längengrad in dem sich das Fahrzeug befindet. boolean hasaltitude: Beinhaltet die Nachricht Informationen über die Höhe? double altitude: Höhe über Normal-Null in Meter. boolean hasaccuracy: Beinhaltet die Nachricht Informationen über die Genauigkeit der Position? float accuracy: Genauigkeit der Position in Meter. boolean hasbearing: Beinhaltet die Nachricht Informationen über die (Kompass-)Richtung in die sich das Fahrzeug bewegt? float bearing: Richtung in die sich das Fahrzeug bewegt, östlich vom geografischen Norden in Grad. boolean hasspeed: Beinhaltet die Nachricht Informationen über die Geschwindigkeit des Fahrzeugs? float speed: Geschwindigkeit des Fahrzeugs in Meter pro Sekunde. Tabelle 7: Batterie-Ladestand-Nachricht BatteryPowerMessage Beschreibung Nachricht enthält Informationen zum Ladestand der Batterie des Fahrzeugs. Vorbedingungen Senden der Nachricht wurde über eine SetUpCyclicUpdateMessage (siehe Tabelle 11 auf Seite 28) aktiviert. Eigenschaften float charginglevel: Ungefährer Ladestand in Prozent (0 100%). Tabelle 8: Authentifizierung-Fehlgeschlagen-Nachricht AuthenticationFailedMessage Beschreibung Authentifizierung ist fehlgeschlagen. Nachdem die Nachricht gesendet wurde, sollte die Verbindung geschlossen werden. Vorbedingungen Client hat AuthenticationMessage (siehe Tabelle 9 auf der nächsten Seite) gesendet, jedoch mit falschem Passwort. Eigenschaften String reason: Begründung, warum die Authentifizierung fehlgeschlagen ist. Zurzeit nur: Der Client hat das falsche Passwort gesendet. Sven Nobis Seite 26 von 110

27 5.1.2 Nachrichten zum Host In den Tabellen 9 bis 14 auf Seite 29 werden die Nachrichten beschrieben, die der Client zum Host senden kann. Die Beschreibung erfolgt wie in Tabelle 9: Authentifizierungs-Nachricht AuthenticationMessage Beschreibung Der Client authentisiert sich am Host mittels Passwort. Vorbedingungen GreetingMessage (siehe Tabelle 3 auf Seite 24) wurde empfangen. Noch keine AuthenticationMessage gesendet. Eigenschaften String passwordhash: Das SHA-1 Hash aus dem Passwort verkettet mit dem vom Host gesendetem Salt (sha1sum(passwort + salt)). Tabelle 10: Kamera-Anforderungs-Nachricht RequestCameraMessage Beschreibung Teilt dem Host mit, dass er die Übertragung des Kamerabilds starten bzw. stoppen soll. Vorbedingungen FeatureMessage (siehe Tabelle 4 auf Seite 25) wurde empfangen. Eigenschaften boolean activatecamera: Ob die Kamera aktiviert (true) oder deaktivert (false) werden soll Sven Nobis Seite 27 von 110

28 Tabelle 11: Zyklische-Aktualisierung-Einrichten-Nachricht SetUpCyclicUpdateMessage Beschreibung Teilt dem Host mit, dass der Client über Aktualisierungen eines Sensors (Ort oder Batterieleistung) informiert werden will. Vorbedingungen FeatureMessage (siehe Tabelle 4 auf Seite 25) wurde empfangen. Eigenschaften enum { location, batterypower } featuretype: Auf welchen Sensor sich die Nachricht bezieht: location: Ortungsdaten des Fahrzeugs (siehe Tabelle 6 auf Seite 26) batterypower: Noch verfügbare Akkuleistung des Fahrzeugs (siehe Tabelle 7 auf Seite 26) int interval: Intervall in dem der Host Aktualisierungen senden soll. Das Intervall kann jedoch unterschritten werden, wenn keine neuen Informationen verfügbar sind. Ist das Intervall kleiner gleich null, dann werden keine Aktualisierungen gesendet. TurnCarMessage Beschreibung Vorbedingungen Eigenschaften Tabelle 12: Fahrzeug-Lenken-Nachricht Das Lenkrad soll gedreht werden. FeatureMessage (siehe Tabelle 4 auf Seite 25) wurde empfangen. float rotation: Rotation des Lenkrads; Positive Werte lenken nach rechts, negative nach links. Dabei ist +1, 0 maximal nach rechts und 1, 0 maximal nach links. Bei 0, 0 ist das Lenkrad nicht eingeschlagen. Tabelle 13: Geschwindigkeit-Anpassen-Nachricht AdjustSpeedMessage Beschreibung Die Geschwindigkeit soll angepasst werden. Vorbedingungen FeatureMessage (siehe Tabelle 4 auf Seite 25) wurde empfangen. Eigenschaften float speed: Neue Geschwindigkeit; Dabei ist +1, 0 die Höchstgeschwindigkeit nach vorne, 1, 0 nach hinten und 0 ist Stopp. Negative Werte ( Rückwärts) sind nur erlaubt, sofern vom Fahrzeug unterstützt. Sven Nobis Seite 28 von 110

29 Tabelle 14: Kamera-Drehen-Schwenken-Nachricht RotateCameraMessage Beschreibung Die Kamera soll gedreht und/oder geschwenkt werden. Vorbedingungen FeatureMessage (siehe Tabelle 4 auf Seite 25) wurde empfangen. Drehen oder Schwenken wird unterstützt. Eigenschaften float pan: Drehe die Kamera (horizontal) zur Position in pan. 0 dreht die Kamera nach vorne. Positive Werte nach rechts davon, negative nach links. float tilt: Schwenke die Kamera (vertical) zur Position in tilt. 0 dreht die Kamera nach vorne. Positive Werte drehen die Kamera nach oben, negative nach unten. Für beide Parameter gilt: Die Maximalwerte sind durch die FeatureMessage gegeben (siehe Tabelle 4 auf Seite 25). Falls einer der beiden Parameter nicht untersützt wird, sollte dort 0 übergeben werden. Sven Nobis Seite 29 von 110

30 5.1.3 Übertragung des Kamerabilds Um ein Steuern des Fahrzeugs ohne Sichtkontakt zu ermöglichen, soll das Bild der Kamera zur Fernsteuerung übertragen werden. Die Android API bietet für das Aufnehmen von Videos und Bildern eine API an (android.hardware.camera). Diese ist jedoch nur darauf ausgelegt, die Bilder oder Videos auf lokal zu speichern. Die Videodaten über das Netzwerk an andere Geräte weiterzugeben, ist ersteinmal nicht vorgesehen. Für das Abspielen von Videos aus dem Netzwerk hingegen unterstützt Android zwei verschiedene Protokolle. Das erste Protokoll ist der HTTP Progressive Download. In diesem Verfahren wird das Video wie bei einem Download einer Datei einfach herruntergeladen. Damit es abgespielt werden kann, während es herruntergeladen wird, muss es am Anfang einen Index besitzen. In diesem steht was in der Datei ist und wie sie organisiert ist, den sogennanten moov atom. Wie sich aus der Beschreibung schon erkennen lässt, ist dieses Verfahren nicht für eine Live- Übertragung der Kamera geeignet. Einige neuere Techniken, die die Live-Übertragung erlauben, werden von Android noch nicht unterstützt.[18, S. 218f] Das zweite Protokoll ist das Real Time Streaming Protocol (RTSP). Technisch gesehen ist RTSP ein Protokoll zur Steuerung der kontinuierlichen Übertragung von Audio/Video-Daten. Anders als die erste Methode ist dieses Protokoll auf die Live-Übertragung von Daten ausgelegt. RTSP wird oft in Verbindung mit dem Real-Time Transport Protocol (RTP) eingesetzt, welches für die Übertragung der Daten sorgt. [18, S. 219f] Es muss also entweder eine Möglichkeit geschaffen werden, die Bilder der Kamera in ein, für Android abspielbaren, RTSP-Stream zu wandeln oder es muss auf beiden Seiten (Server und Client) eine spezielle Lösung implementiert werden. Mit der Aufgabe der Echtzeit-Videoübertragung auf Android haben sich schon mehrere Projekte beschäftigt. So bieten diese Funktion bereits einige propetäre Applikationen mit sehr guten Resultaten an. Dazu zählt z.b. die Google Plus App. Verfolgt wurde das Ziel ebenfalls von Dominic Janßen in seiner Diplomarbeit Implementierung & Evaluierung von IP-Video-Streaming unter Android [21]. Dabei hat er verschiedene Ansätze verfolgt, wie die Aufnahme von Einzelbildern, die Aufnahme einzelner Video-Tracks und die Manipulation des 3GP-Containers. Letzteres war der Versuch, den Videostrom der Kamera so abzuändern, dass er streamingfähig ist. Dieses Vorgehen führte nicht zum Erfolg. Die beiden anderen Methoden funktionierten zwar, jedoch nur mit erheblichen Verzögerungen. Die Übertragung vieler einzelner Videotracks hintereinander war hier die schnellste Lösung. Jedoch lag auch hier die durchschnittliche Verzögerung bei 2,73 Sekunden plus Länge des Videotracks. Ein Steuern des Fahrzeugs wäre mit dieser Lösung nur schwer möglich. Einen anderen Ansatz verfolgt der von den Orange Labs implementierte Rich Communication Suite-enhanced (RCS-e) stack. RCS-e soll in Zukunft der Nachfolger von SMS werden und auch Videotelefonie ermöglichen [15, S. 37] [12]. So wird hier ein Camera.PreviewCallback implementiert, um aus den Vorschaubildern der Kamera den Videostream zu erzeugen. Dazu werden die Frames (einzelene Video Bilder) über JNI an einen nativen Software Videos Codec weitergegeben. Diese werden dann über RTP weitergeben. JNI bedeutet Java Native Interface und ermöglicht es, unter Android mit dem Android Native Development Kit nativen Quelltext in C oder C++ zu schreiben [5]. Sven Nobis Seite 30 von 110

31 In dem Projekt RTSP-Camera-for-Android von Peter Arwanitis und Stefan Krusche [14] wurde die Funktionalität aus dem RCS-e stack extrahiert und als Lösung zur Übertragung des Kamerabildes über RTSP veröffentlicht. Nach ein paar Tests der Applikationen wurde eine geringe Verzögerung (< 1 s) festgestellt. Außerdem lässt sie sich sehr einfach als Bibliothek einbinden und ist unter der freien Softwarelizenz GNU General Public License veröffentlicht. (Der RCS-e stack ist ebenfall freie Software.) Somit ist mit der Nutzung der RTSP-Camera-for-Android eine geeignete Lösung für die Übertragung des Kamerabildes zur Fernsteuerung gefunden. 5.2 Schnittstelle zwischen Mikrocontroller und Smartphone Der Mikrocontroller und das Smartphone kommunizieren über USB miteinander. Mittels des Accessory Development Kit (ADK) existiert dafür eine Möglichkeit bei Android. Da die Hardware vieler Smartphones keinen USB-Host-Modus unterstützen, arbeitet der Mikrocontroller als USB-Host und das Smartphone als USB-Gerät (siehe Abbildung 13). Dieser sogennante Android USB Accessory Modus ist seit Android 3.1 (API level 12) integriert. Durch eine Add-On Library kann es auch schon ab Android (API level 10) genutzt werden. Jedoch wird der Modus auch nicht von allen Geräten ab dieser Version unterstützt [1]. Abbildung 13: USB Accessory Modus [3, Figure 1] Der Verbindungsaufbau ist durch das Android Open Accessory Protocol definiert: Zu Beginn muss der Mikrocontroller feststellen, ob ein Smartphone angeschlossen ist, welches den Android USB Accessory Modus unterstützt. Danach muss der Modus noch gegebenenfalls aktiviert werden. Ist der Modus aktiviert, sollte das Smartphone nun einen USB-Endpunkt mit einer bestimmten Geräte-ID (0x2D00 oder 0x2D01) haben. Über diesen steht ein Eingabe- und Ausgabe- Datenstrom zur Kommunikation zur Verfügung [2]. Da der Mikrocontroller weitaus weniger Leistung und Speicher hat als die beiden Smartphones, wird bei der Kommunikation mit diesem ein einfacheres Protokoll implementiert. Dabei sendet das Smartphone Befehle an den Mikrocontroller, der diese beantwortet. Es wird immer nur ein Befehl gesendet und danach auf die Antwort des Mikrocontrollers gewartet. Ohne einen Befehl darf der Mikrocontroller keine Nachrichten an das Smartphone senden. Der Aufbau eines Befehls ist in Abbildung 14 auf der nächsten Seite dargestellt. Dabei werden Pakete mit einer Größe von 16 Bytes gesendet. Das erste Byte enthält den Typ des Befehls, den Request Command Type. Danach folgen die zum Befehl dazugehörigen Daten, der Payload. Dieser darf maximal 14 Bytes groß sein. Alle nicht genutzten Bytes sollten mit 0 gefüllt sein. Das letzte Byte enthält eine CRC-8-Prüfsumme über die ersten 15 Bytes. Das auf Deutsch zyklische Redundanzprüfung genannte Verfahren beruht auf der Polynomdivision [23, S.34ff.]. Das Sven Nobis Seite 31 von 110

32 zu verwendene Generatorpolynom lautet x 8 +x 2 +x+1 = (x+1)(x 7 +x 6 +x 5 +x 4 +x 3 +x 2 +1) mit einem Startwert von 0. CRC-8 in dieser Variante kommt u.a. so in der Audiodatenkompression Free Lossless Audio Codec zum Einsatz [17]. Die Redundanzprüfung soll dazu beitragen, dass bei fehlerhafter oder gar falscher Software auf einem der Geräte kein unerwünschtes Verhalten auftritt. Stattdessen kann die andere Software dies erkennen und eine Fehlerbehandlung durchführen. Fehler bei der Datenübertragung müssen hingegen nicht geprüft werden, da der USB-Standard bereits eine Fehlererkennung implementiert hat [30, Abschn. Arten des Datenflusses ]. Eine Antwort hat den gleichen Aufbau wie ein Befehl. Anstatt des Befehls-Typs enthält sie jedoch den Antwort-Typ (Response Message Type) im ersten Byte. Paket: Byte: Request Command Type/ Response Message Type Payload CRC8-Checksum Abbildung 14: Aufbau eines Befehls-/Antwort-Paketes Befehle an den Mikrocontroller In den folgenden Tabellen 15 bis 21 (Seite 35) werden die Befehle beschrieben, die das Smartphone an den Mikrocontroller senden kann. Zu jedem Befehl ist eine eindeutige Bezeichnung, der Request Command Type (erstes Byte im Befehl), eine Beschreibung und die Antwort, die im Normalfall erwartet wird. Zusätzlich wird der Inhalt des Payloads angegeben. Zum Inhalt des Payloads werden die einzelnen Daten mit einer Bezeichnung, dem Datentyp und einer Beschreibung aufgelistet. Die angegeben Datentypen beziehen sich auf die Java-Typen. Wenn in der Beschreibung von MAX und MIN gesprochen wird, dann ist damit das Maximum und Minimum des Wertbereichs vom Datentyp gemeint. Bei einem šhort liegt dieser bei und Sven Nobis Seite 32 von 110

33 NOOP Request Command Type Beschreibung Erwartete Antwort Payload Hinweis 0x01 Tabelle 15: Befehl NOOP Anfrage, ohne Funktion. Kann zum Testen genutzt werden: Ist alles in Ordnung? REQUEST OK (siehe Tabelle 22 auf Seite 36) keiner (0 Bytes) Dieser Befehl sollte in zunkünftigen Versionen nicht geändert werden. Tabelle 16: Befehl GET PROTOCOL VERSION GET PROTOCOL VERSION Request Command 0x02 Type Beschreibung Der Mikrocontroller soll die Proktollversion senden, die er implementiert hat. Erwartete Antwort PROTOCOL VERSION (siehe Tabelle 25 auf Seite 37) Payload keiner (0 Bytes) Hinweis Dieser Befehl sollte in zunkünftigen Versionen nicht geändert werden. Tabelle 17: Befehl GET FEATURES GET FEATURES Request Command 0x03 Type Beschreibung Der Mikrocontroller soll die Funktionen senden, die er unterstützt. Erwartete Antwort FEATURES (siehe Tabelle 26 auf Seite 38) Payload keiner (0 Bytes) Sven Nobis Seite 33 von 110

34 TURN CAR Request Command Type Beschreibung Erwartete Antwort Payload 0x04 Tabelle 18: Befehl TURN CAR Das Lenkrad soll gedreht werden. REQUEST OK (siehe Tabelle 22 auf Seite 36) 2 Bytes short rotation: Rotation des Lenkrads; Positive Werte lenken nach links, negative nach rechts. MIN und MAX bilden dabei die Maxima in die jeweiligen Richtungen. Bei 0 ist das Lenkrad nicht eingeschlagen. Tabelle 19: Befehl ADJUST SPEED ADJUST SPEED Request Command 0x05 Type Beschreibung Die Geschwindigkeit soll angepasst werden. Erwartete Antwort REQUEST OK (siehe Tabelle 22 auf Seite 36) Payload 2 Bytes short rotation: Neue Geschwindigkeit; Dabei ist MAX die Höchstgeschwindigkeit nach vorne, MIN nach hinten und 0 ist Stopp. Negative Werte ( Rückwärts) sind nur erlaubt, sofern vom Fahrzeug unterstützt. Sven Nobis Seite 34 von 110

35 ROTATE CAM Request Command Type Beschreibung Erwartete Antwort Payload Hinweis 0x06 Tabelle 20: Befehl ROTATE CAM Die Kamera soll gedreht und/oder geschwenkt werden. REQUEST OK (siehe Tabelle 22 auf der nächsten Seite) 4 Bytes short pan: Drehe die Kamera (horizontal) zur Position in pan. 0 dreht die Kamera nach vorne. Positive Werte nach rechts davon, negative nach links. short tilt: Schwenke die Kamera (vertical) zur Position in tilt. 0 dreht die Kamera nach vorne. Positive Werte drehen die Kamera nach oben, negative nach unten. Für beide Parameter gilt: Wird ein Wert nicht unterstützt, so sollte 0 übergeben werden. Die Werte MAX und MIN bilden jeweils die maximal mögliche Drehung in die jeweilige Richtung ab. Diese werden vom Mikrocontroller durch die FEATURES-Antwort (siehe Tabelle 26 auf Seite 38) vorgegeben. Dieser Befehl sollte nur gesendet werden, wenn die Funktion auch unterstützt wird. Tabelle 21: Befehl GET BATTERY STATE GET BATTERY STATE Request Command 0x07 Type Beschreibung Der Mikrocontroller soll den Ladestand der Batterie zurückmelden. Erwartete Antwort BATTERY STATE (siehe Tabelle 27 auf Seite 38) Payload keiner (0 Bytes) Hinweis Dieser Befehl sollte nur gesendet werden, wenn die Funktion auch unterstützt wird. Sven Nobis Seite 35 von 110

36 5.2.2 Antworten vom Mikrocontroller Die folgenden Tabellen 22 bis 27 (Seite 35) beschreiben die Antworten vom Mikrocontroller auf einen Befehl. Zu jeder Antwort ist eine eindeutige Bezeichnung, der Response Message Type (erstes Byte im Befehl), eine Beschreibung und der Inhalt des Payloads angegeben. Außerdem werden die Befehle aufgelistet, auf die diese Antwort folgen kann. Der Inhalt des Payload wird wie im vorherigen Abschnitt angegeben. REQUEST OK Response Message Type Beschreibung Antwort auf Payload Hinweis 0x01 Tabelle 22: Antwort REQUEST OK Der gesendete Befehl wurde ausgeführt. Es sind keine Probleme aufgetreten. NOOP (siehe Tabelle 15 auf Seite 33), TURN CAR (siehe Tabelle 18 auf Seite 34), ADJUST SPEED (siehe Tabelle 19 auf Seite 34) und ROTATE CAM (siehe Tabelle 20 auf der vorherigen Seite) keiner (0 Bytes) Dieser Befehl sollte in zukünftigen Versionen nicht geändert werden. ERROR Response Message Type Beschreibung Antwort auf Payload Hinweis Tabelle 23: Antwort ERROR 0x02 Der gesendete Befehl wurde nicht verarbeitet. Der Grund wird als Fehlercode mitgeliefert. Kann bei jedem Befehl als Antwort auftreten. 2 Bytes short errorid: Ein Fehlercode. Siehe Abschnitt auf Seite 39. Dieser Befehl sollte in zukünftigen Versionen nicht geändert werden. Sven Nobis Seite 36 von 110

37 Tabelle 24: Antwort BATTERY NEAR EMPTY BATTERY NEAR EMPTY Response Message 0x03 Type Beschreibung Die Batterie des Fahrzeugs ist nahezu leer, deshalb werden keine Befehle mehr verarbeitet. Der Benutzer sollte angewiesen werden, dass Fahrzeug zu laden. Antwort auf Kann bei jedem Befehl als Antwort auftreten. Payload keiner (0 Bytes) Hinweis Dieser Befehl sollte in zukünftigen Versionen nicht geändert werden. Tabelle 25: Antwort PROTOCOL VERSION PROTOCOL VERSION Response Message 0x04 Type Beschreibung Liefert die vom Mikrocontroller implementierte Protokollversion. Antwort auf GET PROTOCOL VERSION (siehe Tabelle 16 auf Seite 33) Payload 4 Bytes short version: Implementierte Protokollversion. short update: Version der implementierten Proktoll- Erweiterungen. Diese Erweiterungen sind kompatibel zur Version (und vorherigen Erweiterungen). Sie ändern also keine bestehende Funktionalität, sondern fügen unabhängig davon Funktionalität hinzu. Sind keine Erweiterungen implementiert, dann enhält dieses Feld 0. Hinweis Dieser Befehl sollte in zukünftigen Versionen nicht geändert werden. Sven Nobis Seite 37 von 110

38 Tabelle 26: Antwort FEATURES FEATURES Response Message Type 0x05 Beschreibung Enthält die vom Fahrzeug unterstützten Funktionen. Antwort auf GET FEATURES (siehe Tabelle 17 auf Seite 33) Payload 9 Bytes Byte 0 - bit 0 adjustablespeed: Ist die Geschwindigkeit anpassbar? Wenn nicht, dann wird nur eine konstante Geschwindigkeit unterstützt. Byte 0 - bit 1 drivebackward: Wird Rückwärtsfahren unterstützt? Byte 0 - bit 2 batterypower: Kann der Batterie-Ladestand abgerufen werden? Byte 0 - bit 3-7 : Unbenutzt Maximale mögliche Drehung der Kamera... short camerapanmin:...nach links. short camerapanmax:...nach rechts. short cameratiltmin:...nach unten. short cameratiltmax:...nach oben. Für die vier Kamera-Werte gilt: Mögliche Wert sind 0 MAX für Wenn die Drehung bzw. Schwenkung nicht untersützt wird, enhalten die beiden Werte 0. Tabelle 27: Antwort BATTERY STATE BATTERY STATE Response Message 0x07 Type Beschreibung Enthält Informationen zum Ladestand der Batterie des Fahrzeugs Antwort auf GET BATTERY STATE (siehe Tabelle 21 auf Seite 35) Payload 2 Bytes short charinglevel: Ungefährer Ladestand; Mögliche Wert sind 0 MAX für 0% 100%. Sven Nobis Seite 38 von 110

39 5.2.3 Fehlercodes des Mikrocontrollers Im folgenden werden die Fehlercodes beschrieben, mit die der Mikrocontroller einen Befehl beantwortet kann (siehe auch Tabelle 23 auf Seite 36): 0x00 UNDEFINED ERROR: Undefinierter Fehler (wenn kein anderer Fehlercode zutrifft) 0x01 INVALID COMMAND ERROR: Der Mikrocontroller hat einen invaliden Befehl empfangen. Die Prüfsumme war falsch. 0x02 UNKOWN COMMAND ERROR: Der Mikrocontroller kennt den empfangenen Befehl nicht. 0x03 PROCESS COMMAND ERROR: Beim Verarbeiten des Befehls ist ein Fehler aufgetreten. Sven Nobis Seite 39 von 110

40 6 Subsystementwurf: Software auf dem Mikrocontroller Die zu entwickelnde Software für den Mikrocontroller soll mittels der offizellen IDE für die Arduino-Plattform umgesetzt werden. Eine Applikation für den Arduino wird dort ein Sketch genannt und ist in C oder C++ geschrieben. Dabei steht die AVR Libc zur Verfügung [6]. Es handelt sich um eine Teil-Implementierung der Standard-C-Bibliothek für AVR-Mikrocontroller. Dazu werden noch ein paar Plattform spezifische Bibliotheken und wenige weitere Bibliotheken mitgeliefert [9, Abschn. General information about this library ]. Aufbauend auf dieser, bringt auch die Arduino-Plattform ein paar Bibliotheken mit, welche unter anderem die Port-Zuordnungen zum Arduino ADK definieren. Außerdem können weitere Bibliotheken unter dem Ordner libraries im Installationsverzeichnis der IDE hinzugefügt werden. Eine Arduino- Bibliothek besteht aus ein oder mehreren C++-Quelldateien und kann im Unterordner example zusätzliche Beispiele mitliefern. Ein Sketch besteht aus einer.ino-dateie, welche beim Kompilieren in eine.cpp-datei gewandelt wird. Dabei wird zu jeder enthaltenen Funktion der Funktionsprototyp am Beginn der Datei eingefügt. Dazu wird die Arduino.h eingebunden [8, Abschn. Transformations to the main sketch file ]. Ansonsten unterscheidet sich die Datei nicht von einer normalen C++-Datei. Anstatt einer main()-funktion, sind die beiden Funktionen void setup() und void loop() vorgesehen. Die Funktion setup() wird einmalig beim Anschalten des Mikrocontrollers aufgerufen. Danach wird die Funktion loop() in einer Endlosschleife ausgeführt. 6.1 Externe Bibliotheken Neben den mitgelieferten Bibliotheken sollen mehrere externe Bibliotheken zum Einsatz kommen: Adafruit Motor shield library [19]: Diese Bibliothek wird genutzt, um die Motoren, die über das Motor Shield angeschlossen sind, anzusteuern. AndroidAccessory [1]: Gehört zum Accessory Development Kit und bietet die Schnittstelle zum Smartphone. USB Host Shield (Version: legacy) [25]: Wird mit dem Accessory Development Kit mitgeliefert und steuert den USB-Chip auf der Arduino-ADK-Platine an. 6.2 Architektur Das Klassendiagramm in der Abbildung 15 auf der nächsten Seite zeigt, welche Klassen für die Mikrocontroller-Software vorgesehen sind. Dabei wird die Software in zwei Pakete aufgeteilt: Die oberen drei Klassen bilden das Paket AndroidRCCar und die unteren zwei das Paket AndroidRCReferenceCar. Jedes Paket soll bei der Implementierung später als Arduino-Bibliothek umgesetzt werden. Sven Nobis Seite 40 von 110

41 class AndroidRCCar.Arduino AndriodRCCar::AndroidRCCarCommunication - accessory: AndroidAccessory - crc: CRC8 «struct» AndriodRCCar::CarFeatures # adjustspeed(speed :int16_t) : bool + AndroidRCCarCommunication() + AndroidRCCarCommunication(deviceDescription :char*) # answerbatterynearempty() : bool # dosetup() : void # getbatterystate() : int16_t # getfeatures() : CarFeatures + handlenextcommand() : void + isconnected() : bool - processcommand(buffer[] :byte) : void # rotatecam(pan :int16_t, tilt :int16_t) : bool - senderror(errorid :ErrorId) : void - sendresponse(responsemsgtype :ResponseMessage, payload[] :byte, payloadlen :unsigned int) : void - sendresponse(responsemsgtype :ResponseMessage) : void + setup() : void # turncar(rotation :int16_t) : bool - validatecommand(buffer[] :byte, len :int) : bool -crc + adjustablespeed: bool + batterypower: bool + camerapanmax: int16_t + camerapanmin: int16_t + cameratiltmax: int16_t + cameratiltmin: int16_t + drivebackward: bool AndriodRCCar::CRC8 + from_array(buffer[] :unsigned char, len :unsigned int) : char AndroidRCReferenceCar::AndroidRCReferenceCar - backleftmotor: AF_DCMotor - backrightmotor: AF_DCMotor - battery: TwoCellLiPolBattery - frontleftmotor: AF_DCMotor - frontrightmotor: AF_DCMotor - panservo: Servo - tiltservo: Servo -battery - bothcellinpin: uint8_t - enablepin: uint8_t - onecellinpin: uint8_t AndroidRCReferenceCar::TwoCellLiPolBattery # adjustspeed(speed :int16_t) : bool + AndroidRCReferenceCar() # answerbatterynearempty() : bool # dosetup() : void # getbatterystate() : int16_t # getfeatures() : CarFeatures + resetall() : void # rotatecam(pan :int16_t, tilt :int16_t) : bool # turncar(rotation :int16_t) : bool + batterynearempty() : bool + getvalue() : int + setup() : void + TwoCellLiPolBattery(enablePin :uint8_t, bothcellanaloginpin :uint8_t, onecellanaloginpin :uint8_t) + update() : void Abbildung 15: Klassendiagramm der Mikrocontroller Software Sven Nobis Seite 41 von 110

42 6.2.1 Paket AndroidRCCar Im Paket AndroidRCCar wird die Schnittstelle zum Smartphone durch die abstrakte Klasse AndroidRCCarCommunication umgesetzt. Diese kann über die Klasse AndroidAccessory mit dem Smartphone kommunizieren. AndroidRCCarCommunication ist dabei für das Auslesen und Prüfen von Befehlen, sowie das Senden der Antworten zuständig. Die Berechnung der CRC8- Prüfsummen, bei Überprüfung ankommender Befehle und dem Erstellen der Antworten, wird durch die Klasse CRC8 durchgeführt. Für die Verarbeitung der Befehle bietet die Klasse AndroidRCCarCommunication virtuelle Methoden an. Dadurch ist das Paket AndroidRCCar, abgesehen von einem ADK-kompatiblen Arduino-Mikrocontroller, an keiner spezifischen Hardware gebunden. Durch die abstrakte Methode CarFeatures getfeatures() kann die konkrete Klasse angeben, welche Funktionen von dem Fahrzeug unterstützt werden. Dabei müssen die Methoden int16 t getbatterystate(), bool rotatecam(...) nur überschrieben werden, wenn die Funktionen auch unterstüzt werden sollen. Die Methoden bool turncar(...) und bool adjustspeed(...) müssen implementiert werden. Durch den Rückgabwert kann angegeben werden, ob der Befehl erfolgreich (= true) ausgeführt wurde. Die Methode setup() führt die Initialisierung des AndroidAccessory durch und ruft dann die virutelle Methode dosetup() auf. Diese kann von den konkreten Klassen genutzt werden, um eigene Initialisierungen vorzunehmen. Durch das Überschreiben der Methode bool answerbatterynearempty() kann angegeben werden, dass die Batterien des Fahrzeug nahezu leer sind. Ist dies der Fall, so wird die Verarbeitung der Befehle eingestellt und jeder Befehl mit der Antwort BATTERY NEAR EMPTY (siehe Tabelle 24 auf Seite 37) quittiert. Die Standardimplementierung gibt immer false zurück Paket AndroidRCReferenceCar Die Klasse AndroidRCReferenceCar implementiert die abstrakte Klasse AndroidRCCarCommunication für das in Subsystementwurf Hardware (Abschnitt 4 auf Seite 11) beschriebene Fahrzeug. Das konkrete Fahrzeug beherrscht alle möglichen Features. Deswegen werden alle virtuellen Methoden der Basisklasse überschrieben und mit Funktionalität gefüllt. Außerdem führt sie die Methode resetall() ein, die alle Motoren stoppt und in den Anfangszustand zurücksetzt. Zur Ansteuerung der vier Motoren wird die Klasse AF DCMotor aus der Adafruit Motor shield library verwendet. Die Servo-Motoren werden mittels Klasse Servo angesteuert. Diese wird mit der Arduino-Plattform mitgeliefert. Für das Auslesen der verbleibenden Batterie-Leistung wird die Klasse TwoCellLiPolBattery umgesetzt. Durch die Methode update() werden neue Werte über die analogen Eingänge eingelesen und umgerechnet. Die Methode int16 t getvalue() liefert dann die verbleibende Leistung. Sven Nobis Seite 42 von 110

43 6.3 Ablauf der Methode loop() Die Abbildung 16 auf der nächsten Seite zeigt den Ablauf der Funktion loop() als Sequenzdiagramm. Zur Verdeutlichung sind AndroidRCCarCommunication und AndroidRCReferenceCar getrennt aufgeführt. Es wird zuerst geprüft, ob die Verbindung zum Smartphone besteht. Besteht keine Verbindung, werden alle Motoren zurückgesetzt (resetall()). Besteht eine Verbindung so wird der nächste Befehl eingelesen. Nach dem Einlesen wird der Befehl validiert. Stimmt die CRC8-Prüfsumme nicht überein, wird der Fehlercode INVALID COMMAND ERROR zurückgesendet (siehe auch Abschnitt auf Seite 39). Bei erfolgreicher Validierung wird der Befehl von AndroidRCReferenceCar verarbeitet. Als Beispiel ist hier der Befehl GET BATTERY STATE (siehe auch Tabelle 21 auf Seite 35) aufgeführt. Bei diesem wird ein neuer Wert von TwoCellLiPolBattery eingelesen und dann zurückgegeben. Sofern der Befehl erfolgreich ausgeführt wurde, erstellt AndroidRCCarCommunication daraus die Antwort und sendet diese (sendresponse(...)). Da getbatterystate() kein bool zurückliefert, bedeuten positive Rückgabewerte, dass der Befehl erfolgreich ausgeführt wurde. Bei negativen Rückgabewerten wird der Fehlercode PROCESS COMMAND ERROR gesendet. Sven Nobis Seite 43 von 110

44 sd AndroidRCCar.Arduino - Verarbeitung eines Befehls loop() AndroidRCReferenceCar::AndroidRCReferenceCar AndriodRCCar::AndroidRCCarCommunication AndriodRCCar::CRC8 AndroidRCReferenceCar::TwoCellLiPolBattery AndroidAccessory connected= isconnected() :bool alt connected handlenextcommand() [true] read(buffer, sizeof(buffer)) validatecommand(buffer[], len) : bool from_array(buffer[], len) :char alt [Validation erfolgreich] processcommand(buffer[]) Bei BatteryNearEmpty() == true, würde hier nur BATTERY_NEAR_EMPTY geantwortet werden. alt commandtype [GET_BATTERY_STATE] getbatterystate() :int16_t update() getvalue() :int [Weitere...] Wird hier nicht weiter detailiert. alt [Befehl erfolgreich ausgeführt] sendresponse(responsemsgtype, payload[], payloadlen) write(buffer, len) [Befehl nicht erfolgreich ausgeführt] Siehe Validation nicht erfolgreich (mit PROCESS_COMMAND_ERROR) [Validation nicht erfolgreich] senderror(errorid = INVALID_COMMAND_ERROR) sendresponse(responsemsgtype, payload[], payloadlen) write(buffer, len) [false] resetall() Motoren stoppen Abbildung 16: Sequenzdiagramm zum Ablauf der Funktion loop() Sven Nobis Seite 44 von 110

45 7 Subsystementwurf: Software für das Smartphone Dieser Abschnitt zeigt den Entwurf der Software für das Smartphone. Die Entwicklung dieses Teils wurde inkrementell durchgeführt. Das heißt, es wurde in einem zyklischen Prozess der Entwurf, die Implementierung und der Test von kleinen Teilen der Software durchgeführt. Dabei wurde versucht den Entwurf möglichst synchron mit der Implementierung zu halten, so dass Diskrepanzen zwischen dem Entwurf und der implementierten Software gering gehalten werden. So wurde Reverse Engineering eingesetzt, um Änderungen des Quelltexts zurück in den Entwurf zu nehmen. Die Dokumentation in diesem Abschnitt soll den groben Entwurf auf Klassenebene zeigen und die grundlegenden Konzepte erläutern. Die Dokumentationen der Methoden oder auch einzelner Klassen kann den JavaDoc-Kommentaren im Quelltext oder der daraus als HTML generierten Dokumentation auf der CD entnommen werden. Die Benennung der Bezeichner erfolgt in Englisch und es werden die Namenskonventionen für Java befolgt. Die Benennung von Interfaces erfolgt, anders als in der Java-API, immer mit einem I vor dem Bezeichner des Typs (z.b. IMyInterface). 7.1 Softwareentwicklung für Android Die zu entwickelnde Software soll für Smartphones mit dem Android-Betriebsystem geschrieben werden. Dafür steht das Android SDK für die Entwicklung zur Verfügung. Applikationen werden in der Programmiersprache Java geschrieben. Dabei steht ein großer Teil der Bibliotheken der Java Standard Edition zur Verfügung. Dazu kommen noch einige weitere Bibliotheken, wie z.b. JUnit zum Testen. Einen wichtigen Teil bilden jedoch die Android-spezifischen Bibliotheken. Diese bringen die Funktionalitäten zum Erstellen der Benutzeroberfläche oder den Zugriff auf die Hardware, wie z.b. die Kamera oder GPS, mit. Bei der Entwicklung müssen ein paar grundlegende Techniken beachtet werden. So existiert keine klassische main()-funktion sondern eine Applikation besteht aus Aktivitäten, Services und ein paar weiteren Komponenten. Gestartet werden diese über sogennante Intents. Ein kurze Erläuterung dieser drei Komponenten lässt sich im Buch Android: Anwendungen für das Handy-Betriebssystem erfolgreich programmieren von Heiko Mosemann and Matthias Kose finden [26, S. 73f]: Activity (Aktivität): Jede Aktivität repräsentiert für den Anwender einen Bildschirm mit Benutzungsschnittstellen, die Informationen anzeigen, oder Interaktionen wie Texteingaben oder Auswahl von Elementen erlauben. Service (Service): Services laufen im Hintergrund der Applikation und haben keine Benutzungsschnittstellen. Services reagieren auf Ereignisse, wie Verbindungsanfragen oder -abbrüche, laden Daten aus dem Internet im Hintergrund oder aktualisieren die Koordinaten über GPS und können auch dann ausgeführt werden, wenn die Applikation nicht sichtbar oder sogar inaktiv ist. [...] [...] Intent (Intent): Mit Intents kann man Nachrichten auf dem ganzen System verschicken. So ist man in der Lage, Nachrichten an andere Aktivitäten und Services zu senden. Diese Nachrichten können Daten und Aktionen beinhalten. [...] Sven Nobis Seite 45 von 110

46 Jede Android-Applikation enthält eine Manifest-Datei (AndroidManifest.xml), in der die Aktivitäten und Services definiert werden. Dort wird auch festgelegt, auf welche Intents die Komponente reagiert. So kann definiert werden, welche Aktivität gestartet werden soll, wenn der Benutzer das App-Icon anklickt. Es kann auch auf andere Dinge reagiert werden, z.b. in unserem Fall sehr nützlich, wenn ein USB-Accessory angeschlossen wird. In der Mainifest-Datei wird außerdem angegeben, welche SDK-Version vorrausgesetzt wird und welche Berechtigungen und Features genutzt werden. Dabei werden in unserer Applikation die Berechtigungen für die Kamera, GPS-Lokalisierung, Internet-Zugriff und der Zugriff auf USB- Accessories benötigt. Desweiteren wird häufiger der Gebrauch von der Klasse Handler gemacht. Diese Klasse kann zur Synchronisation von Threads eingesetzt werden. So ist es notwendig, bestimmte Aktionen in einem anderen Thread auszuführen. Dazu zählt unter anderem die Kommunikation mit den anderen Geräten: Der Empfang von Nachrichten findet in einem anderen Thread statt. Die Verarbeitung der Nachricht soll danach von der Logik durchgeführt werden. Die Logik ist nicht threadsicher, weshalb nur der Hauptthread darin arbeiten sollte. Hier kommt der Handler ins Spiel. Der Kommunikations-Thread gibt einem Handler, der im Hauptthread abgearbeitet wird, per post(runnable r) ein Runnable mit. In diesem wird z.b. die Logik über die neue Nachricht informiert. Der Handler implementiert eine Warteschleife, in dem die post(..)s gesammelt werden. Diese werden dann im Hauptthread der Reihe nach von der Klasse Looper abgearbeitet. Die Gestaltung der Benutzeroberfläche erfolgt mittels eines XML-Formats. 7.2 Gesamtarchitektur Für die beiden Android-Smartphones werden zwei Applikationen entwickelt: Die erste Applikation AndroidRCCar Host für das Smartphone auf dem Fahrzeug. Mit der zweiten Applikation wird es dem Benutzer ermöglicht, das Fahrzeug zu steuern. Diese Applikation wird AndroidRCCar Client gennant. Da die beiden Applikationen einige Gemeinsamkeiten aufweisen, wie z.b. das Protokoll, wird die Bibliothek AndroidRCCar Common entwickelt. In den beiden Applikationen wird die Bibliothek eingebunden. Die Abbildung 17 auf der nächsten Seite zeigt die Paketstruktur der drei Teile grafisch. to.sven.androidrccar ist das Basispaket. Die Klassen der Bibliothek AndroidRCCar Common befinden sich in common, die der Applikation AndroidRCCar Host in host und AndroidRCCar Client in client. Innerhalb der drei Pakete sind jeweils die Unterpakete aufgelistet. Der Entwurf der aufgelisteten Pakete wird in den folgenden Abschnitten erläutert. An der rechten Seite werden die externen Bibliotheken aufgelistet. Die Abbildung 18 auf Seite 48 zeigt eine stark vereinfachte Übersicht mit den wichtigsten Klassen und deren Abhängigkeiten untereinander. Dabei zeigen die drei senkrechten und die drei waagerechten Kästen die Pakete an, in dem sich die Klassen befinden. Die Klasse ClientActivity befindet sich z.b. in to.sven.androidrccar.client.presentation. Die Anwendung ist nach einem drei (bzw. vier) Schichtmodell aufgebaut: Die presentation-schicht für die Anzeige, die logic-das konkrete Versuchs-Auto beherrscht alle möglichen Features. Deswegen werden alle virtuellen Methoden der Basisklasse überschrieben und mit Funktionalität gefüllt. mit der Logik der Applikation und die Kommunikations-Pakete als un- Sven Nobis Seite 46 von 110

47 pkg androidrccar androidrccar host client + framework + logic + presentation + service + accessorycommunication + communication + controller + framework + logic + presentation + service Externe Biblotheken RTSP-Camera «import» «import» Jackson Java JSON-processor common + communication + exception + framework + logic + model + service + utils Abbildung 17: Paketstruktur terste Schicht. Ein direkter Zugriff der Anzeigeschicht auf die Kommunikationsklassen ist nicht erlaubt. Auch kennen die Schichten nur die direkt unter ihnen liegende Schicht, nicht jedoch die Schicht oberhalb. Ziel ist es dadurch eine hohe Kohäsion und eine geringere Kopplung der Klassen zu erreichen. Im Host befindet sich zwischen der Schicht presentation und logic noch die Schicht controller, die den HostService beinhaltet (siehe hierzu Abschnitt 7.9 auf Seite 71). Zwischen den Schichten, aber auch an vielen anderen Stellen, wurde das Entwurfsmuster Observer eingesetzt. Da z.b. die Klasse RemoteCommunication nicht die Klasse AbstractLogic kennt, kann sie die Klasse nicht direkt informieren, wenn z.b. eine neue Nachricht empfangen wurde. Da kommt das Observer-Muster zum Einsatz. Die AbstractLogic implementiert ein von der Kommunikationsschicht vorgegebenes Interface. Im Projekt werden diese Interfaces immer mit dem Suffix Listener angegeben. In der RemoteCommunication kann sich die AbstractLogic nun als Beobachter registrieren. Tritt ein Ereignis auf, kann die RemoteCommunication den Beobachter, also die AbstractLogic, darüber informieren. Außerdem kommt, abgesehen von der presentation- und controller-schicht, Dependency Injection zum Einsatz. Anstatt sich die Abhängigkeiten selber zu erzeugen, werden die Abhängigkeiten in die Klassen hereingegeben. Dies erfolgt meist über den Konstruktor. Dabei werden den Klassen nur Interfaces übergeben. Der Einsatz von Dependency Injection und der Übergabe von Interfaces soll die Testbarkeit der einzelnen Klassen ermöglichen. So kann anstatt einer konkreten Abhängigkeit ein Mock-Objekt für den Test hereingegeben werden. Ein Mock-Objekt ist eine Attrappe, die ein bestimmtes Verhalten vortäuscht. Sven Nobis Seite 47 von 110

48 Client Common Host Presentation ClientActivity AbstractHostActivity Controller HostService ClientLogic AbstractLogic HostLogic Logic *Communication RemoteCommunication AccessoryCommunication Abbildung 18: Stark vereinfachte Übersicht mit den wichtigsten Klassen und den Abhängigkeiten untereinander 7.3 Externe Bibliotheken Neben Bibliotheken der Android SDK werden noch zwei weitere Bibliotheken eingebunden. Die erste ist Jackson, ein JSON-Prozessor [29], welcher auch in sehr bekannten Android-Anwendungen, wie die Facebook-App und die Youtube-App zum Einsatz kommt. Dieser wird genutzt, um die Nachrichten, die zwischen den beiden Smartphones gesendet werden, zu (de-)serialisieren. Jackson unterstüzt Data Binding über die Klasse ObjectMapper. Damit können die Datenobjekte direkt in JSON umgewandelt werden und umgekehrt. Die zweite ist die schon im Abschnitt auf Seite 30 erläuterte Bibliothek RTSP-Camerafor-Android. Mit dieser wird die Übertragung des Kamerabilds umgesetzt. Sven Nobis Seite 48 von 110

49 7.4 Paket communication Das Paket communication ermöglicht die Kommunikation zum Host bzw. zum Client. Die Abbildung 19 auf der nächsten Seite zeigt die Klassen des Pakets. Die beiden Klassen oben zeigen die Schnittstelle nach außen, also zur Logik. Über IRemoteCommunication kann die Logik Nachrichten senden oder die Verbindung schließen. Das Interface IRemoteCommunicationListener implementiert der Beobachter, um über eine neue Nachricht oder ein Verbindungsproblem informiert zu werden. Rechts unten ist das Paket model zu sehen. Dieses enhält alle in der Schnittstelle zwischen den beiden Smartphones (Abschnitt 5.1 auf Seite 23) definierten Nachrichten mit den zugehörigen Attributen. Alle Nachrichten erben von Message und sind einfache Datenobjekte (DTOs). Sie enthalten nur primitive Datentypen und haben meist keine Logik. Die Attribute der Klassen sind unveränderlich. Das bedeutet sie nach dem Anlegen nicht mehr geändert werden. Das soll verhindern, dass eine Nachricht nach dem Empfangen versehentlich geändert wird. Durch entsprechende Annotierung lassen sie sich mit der Jackson-JSON-Bibliothek direkt in JSON- Objekte serialisieren und auch wieder deserialisieren. Die Klasse RemoteCommunication erhält über den Konstruktor (mittels des dependencycontainer, siehe Abschnitt 7.7 auf Seite 65) den Socket. Der Socket ist die Kommunikations- Schnittstelle zum anderen Gerät. Über diese können Daten gesendet und empfangen werden. Zum Empfangen von Nachrichten wird der MessageListenerThread gestartet. Empfängt er eine Nachricht, so wandelt er diese mit der Jackson-JSON-Bibliothek in eine Message um. Diese wird mit einen Android-Handler zurück in den Hauptthread gesendet und dann an den IRemoteCommunicationListener weitergegeben. Tritt ein Fehler beim Senden oder Empfangen auf, soll die Verbindung beendet und der IRemoteCommunicationListener darüber informiert werden. Sven Nobis Seite 49 von 110

50 class communication Closeable «interface» contract::iremotecommunication + close() : void + sendmessage(message :Message) : void + startmessagelistener() : void «interface» contract::iremotecommunicationlistener + connectionproblem(ex :Exception) : void + messagereceived(message :Message) : void -listener impl::remotecommunication - jsonmapper: ObjectMapper = new ObjectMapper() {readonly} - listener: IRemoteCommunicationListener {readonly} - messagelistenerthread: MessageListenerThread {readonly} - socket: Socket {readonly} + close() : void ~ connectionproblem(e :Exception) : void ~ getjsonobjectmapper() : ObjectMapper ~ getsocket() : Socket ~ messagerecived(message :Message) : void + RemoteCommunication(dependencyContainer :IDependencyContainer<?,?>, listener :IRemoteCommunicationListener) + sendmessage(message :Message) : void + startmessagelistener() : void -initiator -messagelistenerthread impl::messagelistenerthread - handler: Handler - initiator: RemoteCommunication {readonly} Thread - connectionproblem(e :Exception) : void + MessageListenerThread(initiator :RemoteCommunication, handler :Handler) - messagerecived(msg :Message) : void + run() : void model + AdjustSpeedMessage + AuthenticationFailedMessage + AuthenticationMessage + BatteryPowerMessage + CameraConnectionParameterMessage + CyclicUpdateFeatureType + FeatureMessage + GreetingMessage + LocationMessage + Message + RequestCameraMessage + RotateCameraMessage + SetUpCyclicUpdateMessage + TurnCarMessage Abbildung 19: Klassendiagramm zum Paket communication Sven Nobis Seite 50 von 110

51 7.4.1 Verbindungsaufbau zum Client Der Host muss einen Server-Socket öffnen, um dann auf eine Verbindung des Clients warten zu können. Diese Aufgabe wird durch den SocketConnector umgesetzt (siehe auch Abbildung 20). Dieser implementiert wieder das erwähnte Entwurfsmuster Observer über das Interface ISocket- ConnectorListener. Der ISocketConnector ist die Schnittstelle nach außen. Über die Methode listen() wird asynchron auf eine neue Verbindung gewartet. Wurde eine Verbindung aufgebaut, so wird der Beobachter mittels connectionestablished(...) informiert. Bei einem Fehler wird er mittels error(...) informiert. cancel() bricht den Vorgang ab. class host.communication SocketConnector «interface» contract::isocketconnectorlistener + connectionestablished(socket) : void + error(int, Object) : void «interface» contract::isocketconnector + cancel() : void + finishedlistening() : boolean + getconnectiondetails() : ConnectionParameter + listen() : void impl::socketconnector AsyncTask - dc: IHostDependencyContainer {readonly} - LOG_TAG: String = "SocketConnector" {readonly} - port: volatile int + cancel() : void # doinbackground(object) : AsyncTaskResult<Socket> + finishedlistening() : boolean + getconnectiondetails() : ConnectionParameter - getlocalipaddress() : String + listen() : void # onpostexecute(asynctaskresult<socket>) : void # onpreexecute() : void + SocketConnector(IHostDependencyContainer) Abbildung 20: Klassendiagramm zum SocketConnector im Paket host.communication 7.5 Paket accessorycommunication Das Paket accessorycommunication enthält die Klassen zur Kommunikation mit dem Mikrocontroller Architektur Die Abbildung 21 auf der nächsten Seite zeigt das Unterpaket model. Zu den Befehl- und Antworttypen aus der Beschreibung der Schnittstelle zwischen Mikrocontroller und Smartphone (Abschnitt 5.2 auf Seite 31) wurde je eine Enumeration (RequestCommand und ResponseMessage) erstellt. Diese enhält alle Befehle bzw. Antworten mit ihrer Id und Länge des Payloads. Die in der Schnittstelle definierten Fehlercodes (Abschnitt auf Seite 39) werden in der Enume- Sven Nobis Seite 51 von 110

52 ration ErrorId definiert. Die Klasse CarFeatures ist eine Datenklasse, die die vom Fahrzeug unterstützten Funktionen enthält. Die Attribute der Klassen sind unveränderlich, so dass sie nach der Erstellung der Klasse nicht versehentlich geändert werden können. class accessorycommunication.model «enumeration» RequestCommand NOOP GET_PROTOCOL_VERSION GET_FEATURES TURN_CAR ADJUST_SPEED ROTATE_CAM GET_BATTERY_STATE Attributes + messageid: byte {readonly} + payloadlength: short {readonly} ~ RequestCommand(byte, short) REQUEST_OK ERROR BATTERY_NEAR_EMPTY PROTOCOL_VERSION FEATURES BATTERY_STATE «enumeration» ResponseMessage Attributes + messageid: byte {readonly} + payloadlength: short {readonly} - map: SortedMap<Byte, ResponseMessage> = new TreeMap<Byt... {readonly} ~ ResponseMessage(byte, short) + get(byte) : ResponseMessage CarFeatures + adjustablespeed: boolean {readonly} + batterypower: boolean {readonly} + camerapanmax: float {readonly} + camerapanmin: float {readonly} + cameratiltmax: float {readonly} + cameratiltmin: float {readonly} + drivebackward: boolean {readonly} + CarFeatures(float, float, float, float, boolean, boolean, boolean) + supportpancamera() : boolean + supporttiltcamera() : boolean «enumeration» ErrorId UNDEFINED_ERROR INVALID_COMMAND_ERROR UNKOWN_COMMAND_ERROR PROCESS_COMMAND_ERROR Attributes + errorid: short {readonly} - map: SortedMap<Short, ErrorId> = new TreeMap<Sho... {readonly} ~ ErrorId(short) + get(short) : ErrorId Abbildung 21: Klassendiagramm zum Paket accessorycommunication.model Die Abbildung 22 auf der nächsten Seite zeigt die Klassen, durch die die Kommunikation realisiert wird. Die Schnittstelle zur Logik ist durch die Klasse IAccessoryCommunication definiert. Die Logik kann sich als Beobachter mittels der Funktion AccessoryCommunication.setListener(...) registrieren. Dabei muss sie das Interface IAccessoryCommunication- Listener implementieren. Für jeden Befehl existiert im Unterpaket command eine Klasse, welche die Logik für das Senden des Befehls und das Verarbeiten der Antwort enthält. Dabei erben diese Klassen alle von AbstractCommand. Diese abstrakte Klasse implementiert die allgemeine Logik der Commands. Von der Klasse AbstractCommandWithOkResponse erben die Klassen, die als Antwort REQUEST OK erwarten. Die Commands haben als einzige Abhängigkeit das Interface ICommandListener. Dieses wird von AccessoryCommunication implementiert und stellt im Prinzip das Entwurfsmuster Fassade dar. So werden den Commands nur ausgewählte Methoden angeboten genau die, die für die Commands relevant sind. Sven Nobis Seite 52 von 110

53 class accessorycommunication Closeable «interface» contract::iaccessorycommunication + adjustspeed(float) : void + getcarfeatures() : CarFeatures + requestbatterystate() : void + rotatecamera(float, float) : void + setlistener(iaccessorycommunicationlistener) : void + startcommunication() : void + turncar(float) : void «interface» contract::iaccessorycommunicationlistener + batterynearempty() : void + batterystatereceived(float) : void + connectioninitialized() : void + connectionproblem(accessoryconnectionproblemexception) : void + errorreceived(string) : void + protocolversionnotmatch(short, short) : void -listener impl::accessorycommunication - carfeatures: volatile CarFeatures + COMMAND_LENGTH: int = 16 {readonly} - communicationthread: Thread = new Thread() {... - communicationthreadhandler: volatile Handler - inputstream: InputStream {readonly} - listener: IAccessoryCommunicationListener - mainthreadhandler: Handler {readonly} - monitor: Object = new Object() {readonly} - outputstream: OutputStream {readonly} + PROTOCOL_VERSION: short = 1 {readonly} + REPSONE_MESSAGE_LENGTH: int = 16 {readonly} + AccessoryCommunication(FileDescriptor, Handler) + AccessoryCommunication(OutputStream, InputStream, Handler) + adjustspeed(float) : void + batterynearempty() : void + batterystatereceived(float) : void + close() : void + connectioninitialized() : void + connectionproblem(accessoryconnectionproblemexception) : void + errorreceived(string) : void + getcarfeatures() : CarFeatures + getinputstream() : InputStream + getoutputstream() : OutputStream + postcommand(abstractcommand) : void + protocolversionnotmatch(short, short) : void + requestbatterystate() : void + rotatecamera(float, float) : void + setcarfeatures(carfeatures) : void + setlistener(iaccessorycommunicationlistener) : void + startcommunication() : void + turncar(float) : void command + AbstractCommand + AbstractCommandWithOkResponse + AdjustSpeedCommand + GetBatteryStateCommand + GetFeaturesCommand + GetProtocolVersionCommand + NoopCommand + RotateCameraCommand + TurnCarCommand + ICommandListener «interface» command::icommandlistener + getcarfeatures() : CarFeatures + getinputstream() : InputStream + getoutputstream() : OutputStream + postcommand(abstractcommand) : void + setcarfeatures(carfeatures) : void #commandlistener command::abstractcommand # commandlistener: ICommandListener {readonly} - inputstream: InputStream {readonly} - outputstream: OutputStream {readonly} # utf8: Charset = Charset.forName... {readonly} Runnable # AbstractCommand(ICommandListener) # fillpayload(bytebuffer) : void # getexpectedresponsemessagetype() : ResponseMessage - getpayload(responsemessage, byte[]) : ByteBuffer # getrequestcommandtype() : RequestCommand - mapresponsemessage(byte[]) : ResponseMessage - processbatterynearempty() : void - processerror(bytebuffer) : void # processexpectedresponse(bytebuffer) : void - processresponse(responsemessage, ByteBuffer) : void # rangeconvert(short, float) : float - receiveandprocessresponse() : void - receiveresponse() : byte[] + run() : void - sendcommand() : void - validatemessage(byte[]) : void command::abstractcommandwithokresponse # AbstractCommandWithOkResponse(ICommandListener) # getexpectedresponsemessagetype() : ResponseMessage # processexpectedresponse(bytebuffer) : void Abbildung 22: Klassendiagramm zum Paket accessorycommunication Sven Nobis Seite 53 von 110

54 7.5.2 Ablauf der Verarbeitung eines Befehls Das Sequenzdiagramm in Abbildung 23 auf der nächsten Seite zeigt beispielhaft den Ablauf anhand des Befehls GET BATTERY STATE. Das Verarbeiten eines Commands findet komplett in einem eigenen Thread statt. In diesem läuft ein Looper, der die Warteschleife eines Handlers abarbeitet. In dieser Warteschleife werden die Commands per Handler.post(Runnable r) reingegeben. Das ist möglich, da AbstractCommand das Interface Runnable implementiert. Wird also AccessoryCommunication.requestBatteryState() aufgerufen, wird eine neue Instanz vom GetBatteryStateCommand erstellt und an den Handler gegeben. Ist der Command an der Reihe, wird AbstractCommand.run() ausgeführt. Darin findet das Senden des Befehls durch sendcommand() und das Verarbeiten der Antwort durch receiveresponse() statt. Vor dem Senden holt sich der AbstractCommand den zu sendenen Typ und die Nutzlast. Nachdem die Antwort empfangen wurde, wird diese validiert, danach analysiert und dann entsprechend verarbeitet. Die Verarbeitung findet in processresponse(...) statt. Je nach empfangenen Antworttyp werden letztendlich verschiedene Methoden in der AccessoryCommunication aufgerufen. Dieser holt über einen weiteren Handler die Nachrichten ersteinmal wieder in den Hauptthread und informiert dann den Listener. Bevor Befehle gesendet werden können, muss erst AccessoryCommunication.startCommunication() aufgerufen werden. Die Methode startet den Thread und sendet danach die Protokollversion (GET PROTOCOLL VERSION) ab. Stimmt die Version überein, werden danach die Features angefragt. Liegen dann die Features vor, wird der Listener über connectioninitialized() informiert, dass die Initialisierung abgeschlossen ist. Ab diesem Zeitpunkt können die Features auch über AccessoryCommunication.getCarFeatures() abgerufen werden. Sven Nobis Seite 54 von 110

55 sd accessorycommunication impl::accessorycommunication Looper Handler command::abstractcommand command::getbatterystatecommand requestbatterystate() (Aus der Logik) postcommand(command : AbstractCommand) post(new GetBatteryStateCommand(...)) obtainmessage() Die Verarbeitung findet im Thread statt. Per post(...) wurde die Message einer Wartschlange hinzugefügt. Diese wird in einer Schleife abgearbeitet. Sobald der Command an der Reihe ist wird er verarbeitet. run() sendcommand() getrequestcommandtype() :RequestCommand alt [payloadlength > 0] fillpayload(payload :ByteBuffer) receiveandprocessresponse() receiveresponse() :byte Die Aufrufe an AccessoryCommunication werden hier wieder in den ursprünglichen Thread zurückgepostet und dann an den Listener weitergegeben. alt ResponseMessage [ERROR] validatemessage(responsebuffer :byte[]) mapresponsemessage(responsebuffer :byte[]) : ResponseMessage getpayload(responsemessage : ResponseMessage, responsebuffer :byte[]) : ByteBuffer processresponse(responsemessage : ResponseMessage, payload : ByteBuffer) processerror(payload :ByteBuffer) errorreceived(message :String) [BATTERY_NEAR_EMPTY] batterynearempty() processbatterynearempty() [getexpectedresponetype() (hier BATTERY_STATE)] processexpectedresponse(payload :ByteBuffer) batterystatereceived(charginglevel :float) [Andere] Fehler Abbildung 23: Sequenzdiagramm zum senden des Befehls RequestBatteryState Sven Nobis Seite 55 von 110

56 7.5.3 Verbindungsaufbau zum Mikrocontroller Bevor der Host mit dem Mikrocontroller kommunizieren kann, muss die Verbindung zum Mikrocontroller aufgebaut werden. Um diese Aufgabe kümmert sich die Klasse AccessoryConnector. Die Abbildung 24 zeigt das Klassendiagramm dazu. Es kommt wieder das bekannte Observer- Entwurfsmuster zum Einsatz. Der AccessoryConnector prüft, ob ein USB-Accessory angeschlossen ist. Sofern noch keine Berechtigung für den Zugriff auf das Accessory besteht, wird diese versucht zu holen. Danach wird das Accessory geöffnet und an AccessoryCommunication übergeben. Sollte dieser die Verbindung erfolgreich initialisiert haben (d.h. Version stimmt und Features sind da), informiert er den Listener darüber. Der Listener wird ebenfalls informiert, wenn das USB-Accessory abgeschlossen wird oder ein Fehler auftritt. class accessorycommunication connector «interface» contract:: IAccessoryConnectorListener + accessorydetached() : void + accessoryopend() : void + error(int, Object) : void «interface» contract::iaccessoryconnector + accessoryconnected() : boolean + close() : void + tryopenaccessory() : void impl::accessoryconnector - accessory: UsbAccessory - accessorycommunication: IAccessoryCommunication - acclistener: IAccessoryCommunicationListener = new IAccessoryC... {readonly} - ACTION_USB_PERMISSION: String = "to.sven.androi... {readonly} - context: Context {readonly} - dc: IHostDependencyContainer - LOG_TAG: String = "AccessoryConnector" {readonly} - paracelfd: ParcelFileDescriptor - permissionintent: PendingIntent = null - usbmanager: UsbManager - usbreceiver: BroadcastReceiver = new BroadcastRe... {readonly} + accessoryconnected() : boolean + AccessoryConnector(IHostDependencyContainer) + close() : void - closeaccessory() : void - handleerror(int, Object) : void - openaccessory(usbaccessory) : void + tryopenaccessory() : void Abbildung 24: Klassendiagramm zum AccessoryConnector Sven Nobis Seite 56 von 110

57 7.6 Paket logic Das Paket logic soll die Anwendungslogik nach dem Aufbau einer Verbindung enthalten. Es verarbeitet die angekommenen Nachrichten von der RemoteCommunication und der AccessoryCommunication, sowie die Aktionen, die von der Benutzeroberfläche aus kommen. Dabei existiert eine abstrakte Logik im Paket common.logic und die konkreten Implementierungen in den Paketen client.logic und host.logic Abstrakte Logik Die Abbildung 26 auf Seite 59 zeigt die Klassen des Pakets common.logic. Die Schnittstelle zur übergeordneten Schicht bildet das Interface ILogic. ILogicListener wird von der übergeordneten Schicht implementiert, um über Ereignisse informiert zu werden ( Entwurfsmuster Observer). Bei Aufruf von messagereceived(message message) durch RemoteCommunication erfolgt die Verarbeitung der Nachrichten nicht von der AbstractLogic bzw. ihren Spezialisierungen selbst, sondern von den MessageHandlern. Diese befinden sich in den Paketen client.logic.handler und host.logic.handler. Zu jeder Message existiert dabei eine Realisierung des Interface IMessageHandler. Die Handler mit den Messages, die vom Server gesendet werden, werden vom Client implementiert und die vom Client im Server (da sie dort natürlich auch verarbeitet werden müssen). Über IMessageHandler.getMessageType() muss der Typ der Nachricht zurückgegeben werden, der von der Klasse verarbeitet wird. Kommt eine Nachricht mit dem Typ an, so wird IMessageHandler.handleMessage(T message) mit der Nachricht als Parameter aufgerufen. Darin ist die Logik enthalten, um die Nachricht zu verarbeiten. Das Sequenzdiagramm in Abbildung 25 auf der nächsten Seite zeigt den Vorgang grafisch. Je nach Zeitpunkt oder unterstüzten Features dürfen nur bestimmte Nachrichten gesendet und so auch empfangen werden. Um das zu Realisieren, können die MessageHandler über die Methode AbstractLogic.registerMessageHandler(...) registriert werden und über die Methode AbstractLogic.clearMessageHandlers() können alle wieder entfernt werden. Wenn eine Nachricht empfangen wird, zu der kein MessageHandler registriert ist, so wird ein Fehler geworfen. Die Handler erhalten die Logik als ein ILogicHandlerFacade (genauer gesagt die Spezialisierungen IClientLogicHandler und IHostLogicHandler) über den Konstruktor. Über diese Fassade haben die Handler zugriff auf alle notwendigen Methoden der Logik und auf weitere Abhängigkeiten über den DependencyContainer (siehe hierzu auch Abschnitt 7.7 auf Seite 65). Sven Nobis Seite 57 von 110

58 sd AbstractLogic.messageReceived() impl::abstractlo... «interface» handler::imessagehandler messagereceived(message :Message) RemoteCommunication alt messagehandler = messagehandlers.get(messagetype); [messagehandler!= null] handlemessage(message :Message, messagehandler :IMessageHandler<T>) handlemessage(message :T) [messagehandler == null] handleunsupportedmessage(message :Message) handleerror(ex :Exception) Abbildung 25: Sequenzdiagramm zum Empfang einer Nachricht in der Logik Sven Nobis Seite 58 von 110

59 class common.logic «interface» contract::ilogiclistener + connectionlost(ex :ConnectionProblemException) : void «interface» contract::ilogic + close() : void impl::abstractlogic TDependencyContainer:extends IDependencyContainer<? extends IFactory, TListener> TListener:extends ILogicListener - container: TDependencyContainer {readonly} - listener: TListener {readonly} - LOG_TAG: String = "AbstractLogic" {readonly} - messagehandlers: SortedMap<String,IMessageHandler<?>> = new TreeMap<Str... {readonly} - remotecommunication: IRemoteCommunication {readonly} + AbstractLogic(container :TDependencyContainer) + clearmessagehandlers() : void + close() : void + connectionproblem(ex :Exception) : void + enablelocationservice() : void + getdependency() : TDependencyContainer + handleerror(ex :Exception) : void + handleerror(ex :Exception, logmessage :String) : void - handlemessage(message :Message, messagehandler :IMessageHandler<T>) : void # handleunsupportedmessage(message :Message) : void # initialized() : void + messagereceived(message :Message) : void + registermessagehandler(messagehandlerclass :Class<T>) : void - registermessagehandler(messagehandler :IMessageHandler<? extends Message>) : void + sendmessage(message :Message) : void «interface» contract::iremotecommunicationlistener + connectionproblem(ex :Exception) : void + messagereceived(message :Message) : void aus host.accessorycommunication.co ntract «interface» handler::ilogichandlerfacade + clearmessagehandlers() : void + close() : void + enablelocationservice() : void + getdependency() : TDependencyContainer + handleerror(ex :Exception) : void + handleerror(ex :Exception, logmessage :String) : void + registermessagehandler(messagehandlerclass :Class<T>) : void + sendmessage(message :Message) : void «interface» handler::imessagehandler + getmessagetype() : Class<T> + handlemessage(message :T) : void Abbildung 26: Klassendiagramm zum Paket common.logic Sven Nobis Seite 59 von 110

60 7.6.2 Client Logik In der Abbildung 27 sind die Klassen der Client Logik zu sehen. Die oberen beiden Klassen bilden wieder die Schnittstelle zur Präsentationsebene und erben von Interfaces in common. Die Handler sind im Paket handler zu sehen. Sie erben alle von der Klasse AbstractClientMessageHandler. Der Ablauf der Initialisierung der Verbindung wird im Sequenzdiagramm der Abbildung 28 auf der nächsten Seite gezeigt. Das Diagramm soll zeigen, was bei der Erstellung der ClientLogic passiert. So soll dargestellt werden, welche Nachrichten gesendet werden und wann welche Handler registriert werden. class client.logic ILogicListener «interface» contract::iclientlogiclistener + authenticationfalied(reason :String) : void + enabledriving(adjustablespeed :boolean, drivebackward :boolean) : void + enablepan(min :float, max :float) : void + enabletilt(min :float, max :float) : void + setbatterypower(charginglevel :float) : void + setbearing(bearing :float) : void + setdistance(distance :float, bearingto :float) : void + setspeed(speed :float) : void «interface» contract::iclientlogic ILogic + adjustspeed(speed :float) : void + rotatecamera(pan :float, tilt :float) : void + turncar(rotation :float) : void handler + AbstractClientMessageHandler + AuthenticationFailedMessageHandler + BatteryPowerMessageHandler + CameraConnectionParameterMessageHandler + FeatureMessageHandler + GreetingMessageHandler + LocationMessageHandler + IClientLogicHandlerFacade impl::clientlogic AbstractLogic + adjustspeed(speed :float) : void + ClientLogic(container :IClientDependencyContainer) + close() : void + rotatecamera(pan :float, tilt :float) : void + turncar(rotation :float) : void T:extends Message handler::abstractclientmessagehandler # dependences: IClientDependencyContainer {readonly} # logic: IClientLogicHandlerFacade {readonly} + AbstractClientMessageHandler(logic :IClientLogicHandlerFacade) + getmessagetype() : Class<T> #logic ILogicHandlerFacade «interface» handler::iclientlogichandlerfacade «interface» handler::imessagehandler aus common.logic.handler Abbildung 27: Klassendiagramm zum Paket client.logic Sven Nobis Seite 60 von 110

61 sd Initialisierung der Verbindung in client.logic impl::clientlogic handler::greetingmessagehandler handler::featuremessagehandler handler::authenticationfailedmessagehandler «interface» contract::iclientlogiclistener ClientLogic(container : IClientDependencyContainer) new registermessagehandler(new GreetingMessageHandler(...)) initialized() messagereceived(message :Message) Nachricht vom Server empfangen handlemessage(message :GreetingMessage) clearmessagehandlers() registermessagehandler(new FeatureMessageHandler(...)) registermessagehandler(new AuthenticationFailedMessageHandler(...)) sendmessage(new AuthenticationMessage(...)) Nachricht vom Server empfangen messagereceived(message :Message) alt [FeatureMessage empfangen] handlemessage(message :FeatureMessage) clearmessagehandlers() Die drei Methoden registrieren entsprechend der Features die restlichen MessageHandler, etc. setupcyclicupdates(message :FeatureMessage) opt [Falls ein Location-Feature unterstüzt wird] sendmessage(new SetUpCyclicUpdateMessage(...)) registermessagehandler(new LocationPowerMessageHandler()) [Falls das Batterie-Feature unterstüzt wird] sendmessage(new SetUpCyclicUpdateMessage(...)) registermessagehandler(new BatteryPowerMessageHandler()) setupcamerastream(message :FeatureMessage) alt [Falls Kamera unterstützt wird] registermessagehandler(new CameraConnectionParameterMessageHandler(...)) Sofern untersützt: enablepan(min :float, max :float) sendmessage(new RequestCameraMessage(...)) enabletilt(min :float, max :float) setupdriving(message :FeatureMessage) enabledriving(adjustablespeed :boolean, drivebackward :boolean) [AuthenticationFailedMessage] handlemessage(message :AuthenticationFailedMessage) close() authenticationfalied(reason :String) Abbildung 28: Sequenzdiagramm zur Initialisierung der Verbindung in der ClientLogic Sven Nobis Seite 61 von 110

62 7.6.3 Host Logik Das Klassendiagramm der Host Logik ist in Abbildung 29 auf der nächsten Seite zu sehen. Da die HostLogic keine weiteren Methoden zu der Schnittstelle ILogic hinzufügt, wurde die Schnittstelle IHostLogic weggelassen. Der Listener hingegen definiert zusätzlich die Methode connectedestablished(). Die Implementierung der Handler wurde vergleichbar mit der ClientLogic vorgenommen. Dazu implementiert die HostLogic noch das Interface IAccessoryCommunicationListener aus der accessorycommunication, um über die Ereignisse in der AccessoryCommunication informiert zu werden. (Auf diese Klasse kann sie über den HostDependencyContainer zugreifen.) AbstractCyclicTask definiert eine abstrakte Klasse, die eine bestimmte Aufgabe in einem bestimmten Intervall ausführt. Diese wird für das Senden der Ortungs-Nachricht und der Batterie- Ladestand-Nachricht benötigt und durch LocationCyclicTask und BatteryPowerCyclicTask realisiert. Die HostLogic steuert diese beiden Tasks über die Klasse CyclicTask. Die Abbildung 30 auf Seite 64 zeigt analog zum Ablauf in der Client Logic (Abbildung 28 auf der vorherigen Seite), was bei der Erstellung der HostLogic passiert. Sven Nobis Seite 62 von 110

63 class host.logic handler + AbstractHostMessageHandler + AdjustSpeedMessageHandler + AuthenticationMessageHandler + RequestCameraMessageHandler + RotateCameraMessageHandler + SetUpCyclicUpdateMessageHandler + TurnCarMessageHandler + IHostLogicHandlerFacade «interface» handler::imessagehandler handler::abstracthostmessagehandler aus common.logic.handler T:extends Message # dependences: IHostDependencyContainer {readonly} # logic: IHostLogicHandlerFacade {readonly} impl::hostlogic - batterypowercyclictask: ICyclicTask - locationcyclictask: ICyclicTask - LOG_TAG: String = "HostLogic" {readonly} # salt: String {readonly} ILogicListener «interface» contract::ihostlogiclistener + connectedestablished() : void AbstractLogic + batterynearempty() : void + batterystatereceived(charginglevel :float) : void + close() : void + connectioninitialized() : void + connectionproblem(ex :AccessoryConnectionProblemException) : void + errorreceived(message :String) : void + getbatterypowercyclictask() : ICyclicTask + getlocationcyclictask() : ICyclicTask + getsalt() : String + HostLogic(container :IHostDependencyContainer) + protocolversionnotmatch(hostversion :short, microcontrollerversion :short) : void + AbstractHostMessageHandler(logic :IHostLogicHandlerFacade) + getmessagetype() : Class<T> -batterypowercyclictask -locationcyclictask #logic ILogicHandlerFacade «interface» handler::ihostlogichandlerfacade + getbatterypowercyclictask() : ICyclicTask + getlocationcyclictask() : ICyclicTask + getsalt() : String -facade «interface» impl::icyclictask + isrunning() : boolean + setinterval(interval :int) : void + start() : void + stop() : void impl::abstractcyclictask - handler: Handler {readonly} - interval: int = 0 - started: boolean Runnable + AbstractCyclicTask(handler :Handler) + isrunning() : boolean + run() : void # runtask() : void + setinterval(interval :int) : void + start() : void + stop() : void «interface» contract:: IAccessoryCommunicationListener aus host.accessorycommunication.co ntract impl::locationcyclictask - facade: IHostLogicHandlerFacade {readonly} - oldlocation: Location + LocationCyclicTask(facade :IHostLogicHandlerFacade) + runtask() : void + start() : void impl::batterypowercyclictask - accessorycommunication: IAccessoryCommunication {readonly} + BatteryPowerCyclicTask(accessoryCommunication :IAccessoryCommunication, handler :Handler) + runtask() : void Abbildung 29: Klassendiagramm zum Paket host.logic Sven Nobis Seite 63 von 110

64 sd Initialisierung der Verbindung in host.logic impl::hostlogic handler::authenticationmessagehandler «interface» contract::ihostlogiclistener AbstractLogic(container : TDependencyContainer) new registermessagehandler(new AuthenticationMessageHandler(...)) initialized() sendmessage(new GreetingMessage(...)) messagereceived(message :Message) Nachricht vom Client empfangen handlemessage(message :AuthenticationMessage) clearmessagehandlers() alt Passwort korrekt? [Ja] AuthenticationSuccessfull() registermessagehandler(new AdjustSpeedMessageHandler(...)) registerhandlers(featuremessage :FeatureMessage) registermessagehandler(new TurnCarMessageHandler(...)) opt Falls unterstützt [Kamera] registermessagehandler(new RequestCameraMessageHandler(...)) [Kamera rotieren] registermessagehandler(new RotateCameraMessageHandler(...)) [Batterie Leistung oder Lokalisierung] registermessagehandler(new SetUpCyclicUpdateMessageHandler(...)) connectedestablished() sendmessage(new FeatureMessage(...)) [Nein] sendmessage(new AuthenticationFailedMessage(...)) AuthenticationFailed() Abbildung 30: Sequenzdiagramm zur Initialisierung der Verbindung in der HostLogic Sven Nobis Seite 64 von 110

65 7.7 Paket framework Das Paket framework bildet das Rahmenwerk für die Dependency Injection. Zum einen realisiert es eine Factory zur Erzeugung von Objekten, zum anderen bietet es einen Container für die Abhängigkeiten (DependencyContainer). Über diesen Container werden die Klassen, wie die Logik, mit Ihren Abhängigkeiten versorgt DependencyContainer Die Abbildung 19 auf Seite 50 zeigt die Klassen des DependencyContainers. So bietet common eine abstrakte Implementierung des DependencyContainers, welche die Abhängigkeiten beinhaltet, die in beiden Applikationen gebraucht werden. Dieser nutzt die AbstractLogic und andere Klassen in common über das Interface IDependencyContainer, um die benötigten Abhängigkeiten zu bekommen. In den konkreten Implementierungen werden die Container noch um die Host und Client spezifischen Abhängigkeiten erweitert. Je nach Abhängigkeit wird diese entweder über den Konstruktor hereingegeben, selbst erstellt oder erst später gesetzt (auch Lazy Binding gennant). Sven Nobis Seite 65 von 110

66 class DependencyContainer client framework::clientdependencycontainer - clientconfigurationservice: IClientConfigurationService {readonly} - connectionparameter: ConnectionParameter {readonly} - featuremessage: FeatureMessage - videoclientservice: IVideoClientService {readonly} + ClientDependencyContainer(listener, socket, context, connectionparameter, videoview) + getconfiguration() : IClientConfigurationService + getconnectionparameter() : ConnectionParameter + getfeatures() : FeatureMessage + getvideoclientservice() : IVideoClientService + setfeatures(message) : void «interface» framework::iclientdependencycontainer + getconfiguration() : IClientConfigurationService + getconnectionparameter() : ConnectionParameter + getfeatures() : FeatureMessage + getvideoclientservice() : IVideoClientService + setfeatures(message) : void impl::clientlogic common «import» framework::abstractdependencycontainer - context: Context {readonly} - factory: TFactory {readonly} - handler: Handler {readonly} - listener: TListener {readonly} - locationservice: ILocationService - socket: Socket TFactory:extends IFactory TListener:extends ILogicListener + AbstractDependencyContainer(factory, listener, context) + getcontext() : Context + getfactory() : TFactory + gethandler() : Handler + getlocationservice() : ILocationService + getlogiclistener() : TListener + getsocket() : Socket + setlocationservice(locationservice) : void + setsocket(socket) : void «interface» framework::idependencycontainer + getcontext() : Context + getfactory() : TFactory + gethandler() : Handler + getlocationservice() : ILocationService + getlogiclistener() : TListener + getsocket() : Socket + setlocationservice(locationservice) : void + setsocket(socket) : void impl::abstractlogic TDependencyContainer:ext TListener:extends ILogicLi host «import» framework::hostdependencycontainer - accessorycommunication: IAccessoryCommunication - accessoryconnectorlistener: IAccessoryConnectorListener {readonly} - camerastreamingprovider: ICameraStreamingService - hostconfigurationservice: IHostConfigurationService {readonly} - socketconnectorlistener: ISocketConnectorListener + getaccessorycommunication() : IAccessoryCommunication + getaccessoryconnectorlistener() : IAccessoryConnectorListener + getcamerastreamingservice() : ICameraStreamingService + getcarfeatures() : CarFeatures + getconfiguration() : IHostConfigurationService + getsocketconnectorlistener() : ISocketConnectorListener + HostDependencyContainer(listener, context, accessoryconnectorlistener) + setaccessorycommunication(accessorycommunication) : void + setcamerastreamingservice(service) : void + setsocketconnectorlistener(listener) : void «interface» framework::ihostdependencycontainer + getaccessorycommunication() : IAccessoryCommunication + getaccessoryconnectorlistener() : IAccessoryConnectorListener + getcamerastreamingservice() : ICameraStreamingService + getcarfeatures() : CarFeatures + getconfiguration() : IHostConfigurationService + getsocketconnectorlistener() : ISocketConnectorListener + setaccessorycommunication(accessorycommunication) : void + setcamerastreamingservice(service) : void + setsocketconnectorlistener(listener) : void impl::hostlogic Abbildung 31: Klassendiagramm zum DependencyContainer im Paket framework Sven Nobis Seite 66 von 110

67 7.7.2 Factory In der Abbildung 32 werden die Factory-Klassen gezeigt. Genauso wie beim DependencyContainer existiert hier auch wieder eine abstrakte Factory in common und die beiden konkreten Factorysin client und host. Auf die Interfaces der Factory kann über den DependencyContainer zugegriffen werden. Dadurch kann für Tests eine Mock-Factory eingesetzt werden. Diese erzeugt dann Mocks und keine echten Abhängigkeiten. class Factory client host «interface» framework:: IClientDependencyContainer «interface» framework:: IHostDependencyContainer «interface» framework::iclientfactory + createclientconfigurationservice(context) : IClientConfigurationService + createvideoclientservicer(videoview) : IVideoClientService «interface» framework::ihostfactory + createaccessorycommunication(filedescriptor, mainthreadhandler) : IAccessoryCommunication + createcamerastreamingservice() : ICameraStreamingService + createhostconfigurationservice(context) : IHostConfigurationService framework::clientfactory + createclientconfigurationservice(context) : IClientConfigurationService + createmessagehandler(type, logic) : THandler + createvideoclientservicer(videoview) : IVideoClientService framework::hostfactory + createaccessorycommunication(filedescriptor, mainthreadhandler) : IAccessoryCommunication + createcamerastreamingservice() : ICameraStreamingService + createhostconfigurationservice(context) : IHostConfigurationService + createmessagehandler(type, logic) : THandler «import» «import» common «interface» framework:: IDependencyContainer «interface» framework::ifactory + createlocationservice(context) : ILocationService + createmessagehandler(type, logic) : THandler + createremotecommuncation(dependencycontainer, cplistener) : IRemoteCommunication framework::abstractfactory + createlocationservice(context) : ILocationService + createmessagehandler(type, logic) : THandler + createremotecommuncation(dependencycontainer, cplistener) : IRemoteCommunication Abbildung 32: Klassendiagramm zur Factory im Paket framework Sven Nobis Seite 67 von 110

68 7.8 Paket services Bei den Klassen im Paket services handelt es sich nicht um Android Services. Vielmehr bieten die Klassen in diesem Paket einen bestimmten Dienst an. Diese Dienste nutzt die Logik. Im Paket common befindet sich der LocationService (siehe Klassendiagramm in Abbildung 33). Dieser bietet der Logik über das Interace ILocationService die aktuellen Ortungsdaten an. Er ist der einzige Service der vom Host und Client genutzt wird. Der Client hat im Paket client.service noch zwei weitere Dienste (siehe Klassendiagramm in Abbildung 34 auf der nächsten Seite): Der ClientConfigurationService bietet den Zugriff auf die gespeicherte Konfiguration. Der VideoClientService kümmert sich um das Abspielen eines Netzwerk-Video-Streams. Der Host hat analog dazu im Paket host.service (siehe Klassendiagramm in Abbildung 35 auf Seite 70) den Dienst HostConfigurationService und den Dienst CameraStreamingService. Der zweite kümmert sich um das Versenden des Kamerabildes. class common.service «interface» contract::ilocationservice + getcurrentlocation() : Location + haslocationchanged() : boolean + startlisten() : void + stoplisten() : void impl::locationservice LocationListener - location: Location - locationchanged: boolean - locationmanager: LocationManager + getcurrentlocation() : Location + haslocationchanged() : boolean + LocationService(LocationManager) + onlocationchanged(location) : void + onproviderdisabled(string) : void + onproviderenabled(string) : void + onstatuschanged(string, int, Bundle) : void + startlisten() : void + stoplisten() : void Abbildung 33: Klassendiagramm zum Paket common.service Sven Nobis Seite 68 von 110

69 class client.service «interface» contract::ivideoclientservice + playstream(string) : void + stop() : void impl::videoclientservice «interface» contract::iclientconfigurationservice + getbatterypowermessageinterval() : int + getcameraenabled() : boolean + getconnectionparameter() : ConnectionParameter + getlasthostadress() : String + getlastport() : int + getlocationmessageinterval() : int + getsavedpassword() : String + reset() : void + resetsavedconnectionparameter() : void + saveconnectionparameter(connectionparameter) : void - LOG_TAG: String = "VideoClientService" {readonly} - renderer: RtpVideoRenderer - videoview: VideoSurfaceView {readonly} + playstream(string) : void + stop() : void + VideoClientService(VideoSurfaceView) impl::clientconfigurationservice - BATTERY_POWER_MESSAGE_INTERVAL_KEY: String = "BatteryPowerMe... {readonly} - CAMERA_ENABLED_KEY: String = "CameraEnabled" {readonly} - LAST_HOST_ADRESS_KEY: String = "LastHostAdress" {readonly} - LAST_PORT_KEY: String = "LastPort" {readonly} - LOCATION_MESSAGE_INTERVAL_KEY: String = "LocationMessag... {readonly} - prefs: SharedPreferences {readonly} - SAVED_PASSWORD_KEY: String = "SavedPassword" {readonly} + ClientConfigurationService(Context) + getbatterypowermessageinterval() : int + getcameraenabled() : boolean + getconnectionparameter() : ConnectionParameter + getlasthostadress() : String + getlastport() : int + getlocationmessageinterval() : int + getsavedpassword() : String + reset() : void + resetsavedconnectionparameter() : void + saveconnectionparameter(connectionparameter) : void Abbildung 34: Klassendiagramm zum Paket client.service Sven Nobis Seite 69 von 110

70 class host.service «interface» contract::ihostconfigurationservice + canrotatecamera() : boolean + getpassword() : String + getport() : int + shareanylocationdependingfeature() : boolean + sharebearing() : boolean + sharecamera() : boolean + sharelocation() : boolean + sharespeed() : boolean «interface» contract::icamerastreamingservice + activated() : boolean + close() : void + getpath() : String + getport() : int + getscheme() : String + initialize(context :Context) : void impl::hostconfigurationservice - CAN_ROTATE_CAMERA_KEY: String = "CanRotateCamera" {readonly} - PASSWORD_KEY: String = "Password" {readonly} - PORT_KEY: String = "Port" {readonly} - prefs: SharedPreferences {readonly} - SHARE_BEARING_KEY: String = "ShareBearing" {readonly} - SHARE_CAMERA_KEY: String = "ShareCamera" {readonly} - SHARE_LOCATION_KEY: String = "ShareLocation" {readonly} - SHARE_SPEED_KEY: String = "ShareSpeed" {readonly} + canrotatecamera() : boolean + getpassword() : String + getport() : int + HostConfigurationService(context :Context) + reset() : void + shareanylocationdependingfeature() : boolean + sharebearing() : boolean + sharecamera() : boolean + sharelocation() : boolean + sharespeed() : boolean impl::camerastreamingservice + activated() : boolean + close() : void + getpath() : String + getport() : int + getscheme() : String + initialize(context :Context) : void Abbildung 35: Klassendiagramm zum Paket host.service Sven Nobis Seite 70 von 110

71 7.9 Paket presentation und controller im Host Die Host-Applikation lässt sich in drei Zustände einteilen. Das Zustandsdiagramm in Abbildung 36 zeigt diese drei Zustände. So besteht nach dem Aufrufen der Applikation zuerst einmal keine Verbindung zum Mikrocontroller oder dem Client. Sie befindet sich im Zustand Nicht verbunden. Kann nun erfolgreich eine Verbindung zum Mikrocontroller aufgebaut werden, so befindet sie sich im Zustand Warte auf Verbindung der Client-App. Nun kann ein Client sich mit dem Host verbinden. Sobald dies ein Client erfolgreich getan hat, geht die App in den Zustand Fahren über. In diesem Zustand ist die ClientLogic aktiv. Sie leitet die Befehle weiter und gibt diverse Informationen zurück. Geht eine der beiden Verbindungen verloren, so wechselt die Applikation wieder in den vorherigen Zustand. Je nach Zustand müssen dem Benutzer andere Informationen angezeigt werden, damit er weiß, was er tun muss. Benutzer ruft App auf Anschluss an den µcontroller Nicht verbunden do / Benutzer zum Anschluss des µcontroller auffordern [Verbindung zum µcontroller besteht] [Keine Verbindung zum µcontroller] Warte auf Verbindung von Client-App do / Benutzer Informationen zum Verbinden anzeigen [Verbindung zur Client-App besteht] [Keine Verbindung zur Client-App] Fahren [Keine Verbindung zum µcontroller] / Verbindung zur Client-App trennen Abbildung 36: Zustandsdiagramm der Host-Applikation Um dieses Verhalten umsetzen zu können, wurde die Klasse HostService im Paket controller entworfen (siehe auch Abbildung 37 auf Seite 73). Diese Klasse ist ein Android Service und läuft im Hintergrund. Die erwähnten Zustände wurden mit der Enumeration ServiceState abgebildet. Diese enthält zusätzlich noch den Zustand ERROR. Diesen nimmt der Service an, falls ein Fehler auftritt. Um den Benutzer eine Rückmeldung zu geben, dass der Service läuft, wird in der Benachrichtung-Leiste von Android ein Icon eingeblendet. Dieser wird durch die Klasse HostServiceNotification realisiert. Über das Interface IHostService können die Aktivitäten sich Informationen über den aktuellen Zustand, in dem sich die Applikation befindet, holen. Über den Listener IHostServiceListener werden sie über Änderungen des Zustands informiert. Den drei Zuständen entsprechend existiert je eine Aktivität. Die drei Aktivitäten erben alle von der AbstractHostActivity. Diese kümmert sich darum, das der Service gestartet oder wieder beendet wird. Außerdem baut sie beim Anzeigen der Aktivität die Verbindung zum Service auf und, wenn die Aktivität in dern Hintergrund geht, wieder ab. Sobald die Aktivitäten über eine Zustandsänderung informiert werden, starten sie die nächste Sven Nobis Seite 71 von 110

72 Aktivität oder kehren zur vorherigen zurück. So wird die UnconnectedActivity nach dem Aufbau der Verbindung zum Mikrocontroller die WaitForOtherPhoneActivity starten. Oder die ConnectedActivity beendet sich, wenn die Verbindung zum anderen Smartphone verloren geht, so dass die WaitForOtherPhoneActivity wieder sichtbar wird. Wie schon erwähnt, läuft der HostService im Hintergrund. Gehen die Aktivitäten in den Hintergrund, werden diese pausiert. Der HostService läuft der in der Regel jedoch weiter. Die Ausnahme von der Regel bildet dabei der UNCONNECTED-Zustand, da es hier keinen Grund gibt, das der Service weiterlaufen muss. Wenn die UnconnectedActivity in den Hintergrund geht, wird der Service geschlossen. In den anderen Zuständen hat der Benutzer die Möglichkeit z.b. über den Benachrichtungs-Eintrag die App wieder aufzurufen und die Applikation zu beenden. Die Aktivität AccessoryAttachedActivity wird aufgerufen, wenn der Mikrocontroller angeschlossen wird und informiert nur den Service darüber. Das ist notwendig, da der Intent nur von einer Aktivität entgegengenommen werden kann. (Anmerkung: Ein BroadcastReceiver kann bei diesem Intent nicht genutzt werden.) Die Aktivität HostPreferencesActivity realisiert die Aktivität zum Konfigurieren der Anwendung mittels der von Android angebotenen PreferenceActivity. Sven Nobis Seite 72 von 110

73 class host.presentation presentation::waitforotherphoneactivity + cancelclicked(view) : void # handlestate(servicestate) : void # oncreate(bundle) : void # onserviceconnected() : void + sendclicked(view) : void + statechanged(servicestate) : void presentation::connectedactivity # handlestate(servicestate) : void # oncreate(bundle) : void # onserviceconnected() : void + quitclicked(view) : void + statechanged(servicestate) : void presentation::unconnectedactivity presentation::abstracthostactivity Activity # boundservice: IHostService - dialog: ProgressDialog - isbound: boolean # LOG_TAG: String = getclass().gets... {readonly} - mconnection: ServiceConnection = new ServiceConn... # menu_id: int = R.menu.menu - nobinding: boolean = false # RESULT_USER_EXIT: int = 42 {readonly} # completeexit() : void ~ dobindservice() : void ~ dounbindservice() : void + onactivityresult(int, int, Intent) : void + oncreateoptionsmenu(menu) : boolean + onoptionsitemselected(menuitem) : boolean # onpause() : void # onresume() : void # onserviceconnected() : void - removeservicebinding() : void - showabout() : void # showerrordialog() : void - showsettings() : void + statechanged(servicestate) : void # handlestate(servicestate) : void # oncreate(bundle) : void # onserviceconnected() : void + statechanged(servicestate) : void #boundservice «interface» controller::ihostservicelistener + statechanged(servicestate) : void «interface» controller::ihostservice + getconnectiondetails() : ConnectionParameter + geterrormsg() : String + getstate() : ServiceState + setlistener(ihostservicelistener) : void -servicelistener controller::hostservice Service - accessoryconnector: IAccessoryConnector + ACTION_USB_ACCESSORY_ATTACHED: String = "to.sven.androi... {readonly} - binder: IBinder = new HostBinder() {readonly} - connectorlistener: IAccessoryConnectorListener = new IAccessoryC... {readonly} - dependencycontainer: IHostDependencyContainer - errormsg: String - hostlogiclistener: IHostLogicListener = new IHostLogicL... {readonly} - LOG_TAG: String = "HostService" {readonly} - logic: ILogic - notification: HostServiceNotification - servicelistener: IHostServiceListener - socketconnector: ISocketConnector - socketconnectorlistener: ISocketConnectorListener = new ISocketConn... {readonly} - state: ServiceState = ServiceState.NO... -notification controller::hostservicenotification - context: Context {readonly} - notification: Notification - NOTIFICATION_ID: int = R.string.host_s... - notificationmanager: NotificationManager + cancel() : void + changenotification(int) : void + HostServiceNotification(Context) + statechanged(servicestate) : void presentation::accessoryattachedactivity Activity - LOG_TAG: String = "AccessoryAttac... {readonly} + changestate(servicestate) : void - executesocketconnector() : void + getconnectiondetails() : ConnectionParameter + geterrormsg() : String + getstate() : ServiceState + onbind(intent) : IBinder + oncreate() : void + ondestroy() : void + onstartcommand(intent, int, int) : int + onunbind(intent) : boolean + setlistener(ihostservicelistener) : void -state # oncreate(bundle) : void «enumeration» controller::servicestate NOT_CONNECTED WAIT_FOR_OTHER_PHONE CONNECTED CONNECTION_LOST ERROR PreferenceActivity presentation:: HostPreferencesActivity # oncreate(bundle) : void Abbildung 37: Klassendiagramm zum Paket host.presentation Sven Nobis Seite 73 von 110

74 7.10 Paket presentation im Client Im Client werden drei Aktivitäten umgesetzt: die ConnectionParamActivity zum Eingeben der Verbindungsparameter die ClientActivity zum Steuern des Fahrzeugs die ClientPreferenceAcitvity zur Konfiguration Die Abbildung 38 auf der nächsten Seite zeigt dazu das Klassendiagramm des Pakets presentation. Die grün gefärbten Klassen setzen jeweils ein Oberflächen-Element um (siehe hierzu auch Abschnitt auf Seite 79): Die VirtualJoystickView setzt die beiden Steuerelemente zum Drehen und Bewegen des Fahrzeugs um. Die BatteryView setzt die Batterieanzeige um. Die DistanceView setzt die Anzeige der Entfernung zum Fahrzeug um. Die BearingOfCarView setzt die Anzeige der Fahrtrichtung des Fahrzeugs um. Beim Aufruf der Applikation wird die ConnectionParamActivity angezeigt, die dann die ClientActivity startet. Über einen speziellen Link, der die Verbindungsparameter enthält, kann die ClientActivity auch direkt gestartet werden. So bietet dann später Android an, die Applikation zu starten, sobald der Link &port=[...]&password=[...] aus einer anderen Applikation heraus aufgerufen wird. Aus dem Link können dann die Verbindungsparameter gelesen werden. Sven Nobis Seite 74 von 110

75 class client.presentation «interface» view::onvirtualjoystickmovelistener + onleftmove(x :float, y :float) : void + onrightmove(x :float, y :float) : void -listener -joystickmovelistener ClientActivity Activity - alert: AlertDialog - batteryview: BatteryView - bearingview: BearingOfCarView - connectionparameter: ConnectionParameter - connecttask: ConnectTask - dialog: ProgressDialog - distanceview: DistanceView - isonstop: boolean - joystickmovelistener: OnVirtualJoystickMoveListener = new OnVirtualJo... {readonly} - joystickview: VirtualJoystickView - LOG_TAG: String = "ClientActivity" {readonly} - logic: IClientLogic - logiclistener: IClientLogicListener = new IClientLogi... {readonly} view::bearingofcarview View + BearingOfCarView(context :Context, attrs :AttributeSet, defstyle :int) + BearingOfCarView(context :Context, attrs :AttributeSet) + BearingOfCarView(context :Context) + setbearing(bearing :float) : void -bearingview +distanceview view::distanceview View - getvideoview() : VideoSurfaceView + oncreate(savedinstancestate :Bundle) : void # ondestroy() : void # onstart() : void # onstop() : void - showerrordialog(resid :int, args :Object) : void + DistanceView(context :Context, attrs :AttributeSet, defstyle :int) + DistanceView(context :Context, attrs :AttributeSet) + DistanceView(context :Context) + setdistance(distance :float, bearingto :float) : void view::virtualjoystickview + enableleftstick(enabled :boolean) : void + enablerightstick(enabled :boolean) : void + ontouchevent(event :MotionEvent) : boolean + setonvirtualjoystickmovelistener(listener :OnVirtualJoystickMoveListener) : void + updated(joystick :VirtualJoystick, x :float, y :float) : void + VirtualJoystickView(context :Context, attrs :AttributeSet, defstyle :int) + VirtualJoystickView(context :Context, attrs :AttributeSet) + VirtualJoystickView(context :Context) -view -joystickview View -batteryview view::batteryview ConnectionParamAcitivity Activity View + BatteryView(context :Context, attrs :AttributeSet, defstyle :int) + BatteryView(context :Context, attrs :AttributeSet) + BatteryView(context :Context) + setcharginglevel(charginglevel :float) : void -leftjoystick -rightjoystick view::virtualjoystick + draw(canvas :Canvas) : void + isenabled() : boolean + onsizechanged(top :float, left :float, size :float) : void + ontouchevent(event :MotionEvent) : void + setenabled(enabled :boolean) : void + VirtualJoystick(view :VirtualJoystickView, paint :Paint, borderpaint :Paint) ClientPreferenceActivity PreferenceActivity # oncreate(savedinstancestate :Bundle) : void - configurationservice: ClientConfigurationService - hostnameedit: TextView # menu_id: int = R.menu.menu - passwordedit: TextView - remembersettingscb: CheckBox - welcometextview: TextView + connectclick(v :View) : void - loadsettingsfromconfig() : void # oncreate(savedinstancestate :Bundle) : void + oncreateoptionsmenu(menu :Menu) : boolean + onoptionsitemselected(item :MenuItem) : boolean - showabout() : void - showsettings() : void Abbildung 38: Klassendiagramm zum Paket client.presentation Sven Nobis Seite 75 von 110

76 7.11 Sonstige Pakete Die noch unerwähnten Pakete sind common.exception und common.utils. Im Ersten befinden, wie der Name vermuten lässt, eigene Exception-Klassen. Die Abbildung 39 zeigt die Klassen im Paket common.utils. Diese Klassen bieten diverse allgemeine Funktionalitäten an: Zur Verschlüsselung des Passworts, die Klasse CryptUtils, zur Berechnung des CRC8-Prüfsumme die Klasse CRC8 und die Klasse AsyncTaskResult ist ein Datencontainer, mit dem entweder ein Fehler oder ein Ergebnis zurückgegeben werden kann. Dieser ist nützlich bei der Verwendung der Android Klasse AsyncTask. Mit einem AsyncTask kann eine Aufgabe asynchron ausgeführt werden. Diese kann dann z.b. ein AsyncTaskResult als Ergebnis liefern. class utils CryptUtils - LOG_TAG: String = "CryptUtils" {readonly} - CryptUtils() + encryptpassword(string, String) : String + generatesalt() : String TResult CRC8 {leaf} - CRC8_TABLE: byte ([]) = new byte[] {... {readonly} + calc(byte[], int) : byte + update(byte, byte) : byte + updateblock(byte[], int, byte) : byte AsyncTaskResult - error: Exception - result: TResult + AsyncTaskResult(TResult) + AsyncTaskResult(Exception) + geterror() : Exception + getresult() : TResult Abbildung 39: Klassendiagramm zum Paket common.utils 7.12 Benutzeroberfläche Vor der Umsetzung wurden Skizzen der Benutzeroberfläche entworfen. Diese werden im folgenden erläutert Host Die folgenden drei Abbildungen zeigen den Entwurf der Benutzeroberfläche für den Host. Der Kopfbereich entspricht einer typischen Applikation auf einem aktuellen Android-Smartphone. So bietet diese neben dem Namen der Applikation noch den Zugriff auf den Konfiguration und den Info-Dialog. Im ersten Schritt (Abbildung 40 auf der nächsten Seite) soll zur Unterstützung des Benutzers eine Grafik angzeigt werden, die symbolhaft zeigt, was zu tun ist. Hat der Benutzer das Fahrzeug verbunden, so sieht er Abbildung 41 auf Seite 78 mit der Adresse zum Verbinden. Die Adresse kann dann auch per Verbindungslink senden an das andere Smartphone gesendet werden. Wird der Link dorf angeklickt, startet sofort die App und verbindet sich. Ist die Verbindung Sven Nobis Seite 76 von 110

77 aufgebaut, wird Abbildung 42 auf der nächsten Seite angezeigt. Dort hat er, wie auch in der vorherigen Ansicht (mit Abbruch ), die Möglichkeit die Applikation zu beenden. Abbildung 40: Entwurf der Benutzeroberfläche für die UnconnectedActivity Sven Nobis Seite 77 von 110

78 Abbildung 41: Entwurf der Benutzeroberfläche für die WaitForOtherPhoneActivity Abbildung 42: Entwurf der Benutzeroberfläche für die ConnectedActivity Sven Nobis Seite 78 von 110

79 Client Die Abbildung 43 zeigt die Aktivität zum Herstellen einer Verbindung. Es müssen die Adresse und das Passwort eingegeben werden. Der Port wird mit : an den Host angehängt und kann beim vorgegebenen Port weggelassen werden. Bei Bedarf lassen sich die Daten speichern. Abbildung 43: Aktivität zur Eingabe der Verbindungsparameter In der Abbildung 44 auf der nächsten Seite ist die Oberfläche zu sehen, mit der das Fahrzeug gesteuert werden kann. Unten werden virtuelle Steuerpads zum Bewegen des Fahrzeugs und Drehen der Kamera angezeigt. Im oberen Bereich befinden sich die Informationen, die vom Fahrzeug gesendet werden. Das Bild der Kamera befindet sich im Hintergrund. Sven Nobis Seite 79 von 110

80 Position des Fahrzeugs (relativ zur Fernsteuerung) Fahrtrichtung des Fahrzeugs Ungefähre verbleibende Akkuleistung des Fahrzeugs N O 5 km Bild der Kamera Virtuelles Steuerpad zum Drehen und Schwenken der Kamera Virtuelles Steuerpad zum Bewegen des Fahrzeugs Abbildung 44: Aktivität zur Steuerung des Fahrzeugs Sven Nobis Seite 80 von 110

81 8 Realisierung Entsprechend dem Entwurf wurde das Projekt realisiert. Der folgende Abschnitt zeigt die Umsetzung des Projekts. 8.1 Hardware Die Abbildung 45 auf der nächsten Seite zeigt das umgesetzte Fahrzeug. 8.2 Software Die Umsetzung der Software kann im Verzeichnis Sources auf der beiliegenden CD gefunden werden. Die Software für das Smartphone wurde mit der Eclipse IDE umgesetzt und besteht aus den drei Projekten: AndroidRCCar.Common, AndroidRCCar.Client, und AndroidRCCar.Host. Die Quellen sind im Unterordner src der Projekte zu finden. Die Quelltext-Dokumentation ist außerdem in HTML-Form im Unterordner doc einsehbar. Diese Dateien wurden mit dem Tool JavaDoc generiert. Die Mikrocontroller Software befindet sich im Verzeichnis AndroidRCCar.Arduino unter Sources. Der Quelltext ist unter der GNU General Public License Version 3 (GPL v3) lizensiert. Ein Quelltext aus fremden Quellen enhält am Anfang der Datei einen Vermerk des Authors. Es wurden ausschließlich Fremdquellen genutzt, deren Lizenz eine Nutzung zusammen mit der GPL v3 erlaubt. Die Kommentierung des Quelltexts ist in Englisch. Die Smartphone Software setzt mindestens Android Version vorraus. Die Host-Software kann nur auf einem Android-Smartphone installiert werden, welche USB-Accessorys unterstützt. Wird diese Funktion nicht unterstützt, so schlägt die Installation fehl Benutzeroberfläche Die Abbildung 46 auf Seite 83 zeigt die Benutzeroberfläche des Hosts. Die grafischen Hinweise auf der Benutzeroberfläche wurden aus Grafiken von und http: //developers.android.com erstellt. Die Quellen und die erstellten Grafiken sind auf der CD unter Graphics zu finden. Die Benutzeroberfläche des Clients ist in der Abbildung 47 auf Seite 84 dargestellt. Das Aussehen der Benutzeroberfläche des Hosts und des Clients passt sich der Version des Betriebsystems an. Die Bildschirmfotos vom Host wurden mit Android 4.0 aufgenommen und die des Clients mit Android (auf einem Motorola). Es wurde versucht, die Benutzeroberfläche so umzusetzen, dass sie selbsterklärend ist. In der Abbildung 47(c) auf Seite 84 wurden Hinweise zur Erläuterung eingefügt, da diese innerhalb der Applikation eher störend wären. Sven Nobis Seite 81 von 110

82 Bachelor-Thesis 17. Juli 2012 (a) Ru ckseite (b) Seite (c) Schaltung zur Messung der Batterie (d) Fahrzeug in Benutzung (1) (e) Fahrzeug in Benutzung (2) Abbildung 45: Realisierte Hardware Sven Nobis Seite 82 von 110

83 (a) UnconnectedActivity (b) WaitForOtherPhoneActivity (c) ConnectedActivity (d) HostPreferenceAcitvity Abbildung 46: Oberfläche des Hosts Sven Nobis Seite 83 von 110

84 (a) Aktivität zur Eingabe der Verbindungsparameter (b) Konfiguration Position des Fahrzeugs (relativ zur Fernsteuerung) Fahrtrichtung des Fahrzeugs Ungefähre verbleibende Akkuleistung des Fahrzeugs Geschwindigkeit des Fahrzeugs Bild der Kamera Virtuelles Steuerpad zum Drehen und Schwenken der Kamera (c) Aktivität zur Steuerung des Fahrzeugs Virtuelles Steuerpad zum Bewegen des Fahrzeugs Abbildung 47: Oberfläche des Clients Sven Nobis Seite 84 von 110

85 9 Komponententest Während der Entwicklung wurden Komponententests durchgeführt. Im folgenden wird das Testziel, das Vorgehen und die Durchführung beschrieben. 9.1 Testziel Im Komponententest sollen die einzelnen Komponenten des Systems isoliert getestet werden. Aufgrund des zeitlich bergenzten Rahmens der Bachelor-Thesis beschränkt sich der Komponententest auf die wichtigsten Komponenten des Systems. Dabei soll für die folgenden Komponenten Testfälle durchgeführt werden: Mikrocontroller-Software Smartphone-Software Klassen in common.communication Klassen in common.logic Klassen in common.utils Klassen in host.accssorycommunication Klassen in host.logic Klassen in client.logic Die Klassen in *.presentation, *.service, *.framework, host.controller und die beiden Connector-Klassen sind nur sehr schwer testbar. Deshalb werden sie nur manuell gestestet. Durch den Systemtest sollte jedoch sichergestellt sein, dass auch diese Klassen funktionieren. Die Datenobjekte in den *.model-klassen enthalten in der Regel keine Logik und brauchen deshalb nicht getestet werden. In Fällen wo sich Logik in den Datenklassen befindet, wird diese bereits durch die zu testenden Komponenten genutzt und deshalb mitgetestet. Damit die Testsfälle möglichst einfach jederzeit wiederholt werden können, soll die Ausführung automatisiert erfolgen. 9.2 Testwerkzeuge Zur Umsetzung des Komponententest wurden verschiedene Testwerkzeuge eingesetzt. Es kann dabei unterschieden werden, zwischen den Testwerkzeugen für den Test der Smartphone-Software und den Test der Mikrocontroller-Software Werkzeuge für den Test der Smartphone-Software Für den Test der Smartphone-Software wurde das Android Testing Framework eingesetzt. Das Android Testing Framework basiert auf dem bekannten Test-Framework JUnit und ermöglicht unter anderem die automatisierte Ausführung von Unit-Tests unter Android [13]. Dazu wird ein Testprojekt zu der zu testenenden Applikation oder Bibliothek angelegt. In dem werden die Sven Nobis Seite 85 von 110

86 Testklassen erstellt. Die Testklassen erben von der Klasse AndroidTestCase, die wiederum von der Klasse TestCase aus dem JUnit-Framework erbt. Erstmal unterscheidet sich das Schreiben von Unit-Tests unter Android sonst nicht von normalen JUnit-Tests. Jedoch bringt das Framwork noch Möglichkeiten mit, Android-spezifische Teile zu testen, wie etwa das Testen von Aktivitäten oder Services. Diese werden in diesem Projekt nicht eingesetzt und deshalb nicht weiter erläutert. Neben den Android Testing Framwork wird außerdem noch Android Mock eingesetzt [4]. Android Mock ist ein Framework zur Erstellung von Mock-Objekten unter Android. Es basiert auf dem Java-Framework Easymock. Durch die Nutzung von Android Mock kann auf das manuelle Erstellen von Mock-Objekten verzichtet werden. So müsste normalerweise zum Testen einer Komponente zu jeder Abhängigkeit eine Mock-Klasse erstellt werden. Diese Mock-Klasse simuliert dann das gewünschte Verhalten der Abhängigkeit. Android Mock nimmt einem diese Aufgabe ab. So erstellt es die Mock-Klassen automatisiert, die sich dann für jeden Test anders konfigurieren lassen. Android Mock unterstützt dabei sowohl die Erstellung aus Interfaces als auch echten Klassen. Bei echten Klassen können jedoch Seiteneffekte auftreten, da Android Mock von der ursprünglichen Klasse erben muss und somit auch der Basis-Konstruktur ausgeführt wird. Da in diesem Projekt die Abhängigkeiten größtenteils als Interfaces realisiert sind, sollten hier keine Probleme auftreten Werkzeuge für den Test der Mikrocontroller-Software Mit der Applikation AndroidRCCar.Arduino.Test (Abbildung 48 auf der nächsten Seite) im Verzeichnis Sources, wurde ein kleines Werkzeug geschaffen, um die Software auf dem Mikrocontroller testen zu können. Die Applikation wird auf dem Smartphone ausgeführt und verbindet sich mit Mikrocontroller über das ADK. Danach sendet es eine Testfolge, die sich in der Datei res/raw/test suite befindet. Die Testfolge wird im Datenformat JSON angegeben. Das Listing 2 zeigt einen Ausschnitt daraus zur Erläuterung. Zu einer Testfolge gehören die Attribute title, waitbeforereadresponse, waitbetweentests und tests. Mit dem title kann man der Testfolge eine Bezeichnung geben. waitbeforereadresponse gibt die Millisekunden an, die vor dem Lesen jeder Antwort gewartet werden soll. waitbetweentests gibt die Millisekunden an, die zwischen der Ausführung der Tests gewartet werden soll. Durch diese Verzögerungen soll die korrekte Ausführung des Befehls visuell nachvollzogen werden können. So sollten sich z.b. nach dem Setzen der vollen Geschwindigkeit nach vorne, die Reifen auch nach vorne drehen. { Listing 2: Beispiel zum Datenformat der Testfolge t i t l e : AndroidRCCar TestSuite, waitbeforereadresponse : 5 0 0, waitbetweentests : , t e s t s : [ { t i t l e : GET PROTOCOL VERSION, senddata : D, exceptedresponsedata : Sven Nobis Seite 86 von 110

87 } ] }, { E t i t l e : GET BATTERY STATE, senddata : , printresponseonly : true }, // [... ] In tests sind die einzelenen Testfälle enthalten. Dabei muss eine Bezeichnung (title) zu jedem Testsfall angegeben werden. In senddata sind die hex-encodierten Daten enthalten, die gesendet werden sollen. Unter exceptedresponsedata ist die erwartete Antwort angegeben. Diese ist ebenfalls hex-encodiert. Falls ein Ergebnis nicht genau vorhersehbar ist, wie z.b. die Ladung der Batterie, kann anstatt der exceptedresponsedata, auch printresponseonly mit true angegeben werden. Dann wird die Antwort nach dem Test ausgegeben. Abbildung 48: Screenshot der Applikation AndroidRCCar.Arduino.Test Sven Nobis Seite 87 von 110

AndroidRCCar & Physical Computing mit Android

AndroidRCCar & Physical Computing mit Android AndroidRCCar & Physical Computing mit Android Präsentation zum GDG-Bremen-Stammtisch Sven Nobis (http://www.sven.to) 6. August 2012 Bremen Übersicht Physical Computing mit Android Was ist Physical Computing?

Mehr

Quanton Manual (de) Datum: 20.06.2013 URL: http://wiki:8090/pages/viewpage.action?pageid=9928792 )

Quanton Manual (de) Datum: 20.06.2013 URL: http://wiki:8090/pages/viewpage.action?pageid=9928792 ) Datum: 20.06.2013 URL: http://wiki:8090/pages/viewpage.action?pageid=9928792 ) Inhaltsverzeichnis 1 quanton flight control rev. 1 3 1.1 Anschlüsse für Peripheriegeräte 3 1.1.1 Eingänge / Ausgänge 3 1.1.2

Mehr

Hier ist die Anleitung zum Flashen des MTK GPS auf der APM 2.0. Prinzipiell funktioniert es auch auf der APM 2.5 und APM 1.

Hier ist die Anleitung zum Flashen des MTK GPS auf der APM 2.0. Prinzipiell funktioniert es auch auf der APM 2.5 und APM 1. Hier ist die Anleitung zum Flashen des MTK GPS auf der APM 2.0. Prinzipiell funktioniert es auch auf der APM 2.5 und APM 1. Vorweg: Die neue MTK Firmware 1.9 (AXN1.51_2776_3329_384.1151100.5_v19.bin) ist

Mehr

WLAN Konfiguration. Michael Bukreus 2014. Seite 1

WLAN Konfiguration. Michael Bukreus 2014. Seite 1 WLAN Konfiguration Michael Bukreus 2014 Seite 1 Inhalt Begriffe...3 Was braucht man für PureContest...4 Netzwerkkonfiguration...5 Sicherheit...6 Beispielkonfiguration...7 Screenshots Master Accesspoint...8

Mehr

Bedienungsanleitung Lithium Akku mit Fernbedienung

Bedienungsanleitung Lithium Akku mit Fernbedienung Bedienungsanleitung Lithium Akku mit Fernbedienung 22/12 /2014 (01) Übersicht 1. Technische Daten 2. Laden des AMG-Akku 3. Funktionen der Fernbedienung 4. Anschluss der DC-Steckverbindung 5. Einstellen

Mehr

Microcontroller Kurs. 08.07.11 Microcontroller Kurs/Johannes Fuchs 1

Microcontroller Kurs. 08.07.11 Microcontroller Kurs/Johannes Fuchs 1 Microcontroller Kurs 08.07.11 Microcontroller Kurs/Johannes Fuchs 1 Was ist ein Microcontroller Wikipedia: A microcontroller (sometimes abbreviated µc, uc or MCU) is a small computer on a single integrated

Mehr

Das große ElterngeldPlus 1x1. Alles über das ElterngeldPlus. Wer kann ElterngeldPlus beantragen? ElterngeldPlus verstehen ein paar einleitende Fakten

Das große ElterngeldPlus 1x1. Alles über das ElterngeldPlus. Wer kann ElterngeldPlus beantragen? ElterngeldPlus verstehen ein paar einleitende Fakten Das große x -4 Alles über das Wer kann beantragen? Generell kann jeder beantragen! Eltern (Mütter UND Väter), die schon während ihrer Elternzeit wieder in Teilzeit arbeiten möchten. Eltern, die während

Mehr

Technische Informatik Basispraktikum Sommersemester 2001

Technische Informatik Basispraktikum Sommersemester 2001 Technische Informatik Basispraktikum Sommersemester 2001 Protokoll zum Versuchstag 4 Datum: 21.6.2001 Gruppe: David Eißler/ Autor: Verwendete Messgeräte: - digitales Experimentierboard (EB6) - Netzgerät

Mehr

tensiolink USB Konverter INFIELD 7

tensiolink USB Konverter INFIELD 7 tensiolink USB Konverter INFIELD 7 UMS GmbH München, August 2005 tensiolink USB Konverter Einleitung Der tensiolink USB Konverter dient zum direkten Anschluss von Sensoren und Geräten mit serieller tensiolink

Mehr

schnell und portofrei erhältlich bei beck-shop.de DIE FACHBUCHHANDLUNG mitp/bhv

schnell und portofrei erhältlich bei beck-shop.de DIE FACHBUCHHANDLUNG mitp/bhv Roboter programmieren mit NXC für Lego Mindstorms NXT 1. Auflage Roboter programmieren mit NXC für Lego Mindstorms NXT schnell und portofrei erhältlich bei beck-shop.de DIE FACHBUCHHANDLUNG mitp/bhv Verlag

Mehr

Installationsanleitung. Hardlock Internal PCI Hardlock Server Internal PCI

Installationsanleitung. Hardlock Internal PCI Hardlock Server Internal PCI Installationsanleitung Hardlock Internal PCI Hardlock Server Internal PCI Aladdin Knowledge Systems 2001 Aladdin Document : Hardlock Internal PCI Guide D Hl-mn (10/2001) 1.1-00851 Revision: 1.1 Stand:

Mehr

DRF-A3 IEEE 1394 FireWire Adapter Schnellinstallationsleitfaden

DRF-A3 IEEE 1394 FireWire Adapter Schnellinstallationsleitfaden DRF-A3 IEEE 1394 FireWire Adapter Schnellinstallationsleitfaden DRF-A3 Schnellinstallationsleitfaden Vielen Dank, dass Sie die D-Link DRF-A3 PCI FireWire Upgradekarte gekauft haben. Dieser Leitfaden zeigt

Mehr

Konfiguration VLAN's. Konfiguration VLAN's IACBOX.COM. Version 2.0.1 Deutsch 01.07.2014

Konfiguration VLAN's. Konfiguration VLAN's IACBOX.COM. Version 2.0.1 Deutsch 01.07.2014 Konfiguration VLAN's Version 2.0.1 Deutsch 01.07.2014 In diesem HOWTO wird die Konfiguration der VLAN's für das Surf-LAN der IAC-BOX beschrieben. Konfiguration VLAN's TITEL Inhaltsverzeichnis Inhaltsverzeichnis...

Mehr

Schulungsunterlagen zur Version 3.3

Schulungsunterlagen zur Version 3.3 Schulungsunterlagen zur Version 3.3 Versenden und Empfangen von Veranstaltungen im CMS-System Jürgen Eckert Domplatz 3 96049 Bamberg Tel (09 51) 5 02 2 75 Fax (09 51) 5 02 2 71 Mobil (01 79) 3 22 09 33

Mehr

Bewusster Umgang mit Smartphones

Bewusster Umgang mit Smartphones Bewusster Umgang mit Smartphones Komponenten Hardware OS-Prozessor, Baseband-Prozessor Sensoren Kamera, Mikrofon, GPS, Gyroskop, Kompass,... Netzwerk: WLAN-Adapter, NFC, Bluetooth,... Software Betriebssystem

Mehr

easyident Türöffner easyident Türöffner Art. Nr. FS-0007 FS Fertigungsservice

easyident Türöffner easyident Türöffner Art. Nr. FS-0007 FS Fertigungsservice easyident Türöffner Art. Nr. FS-0007 Wir freuen uns, das sie sich für unser Produkt easyident Türöffner, mit Transponder Technologie entschieden haben. Easyident Türöffner ist für Unterputzmontage in 55mm

Mehr

GeoPilot (Android) die App

GeoPilot (Android) die App GeoPilot (Android) die App Mit der neuen Rademacher GeoPilot App machen Sie Ihr Android Smartphone zum Sensor und steuern beliebige Szenen über den HomePilot. Die App beinhaltet zwei Funktionen, zum einen

Mehr

trivum Multiroom System Konfigurations- Anleitung Erstellen eines RS232 Protokolls am Bespiel eines Marantz SR7005

trivum Multiroom System Konfigurations- Anleitung Erstellen eines RS232 Protokolls am Bespiel eines Marantz SR7005 trivum Multiroom System Konfigurations- Anleitung Erstellen eines RS232 Protokolls am Bespiel eines Marantz SR7005 2 Inhalt 1. Anleitung zum Einbinden eines über RS232 zu steuernden Devices...3 1.2 Konfiguration

Mehr

Batterie richtig prüfen und laden

Batterie richtig prüfen und laden Batterie richtig prüfen und laden Vor allem kleine Mopeds, Motorräder und Roller, also 50er und 125er, kämpfen häufig mit Elektrikproblemen. Hauptursache ist meist eine schwache Batterie. Die Licht- und

Mehr

Eltako FVS. Verwendung von Systemfunktionen. Grenzenlose Flexibilität und Komfort in der Gebäudeinstallation

Eltako FVS. Verwendung von Systemfunktionen. Grenzenlose Flexibilität und Komfort in der Gebäudeinstallation Eltako FVS Verwendung von Systemfunktionen Grenzenlose Flexibilität und Komfort in der Gebäudeinstallation 1. Erstellen einer Systemfunktion 1. Beachten Sie zur Voreinstellung/Inbetriebnahme Ihres FVS-Systems

Mehr

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang sysplus.ch outlook - mail-grundlagen Seite 1/8 Outlook Mail-Grundlagen Posteingang Es gibt verschiedene Möglichkeiten, um zum Posteingang zu gelangen. Man kann links im Outlook-Fenster auf die Schaltfläche

Mehr

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER Inhalt 1 Einleitung... 1 2 Einrichtung der Aufgabe für die automatische Sicherung... 2 2.1 Die Aufgabenplanung... 2 2.2 Der erste Testlauf... 9 3 Problembehebung...

Mehr

Tutorial about how to use USBView.exe and Connection Optimization for VNWA.

Tutorial about how to use USBView.exe and Connection Optimization for VNWA. Tutorial about how to use USBView.exe and Connection Optimization for VNWA. Tutorial über den Gebrauch von USBView.exe und die Anschluss-Optimierung für den VNWA. Es wurde beobachtet, dass bestimmte VNWA

Mehr

Forumslader App für Android Kurzbeschreibung

Forumslader App für Android Kurzbeschreibung Forumslader App für Android Kurzbeschreibung Für den Forumslader ab Firmware xx281112 steht ein spezielles Bluetoothmodul mit integriertem Fahrradcomputer als Zusatzkomponente zur Verfügung. Dieses sammelt,

Mehr

Basisanforderungen: EVA-Prinzips. Erweiterte Anforderungen: wirtschaftlichen und privaten Alltag.

Basisanforderungen: EVA-Prinzips. Erweiterte Anforderungen: wirtschaftlichen und privaten Alltag. Basisanforderungen: 1. Erstelle eine einfache Motor-Steuerung (siehe Anforderungen) 2. Erläutere den Begriff Steuerung. 3. Benenne die Sensoren und Aktoren dieser Steuerung. 4. Beschreibe die Informationsverarbeitung

Mehr

Version 2.0.1 Deutsch 03.06.2014. In diesem HOWTO wird beschrieben wie Sie Ihren Gästen die Anmeldung über eine SMS ermöglichen.

Version 2.0.1 Deutsch 03.06.2014. In diesem HOWTO wird beschrieben wie Sie Ihren Gästen die Anmeldung über eine SMS ermöglichen. Version 2.0.1 Deutsch 03.06.2014 In diesem HOWTO wird beschrieben wie Sie Ihren Gästen die Anmeldung über eine SMS ermöglichen. Inhaltsverzeichnis... 1 1. Hinweise... 2 2. Konfiguration... 3 2.1. Generische

Mehr

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 von Markus Mack Stand: Samstag, 17. April 2004 Inhaltsverzeichnis 1. Systemvorraussetzungen...3 2. Installation und Start...3 3. Anpassen der Tabelle...3

Mehr

Anleitung zur Nutzung des SharePort Utility

Anleitung zur Nutzung des SharePort Utility Anleitung zur Nutzung des SharePort Utility Um die am USB Port des Routers angeschlossenen Geräte wie Drucker, Speicherstick oder Festplatte am Rechner zu nutzen, muss das SharePort Utility auf jedem Rechner

Mehr

CU-R-CONTROL. Beschreibung zur Schaltung ATMega16-32+ISP MC-Controller Steuerung auf Basis ATMEL Mega16/32. Autor: Christian Ulrich

CU-R-CONTROL. Beschreibung zur Schaltung ATMega16-32+ISP MC-Controller Steuerung auf Basis ATMEL Mega16/32. Autor: Christian Ulrich Seite 1 von 10 CU-R-CONTROL Beschreibung zur Schaltung ATMega16-32+ISP MC-Controller Steuerung auf Basis ATMEL Mega16/32 Autor: Christian Ulrich Datum: 08.12.2007 Version: 1.00 Seite 2 von 10 Inhalt Historie

Mehr

10.0 Quick Start mit AT89LP2052 Elliptecmotor Kit

10.0 Quick Start mit AT89LP2052 Elliptecmotor Kit 10.0 Quick Start mit AT89LP2052 Elliptecmotor Kit Dieses Kapitel beschreibt die Inbetriebnahme und den ersten Test mit dem AT89LP2052 Elliptecmotor Kit. Eine einfache Access Software für die Steuerung

Mehr

Anleitung über den Umgang mit Schildern

Anleitung über den Umgang mit Schildern Anleitung über den Umgang mit Schildern -Vorwort -Wo bekommt man Schilder? -Wo und wie speichert man die Schilder? -Wie füge ich die Schilder in meinen Track ein? -Welche Bauteile kann man noch für Schilder

Mehr

Man liest sich: POP3/IMAP

Man liest sich: POP3/IMAP Man liest sich: POP3/IMAP Gliederung 1. Einführung 1.1 Allgemeiner Nachrichtenfluss beim Versenden von E-Mails 1.2 Client und Server 1.2.1 Client 1.2.2 Server 2. POP3 2.1 Definition 2.2 Geschichte und

Mehr

COM-1 Anleitung zur Installation und Inbetriebnahme

COM-1 Anleitung zur Installation und Inbetriebnahme COM-1 Anleitung zur Installation und Inbetriebnahme 06.07.10 COM-1-Bedienungsanleitung - V 1.4 Seite 1 von 10 Wichtige Informationen Das COM 1 wurde mit großer Sorgfalt entworfen und hergestellt und sollte

Mehr

Praktikum Nr. 3. Fachhochschule Bielefeld Fachbereich Elektrotechnik. Versuchsbericht für das elektronische Praktikum

Praktikum Nr. 3. Fachhochschule Bielefeld Fachbereich Elektrotechnik. Versuchsbericht für das elektronische Praktikum Fachhochschule Bielefeld Fachbereich Elektrotechnik Versuchsbericht für das elektronische Praktikum Praktikum Nr. 3 Manuel Schwarz Matrikelnr.: 207XXX Pascal Hahulla Matrikelnr.: 207XXX Thema: Transistorschaltungen

Mehr

Windkraft-Ersatzlastregler bzw. Heizungsversion

Windkraft-Ersatzlastregler bzw. Heizungsversion Windkraft-Ersatzlastregler bzw. Heizungsversion Abbildung kann vom gelieferten Gerät abweichen zur Verhinderung von Überspannung und zum Schutz der Batterie Technische Daten: Stromaufnahme: Spannung: Ersatzlast:

Mehr

HTBVIEWER INBETRIEBNAHME

HTBVIEWER INBETRIEBNAHME HTBVIEWER INBETRIEBNAHME Vorbereitungen und Systemvoraussetzungen... 1 Systemvoraussetzungen... 1 Betriebssystem... 1 Vorbereitungen... 1 Installation und Inbetriebnahme... 1 Installation... 1 Assistenten

Mehr

Projekt 2HEA 2005/06 Formelzettel Elektrotechnik

Projekt 2HEA 2005/06 Formelzettel Elektrotechnik Projekt 2HEA 2005/06 Formelzettel Elektrotechnik Teilübung: Kondensator im Wechselspannunskreis Gruppenteilnehmer: Jakic, Topka Abgabedatum: 24.02.2006 Jakic, Topka Inhaltsverzeichnis 2HEA INHALTSVERZEICHNIS

Mehr

2. ERSTELLEN VON APPS MIT DEM ADT PLUGIN VON ECLIPSE

2. ERSTELLEN VON APPS MIT DEM ADT PLUGIN VON ECLIPSE 2. ERSTELLEN VON APPS MIT DEM ADT PLUGIN VON ECLIPSE 2.1 Die Einrichtung der Benutzeroberfläche Das Einrichten einer Android-Eclipse-Entwicklungsumgebung zur Android-Entwicklung ist grundsätzlich nicht

Mehr

Einrichten eines Postfachs mit Outlook Express / Outlook bis Version 2000

Einrichten eines Postfachs mit Outlook Express / Outlook bis Version 2000 Folgende Anleitung beschreibt, wie Sie ein bestehendes Postfach in Outlook Express, bzw. Microsoft Outlook bis Version 2000 einrichten können. 1. Öffnen Sie im Menü die Punkte Extras und anschließend Konten

Mehr

Öffnen Sie den Internet-Browser Ihrer Wahl. Unabhängig von der eingestellten Startseite erscheint die folgende Seite in Ihrem Browserfenster:

Öffnen Sie den Internet-Browser Ihrer Wahl. Unabhängig von der eingestellten Startseite erscheint die folgende Seite in Ihrem Browserfenster: Schritt 1: Verbinden Sie Ihr wireless-fähiges Gerät (Notebook, Smartphone, ipad u. ä.) mit dem Wireless-Netzwerk WiFree_1. Die meisten Geräte zeigen Wireless-Netzwerke, die in Reichweite sind, automatisch

Mehr

Platinen mit dem HP CLJ 1600 direkt bedrucken ohne Tonertransferverfahren

Platinen mit dem HP CLJ 1600 direkt bedrucken ohne Tonertransferverfahren Platinen mit dem HP CLJ 1600 direkt bedrucken ohne Tonertransferverfahren Um die Platinen zu bedrucken, muß der Drucker als allererstes ein wenig zerlegt werden. Obere und seitliche Abdeckungen entfernen:

Mehr

Enigmail Konfiguration

Enigmail Konfiguration Enigmail Konfiguration 11.06.2006 Steffen.Teubner@Arcor.de Enigmail ist in der Grundkonfiguration so eingestellt, dass alles funktioniert ohne weitere Einstellungen vornehmen zu müssen. Für alle, die es

Mehr

Konfiguration des ewon GSM Modems Kurzbeschreibung zum Aufbau einer GSM Verbindung

Konfiguration des ewon GSM Modems Kurzbeschreibung zum Aufbau einer GSM Verbindung ewon - Technical Note Nr. 004 Version 1.2 Konfiguration des ewon GSM Modems Kurzbeschreibung zum Aufbau einer GSM Verbindung 08.08.2006/SI Übersicht: 1. Thema 2. Benötigte Komponenten 3. Modemkonfiguration

Mehr

1. Einführung. 2. Archivierung alter Datensätze

1. Einführung. 2. Archivierung alter Datensätze 1. Einführung Mit wachsender Datenmenge und je nach Konfiguration, kann orgamax mit der Zeit langsamer werden. Es gibt aber diverse Möglichkeiten, die Software wieder so zu beschleunigen, als würden Sie

Mehr

EasyWk DAS Schwimmwettkampfprogramm

EasyWk DAS Schwimmwettkampfprogramm EasyWk DAS Schwimmwettkampfprogramm Arbeiten mit OMEGA ARES 21 EasyWk - DAS Schwimmwettkampfprogramm 1 Einleitung Diese Präsentation dient zur Darstellung der Zusammenarbeit zwischen EasyWk und der Zeitmessanlage

Mehr

IRF2000 Application Note Lösung von IP-Adresskonflikten bei zwei identischen Netzwerken

IRF2000 Application Note Lösung von IP-Adresskonflikten bei zwei identischen Netzwerken Version 2.0 1 Original-Application Note ads-tec GmbH IRF2000 Application Note Lösung von IP-Adresskonflikten bei zwei identischen Netzwerken Stand: 27.10.2014 ads-tec GmbH 2014 IRF2000 2 Inhaltsverzeichnis

Mehr

Der Anschluss an einen Computer

Der Anschluss an einen Computer Firmware version: 2.1 GUI version: 2.1 Board version: siehe Abbildung Der Anschluss an einen Computer Man verbindet das Controllerboard mit dem PC mit einem USB-Kabel und natürlich den Sensor mit dem entsprechenden

Mehr

Anleitung TempCW 2011

Anleitung TempCW 2011 TempCW - Wirberg 0 30.09.0 Anleitung TempCW 0 vorläufig Inhaltsverzeichnis Aufbauanleitung... Platine... Programmierstecker... Bestückung...3 Inbetriebnahme... 5 Spannungsversorgung... 5 LEDs... 5 NF Teil...

Mehr

AVR Experimentierboard

AVR Experimentierboard Vorwort Damit ich eine flexible und anpassungsfähige Experimentier- und Entwicklungs-Umgebung bekomme, habe ich nach einer kostengünstige Lösung gesucht. Hierbei bin ich auf das Atmel-Evalutionboard von

Mehr

M a i l C r e d i t. \\Burt\user\Soutschek\FP\Technik\Frankiermaschinen\00_PC Software\MailCredit\Anleitung MailCredit Installation.

M a i l C r e d i t. \\Burt\user\Soutschek\FP\Technik\Frankiermaschinen\00_PC Software\MailCredit\Anleitung MailCredit Installation. M a i l C r e d i t MailCredit ist eine Software, die auf einem PC installiert wird. Diese Software ermöglicht es, dass eine Frankiermaschine über das Internet Portoladungen bzw. Kommunikation mit dem

Mehr

AVR Net-IO. Der originale von Pollin vertriebene Bausatz hat folgende Eckdaten:

AVR Net-IO. Der originale von Pollin vertriebene Bausatz hat folgende Eckdaten: AVR Net-IO 2013 DL2USR Bitte alles sorgfältig lesen. Weitere Hinweise enthält die Readme.txt im Softwareordner. Keine Garantie für Vollständigkeit und Fehlerfreiheit, kein Support in irgendeiner Art! Ein

Mehr

Guide DynDNS und Portforwarding

Guide DynDNS und Portforwarding Guide DynDNS und Portforwarding Allgemein Um Geräte im lokalen Netzwerk von überall aus über das Internet erreichen zu können, kommt man um die Themen Dynamik DNS (kurz DynDNS) und Portweiterleitung(auch

Mehr

Lizenzen auschecken. Was ist zu tun?

Lizenzen auschecken. Was ist zu tun? Use case Lizenzen auschecken Ihr Unternehmen hat eine Netzwerk-Commuterlizenz mit beispielsweise 4 Lizenzen. Am Freitag wollen Sie Ihren Laptop mit nach Hause nehmen, um dort am Wochenende weiter zu arbeiten.

Mehr

TeamSpeak3 Einrichten

TeamSpeak3 Einrichten TeamSpeak3 Einrichten Version 1.0.3 24. April 2012 StreamPlus UG Es ist untersagt dieses Dokument ohne eine schriftliche Genehmigung der StreamPlus UG vollständig oder auszugsweise zu reproduzieren, vervielfältigen

Mehr

LED WIFI Controller - Bedienungsanleitung

LED WIFI Controller - Bedienungsanleitung LED WIFI Controller - Bedienungsanleitung Inhaltsverzeichnis 1. Übersicht...1 2. Software/Technische Daten...2 3. Software für Android...2 3.01 Installationsanleitung...2 3.02 WiFi Verbindungseinstellungen...3

Mehr

Datensicherung. Beschreibung der Datensicherung

Datensicherung. Beschreibung der Datensicherung Datensicherung Mit dem Datensicherungsprogramm können Sie Ihre persönlichen Daten problemlos Sichern. Es ist möglich eine komplette Datensicherung durchzuführen, aber auch nur die neuen und geänderten

Mehr

Grundlagen der Technischen Informatik. Sequenzielle Netzwerke. Institut für Kommunikationsnetze und Rechnersysteme. Paul J. Kühn, Matthias Meyer

Grundlagen der Technischen Informatik. Sequenzielle Netzwerke. Institut für Kommunikationsnetze und Rechnersysteme. Paul J. Kühn, Matthias Meyer Institut für Kommunikationsnetze und Rechnersysteme Grundlagen der Technischen Informatik Paul J. Kühn, Matthias Meyer Übung 2 Sequenzielle Netzwerke Inhaltsübersicht Aufgabe 2.1 Aufgabe 2.2 Prioritäts-Multiplexer

Mehr

Das Handbuch zu Simond. Peter H. Grasch

Das Handbuch zu Simond. Peter H. Grasch Peter H. Grasch 2 Inhaltsverzeichnis 1 Einführung 6 2 Simond verwenden 7 2.1 Benutzereinrichtung.................................... 7 2.2 Netzwerkeinrichtung.................................... 9 2.3

Mehr

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016

L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 L10N-Manager 3. Netzwerktreffen der Hochschulübersetzer/i nnen Mannheim 10. Mai 2016 Referentin: Dr. Kelly Neudorfer Universität Hohenheim Was wir jetzt besprechen werden ist eine Frage, mit denen viele

Mehr

Autoradio On Off Schaltung

Autoradio On Off Schaltung Autoradio On Off Schaltung Konzeption, Anleitung und Hinweise Christian Schönig Schöneberger Str. 20 82377 Penzberg Inhalt 1. MOTIVATION... 3 1.1. AKTUELLER STAND BEI HERSTELLER RADIO... 3 1.2. ANSCHLUSS

Mehr

Versuch 3. Frequenzgang eines Verstärkers

Versuch 3. Frequenzgang eines Verstärkers Versuch 3 Frequenzgang eines Verstärkers 1. Grundlagen Ein Verstärker ist eine aktive Schaltung, mit der die Amplitude eines Signals vergößert werden kann. Man spricht hier von Verstärkung v und definiert

Mehr

Kapiteltests zum Leitprogramm Binäre Suchbäume

Kapiteltests zum Leitprogramm Binäre Suchbäume Kapiteltests zum Leitprogramm Binäre Suchbäume Björn Steffen Timur Erdag überarbeitet von Christina Class Binäre Suchbäume Kapiteltests für das ETH-Leitprogramm Adressaten und Institutionen Das Leitprogramm

Mehr

USB Signalverstärker XL

USB Signalverstärker XL USB Signalverstärker XL Bedienungsanleitung Identifizierung Hersteller:... TLS Communication GmbH Marie-Curie-Straße 20 D-40721 Hilden Tel: +49 (0) 2103 5006-0 Fax: +49 (0) 02103 5006-90 Produkt:... USB

Mehr

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken. Seite erstellen Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken. Es öffnet sich die Eingabe Seite um eine neue Seite zu erstellen. Seiten Titel festlegen Den neuen

Mehr

MOTORISIERTER COIN FEEDER

MOTORISIERTER COIN FEEDER MOTORISIERTER COIN FEEDER Model: CTI-328(S) Produkt Handbuch Version 1.2 / Aug 2012 Antonie van Leeuwenhoekstraat 9 3261 LT Oud-Beijerland The Netherlands Telefon : +31(0)186-643333 Fax : +31(0)186-643322

Mehr

App CCTV INET VIEWER. Folgende Funktionen stehen in der App zur Verfügung:

App CCTV INET VIEWER. Folgende Funktionen stehen in der App zur Verfügung: App CCTV INET VIEWER Ab der Version 12.12.0 (Analog) sowie 1.0 Full-HD SDI-System, gibt es die Möglichkeit, auf das Alpha11 KassenVideosystem mit der kostenlosen App CCTV INET VIEWER zuzugreifen. Folgende

Mehr

ICS-Addin. Benutzerhandbuch. Version: 1.0

ICS-Addin. Benutzerhandbuch. Version: 1.0 ICS-Addin Benutzerhandbuch Version: 1.0 SecureGUARD GmbH, 2011 Inhalt: 1. Was ist ICS?... 3 2. ICS-Addin im Dashboard... 3 3. ICS einrichten... 4 4. ICS deaktivieren... 5 5. Adapter-Details am Server speichern...

Mehr

Dokumentation IBIS Monitor

Dokumentation IBIS Monitor Dokumentation IBIS Monitor Seite 1 von 16 11.01.06 Inhaltsverzeichnis 1. Allgemein 2. Installation und Programm starten 3. Programmkonfiguration 4. Aufzeichnung 4.1 Aufzeichnung mitschneiden 4.1.1 Inhalt

Mehr

USB 2.0 PCI-Karte mit NEC CHIPSATZ

USB 2.0 PCI-Karte mit NEC CHIPSATZ Handbuch USB 2.0 PCI-Karte mit NEC CHIPSATZ deutsch Handbuch_Seite 2 Handbuch_Seite 3 Inhalt 1.0 Eigenschaften 4 2.0 Systemvoraussetzungen 4 3.0 Hardware Installation 4 4.0 Treiber Installation (Windows

Mehr

4.1 Download der App über den Play Store

4.1 Download der App über den Play Store 4 4.1 Download der App über den Play Store Die App TopSec Phone kann über den Play Store auf dem Smartphone oder über das Internet an Ihrem Computer heruntergeladen werden. Um Inhalte laden zu können,

Mehr

Thunderbird herunterladen, Installieren und einrichten Version 31.3.0 (portable)

Thunderbird herunterladen, Installieren und einrichten Version 31.3.0 (portable) Thunderbird herunterladen, Installieren und einrichten Version 31.3.0 (portable) Thunderbird ist ein quelloffenes E-Mail-Programm (manchmal auch Client genannt), das leicht herunterzuladen und zu installieren

Mehr

Sensor board EB003-00-2

Sensor board EB003-00-2 Sensor board EB003-00-2 Inhalt 1. Über dieses Dokument...2 2. Allgemeine Information...3 3. Board-Layout...4 4. Schaltungsbeschreibung...5 Anhang 1 Schaltplan Copyright Matrix Multimedia Limited 2005 seite

Mehr

So nutzen Sie die HiDrive App mit Ihrem Android Smartphone

So nutzen Sie die HiDrive App mit Ihrem Android Smartphone So nutzen Sie die HiDrive App mit Ihrem Android Smartphone Die STRATO HiDrive App ermöglicht Ihnen die bequeme Nutzung Ihres Kontos mit Ihrem Android Smartphone. Betrachten Sie direkt Ihre Inhalte und

Mehr

Meine neue CNC-Steuerung mit China CNC Karte. Vorderseite. Rückseite

Meine neue CNC-Steuerung mit China CNC Karte. Vorderseite. Rückseite Meine neue CNC-Steuerung mit China CNC Karte Vorderseite Rückseite Nun die Belegungen der eigenen Anschlüsse Im Folgenden sind diese Anschlüsse für die Achsen und Endschalter zu X, Y, Z und C gleich belegt

Mehr

Das Experimentierbrettchen (Aufbau, Messpunkte): A B + 9V

Das Experimentierbrettchen (Aufbau, Messpunkte): A B + 9V Kojak-Sirene: Experimente zur Funktionsweise 1. astabile Kippstufe 2. astabile Kippstufe Die Schaltung der Kojak-Sirene besteht aus zwei miteinander verbundenen astabilen Kippstufen (Anhang) und einem

Mehr

A.u.S. Spielgeräte GmbH A-1210 Wien Scheydgasse 48 Tel.+43-(0)1-271 66 00 Fax. +43-(0)1-271 66 00 75

A.u.S. Spielgeräte GmbH A-1210 Wien Scheydgasse 48 Tel.+43-(0)1-271 66 00 Fax. +43-(0)1-271 66 00 75 Inhaltsverzeichnis Seite 1. Einleitung. 2 2. Vorraussetzung.. 2 2.1 Software 2 2.2 Hardware.. 2 3. Vorbereitung... 3 4. Programmierung 4 5. Ändern des Schlüssels... 6 6. Test 6 7. Informationen.. 7 1.Einleitung

Mehr

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite.

Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite. ewon - Technical Note Nr. 003 Version 1.2 Universal Dashboard auf ewon Alarmübersicht auf ewon eigener HTML Seite. Übersicht 1. Thema 2. Benötigte Komponenten 3. Downloaden der Seiten und aufspielen auf

Mehr

Local Control Network Technische Dokumentation

Local Control Network Technische Dokumentation Steuerung von Hifi-Anlagen mit der LCN-GVS Häufig wird der Wunsch geäußert, eine Hi-Fi-Anlage in die Steuerung der LCN-GVS einzubinden. Auch das ist realisierbar. Für die hier gezeigte Lösung müssen wenige

Mehr

Facharbeit Informatik. Thema:

Facharbeit Informatik. Thema: Facharbeit Informatik Thema: Rechneraufbau Mit Locad 2002 1 Inhaltsangabe Inhalt: Seite: 1. Einleitung 3 2. Inbetriebnahme der Schaltung 3 3. Eingabe 4 4. CPU 5 5. RAM/HDD 8 6. Ausgabe 10 7. Auf einer

Mehr

Allgemeine USB Kabel Installation und Troubleshooting

Allgemeine USB Kabel Installation und Troubleshooting Allgemeine USB Kabel Installation und Troubleshooting Inhalt Installation der Treiber... 2 BrotherLink... 4 SilverLink... 5 Bei Problemen... 6 So rufen Sie den Geräte-Manager in den verschiedenen Betriebssystemen

Mehr

2 Die Terminaldienste Prüfungsanforderungen von Microsoft: Lernziele:

2 Die Terminaldienste Prüfungsanforderungen von Microsoft: Lernziele: 2 Die Terminaldienste Prüfungsanforderungen von Microsoft: Configuring Terminal Services o Configure Windows Server 2008 Terminal Services RemoteApp (TS RemoteApp) o Configure Terminal Services Gateway

Mehr

Anwendungshinweise zur Anwendung der Soziometrie

Anwendungshinweise zur Anwendung der Soziometrie Anwendungshinweise zur Anwendung der Soziometrie Einführung Die Soziometrie ist ein Verfahren, welches sich besonders gut dafür eignet, Beziehungen zwischen Mitgliedern einer Gruppe darzustellen. Das Verfahren

Mehr

So die eigene WEB-Seite von Pinterest verifizieren lassen!

So die eigene WEB-Seite von Pinterest verifizieren lassen! So die eigene WEB-Seite von Pinterest verifizieren lassen! Quelle: www.rohinie.eu Die eigene Seite auf Pinterest verifizieren Es ist offiziell. Vielleicht haben auch Sie in den vergangenen Wochen die Informationen

Mehr

Installationsanleitung Forest shuttle. Home Automation by

Installationsanleitung Forest shuttle. Home Automation by Installationsanleitung Forest shuttle Installationsanleitung Forest Shuttle 1 Bauen Sie das motorisierte Vorhangsystem zusammen. 2 Bringen Sie die Wandträger an der Wand oder unter der Decke an und befestigen

Mehr

Webstream.eu Live Streaming mit ManyCam

Webstream.eu Live Streaming mit ManyCam Webstream.eu Live Streaming mit ManyCam Einführung Die Software ManyCam ist eine sogenannte 'virtuelle Webcam-Software', die wir als Ergänzung zum Adobe Flash Media Encoder zum Streamen mit Webstream.eu

Mehr

OECD Programme for International Student Assessment PISA 2000. Lösungen der Beispielaufgaben aus dem Mathematiktest. Deutschland

OECD Programme for International Student Assessment PISA 2000. Lösungen der Beispielaufgaben aus dem Mathematiktest. Deutschland OECD Programme for International Student Assessment Deutschland PISA 2000 Lösungen der Beispielaufgaben aus dem Mathematiktest Beispielaufgaben PISA-Hauptstudie 2000 Seite 3 UNIT ÄPFEL Beispielaufgaben

Mehr

Installation und Inbetriebnahme von SolidWorks

Installation und Inbetriebnahme von SolidWorks Inhaltsverzeichnis FAKULTÄT FÜR INGENIEURWISSENSCHAFTEN I Prof. Dr.-Ing. Frank Lobeck Installation und Inbetriebnahme von SolidWorks Inhaltsverzeichnis Inhaltsverzeichnis... I 1. Einleitung... 1 2. Installation...

Mehr

Qt-Projekte mit Visual Studio 2005

Qt-Projekte mit Visual Studio 2005 Qt-Projekte mit Visual Studio 2005 Benötigte Programme: Visual Studio 2005 Vollversion, Microsoft Qt 4 Open Source s. Qt 4-Installationsanleitung Tabelle 1: Benötigte Programme für die Qt-Programmierung

Mehr

MOTORANSTEUERUNG. Schaltzeichen eines Relais:

MOTORANSTEUERUNG. Schaltzeichen eines Relais: A1 H-Brücke: MOTORANSTEUERUNG Je nachdem, wie herum die beiden Pole eines Gleichstrommotors an eine Gleichspannungsquelle angeschlossen werden, ändert er seine Drehrichtung. Die Schaltung links wird als

Mehr

Leichte-Sprache-Bilder

Leichte-Sprache-Bilder Leichte-Sprache-Bilder Reinhild Kassing Information - So geht es 1. Bilder gucken 2. anmelden für Probe-Bilder 3. Bilder bestellen 4. Rechnung bezahlen 5. Bilder runterladen 6. neue Bilder vorschlagen

Mehr

Multiplayer Anweisungen

Multiplayer Anweisungen Multiplayer Anweisungen Mit Multiplayer können Sie über das Internet oder ein lokales Netzwerk gegen echte Renngegner aus der ganzen Welt fahren. Insgesamt können bis zu 10 Personen gemeinsam fahren. Bedienung

Mehr

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom 21.10.2013b AGROPLUS Buchhaltung Daten-Server und Sicherheitskopie Version vom 21.10.2013b 3a) Der Daten-Server Modus und der Tresor Der Daten-Server ist eine Betriebsart welche dem Nutzer eine grosse Flexibilität

Mehr

14 Mee Controller. 14.1 Mee Controller. 14.1.1 Blockschaltbild Mee Controller. 14.1.2 Beschleunigungssensor. HSR Hochschule für Technik Rapperswil

14 Mee Controller. 14.1 Mee Controller. 14.1.1 Blockschaltbild Mee Controller. 14.1.2 Beschleunigungssensor. HSR Hochschule für Technik Rapperswil 14 Mee Controller Der Mee Controller ist ein Gamecontroller, der eine ähnliche Funktionsweise wie jener der bekannten Wii Konsole von Nintendo hat. Dabei werden die Steuerbefehle vom Beschleunigungssensor

Mehr

4. Network Interfaces Welches verwenden? 5. Anwendung : Laden einer einfachen Internetseite 6. Kapselung von Paketen

4. Network Interfaces Welches verwenden? 5. Anwendung : Laden einer einfachen Internetseite 6. Kapselung von Paketen Gliederung 1. Was ist Wireshark? 2. Wie arbeitet Wireshark? 3. User Interface 4. Network Interfaces Welches verwenden? 5. Anwendung : Laden einer einfachen Internetseite 6. Kapselung von Paketen 1 1. Was

Mehr

-------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------- Sicherheitshinweise im Zusammenhang mit Drahtlosnetzwerken: Hier aufgeführt finden Sie wichtige Informationen. Damit Sie als Käufer von drahtlosen Produkten einfach zu einer bestmöglichen Wireless Netzwerkumgebung

Mehr

Eigene Dokumente, Fotos, Bilder etc. sichern

Eigene Dokumente, Fotos, Bilder etc. sichern Eigene Dokumente, Fotos, Bilder etc. sichern Solange alles am PC rund läuft, macht man sich keine Gedanken darüber, dass bei einem Computer auch mal ein technischer Defekt auftreten könnte. Aber Grundsätzliches

Mehr

Eigenen WSUS Server mit dem UNI WSUS Server Synchronisieren

Eigenen WSUS Server mit dem UNI WSUS Server Synchronisieren Verwaltungsdirektion Informatikdienste Eigenen WSUS Server mit dem UNI WSUS Server Synchronisieren Inhaltsverzeichnis Einleitung... 3 Installation WSUS Server... 4 Dokumente... 4 Step by Step Installation...

Mehr

Patch Management mit

Patch Management mit Patch Management mit Installation von Hotfixes & Patches Inhaltsverzeichnis dieses Dokuments Einleitung...3 Wie man einen Patch installiert...4 Patch Installation unter UliCMS 7.x.x bis 8.x.x...4 Patch

Mehr