Englisch version   Deutsche Version


Version Anpassungen
1 (2018-01-27) Initial version
2 (2018-12-08) Since December 2018 there had been problems with network accesses. These accesses must now be executed in a separate thread. The extension had been rewritten accordingly.
In addition, the property InitErr was introduced, which can be used to retrieve errors during initialization of the component.
3 (2019-01-11) Unfortunately, version 2 had a few problems. Version 3 is restructured. Unfortunately, it is not compatible with the previous version. For this reason, please observe the migration instructions listed below for updating existing App Inventor projects.
The old version 2 is archived here.
3.1 (2019-04-29) The new property BinaryMode allows the transfer of binary data. This version is compatible with version 3.0. When uploading the existing links of the blocks are retained.
3.2 (2020-02-17) - DropSentToYourself was not forwarded after the start of the listener.
- Determining the local host IP by enumeration via the network interfaces leads to problems with devices that have more than one interface. DropSentToYourself did not work. DropSentToYourself now compares the sender address with all existing NIC addresses. LocalHost is now the address with which the Internet is reached (google.com, 8.8.8.8).

Motivation

For a project, an Android app should be developed that communicates with an ESP8266 (project). For easy development of the app MIT App Inventor 2 was choosen.

The IP addresses of the available ESP8266 devices should not be fixed in the project. The app should itself determine which devices are currently active and which are the addresses they can be addressed from.

To accomplish this task (name service), you can use the broadcast function of UDP. You simply send a broadcast datagram to a previously agreed port to all devices on the local network, requesting their connection data. The devices that are listening on the agreed port then return their IP and possibly further data to the sender. The sender collects the answers and thus knows all active devices. Because UDP packet delivery is not guaranteed, it's a good idea to repeat this process and use the union set of responses.

In order to be able to address the devices of a project in a targeted manner, you either agree on different ports or you enter a device identifier in the response. The receiver then filters out those devices it is interested in.

The problem is: App Inventor has no built-in UDP and I have found no working extension. So do it yourself.

Notice:

The extension works perfectly if the smartphone and the remote station are in the same (local) network. If the smartphone is only connected via a cellular network, it is usually not reachable. The reason is that the smartphone is not directly connected to the Internet, but only to the local network of the mobile phone provider.

Mobilfunk-Verbindung

A device in your own LAN can be reached from outside via port forwarding on your own router (if necessary via DDNS). You won't be able to influence the provider's router. So sending from the smartphone to a device in the LAN works, the other way around is not possible.

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, initiert 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.

The same also applies to TCP. If the smartphone is only connected to the cellular network, the connection can only be established from the smartphone. The device in the LAN must act as a server, it waits for an incoming connection request. The smartphone acts as a client, i.e. it initiates the connection. Once the connection has been set up, the routers have coordinated internally of addresses and ports. The data transfer is then possible in both directions.

Download

The ZIP archive UrsAI2UDPv3.2 for download. The archive contains the source code, the compiled binary to upload to App Inventor and a sample application.

Migrating from version 2 to version 3

The main differences are:

  • The Xmit and StartListening methods are now functions that return a value indicating whether the method ran successfully.
  • The events XmitError and RcvError are omitted. During App development it was difficult to associate the events with the corresponding action.
  • The names of some functions and function parameters have been adapted to the common names.

The best way to migrate an existing project is as follows:

  • Save the existing project ("Save project as ..." in App Inventors project menu).
  • Import the new version of the extension (in addition to the old one!).
  • In App Inventor Designer: Drag a new instance of the extension onto the screen.
  • In the block editor, transfer the affected code blocks to the new extension block. Pay attention to warnings and errors!
  • It is best to do another backup at this point.
  • In the Designer: Delete the instance of the old extension version and than the outdated extension.
  • In the block editor: check that everything is still correct.

Usage

Transmit datagrams

Block Function Notes
Xmit The Xmit block sends datagrams to the specified remote endpoint (RemoteIP: RemotePort). The local endpoint 0.0.0.0:LocalPort is used, i.e. the service provider selects the appropriate network interface.

The parameter RemoteIP can specify unicast or broadcast addresses.

