Skip to content

Commit 7b3db0b

Browse files
committed
Update to v3.1.0
* 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
1 parent f0e27f9 commit 7b3db0b

File tree

20 files changed

+379
-78
lines changed

20 files changed

+379
-78
lines changed

Library/UniversalBeacon.Library.Android/AndroidBluetoothPacketProvider.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace UniversalBeacon.Library
99
public class AndroidBluetoothPacketProvider : Java.Lang.Object, IBluetoothPacketProvider
1010
{
1111
public event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
12+
public event EventHandler<BTError> WatcherStopped;
1213

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

2829
public void Start()
2930
{
30-
try
31-
{
31+
//try
32+
//{
3233
_scanCallback.OnAdvertisementPacketReceived += ScanCallback_OnAdvertisementPacketReceived;
3334
_adapter.BluetoothLeScanner.StartScan(_scanCallback);
34-
}
35-
catch (Exception)
36-
{
37-
// TODO
38-
}
35+
//}
36+
//catch (Exception)
37+
//{
38+
// // TODO
39+
//}
3940
}
4041

4142
public void Stop()

Library/UniversalBeacon.Library.Core/Entities/BeaconManager.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ namespace UniversalBeacon.Library.Core.Entities
3636
/// </summary>
3737
public class BeaconManager
3838
{
39-
//public event EventHandler BeaconAdded;
39+
/// <summary>
40+
/// Event that is invoked whenever a new (unknown) beacon is discovered and added to the list
41+
/// of known beacons (BluetoothBeacons).
42+
/// To subscribe to updates of every single received Bluetooth advertisment packet,
43+
/// subscribe to the OnAdvertisementPacketReceived event of the IBluetoothPacketProvider.
44+
/// </summary>
45+
public event EventHandler<Beacon> BeaconAdded;
4046

4147
/// <summary>
4248
/// List of known beacons so far, which all have a unique Bluetooth MAC address
@@ -124,6 +130,7 @@ private void ReceivedAdvertisement(BLEAdvertisementPacket btAdv)
124130
// Beacon was not yet known - add it to the list.
125131
var newBeacon = new Beacon(btAdv);
126132
BluetoothBeacons.Add(newBeacon);
133+
BeaconAdded?.Invoke(this, newBeacon);
127134
}
128135
}
129136
}

