Englisch version   English version


Version Anpassungen
1 (2018-01-27) Initiale Version
2 (2018-12-08) Seit Dezember 2018 gab es Probleme mit Netzwerkzugriffen. Diese Zugriffe müssen nun in separaten Threads ausgeführt werden. Die Komponente wurde entsprechend umgeschrieben.
Zusätzlich wurde die Eigenschaft InitErr eingeführt, über die Fehler bei der Initialisierung der Komponente abgerufen werden können.
3 (2019-01-11) Leider hatte die Version 2 ein paar Probleme. Die Version 3 ist neu strukturiert. Sie ist leider nicht kompatibel mit der vorhergehenden Version. Zum Update deshalb die unten aufgeführten Migrationshinweise beachten.
Die alte Version 2 ist hier archiviert.

Motivation

Für ein Projekt sollte eine Android-App entwickelt werden, die mit einem ESP8266(-Projekt) kommuniziert. Zur App-Entwicklung sollte wegen der einfachen Handhabung der MIT App Inventor 2 benutzt werden.

Die IP-Adressen der verfügbaren ESP8266-Geräte sollten im Projekt nicht fest vorgegeben werden. Die App soll selbst ermitteln, welche Geräte gerade aktiv sind und unter welchen Adressen sie angesprochen werden können.

Zur Erledigung dieser Aufgabe (Name Service) bietet sich die Nutzung der Broadcast-Funktion von UDP an. Man sendet einfach an einen vorher vereinbarten Port ein Broadcast-Datagramm an alle im lokalen Netzwerk vorhandenen Geräte mit der Aufforderung, die eigenen Verbindungsdaten zurück zu liefern. Die Geräte, die auf dem vereinbarten Port lauschen, senden daraufhin ihre IP und ggf. weitere Daten an den Absender zurück. Der Absender sammelt die Antworten auf und kennt damit alle aktiven Geräte. Da die Paket-Übermittlung bei UDP nicht garantiert ist, empfiehlt es sich, diesen Vorgang zu wiederholen und die Vereinigungsmenge der Antworten zu nutzen.

Um gezielt die Geräte eines Projekts ansprechen zu können, vereinbart man entweder unterschiedliche Ports oder man gibt eine Geräte-Kennung in der Antwort mit. Der Empfänger filtert dann diejenigen Geräte heraus, die ihn interessieren.

Nun kommt die Krux. Der App Inventor hat kein eingebautes UDP und ich habe auch keine funktionierende Erweiterung (Extension) gefunden. Also selber machen.

Download

Das ZIP-Archiv UrsAI2UDPv3 zum Download. Das Archiv enthält den Quellcode, das kompilierte Binary zum Upload in den App Inventor und eine Beispiel-Anwendung.

Migration von der Version 2 zur Version 3

Die wesentlichen Unterschiede sind:

  • Die Methoden Xmit und StartListening sind nun Funktionen, die einen Rückgabewert liefern, der angibt, ob die Methode erfolgreich ausgeführt wurde.
  • Die Ereignisse XmitError und RcvError entfallen dafür. Bei der App-Entwicklung war es schwierig, diese mit der Aktion in Verbindung zu bringen.
  • Die Namen einiger Funktionen und Funktionsparameter wurden an die gebräuchlichen Bezeichnungen angepasst.

Am besten geht man bei der Migration eines bestehenden Projekts wie folgt vor:

  • Sichern des bestehen Projekts ("Save project as ..." im Projekt-Menü von App Inventor).
  • Importieren der neuen Version der Extension (zusätzlich zu der alten!).
  • Im App Inventor Designer: Eine neue Instanz der Extension auf den Screen ziehen.
  • Im Block-Editor die betroffen Blöcke an den neuen Extension-Block umhängen. Dabei auf Warnungen und Fehler achten!
  • Am besten an dieser Stelle eine weitere Sicherung erstellen.
  • Im Designer: Die Instanz der alten Extension-Version und die alte Extension löschen.
  • Im Block-Editor nachschauen, ob noch alles korrekt ist.

Verwendung

Datagramme versenden

Block Funktion Anmerkung
Xmit Der Block Xmit versendet Datagramme an den angegebenen Remote-Endpunkt (RemoteIP:RemotePort). Dabei wird der lokale Endpunkt 0.0.0.0:LocalPort verwandt, d.h. der Dienstanbieter wählt das passende Netzwerk-Interface aus.

