Bluetooth Beacons + Windows 10



Bluetooth Beacons ermöglichen viele neue mobile App-Szenarien – mit Apple iBeacons wurden sie berühmt, durch die neue Eddystone Smart Beacon Spezifikation von Google noch weit mächtiger. Wie integriert sich Windows in diese Welt?

Windows 10 Unterstützt Beacons

Bluetooth Beacons senden regelmäßig Informationen aus – ungefragt, üblicherweise mehrmals pro Sekunde. Wenn ein Handy in die Nähe des Beacons kommt und damit dieses Signal empfängt, kann es darauf reagieren. Eine passende App kann gestartet werden, oder in der App wird eine spezifische Aktion ausgelöst. Im weitesten Sinne erlauben Bluetooth Beacons also eine sehr genaue Lokalisierung des Benutzers, die im Gegensatz zu GPS auch in Gebäuden funktioniert.

Windows bzw das WinRT Framework unterstützt natürlich bereits seit langer Zeit Bluetooth sowie Bluetooth Smart / Low Energy (LE). Bisher war dafür allerdings stets ein Verbindungsaufbau zwischen den Geräten nötig – das Bluetooth Pairing, das zum Beispiel für einen Brustgurt zur Herzfrequenzmessung oder auch für ein Headset durchgeführt werden muss.

Mit Windows 10 ist es Apps nun auch möglich, die Informationen von Bluetooth Beacons zu empfangen und zu verarbeiten, ohne zuvor ein Pairing mit dem Beacon durchzuführen – was in diesem Fall auch überhaupt nicht zielführend wäre. Zusätzlich können sich Apps auch für bestimmte Beacons registrieren oder das eigene Windows-Gerät sogar selbst in einen Beacon verwandeln.

20150907_Pic1

Beacon Formate

Während die Core Bluetooth Spezifikation zwar vorgibt, wie Bluetooth-Geräte kommunizieren, sind die tatsächlichen Nutzdaten für das Bluetooth Beacon-Szenario jedoch nicht vorgegeben. Apple hat mit der iBeacon-Spezifikation festgelegt, dass mehrere IDs übermittelt werden, auf welche sich Apps registrieren. Allerdings unterliegen iBeacons sowie das spezielle Format den Lizenzbedingungen von Apple, diese sind nicht frei verfügbar.

Mit der Eddystone Smart Beacon Spezifikation hat Google Mitte Juli ein eigenes Format vorgestellt, das nicht nur unter der Apache Lizenz (Open Source) verfügbar ist, sondern auch vielfältigere Möglichkeiten bietet: so kann es zum Beispiel Web-Adressen aussenden („Physical Web“) oder auch Telemetrie-Daten zum Beacon selbst (Temperatur, Batterie-Spannung, etc). Dies erlaubt den Einsatz in weiteren Szenarien.

Microsoft hat aktuell selbst kein eigenes Beacon-Format vorgestellt, stellt mit der Universal Windows Platform jedoch die Tools zur Verfügung, auf einer grundsätzlichen Ebene mit den verschiedenen Beacon-Formaten zu interagieren.

Nach Beacons Ausschau halten

Um tatsächlich mit Beacons arbeiten zu können, muss die entsprechende Capability gesetzt sein. Dies geschieht bei Universal Windows Platform (UWP) Apps über die Package.appxmanifest-Datei. In der ersten Version von Visual Studio 2015 fehlt Bluetooth allerdings in der Checkbox-Liste des Editors – die entsprechende Capability muss also direkt im XML Code der Datei hinzugefügt werden:

1
2
3
<Capabilities>
    <DeviceCapability Name="bluetooth" />
</Capabilities>

Um nach den Beacons Ausschau zu halten, wird die entsprechende Klasse verwendet, dessen Call-Backs für den Erfolgs- und Fehlerfall registriert und der Prozess gestartet:

1
2
3
4
var watcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active };  
watcher.Received += WatcherOnReceived;
watcher.Stopped += WatcherOnStopped;
watcher.Start();

Als Universal Windows Platform funktioniert die App auf allen Windows 10-Geräten. Speziell Desktop PCs haben allerdings oft keinen Bluetooth-Support, oder der Nutzer hat vielleicht am Handy Bluetooth abgeschaltet. Wenn die Initialisierung nicht funktioniert, wird nach dem Aufruf von Start() das Stopped-Callback aufgerufen, mit einem entsprechenden Fehlercode. Die Methode wird natürlich auch aufgerufen, wenn wir als App selbst das Warten auf Beacons stoppen – z.B. wenn die App in den Hintergrund geschickt wird.

1
2
3
4
5
6
7
8
9
10
11
12
13
private void WatcherOnStopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args)
{
    switch (args.Error)
    {
        case BluetoothError.Success:
             // Watcher wurde von der App gestoppt, dies war erfolgreich
             break;
        case BluetoothError.RadioNotAvailable:
             // Kein Bluetooth LE Kompatibles Modul gefunden
             break;
        // Weitere Fehlerfälle behandeln ...
    }
}

Beacon-Daten Analysieren

Falls der Watcher erfolgreich gestartet werden konnte, erhält die App ab sofort eine Vielzahl an Received-Callbacks. In den Event Arguments sind die entsprechenden Nutzdaten im Rohformat enthalten.

Sind mehrere Beacons in der Umgebung, empfängt die App Signale von verschiedenen Mac-Adressen. Beispielsweise beim Eddystone-Format verschickt der Beacon auch nacheinander unterschiedliche Informationen („Frames“). Als App muss man deshalb:

  • Die Informationen dementsprechend aggregieren und die verschiedenen Frames auf einzelne Beacons zuordnen.
  • Das Beacon-Format erkennen (z.B. iBeacon oder Eddystone).
  • Die Rohdaten der einzelnen Frames in Bezug auf das Format parsen und die jeweils aktuellsten Werte speichern.