Library/UniversalBeacon.Library.Core/Interfaces/IBluetoothPacketProvider.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,26 @@ namespace UniversalBeacon.Library.Core.Interfaces
55
{
66
public interface IBluetoothPacketProvider
77
{
8+
/// <summary>
9+
/// Event is invoked whenever a new Bluetooth LE Advertisment Packet has been received.
10+
/// Usually handled directly by the library. If required, your app implementation can
11+
/// also subscribe to get notified about events.
12+
/// </summary>
813
event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
14+
/// <summary>
15+
/// Wrapper for the Bluetooth LE Watcher stopped event of the underlying OS.
16+
/// Currently used by UWP platform and invoked whenever there has been an issue
17+
/// starting the Bluetooth LE watcher or if an issue occured while watching for
18+
/// beacons (e.g., if the user turned off Bluetooth while the app is running).
19+
/// </summary>
20+
event EventHandler<BTError> WatcherStopped;
21+
/// <summary>
22+
/// Start watching for Bluetooth beacons.
23+
/// </summary>
924
void Start();
25+
/// <summary>
26+
/// Stop watching for Bluetooth beacons.
27+
/// </summary>
1028
void Stop();
1129
}
1230
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace UniversalBeacon.Library.Core.Interop
6+
{
7+
/// <summary>
8+
/// Possible status codes of the Bluetooth LE Advertisment Watcher.
9+
/// Binary compatible to the UWP implementation.
10+
/// </summary>
11+
public enum BLEAdvertisementWatcherStatusCodes
12+
{
13+
//
14+
// Summary:
15+
// The initial status of the watcher.
16+
Created = 0,
17+
//
18+
// Summary:
19+
// The watcher is started.
20+
Started = 1,
21+
//
22+
// Summary:
23+
// The watcher stop command was issued.
24+
Stopping = 2,
25+
//
26+
// Summary:
27+
// The watcher is stopped.
28+
Stopped = 3,
29+
//
30+
// Summary:
31+
// An error occurred during transition or scanning that stopped the watcher due
32+
// to an error.
33+
Aborted = 4
34+
}
35+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
namespace UniversalBeacon.Library.Core.Interop
2+
{
3+
public class BTError
4+
{
5+
/// <summary>
6+
/// Possible error codes for Bluetooth handling.
7+
/// Binary compatible to the UWP implementation.
8+
/// </summary>
9+
public enum BluetoothError
10+
{
11+
//
12+
// Summary:
13+
// The operation was successfully completed or serviced.
14+
Success = 0,
15+
//
16+
// Summary:
17+
// The Bluetooth radio was not available. This error occurs when the Bluetooth radio
18+
// has been turned off.
19+
RadioNotAvailable = 1,
20+
//
21+
// Summary:
22+
// The operation cannot be serviced because the necessary resources are currently
23+
// in use.
24+
ResourceInUse = 2,
25+
//
26+
// Summary:
27+
// The operation cannot be completed because the remote device is not connected.
28+
DeviceNotConnected = 3,
29+
//
30+
// Summary:
31+
// An unexpected error has occurred.
32+
OtherError = 4,
33+
//
34+
// Summary:
35+
// The operation is disabled by policy.
36+
DisabledByPolicy = 5,
37+
//
38+
// Summary:
39+
// The operation is not supported on the current Bluetooth radio hardware.
40+
NotSupported = 6,
41+
//
42+
// Summary:
43+
// The operation is disabled by the user.
44+
DisabledByUser = 7,
45+
//
46+
// Summary:
47+
// The operation requires consent.
48+
ConsentRequired = 8,
49+
//
50+
TransportNotSupported = 9
51+
}
52+
53+
54+
public BluetoothError BluetoothErrorCode { get; set; }
55+
56+
public BTError(BluetoothError btErrorCode)
57+
{
58+
BluetoothErrorCode = btErrorCode;
59+
}
60+
}
61+
}

Library/UniversalBeacon.Library.Core/UniversalBeacon.Library.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>netstandard1.3</TargetFramework>
55
<NeutralLanguage>en</NeutralLanguage>
66
<PackageId>UniversalBeaconLibrary</PackageId>
7-
<Version>3.0.0</Version>
7+
<Version>3.1.0</Version>
88
<Authors>Andreas Jakl, Chris Tacke</Authors>
99
<Company>Andreas Jakl, Chris Tacke</Company>
1010
<Product>Universal Beacon Library</Product>

Library/UniversalBeacon.Library.UWP/WindowsBluetoothPacketProvider.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ public class WindowsBluetoothPacketProvider : IBluetoothPacketProvider
1010
private readonly BluetoothLEAdvertisementWatcher _watcher;
1111

1212
public event EventHandler<BLEAdvertisementPacketArgs> AdvertisementPacketReceived;
13+
public event EventHandler<BTError> WatcherStopped;
14+
15+
public BLEAdvertisementWatcherStatusCodes WatcherStatus
16+
{
17+
get
18+
{
19+
if (_watcher == null)
20+
return BLEAdvertisementWatcherStatusCodes.Stopped;
21+
return (BLEAdvertisementWatcherStatusCodes) _watcher.Status;
22+
}
23+
}
1324

1425
public WindowsBluetoothPacketProvider()
1526
{
@@ -27,9 +38,15 @@ private void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, Bluetooth
2738
public void Start()
2839
{
2940
_watcher.Received += WatcherOnReceived;
41+
_watcher.Stopped += WatcherOnStopped;
3042
_watcher.Start();
3143
}
3244

45+
private void WatcherOnStopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args)
46+
{
47+
WatcherStopped?.Invoke(this, new BTError((BTError.BluetoothError) args.Error));
48+
}
49+
3350
public void Stop()
3451
{
3552
_watcher.Received -= WatcherOnReceived;

Library/UniversalBeaconLibrary.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<metadata>
44
<id>UniversalBeaconLibrary</id>
55
<title>Universal Bluetooth Beacon Library</title>
6-
<version>3.0.0</version>
6+
<version>3.1.0</version>
77
<authors>Andreas Jakl, Chris Tacke</authors>
88
<owners>Andreas Jakl, Chris Tacke</owners>
99
<requireLicenseAcceptance>false</requireLicenseAcceptance>

README.md

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,22 @@ Note: for using Apple iBeacon technology in your services (in order to make your
5757
- Eddystone URL frame:
5858
- Ranging data
5959
- Complete URL
60-
- Frames comparable to the Apple iBeacon format
60+
- Proximity Beacon Frames (comparable to the Apple iBeacon format)
61+
- Uuid
62+
- Major ID
63+
- Minor ID
6164
- Raw payload for all other beacons
6265

6366

6467

65-
## Windows 10 Example App
68+
## Example Apps
6669

67-
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.
70+
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).
6871

69-
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.
72+
The example app comes in two versions:
7073

71-
Download and test the example app from the Windows 10 store: https://www.microsoft.com/store/apps/9NBLGGH1Z24K
74+
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
75+
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.
7276

7377

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

8488
## Usage example (C#)
8589

86-
### Registering for beacons and handling the data
90+
### Registering for beacons and handling the data (C#, UWP)
8791

8892
```csharp
8993
public sealed partial class MainPage : Page
@@ -97,55 +101,50 @@ public sealed partial class MainPage : Page
97101
{
98102
// [...]
99103
// Construct the Universal Bluetooth Beacon manager
100-
_beaconManager = new BeaconManager();
101-
102-
// Create & start the Bluetooth LE watcher from the Windows 10 UWP
103-
_watcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active };
104-
_watcher.Received += WatcherOnReceived;
105-
_watcher.Start();
106-
}
107-
108-
private async void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
109-
{
110-
// Let the library manager handle the advertisement to analyse & store the advertisement
111-
_beaconManager.ReceivedAdvertisement(eventArgs);
104+
var provider = new WindowsBluetoothPacketProvider();
105+
_beaconManager = new BeaconManager(provider);
106+
_beaconManager.BeaconAdded += BeaconManagerOnBeaconAdded;
107+
_beaconManager.Start();
112108
}
113109

114110
// Call this method e.g., when tapping a button
115-
private void PrintBeaconInfo()
111+
private void BeaconManagerOnBeaconAdded(object sender, Beacon beacon)
116112
{
117-
Debug.WriteLine("Beacons discovered so far\n-------------------------");
118-
foreach (var bluetoothBeacon in _beaconManager.BluetoothBeacons.ToList())
113+
Debug.WriteLine("\nBeacon: " + beacon.BluetoothAddressAsString);
114+
Debug.WriteLine("Type: " + beacon.BeaconType);
115+
Debug.WriteLine("Last Update: " + beacon.Timestamp);
116+
Debug.WriteLine("RSSI: " + beacon.Rssi);
117+
foreach (var beaconFrame in beacon.BeaconFrames.ToList())
119118
{
120-
Debug.WriteLine("\nBeacon: " + bluetoothBeacon.BluetoothAddressAsString);
121-
Debug.WriteLine("Type: " + bluetoothBeacon.BeaconType);
122-
Debug.WriteLine("Last Update: " + bluetoothBeacon.Timestamp);
123-
Debug.WriteLine("RSSI: " + bluetoothBeacon.Rssi);
124-
foreach (var beaconFrame in bluetoothBeacon.BeaconFrames.ToList())
119+
// Print a small sample of the available data parsed by the library
120+
if (beaconFrame is UidEddystoneFrame)
121+
{
122+
Debug.WriteLine("Eddystone UID Frame");
123+
Debug.WriteLine("ID: " + ((UidEddystoneFrame)beaconFrame).NamespaceIdAsNumber.ToString("X") + " / " +
124+
((UidEddystoneFrame)beaconFrame).InstanceIdAsNumber.ToString("X"));
125+
}
126+
else if (beaconFrame is UrlEddystoneFrame)
127+
{
128+
Debug.WriteLine("Eddystone URL Frame");
129+
Debug.WriteLine("URL: " + ((UrlEddystoneFrame)beaconFrame).CompleteUrl);
130+
}
131+
else if (beaconFrame is TlmEddystoneFrame)
132+
{
133+
Debug.WriteLine("Eddystone Telemetry Frame");
134+
Debug.WriteLine("Temperature [°C]: " + ((TlmEddystoneFrame)beaconFrame).TemperatureInC);
135+
Debug.WriteLine("Battery [mV]: " + ((TlmEddystoneFrame)beaconFrame).BatteryInMilliV);
136+
}
137+
else if (beaconFrame is ProximityBeaconFrame)
125138
{
126-
// Print a small sample of the available data parsed by the library
127-
if (beaconFrame is UidEddystoneFrame)
128-
{
129-
Debug.WriteLine("Eddystone UID Frame");
130-
Debug.WriteLine("ID: " + ((UidEddystoneFrame) beaconFrame).NamespaceIdAsNumber.ToString("X") + " / " +
131-
((UidEddystoneFrame) beaconFrame).InstanceIdAsNumber.ToString("X"));
132-
}
133-
else if (beaconFrame is UrlEddystoneFrame)
134-
{
135-
Debug.WriteLine("Eddystone URL Frame");
136-
Debug.WriteLine("URL: " + ((UrlEddystoneFrame) beaconFrame).CompleteUrl);
137-
}
138-
else if (beaconFrame is TlmEddystoneFrame)
139-
{
140-
Debug.WriteLine("Eddystone Telemetry Frame");
141-
Debug.WriteLine("Temperature [°C]: " + ((TlmEddystoneFrame) beaconFrame).TemperatureInC);
142-
Debug.WriteLine("Battery [mV]: " + ((TlmEddystoneFrame) beaconFrame).BatteryInMilliV);
143-
}
144-
else
145-
{
146-
Debug.WriteLine("Unknown frame - not parsed by the library, write your own derived beacon frame type!");
147-
Debug.WriteLine("Payload: " + BitConverter.ToString(((UnknownBeaconFrame) beaconFrame).Payload));
148-
}
139+
Debug.WriteLine("Proximity Beacon Frame (iBeacon compatible)");
140+
Debug.WriteLine("Uuid: " + ((ProximityBeaconFrame)beaconFrame).UuidAsString);
141+
Debug.WriteLine("Major: " + ((ProximityBeaconFrame)beaconFrame).MajorAsString);
142+
Debug.WriteLine("Major: " + ((ProximityBeaconFrame)beaconFrame).MinorAsString);
143+
}
144+
else
145+
{
146+
Debug.WriteLine("Unknown frame - not parsed by the library, write your own derived beacon frame type!");
147+
Debug.WriteLine("Payload: " + BitConverter.ToString(((UnknownBeaconFrame)beaconFrame).Payload));
149148
}
150149
}
151150
}
@@ -156,7 +155,7 @@ public sealed partial class MainPage : Page
156155

157156
## Availability
158157

159-
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).
158+
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.
160159

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

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

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

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

178177

179178

180179
## Version History
181180

182-
### 3.0.0 - August 2017, coming soon!
181+
### 3.1.0 - August 2017
182+
* 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.
183+
* Adds BeaconAdded event to the BeaconManager class
184+
* Updated sample code to also include handling Proximity Beacon frames (iBeacon compatible)
185+
* UWP Sample app handles additional Bluetooth error status codes
186+
187+
### 3.0.0 - August 2017
183188
* Port from UWP to .NET Standard 1.3, for cross platform compatibility to Windows, Linux, Mac and Xamarin (iOS, Android)
184189
* Library split into core .NET Standard library, plus platform extension libraries for Android and UWP
185190
* New Xamarin example app for Android and UWP

0 commit comments

Comments
 (0)