Beim Parameter RemoteIP können sowohl Unicast- als auch Broadcast-Adressen angegeben werden.

Für den Parameter LocalPort sind auch die Angabe 0 oder negative Werte erlaubt. In diesem Fall sucht der Dienstanbieter einen zufälligen freien Port aus.

Der Rückgabewert bedeutet:
Wert Bedeutung
0 Versand erfolgreich.
1 Angabe zu RemoteIP kann nicht in eine IPv4-Adresse umgewandelt werden.
2 Unter der Angabe LocalPort kann kein Socket angelegt werden. Port-Nummer ist nicht frei oder > 65535.
3 Fehler beim Versenden.
Ein Android-Device hat zu einer Zeit i.d.R. maximal nur ein aktives Netzwerk-Interface. Dies ist entweder die mobile Datenverbindung oder das WLAN.


Zu UDP-Adress-Schemata siehe UdpClient: Aufs Bit geschaut / Adressierungsschemata

Zu Endpunkten in Java UdpClient: Aufs Bit geschaut / Java



Eine typische Verwendung zeigt dieser Block:
Datagramme versenden
Last Error Über die Eigenschaft LastErrorMessage kann ein (englischer) Text abgerufen werden, der den zuletzt aufgetretenen Fehler näher beschreibt.  

 

Datagramme empfangen

Block Funktion Anmerkung
StartListening StartListening startet das "Lauschen" auf Datagramme, die an den angegebenen Port gesendet werden (UDP-Server).

Der Rückgabewert bedeutet:
Wert Bedeutung
0 Start erfolgreich.
1 Mit der Angabe Port kann kein Socket angelegt werden. Port-Nummer ist nicht frei, < 1 oder > 65535.
2 Startvorgang bevor vorhergehender Start abgeschlossen wurde.

StopListening stoppt den Server. Ein mehrfaches Aufrufen von StopListening ist unkritisch.
Zu Endpunkten in Java UdpClient: Aufs Bit geschaut / Java


Eine typische Verwendung zeigt dieser Block:
Listener starten
Last Error Über die Eigenschaft LastErrorMessage kann ein (englischer) Text abgerufen werden, der den zuletzt aufgetretenen Fehler näher beschreibt.  
Server Start/Stop Passend dazu gibt es das Ereignis ServerStarted mit LocalIP und LocalPort als Empfangsadresse und das Ereignis ServerStopped.  
IsRunning Über die Eigenschaft isRunning kann abgefragt werden, ob der Server aktuell aktiv ist.  
Datagramm empfangen Wenn Daten empfangen werden, wird das Ereignis DataReceived ausgelöst.

Data enthält die Datagramm-Daten RemoteIP und RemotePort die Absender-Adresse.
 
DropSentToYourself Die Eigenschaft DropSentToYourself steuert das Verhalten beim Empfang Broadcast-Datagrammen. Der Block ist standardmäßig so eingestellt, dass Nachrichten ignoriert werden, die von der eigenen IP versandt wurden. Sollen diese dennoch empfangen werden, ist DropSentToYourself auf false zu setzen.

Diese Eigenschaft kann auch im Designer eigestellt werden.
Die Voreinstellung ist true.

Diverses

Block Funktion Anmerkung
LocalHost LocalHost ruft die lokale IP-Adresse ab (in der Android-Umgebung ist diese i.d.R. eindeutig).

Ist kein Netzwerk erreichbar, wird der bei Default angegebene Wert zurück geliefert.
Eine typische Verwendung zeigt dieser Block:
LocalHost

Beispiel

Screenshot   Designer

Die Blöcke im Beispiel sind nicht schwer zu verstehen. Den größten Bereich nimmt die Überprüfung valider Eingaben ein.

Werkzeuge

Für die Erstellung eigener Extensions habe ich einige Tipps zusammengestellt: AI2 FAQ: Extensions entwickeln.

Die Entwicklung der Erweiterungen erfolgt mit Java. Ein Tutorial über Datagramme findet man in der Oracle Java Dokumentation. Dort findet man auch Informationen zur verwendeten Klasse DatagramSocket.