Diese Version ist veraltet. Die neue Version befindet sich hier: UrsAI2UDP
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. |
3.1 (2019-04-29) | Die neue Eigenschaft BinaryMode erlaubt das Übertragen von binären Daten. Diese Version ist kompatibel mit der Version 3.0. Beim Hochladen bleiben die bestehenden Verknüpfungen der Blöcke erhalten. |
3.2 (2020-02-17) | - DropSentToYourself wurde nach Start des Listeners nicht
weitergereicht. - Die Bestimmung der Local-Host-IP per Enumration über die Netzwerkinterfaces führt zu Problemen bei Endgeräten, die mehr als ein Interface besitzen. DropSentToYourself hat nicht funktioniert. DropSentToYourself vergleicht nun die Absender-Adresse mit allen vorhandenen NIC-Adressen. LocalHost ist nun die Adresse, mit der das Internet erreicht wird (google.com, 8.8.8.8). |
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.
Hinweis:
Die Extension klappt einwandfrei, wenn sich Smartphone und Gegenstation im gleichen (lokalen) Netzwerk befinden. Ist das Smartphone nur per Mobilfunknetz verbunden, ist es i.d.R. nicht erreichbar. Der Grund ist, dass das Smartphone nicht direkt mit dem Internet verbunden ist, sondern nur mit dem lokalen Netzwerk des Mobilfunkanbieters.
Ein Gerät im eigenen LAN kann man von außerhalb per Port-Weiterleitung (port porwarding) am eigenen Router erreichen (ggf. via DDNS). Den Router des Providers wird man nicht beeinflussen können. Also senden vom Smartphone an ein Gerät im LAN funktioniert, umgekehrt geht es nicht.
Das gleiche gilt übrigens auch für TCP. Wenn das Smartphone nur mit dem Mobilfunknetz verbunden ist, kann die Verbindung kann nur vom Smartphone aus aufgebaut werden. Das Gerät im LAN muss als Server agieren, wartet also auf eine eingehende Verbindungsanforderung. Das Smartphone agiert als Client, initiiert den Verbindungsaufbau. Ist die Verbindung einmal eingerichtet, haben sich die Router intern über Adressen und Ports abgestimmt. Der Datentransfer ist dann in beide Richtungen möglich.
Das ZIP-Archiv UrsAI2UDPv3.2 zum Download. Das Archiv enthält den Quellcode, das kompilierte Binary zum Upload in den App Inventor und eine Beispiel-Anwendung.
Die wesentlichen Unterschiede sind:
Am besten geht man bei der Migration eines bestehenden Projekts wie folgt vor:
Block | Funktion | Anmerkung | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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. Message enthält entweder die Nachricht als Text (BinaryMode = false) oder codierte Binärwerte (BinaryMode = true, s. unten). Der Rückgabewert bedeutet:
|
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: Will man Binärdaten übertragen, muss BinaryMode auf true gesetzt werden und die Werte codiert als String im Parameter Message übergeben werden. Um z.B. drei Byte mit den HEX-Werten 33 48 DF zu versenden, könnte dies durch die Angabe "0x33,0x48,0xDF" geschehen. Details: s.u. |
|||||||||||||
Über die Eigenschaft LastErrorMessage kann ein (englischer) Text abgerufen werden, der den zuletzt aufgetretenen Fehler näher beschreibt. | ||||||||||||||
Wenn BinaryMode auf true gesetzt wird, wird der Inhalt von Message nicht direkt gesendet, sondern in ein Byte-Array übersetzt. | Auswirkung: s.u. |
Block | Funktion | Anmerkung | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
StartListening startet das "Lauschen" auf Datagramme,
die an den angegebenen Port gesendet werden (UDP-Server). Der Rückgabewert bedeutet:
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: |
|||||||||
Über die Eigenschaft LastErrorMessage kann ein (englischer) Text abgerufen werden, der den zuletzt aufgetretenen Fehler näher beschreibt. | ||||||||||
Passend dazu gibt es das Ereignis ServerStarted mit LocalIP und LocalPort als Empfangsadresse und das Ereignis ServerStopped. | ||||||||||
Über die Eigenschaft isRunning kann abgefragt werden, ob der Server aktuell aktiv ist. | ||||||||||
Wenn Daten empfangen werden, wird das Ereignis DataReceived
ausgelöst. Data enthält die Datagramm-Daten RemoteIP und RemotePort die Absender-Adresse. |
||||||||||
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. | |||||||||
Wenn BinaryMode auf true gesetzt wird, wird das empfangene Paket in einen String mit einer Folge von Dezimalzahlen übersetzt. | Auswirkung: s.u. |
Wenn BinaryMode auf true gesetzt ist, akzeptiert Xmit eine Zeichenfolge mit codierten Bytes, die durch ein Komma (’,’) oder ein Semikolon (';') voneinander getrennt sind.
Jedes Byte kann als „0xff“ oder „0xFF“ oder „0Xff“ oder „0XFF“ oder „#ff“ oder „#FF“ für HEX-Input oder „255“ für dezimalen Input oder „0377“ für den Oktal-Input codiert sein.
Man kann die Formate mischen: "0xFF;255,#ff" ist gültig.
Man kann auch Leerzeichen vor und nach der Zahl einfügen: „0xFF; 255, #ff ”ist ebenfalls gültig.
Ein nachfolgendes Komma oder Semikolon wird ignoriert: "0xFF; 255, #ff" und "0xFF; 255, #ff;" sind identisch.
Wenn BinaryMode auf true gesetzt ist, wird das empfangene Paket in eine durch Semikola getrennte Zeichenfolge von Dezimalzahlen übersetzt, z.B. "123;33;0;44". Man kann String.Split verwenden, um eine Liste der Bytes abzurufen.
Die Eigenschaft BinaryMode kann im Entwurfsfenster oder per Code festgelegt werden. Der Standardwert ist false.
Es gibt einen neuen Rückkehrcode: 4. Er bedeutet "Eingabe kann nicht konvertiert werden". Nichts
wird gesendet.
Für die Konvertierung wird dieser Algorithmus verwandt:
1) Ersetzen aller
Kommas durch Semikolons
2) splitten der Zeichenfolge per Semikolons
3) führende und nachfolgende
Leerzeichen löschen
4) Konvertierung in Integer mit
Integer.decode ()
5) auf Werte <0 oder> 255 prüfen.
Die Blöcke im Beispiel sind nicht schwer zu verstehen. Den größten Bereich nimmt die Überprüfung valider Eingaben ein.
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.