Beim BeeWi Car handelt es sich um ein ferngesteuertes Auto der Firma BeeWi. Während meines Besuchs des gestrigen Workshops auf dem Developer Open Space in Leipzig zum Thema "Internet of Things", hatte ich den ersten Kontakt mit diesem kleinen Spielzeugauto.
Ich möchte euch mit diesem Artikel zeigen, wie man mit Xamarin.Android eine kleine Bluetooth-Fernsteuerung für das BeeWi Car schreibt und damit eine spaßige Zeit haben kann.
Ziel des Workshops war es, dass man sich mit dem Auto, einem Arduinos oder anderer Sensor-Hardware, mit der Plattform seiner Wahl verbindet und so erste Gehversuche im Thema IoT unternimmt. In Zeiten von SmartHome und Home-Automation ist an diesem spannenden Thema ohnehin nicht vorbeizukommen.
Um die möglichen Befehle Vorwärts, Rückwärts, Links und Rechts an das BeeWi Car senden zu können, braucht die App entsprechende Eingabemöglichkeiten.
Die Layout-Definition ist sehr einfach gehalten. Sie besteht aus vier Buttons, für die Richtungsbefehle, sowie einer Liste an bekannten Geräten. Bevor der Benutzer ein Fahrzeug steuern kann, wählt er eins aus der Liste aus. Und schon kann es los gehen.
An Hand meiner Beschreibung ergibt sich folgendes XML für das Layout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/btnForward"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Vorwärts" />
<Button
android:id="@+id/btnLeft"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Links" />
<Button
android:id="@+id/btnRight"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Rechts" />
<Button
android:id="@+id/btnBackwards"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Rückwärts" />
<TextView
android:text="Devices"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView1" />
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/listView1" />
</LinearLayout>
Wenn die App nun gestartet wird, ist es sinnvoll den Benutzer darüber aufzuklären ob sein Gerät überhaupt über Bluetooth verfügt. Ist dem so, dann fragt die App auch gleich ob sie Bluetooth aktivieren kann, falls es das nicht schon ist. Ist das nicht der Fall, tue einfach nichts weiter.
Mit folgenden Code kann genau das erreicht werden.
var bluetoothDefaultAdapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
if (bluetoothDefaultAdapter == null)
{
Toast.MakeText(this, "Your device does not support Bluetooth", ToastLength.Long).Show();
return;
}
if (!bluetoothDefaultAdapter.IsEnabled)
StartActivityForResult(new Intent(Android.Bluetooth.BluetoothAdapter.ActionRequestEnable), 1);
Bluetooth ist verfügbar und aktiviert - Zeit die bereits dem Gerät bekannte Bluetooth-Geräte anzuzeigen. Dazu wird über die Liste an BondedDevices iteriert und der Name sowie die Adresse des Gerätes ausgegeben.
var deviceList = new List<string>();
foreach (var device in bluetoothDefaultAdapter.BondedDevices)
deviceList.Add(String.Format("{0} ({1})", device.Name, device.Address));
var deviceAdapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItemMultipleChoice, deviceList.ToArray());
var listView = FindViewById<ListView>(Resource.Id.listView1);
listView.ChoiceMode = ChoiceMode.Single;
listView.Adapter = deviceAdapter;
Der Benutzer wählt das entsprechende Auto aus, in dem er auf eines der in der Liste befindlichen Geräte klickt. In diesem Moment erstellt man die Socket-Verbindung um die Kommunikation mit dem BeeWi Car zu beginnen.
listView.ItemClick += async delegate(object sender, AdapterView.ItemClickEventArgs e)
{
if (currentDevice != null && currentDevice.Address != bluetoothDefaultAdapter.BondedDevices.ToList()[e.Position].Address)
socket.Close();
currentDevice = bluetoothDefaultAdapter.BondedDevices.ToList()[e.Position];
socket = currentDevice.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805f9b34fb"));
try
{
if (!socket.IsConnected)
await socket.ConnectAsync();
}
catch (Exception ex)
{
Toast.MakeText(this, "Could not connect to device", ToastLength.Short).Show();
currentDevice = null;
socket = null;
}
};
"00001101-0000-1000-8000-00805f9b34fb" ist eine Standard-Id für SSP-Bluetooth.
Das Gerät ist nun verbunden, die Kommunikation steht auch. Um die Befehle für entsprechende Richtungsänderungen übermitteln zu können muss noch auf die Eingaben des Benutzers reagiert werden.
Am Beispiel der Vorwärtsbewegung ist ersichtlich wie der Button beim Drücken durch den Benutzer reagiert. Es ist zu sehen, dass wenn der Button gedrückt wird, der Forward_Go-Befehl abgesetzt wird. Sowie der Benutzer den Button nicht mehr drückt, wird der Befehlt aufgehoben.
front.Touch += delegate(object sender, View.TouchEventArgs e)
{
if (e.Event.Action == MotionEventActions.Down || e.Event.Action == MotionEventActions.Move)
SendCommand(BeeWiCarCommands.Forward_Go);
else
SendCommand(BeeWiCarCommands.Forward_Stop);
};
Alle anderen Buttons unterscheiden sich lediglich in der Art des Befehls, sind an sonsten aber gleich implementiert.
Mit SendCommand
werden die ausgewählten Befehle an das BeeWi Car übermittelt. Dazu muss geprüft werden, ob eine Socket-Verbindung besteht und sie mit dem aktuellen Gerät verbunden ist. Ist das der Fall, dann kann der entsprechende Befehl in den Output-Stream geschrieben werden.
void SendCommand(BeeWiCarCommands command)
{
try
{
if (socket == null)
{
Toast.MakeText(this, "No device selected", ToastLength.Short).Show();
return;
}
if (!socket.IsConnected)
{
Toast.MakeText(this, "Device not connected", ToastLength.Short).Show();
return;
}
if (socket.OutputStream.CanWrite)
{
socket.OutputStream.Write(new byte[]{ (byte)command }, 0, 1);
socket.OutputStream.Flush();
}
}
catch (Exception ex)
{
Toast.MakeText(this, ex.Message, ToastLength.Short).Show();
}
}
Um die Bluetooth-Kommunikation in der App verwenden zu können, fehlt noch die Berechtigung im AndroidManifest:
<uses-permission android:name="android.permission.BLUETOOTH" />
Das Verbinden des Gerätes mit dem BeeWi Car, so genanntes Pairing, erfolgt mit den von Android bereitgestellten Möglichkeiten. Wer möchte, kann diese Funktionalität aber gerne in die App einbauen und mir seinen Weg in den Kommentaren beschreiben oder aber ein Pull-Request für das Repository erstellen.
Mit Xamarin.Android ist es ein leichtes sich mit Bluetooth-Geräten zu verbinden, spielerisch die Möglichkeiten der bereits verfügbaren Hardware zu entdecken und sich ein wenig die Zeit zu vertreiben trägt ihr übriges bei.
Ich habe mir sagen lassen, dass mit der gleichen Steuerung auch die von BeeWi angebotenen Helikopter fliegen funktionieren. Wer also lieber Pilot anstatt Rennfahrer sein möchte, kann das mit der gleichen App sein.
Als Mobile-Enthusiast und Geschäftsführer der Cayas Software GmbH ist es mir ein großes Anliegen, mein Team und unsere Kunden zu unterstützen, neue potenziale zu entdecken und gemeinsam zu wachsen. Hier schreibe ich vor allem zur Entwicklung von Android und iOS-Apps mit Xamarin und .NET MAUI.
Voice input makes it possible to intuitively record food eaten and drunk without having to look at a device or tap. Instead of laboriously entering everything by hand, users can simply record their meals and snacks by voice command. This approach can lower the inhibition threshold and encourage users to continuously document their eating habits. This saves time and encourages regular documentation.
Modern applications are becoming more design-centric and therefore end-user-centric. For the user, the technical side of the program is not at all interesting, but rather taken for granted. Attractive design, animation and ease of use, on the contrary, all other things being equal, can make the application more popular among competitors.
Mit dem nahenden Ende des Supports für Xamarin im Mai 2024 sind Entwickler damit beschäftigt, bestehende Xamarin.Forms-Projekte auf .NET MAUI als Nachfolger zu migrieren. Das tun wir natürlich auch. In diesem Artikel zeige ich 7 Schritte, die wir während des Übergangs immer machen mussten, um Ihnen den Umstieg auf .NET MAUI zu erleichtern.