Um diese Arbeit etwas zu erleichtern, habe ich das Universal Beacon Library entwickelt. Es steht unter der Apache-Lizenz zur Verfügung und kann einfach über NuGet eingebunden werden.

Anstatt das empfangene Bluetooth Advertisement selbst zu analysieren, kann man nun einfach dem Library diese Arbeit überlassen:

1
2
3
4
5
6
7
8
9
10
public MainPage()
{
    // Beacon Manager beim App-Start initialiseren
    _beaconManager = new BeaconManager();
}
private async void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
     _beaconManager.ReceivedAdvertisement(eventArgs);
}

Gefundene Beacons

Das Library verarbeitet sofort die Daten. Alle bisher gefundenen Beacons stehen direkt über ein Property des Beacon Managers zur Verfügung.

Die einzelnen Beacons enthalten dann je nach Format verschiedene Frames – Daten nach der Eddystone-Spezifikation werden von der Bibliothek direkt verarbeitet und abgeleitete Typen der Frame-Klassen stehen zur Verfügung. Damit kann auf Informationen wie die Beacon-Temperatur direkt zugegriffen werden, ohne die einzelnen Bits & Bytes aus dem Payload selbst zu verarbeiten.

Das folgende Beispiel zeigt die Verarbeitung der Frame-Daten, die vom Universal Beacon Library zur Verfügung gestellt werden:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
foreach (var bluetoothBeacon in _beaconManager.BluetoothBeacons.ToList())
{
    Debug.WriteLine("Beacon: " + bluetoothBeacon.BluetoothAddressAsString);
    Debug.WriteLine("Type: " + bluetoothBeacon.BeaconType);
    Debug.WriteLine("Last Update: " + bluetoothBeacon.Timestamp);
    Debug.WriteLine("RSSI: " + bluetoothBeacon.Rssi);
    foreach (var beaconFrame in bluetoothBeacon.BeaconFrames.ToList())
    {
        // Print a small sample of the available data parsed by the library
        if (beaconFrame is UidEddystoneFrame)
        {
            Debug.WriteLine("Eddystone UID Frame");
            Debug.WriteLine("ID: " + ((UidEddystoneFrame) beaconFrame).NamespaceIdAsNumber.ToString("X") + " / " +
                            ((UidEddystoneFrame) beaconFrame).InstanceIdAsNumber.ToString("X"));
        }
        else if (beaconFrame is UrlEddystoneFrame)
        {
            Debug.WriteLine("Eddystone URL Frame");
            Debug.WriteLine("URL: " + ((UrlEddystoneFrame) beaconFrame).CompleteUrl);
        }
        else if (beaconFrame is TlmEddystoneFrame)
        {
            Debug.WriteLine("Eddystone Telemetry Frame");
            Debug.WriteLine("Temperature [°C]: " + ((TlmEddystoneFrame) beaconFrame).TemperatureInC);
            Debug.WriteLine("Battery [mV]: " + ((TlmEddystoneFrame) beaconFrame).BatteryInMilliV);
        }
        else
        {
            Debug.WriteLine("Unknown frame - not parsed by the library, write your own derived beacon frame type!");
            Debug.WriteLine("Payload: " + BitConverter.ToString(((UnknownBeaconFrame) beaconFrame).Payload));
        }
    }
}

Beispiel-Apps

Der Code zeigt, wie einfach es ist, mit Windows 10 und dem Universal Beacon Library die empfangenen Daten von Bluetooth Beacons zu verarbeiten. Die Bibliothek ist auch komplett im Quellcode über Github abrufbar.

Eine komplette Beispiel-App ist unter der GPL Open Source-Lizenz als Teil der Bibliothek verfügbar und außerdem für schnelle Tests direkt im Windows 10-Store herunterladbar. Sie läuft sowohl auf Windows 10 PCs und Tablets, als auch auf Handys, die mit der aktuellen Windows 10 Insider Preview-Version laufen.

Als Teil der offiziellen Windows UWP Beispiel-Apps von Microsoft gibt es ein Bluetooth LE-Beispiel, das empfangene Advertisements anzeigt, selbst Beacons simulieren kann und sich auch auf spezielle Beacons registrieren kann. Es arbeitet allerdings direkt mit Rohdaten, versteht und verarbeitet also keine gängigen Beacon-Spezifikationen.

Auf der Build 2015 hat Kiran Pathakota die neuen Bluetooth-APIs von Windows 10 vorgestellt – ein sehr hilfreicher Vortrag für den Einstieg. Weitere Informationen gibt es auch bei meinem Vortrag „Welche neuen Szenarien ermöglicht Windows 10 für Bluetooth LE, Beacons und NFC?“ des MVP Fusion-Events, der sowohl als Video als auch als Slides abrufbar ist. Für weitere Fragen zum Thema stehe ich auch sehr gerne zur Verfügung!

 


Andreas Jakl arbeitet seit 2004 mit mobilen Apps - von der Pionier-Arbeit mit Augmented Reality Apps in den allerersten Phasen bis hin zur Entwicklung & Verwaltung von Cloud-basierenden Enterprise-Lösungen. Er ist Microsoft MVP für Windows Platform Development, arbeitet bei Tieto als Mobility Evangelist und organisiert mit mobility.builders regelmäßige Events für die mobile Entwickler-Community in Österreich. Twitter / LinkedIn

Das ist ein Gastbeitrag. Die Meinung des Autors muss sich nicht mit jener von Microsoft decken. Durch den Artikel ergeben sich keinerlei Handlungsempfehlungen. Microsoft übernimmt keine Gewähr für die Richtigkeit oder Vollständigkeit der Angaben.


Skip to main content