The parameter LocalPort is also allowed to specify 0 or negative values. In this case, the service provider will search for a random free port.

The return code is:
Value Meaning
0 Xmit successful.
1 RemoteIP can not be converted to an IPv4 address.
2 No socket can be created with the specification of LocalPort. Port number is not free or > 65535.
3 Xmit not successful.
An Android device usually has only one active network interface at a time. This is either the mobile data connection or the WLAN.


For UDP address schemes, see UdpClient: Aufs Bit geschaut / Adressierungsschemata (there is a link to a translator).

To endpoints in Java UdpClient: Aufs Bit geschaut / Java (there is a link to a translator).



This block shows a typical application:
Xmit datagrams

If you want to transfer binary data, BinaryMode must be set to true and the binary values must be passed decoded as a string. For example, specifying "0x33,0x48,0xDF" will result in a packet with 3 bytes with HEX values 33 48 DF. Details: see below
Last Error The LastErrorMessage property can be used to retrieve an English text describing the last error.  
BinaryMode If BinaryMode is set to true, the content of Message is not sent directly, but translated into a byte array. Effect: see below

 

Receive datagrams

Block Function Note
StartListening  StartListening starts listening on datagrams sent to the specified port (UDP server).

Return codes:
Value Meaning
0 successful.
1 Port can not be used to create a socket. Port number is not free, < 1 oder > 65535.
2 StartListening before previous StartListening has been completed.

StopListening stops the server. A multiple call to StopListening is not critical.
To endpoints in Java UdpClient: Aufs Bit geschaut / Java (there is a link to a translator).


This block shows a typical application:
v
Last Error The LastErrorMessage property can be used to retrieve an English text describing the last error.  
Server Start/Stop There are corresponding events that are fired when the server was successfully started or stopped. LocalIP and LocalPort is the local endpoint.  
IsRunning The property isRunning can be used to query whether the server is currently active.  
Receive datagrams When data is received, the DataReceived event is fired. Data has the datagram data, RemoteIP and RemotePort is the senders address.  
DropSentToYourself  The property DropSentToYourself controls the behavior of receiving broadcast datagrams. By default, the block is set to ignore messages sent from its own IP. If these are still to be received, DropSentToYourself should be set to false.

This property can also be set in the Designer.
The default is true.
BinaryMode If BinaryMode is set to true, the received packet is translated into a string with a sequence of decimal numbers. Effect: see below

Binary data

BinaryMode

If BinaryMode is set to true method Xmit accepts a string with coded bytes, separated by comma (‘,’) or semicolon.

Each bytes could be coded like “0xff” or “0xFF” or “0Xff” or “0XFF” or “#ff” or “#FF” for HEX input or “255” for decimal input or “0377” for octal input.

You can mix it if you want: “0xFF;255,#ff” is valid.

You can insert blanks before and after the number: “ 0xFF ; 255, #ff” is valid too.

A trailing comma or semicolon will be ignored: “0xFF;255,#ff” and “0xFF;255,#ff;” are identical.

When BinaryMode is set to true, the received packet is translated to a string with decimal numbers as string separated by semicolons, e.g. “123;33;0;44”. You can use String.Split to get a list of the bytes.

You can set this property in the design window or by code. The default value is false.

BinaryMode

There is a new returncode: 4. It means “Cannot convert the input”. Nothing is sent.
For the consversion I use this algorithm:
1) replace all commas by semicolons
2) split the string by semicolons
3) delete leading and trailing blanks
4) convert to integer with Integer.decode ()
5) check for values < 0 or > 255.

Miscellaneous

Block/th> Function Note
LocalHost LocalHost retrieves the local IP address (in the Android environment this is usually unique). This is the address with which the Internet can be reached.

If no network can be reached, the value specified with Default is returned.
This block shows a typical application:
LocalHost

Example

Screenshot   Designer

The blocks in the example are not difficult to understand. Most blocks concern the validation of entries.

Tools

For developing own extensions I gathered some tips: AI2 FAQ: Develop Extensions.

The extensions are developed with Java. A tutorial on datagrams can be found in the Oracle Java documentation. There you will also find information about the DatagramSocket class used.