Skip to content

Commit

Permalink
Update to v3.1.0
Browse files Browse the repository at this point in the history
* Improve events provided by cross-platform interop code to surface more events to the custom app implementation. Based on these improvements, the UWP example app now again correctly displays status and error messages.
* Adds BeaconAdded event to the BeaconManager class
* Updated sample code to also include handling Proximity Beacon frames (iBeacon compatible)
* UWP Sample app handles additional Bluetooth error status codes
  • Loading branch information
andijakl committed Aug 23, 2017
1 parent f0e27f9 commit 7b3db0b
Show file tree
Hide file tree
Showing 20 changed files with 379 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace UniversalBeacon.Library
public class AndroidBluetoothPacketProvider : Java.Lang.Object, IBluetoothPacketProvider
{
public event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
public event EventHandler<BTError> WatcherStopped;

private readonly BluetoothAdapter _adapter;
private readonly BLEScanCallback _scanCallback;
Expand All @@ -27,15 +28,15 @@ private void ScanCallback_OnAdvertisementPacketReceived(object sender, BLEAdvert

public void Start()
{
try
{
//try
//{
_scanCallback.OnAdvertisementPacketReceived += ScanCallback_OnAdvertisementPacketReceived;
_adapter.BluetoothLeScanner.StartScan(_scanCallback);
}
catch (Exception)
{
// TODO
}
//}
//catch (Exception)
//{
// // TODO
//}
}

public void Stop()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ namespace UniversalBeacon.Library.Core.Entities
/// </summary>
public class BeaconManager
{
//public event EventHandler BeaconAdded;
/// <summary>
/// Event that is invoked whenever a new (unknown) beacon is discovered and added to the list
/// of known beacons (BluetoothBeacons).
/// To subscribe to updates of every single received Bluetooth advertisment packet,
/// subscribe to the OnAdvertisementPacketReceived event of the IBluetoothPacketProvider.
/// </summary>
public event EventHandler<Beacon> BeaconAdded;

/// <summary>
/// List of known beacons so far, which all have a unique Bluetooth MAC address
Expand Down Expand Up @@ -124,6 +130,7 @@ private void ReceivedAdvertisement(BLEAdvertisementPacket btAdv)
// Beacon was not yet known - add it to the list.
var newBeacon = new Beacon(btAdv);
BluetoothBeacons.Add(newBeacon);
BeaconAdded?.Invoke(this, newBeacon);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,26 @@ namespace UniversalBeacon.Library.Core.Interfaces
{
public interface IBluetoothPacketProvider
{
/// <summary>
/// Event is invoked whenever a new Bluetooth LE Advertisment Packet has been received.
/// Usually handled directly by the library. If required, your app implementation can
/// also subscribe to get notified about events.
/// </summary>
event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
/// <summary>
/// Wrapper for the Bluetooth LE Watcher stopped event of the underlying OS.
/// Currently used by UWP platform and invoked whenever there has been an issue
/// starting the Bluetooth LE watcher or if an issue occured while watching for
/// beacons (e.g., if the user turned off Bluetooth while the app is running).
/// </summary>
event EventHandler<BTError> WatcherStopped;
/// <summary>
/// Start watching for Bluetooth beacons.
/// </summary>
void Start();
/// <summary>
/// Stop watching for Bluetooth beacons.
/// </summary>
void Stop();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace UniversalBeacon.Library.Core.Interop
{
/// <summary>
/// Possible status codes of the Bluetooth LE Advertisment Watcher.
/// Binary compatible to the UWP implementation.
/// </summary>
public enum BLEAdvertisementWatcherStatusCodes
{
//
// Summary:
// The initial status of the watcher.
Created = 0,
//
// Summary:
// The watcher is started.
Started = 1,
//
// Summary:
// The watcher stop command was issued.
Stopping = 2,
//
// Summary:
// The watcher is stopped.
Stopped = 3,
//
// Summary:
// An error occurred during transition or scanning that stopped the watcher due
// to an error.
Aborted = 4
}
}
61 changes: 61 additions & 0 deletions Library/UniversalBeacon.Library.Core/Interop/BTError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
namespace UniversalBeacon.Library.Core.Interop
{
public class BTError
{
/// <summary>
/// Possible error codes for Bluetooth handling.
/// Binary compatible to the UWP implementation.
/// </summary>
public enum BluetoothError
{
//
// Summary:
// The operation was successfully completed or serviced.
Success = 0,
//
// Summary:
// The Bluetooth radio was not available. This error occurs when the Bluetooth radio
// has been turned off.
RadioNotAvailable = 1,
//
// Summary:
// The operation cannot be serviced because the necessary resources are currently
// in use.
ResourceInUse = 2,
//
// Summary:
// The operation cannot be completed because the remote device is not connected.
DeviceNotConnected = 3,
//
// Summary:
// An unexpected error has occurred.
OtherError = 4,
//
// Summary:
// The operation is disabled by policy.
DisabledByPolicy = 5,
//
// Summary:
// The operation is not supported on the current Bluetooth radio hardware.
NotSupported = 6,
//
// Summary:
// The operation is disabled by the user.
DisabledByUser = 7,
//
// Summary:
// The operation requires consent.
ConsentRequired = 8,
//
TransportNotSupported = 9
}


public BluetoothError BluetoothErrorCode { get; set; }

public BTError(BluetoothError btErrorCode)
{
BluetoothErrorCode = btErrorCode;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>netstandard1.3</TargetFramework>
<NeutralLanguage>en</NeutralLanguage>
<PackageId>UniversalBeaconLibrary</PackageId>
<Version>3.0.0</Version>
<Version>3.1.0</Version>
<Authors>Andreas Jakl, Chris Tacke</Authors>
<Company>Andreas Jakl, Chris Tacke</Company>
<Product>Universal Beacon Library</Product>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ public class WindowsBluetoothPacketProvider : IBluetoothPacketProvider
private readonly BluetoothLEAdvertisementWatcher _watcher;

public event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
public event EventHandler<BTError> WatcherStopped;

public BLEAdvertisementWatcherStatusCodes WatcherStatus
{
get
{
if (_watcher == null)
return BLEAdvertisementWatcherStatusCodes.Stopped;
return (BLEAdvertisementWatcherStatusCodes) _watcher.Status;
}
}

public WindowsBluetoothPacketProvider()
{
Expand All @@ -27,9 +38,15 @@ private void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, Bluetooth
public void Start()
{
_watcher.Received += WatcherOnReceived;
_watcher.Stopped += WatcherOnStopped;
_watcher.Start();
}

private void WatcherOnStopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args)
{
WatcherStopped?.Invoke(this, new BTError((BTError.BluetoothError) args.Error));
}

public void Stop()
{
_watcher.Received -= WatcherOnReceived;
Expand Down
2 changes: 1 addition & 1 deletion Library/UniversalBeaconLibrary.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<metadata>
<id>UniversalBeaconLibrary</id>
<title>Universal Bluetooth Beacon Library</title>
<version>3.0.0</version>
<version>3.1.0</version>
<authors>Andreas Jakl, Chris Tacke</authors>
<owners>Andreas Jakl, Chris Tacke</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
Expand Down
109 changes: 57 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,22 @@ Note: for using Apple iBeacon technology in your services (in order to make your
- Eddystone URL frame:
- Ranging data
- Complete URL
- Frames comparable to the Apple iBeacon format
- Proximity Beacon Frames (comparable to the Apple iBeacon format)
- Uuid
- Major ID
- Minor ID
- Raw payload for all other beacons



## Windows 10 Example App
## Example Apps

The included Windows 10 example app continuously scans for Bluetooth LE advertisements. It associates these with known or new Bluetooth MAC addresses to identify beacons. The individual advertisement frames are then parsed for known frame types - which are currently the three frame types defined by the Eddystone beacon format by Google.
The included example apps continuously scan for Bluetooth LE advertisements. They associate these with known or new Bluetooth MAC addresses to identify beacons. The individual advertisement frames are then parsed for known frame types - which are currently the three frame types defined by the Eddystone beacon format by Google, as well as Proximity Beacon frames (compatible to iBeacons).

The app has been tested on Windows 10 tablets and phones and requires Bluetooth LE (BLE) capable hardware. Make sure your device has Bluetooth activated (in Windows settings and also in hardware in case your device allows turning off bluetooth using a key combination) and is not in airplane mode.
The example app comes in two versions:

Download and test the example app from the Windows 10 store: https://www.microsoft.com/store/apps/9NBLGGH1Z24K
1. WindowsBeacons: Universal Windows app (UWP) called Bluetooth Beacon Interactor. The app has been tested on Windows 10 tablets and phones and requires Bluetooth LE (BLE) capable hardware. Make sure your device has Bluetooth activated (in Windows settings and also in hardware in case your device allows turning off bluetooth using a key combination) and is not in airplane mode. Download and test the example app from the Windows 10 store: https://www.microsoft.com/store/apps/9NBLGGH1Z24K
2. UniversalBeacon: Cross-Platform implementation with Xamarin. Core part in UniversalBeacon.Sample project. Platform-specific implementations in UniversalBeacon.Sample.Android and UniversalBeacon.Sample.UWP. iOS version is coming later. The Xamarin sample apps currently have a simpler UI than the UWP sample app.


### Permissions and Privacy Settings in Windows 10
Expand All @@ -83,7 +87,7 @@ To allow apps to receive data from Bluetooth Beacons, you have to ensure Windows

## Usage example (C#)

### Registering for beacons and handling the data
### Registering for beacons and handling the data (C#, UWP)

```csharp
public sealed partial class MainPage : Page
Expand All @@ -97,55 +101,50 @@ public sealed partial class MainPage : Page
{
// [...]
// Construct the Universal Bluetooth Beacon manager
_beaconManager = new BeaconManager();

// Create & start the Bluetooth LE watcher from the Windows 10 UWP
_watcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active };
_watcher.Received += WatcherOnReceived;
_watcher.Start();
}

private async void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
// Let the library manager handle the advertisement to analyse & store the advertisement
_beaconManager.ReceivedAdvertisement(eventArgs);
var provider = new WindowsBluetoothPacketProvider();
_beaconManager = new BeaconManager(provider);
_beaconManager.BeaconAdded += BeaconManagerOnBeaconAdded;
_beaconManager.Start();
}

// Call this method e.g., when tapping a button
private void PrintBeaconInfo()
private void BeaconManagerOnBeaconAdded(object sender, Beacon beacon)
{
Debug.WriteLine("Beacons discovered so far\n-------------------------");
foreach (var bluetoothBeacon in _beaconManager.BluetoothBeacons.ToList())
Debug.WriteLine("\nBeacon: " + beacon.BluetoothAddressAsString);
Debug.WriteLine("Type: " + beacon.BeaconType);
Debug.WriteLine("Last Update: " + beacon.Timestamp);
Debug.WriteLine("RSSI: " + beacon.Rssi);
foreach (var beaconFrame in beacon.BeaconFrames.ToList())
{
Debug.WriteLine("\nBeacon: " + 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 if (beaconFrame is ProximityBeaconFrame)
{
// 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));
}
Debug.WriteLine("Proximity Beacon Frame (iBeacon compatible)");
Debug.WriteLine("Uuid: " + ((ProximityBeaconFrame)beaconFrame).UuidAsString);
Debug.WriteLine("Major: " + ((ProximityBeaconFrame)beaconFrame).MajorAsString);
Debug.WriteLine("Major: " + ((ProximityBeaconFrame)beaconFrame).MinorAsString);
}
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));
}
}
}
Expand All @@ -156,7 +155,7 @@ public sealed partial class MainPage : Page

## Availability

The Universal Beacon Library is available in C# and includes a dependency to .NETCore the Universal Windows Platform (UWP / UAP) for Windows 10 to directly work with received advertisement packets from the Windows Bluetooth API. The library can therefore be used in applications targeting Windows 10 with support for Bluetooth Low Energy / LE (BLE).
The Core Universal Beacon Library is available in C# for .NET Standard 1.3 - it is therefore compatible to Windows UWP, Xamarin (Android / iOS / UWP / Mac / Linux) and other platforms supported by .NET Standard. Extension libraries are currently included for UWP and Xamarin/Android to interface with the platform Bluetooth APIs.

To keep up to date, either watch this project or [follow me on Twitter](https://twitter.com/andijakl).

Expand All @@ -173,13 +172,19 @@ If you want to use the Universal Beacon Library from your own app, the easiest o

Alternatively, use the NuGet Package Manager console as described here: https://www.nuget.org/packages/UniversalBeaconLibrary

To try the Windows 10 example app, download the complete library package from this site.
To try the Xamarin (Android / UWP) or Windows 10 (UWP) example apps, download the complete library package from this site.



## Version History

### 3.0.0 - August 2017, coming soon!
### 3.1.0 - August 2017
* Improve events provided by cross-platform interop code to surface more events to the custom app implementation. Based on these improvements, the UWP example app now again correctly displays status and error messages.
* Adds BeaconAdded event to the BeaconManager class
* Updated sample code to also include handling Proximity Beacon frames (iBeacon compatible)
* UWP Sample app handles additional Bluetooth error status codes

### 3.0.0 - August 2017
* Port from UWP to .NET Standard 1.3, for cross platform compatibility to Windows, Linux, Mac and Xamarin (iOS, Android)
* Library split into core .NET Standard library, plus platform extension libraries for Android and UWP
* New Xamarin example app for Android and UWP
Expand Down
Loading

0 comments on commit 7b3db0b

Please sign in to comment.