private void RegisterBTWatcherTask() { // Registering a background trigger if it is not already registered. It will start background watcher. // First get the existing tasks to see if we already registered for it if (taskRegistration == null) { ApplicationData.Current.LocalSettings.Values[taskName] = ""; //reset message ApplicationData.Current.LocalSettings.Values[BEACONPREFIX_TAG] = beaconPrefix; //reset message // At this point we assume we haven't found any existing tasks matching the one we want to register // First, configure the task entry point, trigger and name BluetoothLEAdvertisementWatcherTrigger trigger = SetupTrigger(); var builder = new BackgroundTaskBuilder(); builder.TaskEntryPoint = taskEntryPoint; builder.SetTrigger(trigger); builder.Name = taskName; // Now perform the registration. taskRegistration = builder.Register(); // For this scenario, attach an event handler to display the result processed from the background task taskRegistration.Completed += OnBTWatcherTaskCompleted; MainPage.Current.UpdateDebugMessage(this, "RegisterBTWatcherTask: " + taskRegistration.Name + " / " + taskRegistration.TaskId); } }
/// <summary> /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). /// </summary> public Scenario3_BackgroundWatcher() { this.InitializeComponent(); // Create and initialize a new trigger to configure it. trigger = new BluetoothLEAdvertisementWatcherTrigger(); // Configure the advertisement filter to look for the data advertised by the publisher in Scenario 2 or 4. // You need to run Scenario 2 on another Windows platform within proximity of this one for Scenario 3 to // take effect. // Unlike the APIs in Scenario 1 which operate in the foreground. This API allows the developer to register a background // task to process advertisement packets in the background. It has more restrictions on valid filter configuration. // For example, exactly one single matching filter condition is allowed (no more or less) and the sampling interval // For determining the filter restrictions programatically across APIs, use the following properties: // MinSamplingInterval, MaxSamplingInterval, MinOutOfRangeTimeout, MaxOutOfRangeTimeout // Part 1A: Configuring the advertisement filter to watch for a particular advertisement payload // First, let create a manufacturer data section we wanted to match for. These are the same as the one // created in Scenario 2 and 4. Note that in the background only a single filter pattern is allowed per trigger. var manufacturerData = new BluetoothLEManufacturerData(); // Then, set the company ID for the manufacturer data. Here we picked an unused value: 0xFFFE manufacturerData.CompanyId = 0xFFFE; // Finally set the data payload within the manufacturer-specific section // Here, use a 16-bit UUID: 0x1234 -> {0x34, 0x12} (little-endian) DataWriter writer = new DataWriter(); writer.WriteUInt16(0x1234); // Make sure that the buffer length can fit within an advertisement payload. Otherwise you will get an exception. manufacturerData.Data = writer.DetachBuffer(); // Add the manufacturer data to the advertisement filter on the trigger: trigger.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData); // Part 1B: Configuring the signal strength filter for proximity scenarios // Configure the signal strength filter to only propagate events when in-range // Please adjust these values if you cannot receive any advertisement // Set the in-range threshold to -70dBm. This means advertisements with RSSI >= -70dBm // will start to be considered "in-range". trigger.SignalStrengthFilter.InRangeThresholdInDBm = -70; // Set the out-of-range threshold to -75dBm (give some buffer). Used in conjunction with OutOfRangeTimeout // to determine when an advertisement is no longer considered "in-range" trigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = -75; // Set the out-of-range timeout to be 2 seconds. Used in conjunction with OutOfRangeThresholdInDBm // to determine when an advertisement is no longer considered "in-range" trigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000); // By default, the sampling interval is set to be disabled, or the maximum sampling interval supported. // The sampling interval set to MaxSamplingInterval indicates that the event will only trigger once after it comes into range. // Here, set the sampling period to 1 second, which is the minimum supported for background. trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(1000); }
/// <summary> /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). /// </summary> public Scenario5_AggregatingWatcher() { InitializeComponent(); // Create and initialize a new trigger to configure it. trigger = new BluetoothLEAdvertisementWatcherTrigger(); var manufacturerData = new BluetoothLEManufacturerData { CompanyId = 76 }; trigger.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData); _tracker = new Tracker(); }
BluetoothLEAdvertisementWatcherTrigger MakeWatcherTrigger() { var trigger = new BluetoothLEAdvertisementWatcherTrigger(); trigger.AdvertisementFilter.Advertisement.ManufacturerData.Add( new BluetoothLEManufacturerData() { CompanyId = TheTask.MSCompanyId } ); return(trigger); }
private void initBluetoothAdvertisementWatcherTrigger() { this.trigger = new BluetoothLEAdvertisementWatcherTrigger(); // Background advertisements require 1 advertisement filter. Here we filter by Guid in the Advertisement trigger.AdvertisementFilter.Advertisement.ServiceUuids.Add(peripheralDeviceServiceGUID); // Only activate the watcher when we're recieving values >= -80 trigger.SignalStrengthFilter.InRangeThresholdInDBm = -80; // Stop watching if the value drops below -90 (user walked away) trigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = -90; // Wait 5 seconds to make sure the device is really out of range trigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000); trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000); }
/// <summary> /// Registers Bluetooth advertisement listener /// </summary> /// <returns></returns> public bool RegisterAdvertisementWatcherBackgroundTask() { if (BackgroundTaskRegistered(AdvertisementWatcherBackgroundTaskName)) { return(true); } else { BackgroundTaskBuilder backgroundTaskBuilder = new BackgroundTaskBuilder(); backgroundTaskBuilder.Name = AdvertisementWatcherBackgroundTaskName; backgroundTaskBuilder.TaskEntryPoint = AdvertisementWatcherBackgroundTaskEntryPoint; IBackgroundTrigger trigger = null; BluetoothLEAdvertisementWatcherTrigger advertisementWatcherTrigger = new BluetoothLEAdvertisementWatcherTrigger(); //This filter includes UUIDSpace 7367672374000000ffff0000ffff00xx var pattern = BEACONIDToAdvertisementBytePattern(CommonConstants.UUIDSpace1); advertisementWatcherTrigger.AdvertisementFilter.BytePatterns.Add(pattern); //Using MaxSamplingInterval as SamplingInterval ensures that we get an event only when entering or exiting from the range of the beacon advertisementWatcherTrigger.SignalStrengthFilter.SamplingInterval = advertisementWatcherTrigger.MaxSamplingInterval; advertisementWatcherTrigger.SignalStrengthFilter.InRangeThresholdInDBm = CommonConstants.SignalStrengthFilterInRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = CommonConstants.SignalStrengthFilterOutOfRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(9000); trigger = advertisementWatcherTrigger; backgroundTaskBuilder.SetTrigger(trigger); try { BackgroundTaskRegistration backgroundTaskRegistration = backgroundTaskBuilder.Register(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("RegisterAdvertisementWatcherBackgroundTask(): Failed to register: " + ex); return(false); } return(true); } }
/// <summary> /// Registers Bluetooth advertisement listener /// </summary> /// <returns></returns> public bool RegisterAdvertisementWatcherBackgroundTask() { if (BackgroundTaskRegistered(AdvertisementWatcherBackgroundTaskName)) { return true; } else { BackgroundTaskBuilder backgroundTaskBuilder = new BackgroundTaskBuilder(); backgroundTaskBuilder.Name = AdvertisementWatcherBackgroundTaskName; backgroundTaskBuilder.TaskEntryPoint = AdvertisementWatcherBackgroundTaskEntryPoint; IBackgroundTrigger trigger = null; BluetoothLEAdvertisementWatcherTrigger advertisementWatcherTrigger = new BluetoothLEAdvertisementWatcherTrigger(); //This filter includes UUIDSpace 7367672374000000ffff0000ffff00xx var pattern = BEACONIDToAdvertisementBytePattern(CommonConstants.UUIDSpace1); advertisementWatcherTrigger.AdvertisementFilter.BytePatterns.Add(pattern); //Using MaxSamplingInterval as SamplingInterval ensures that we get an event only when entering or exiting from the range of the beacon advertisementWatcherTrigger.SignalStrengthFilter.SamplingInterval = advertisementWatcherTrigger.MaxSamplingInterval; advertisementWatcherTrigger.SignalStrengthFilter.InRangeThresholdInDBm = CommonConstants.SignalStrengthFilterInRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = CommonConstants.SignalStrengthFilterOutOfRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(9000); trigger = advertisementWatcherTrigger; backgroundTaskBuilder.SetTrigger(trigger); try { BackgroundTaskRegistration backgroundTaskRegistration = backgroundTaskBuilder.Register(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("RegisterAdvertisementWatcherBackgroundTask(): Failed to register: " + ex); return false; } return true; } }
private void RegisterTasks() { if (BackgroundTaskRegistration.AllTasks.Any(x => x.Value.Name == TaskName)) { return; } var backgroundTaskBuilder = new BackgroundTaskBuilder { Name = TaskName, TaskEntryPoint = typeof(AdvertisementHandler).FullName }; var trigger = new BluetoothLEAdvertisementWatcherTrigger(); trigger.AdvertisementFilter.Advertisement.ServiceUuids.Add(flicServiceUuid); trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(1000); backgroundTaskBuilder.SetTrigger(trigger); backgroundTaskBuilder.Register(); }
public bool RegisterAdvertisementWatcherTask() { foreach (var task in BackgroundTaskRegistration.AllTasks) { if (task.Value.Name == TaskName) { return(false); } } var builder = new BackgroundTaskBuilder { Name = TaskName, TaskEntryPoint = $"{Namespace}.{TaskName}" }; var trigger = new BluetoothLEAdvertisementWatcherTrigger(); trigger.AdvertisementFilter.Advertisement.LocalName = "Digit"; builder.SetTrigger(trigger); BackgroundTaskRegistration t = builder.Register(); return(true); }
private BluetoothLEAdvertisementWatcherTrigger SetupTrigger() { // The watcher trigger used to configure the background task registration BluetoothLEAdvertisementWatcherTrigger trigger; // Create and initialize a new trigger to configure it. trigger = new BluetoothLEAdvertisementWatcherTrigger(); // We need to add some payload to the advertisement. A publisher without any payload // or with invalid ones cannot be started. We only need to configure the payload once // for any publisher. // Add a manufacturer-specific section: // First, create a manufacturer data section var manufacturerData = new BluetoothLEManufacturerData(); // Then, set the company ID for the manufacturer data. Here we picked an unused value: 0xFFFE manufacturerData.CompanyId = companyId; // Add the manufacturer data to the advertisement publisher: trigger.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData); trigger.SignalStrengthFilter.InRangeThresholdInDBm = App.curScenario.BTFilterInRange; // -50; // -60; trigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = App.curScenario.BTFilterOutRange; // -100; double timeout = App.curScenario.BTSamplingIntervalms * 2.5; if (timeout < App.configManager.BTMinOutRangeTimeoutms) { timeout = App.configManager.BTMinOutRangeTimeoutms; } trigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(timeout); trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(App.curScenario.BTSamplingIntervalms); // Display the information about the published payload Debug.WriteLine(string.Format("Watch BLE payload information: CompanyId=0x{0}", manufacturerData.CompanyId.ToString("X"))); return(trigger); }
/// <summary> /// Registers the Bluetooth LE watcher background task, assuming Bluetooth is available. /// </summary> private async Task EnableWatcherAsync() { if (_taskRegistration != null) { return; } _trigger = new BluetoothLEAdvertisementWatcherTrigger(); // Add manufacturer data. var manufacturerData = new BluetoothLEManufacturerData(); manufacturerData.CompanyId = 0xFFFE; DataWriter writer = new DataWriter(); writer.WriteUInt16(0x1234); manufacturerData.Data = writer.DetachBuffer(); _trigger.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData); // Add signal strength filters and sampling interval. _trigger.SignalStrengthFilter.InRangeThresholdInDBm = -65; _trigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = -70; _trigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromSeconds(2); _trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromSeconds(1); // Create the task. BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync(); var builder = new BackgroundTaskBuilder() { Name = _taskName, TaskEntryPoint = "BackgroundTasks.AdvertisementWatcherTask" }; builder.SetTrigger(_trigger); builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable)); _taskRegistration = builder.Register(); }
/// <summary> /// Registers the BLE advertisement watcher background task. /// </summary> /// <param name="configuration">Configuration for the new registration.</param> /// <returns>The registration result.</returns> private async Task <BackgroundTaskRegistrationResult> RegisterAdvertisementWatcherBackgroundTaskAsync(SdkConfiguration configuration) { BackgroundTaskRegistrationResult result = new BackgroundTaskRegistrationResult() { Success = false, Exception = null }; if (BackgroundTaskRegistered(AdvertisementClass)) { // Already registered Logger.Debug("BackgroundTaskManager.RegisterAdvertisementWatcherBackgroundTask(): Already registered"); result.Success = true; } else { BackgroundTaskBuilder backgroundTaskBuilder = new BackgroundTaskBuilder(); backgroundTaskBuilder.Name = AdvertisementClass + Guid.NewGuid(); backgroundTaskBuilder.TaskEntryPoint = configuration.BackgroundAdvertisementClassName; BluetoothLEAdvertisementWatcherTrigger advertisementWatcherTrigger = new BluetoothLEAdvertisementWatcherTrigger(); // This filter includes all Sensorberg beacons var pattern = BeaconFactory.UuidToAdvertisementBytePattern(configuration.BackgroundBeaconUuidSpace, configuration.ManufacturerId, configuration.BeaconCode); advertisementWatcherTrigger.AdvertisementFilter.BytePatterns.Add(pattern); ILayoutManager layoutManager = ServiceManager.LayoutManager; AppSettings = await ServiceManager.SettingsManager.GetSettings(); // Using MaxSamplingInterval as SamplingInterval ensures that we get an event only // when entering or exiting from the range of the beacon advertisementWatcherTrigger.SignalStrengthFilter.SamplingInterval = advertisementWatcherTrigger.MaxSamplingInterval; if (AppSettings.RssiEnterThreshold != null && AppSettings.RssiEnterThreshold.Value >= -128 && AppSettings.RssiEnterThreshold.Value <= 127) { advertisementWatcherTrigger.SignalStrengthFilter.InRangeThresholdInDBm = AppSettings.RssiEnterThreshold; } else { advertisementWatcherTrigger.SignalStrengthFilter.InRangeThresholdInDBm = Constants.DefaultBackgroundScannerEnterThreshold; } advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = SignalStrengthFilterOutOfRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(AppSettings.BeaconExitTimeout); IBackgroundTrigger trigger = advertisementWatcherTrigger; backgroundTaskBuilder.SetTrigger(trigger); try { BackgroundTaskRegistration backgroundTaskRegistration = backgroundTaskBuilder.Register(); backgroundTaskRegistration.Completed += OnAdvertisementWatcherBackgroundTaskCompleted; backgroundTaskRegistration.Progress += OnAdvertisementWatcherBackgroundTaskProgress; result.Success = true; } catch (Exception ex) { result.Exception = ex; Logger.Error("BackgroundTaskManager.RegisterAdvertisementWatcherBackgroundTask(): Failed to register: ", ex); if (ex.Message.Contains("0x800710DF)")) { await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() => await new MessageDialog("Activate Bluetooth for the app").ShowAsync()); } } if (result.Success) { // Check if there was a pending filter update if (SdkData.BackgroundFilterUpdateRequired) { string upToDateHash = LayoutManager.CreateHashOfBeaconId1SInLayout(layoutManager.Layout); if (!string.IsNullOrEmpty(upToDateHash) && SdkData.LayoutBeaconId1Hash.Equals(upToDateHash)) { // Background filter updated successfully SdkData.BackgroundFilterUpdateRequired = false; BackgroundFiltersUpdated?.Invoke(this, null); } } else if (string.IsNullOrEmpty(SdkData.LayoutBeaconId1Hash)) { // This is the first time the background task is registered with valid layout => // set the hash string upToDateHash = LayoutManager.CreateHashOfBeaconId1SInLayout(layoutManager.Layout); if (!string.IsNullOrEmpty(upToDateHash)) { SdkData.LayoutBeaconId1Hash = upToDateHash; } } } } //Load last events from background await LoadBackgroundActions(); return(result); }
private void Button_Click(object sender, RoutedEventArgs e) { if (taskAdvertisementWatcher != null) { taskAdvertisementWatcher.Completed -= OnBackgroundTaskCompleted; taskAdvertisementWatcher.Unregister(true); taskAdvertisementWatcher = null; btnRegisterUnregister.Content = "Register Background Task"; } else { //Register the new task // Applications registering for background trigger must request for permission. BackgroundExecutionManager.RequestAccessAsync().AsTask().ContinueWith(async (r) => { if (r.IsFaulted || r.IsCanceled) return; if ((r.Result == BackgroundAccessStatus.Denied) || (r.Result == BackgroundAccessStatus.Unspecified)) { await new MessageDialog("Not able to run in background. Application must given permission to be added to lock screen.").ShowAsync(); Application.Current.Exit(); } // Create and initialize a new trigger to configure it. trigger = new BluetoothLEAdvertisementWatcherTrigger(); // Add the manufacturer data to the advertisement filter on the trigger: trigger.AdvertisementFilter.Advertisement.iBeaconSetAdvertisement(new iBeaconData()); // By default, the sampling interval is set to be disabled, or the maximum sampling interval supported. // The sampling interval set to MaxSamplingInterval indicates that the event will only trigger once after it comes into range. // Here, set the sampling period to 1 second, which is the minimum supported for background. trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(1000); // At this point we assume we haven't found any existing tasks matching the one we want to register // First, configure the task entry point, trigger and name var builder = new BackgroundTaskBuilder(); builder.TaskEntryPoint = taskEntryPoint; builder.SetTrigger(trigger); builder.Name = taskName; // Now perform the registration. The registration can throw an exception if the current // hardware does not support background advertisement offloading try { taskAdvertisementWatcher = builder.Register(); Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => { // For this scenario, attach an event handler to display the result processed from the background task taskAdvertisementWatcher.Completed += OnBackgroundTaskCompleted; btnRegisterUnregister.Content = "Unregister Background Task"; }); } catch (Exception ex) { taskAdvertisementWatcher = null; switch ((uint)ex.HResult) { case (0x80070032): // ERROR_NOT_SUPPORTED Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => { await new MessageDialog("The hardware does not support background advertisement offload.").ShowAsync(); Application.Current.Exit(); }); break; default: throw ex; } } }); } }
/// <summary> /// Registers the BLE advertisement watcher background task. /// </summary> /// <param name="manufacturerId">The manufacturer ID of beacons to watch.</param> /// <param name="beaconCode">The beacon code of beacons to watch.</param> /// <returns>The registration result.</returns> private async Task<BackgroundTaskRegistrationResult> RegisterAdvertisementWatcherBackgroundTaskAsync( UInt16 manufacturerId, UInt16 beaconCode) { BackgroundTaskRegistrationResult result = new BackgroundTaskRegistrationResult() { success = false, exception = null }; if (BackgroundTaskRegistered(_advertisementWatcherBackgroundTaskName)) { // Already registered System.Diagnostics.Debug.WriteLine("BackgroundTaskManager.RegisterAdvertisementWatcherBackgroundTask(): Already registered"); result.success = true; } else { BackgroundTaskBuilder backgroundTaskBuilder = new BackgroundTaskBuilder(); backgroundTaskBuilder.Name = _advertisementWatcherBackgroundTaskName; backgroundTaskBuilder.TaskEntryPoint = AdvertisementWatcherBackgroundTaskEntryPoint; IBackgroundTrigger trigger = null; BluetoothLEAdvertisementWatcherTrigger advertisementWatcherTrigger = new BluetoothLEAdvertisementWatcherTrigger(); //BluetoothLEManufacturerData manufacturerData = BeaconFactory.DefaultBeaconManufacturerData(); //advertisementWatcherTrigger.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData); // This filter includes all Sensorberg beacons var pattern = BeaconFactory.UUIDToAdvertisementBytePattern(Constants.SensorbergUuidSpace, manufacturerId, beaconCode); advertisementWatcherTrigger.AdvertisementFilter.BytePatterns.Add(pattern); LayoutManager layoutManager = LayoutManager.Instance; #if FILTER_SUPPORTS_MORE_UUIDS // Only UUIDs that are registered to the app will be added into filter if (await layoutManager.VerifyLayoutAsync(false) && layoutManager.Layout.ContainsOtherThanSensorbergBeaconId1s()) { int counter = 0; foreach (string beaconId1 in LayoutManager.Instance.Layout.AccountBeaconId1s) { if (beaconId1.Length == Constants.BeaconId1LengthWithoutDashes && counter < MaxBeaconId1FilterCount) { if (!beaconId1.StartsWith(Constants.SensorbergUuidSpace, StringComparison.CurrentCultureIgnoreCase)) { pattern = BeaconFactory.UUIDToAdvertisementBytePattern(beaconId1); advertisementWatcherTrigger.AdvertisementFilter.BytePatterns.Add(pattern); counter++; } } } } #endif // Using MaxSamplingInterval as SamplingInterval ensures that we get an event only // when entering or exiting from the range of the beacon advertisementWatcherTrigger.SignalStrengthFilter.SamplingInterval = advertisementWatcherTrigger.MaxSamplingInterval; advertisementWatcherTrigger.SignalStrengthFilter.InRangeThresholdInDBm = SignalStrengthFilterInRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = SignalStrengthFilterOutOfRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(Constants.BeaconExitDelayInMilliseconds); trigger = advertisementWatcherTrigger; backgroundTaskBuilder.SetTrigger(trigger); try { BackgroundTaskRegistration backgroundTaskRegistration = backgroundTaskBuilder.Register(); backgroundTaskRegistration.Completed += new BackgroundTaskCompletedEventHandler(OnAdvertisementWatcherBackgroundTaskCompleted); result.success = true; } catch (Exception ex) { result.exception = ex; System.Diagnostics.Debug.WriteLine("BackgroundTaskManager.RegisterAdvertisementWatcherBackgroundTask(): Failed to register: " + ex); } if (result.success) { SDKData sdkData = SDKData.Instance; // Check if there was a pending filter update if (sdkData.BackgroundFilterUpdateRequired) { string upToDateHash = LayoutManager.CreateHashOfBeaconId1sInLayout(layoutManager.Layout); if (!string.IsNullOrEmpty(upToDateHash) && sdkData.LayoutBeaconId1Hash.Equals(upToDateHash)) { // Background filter updated successfully sdkData.BackgroundFilterUpdateRequired = false; if (BackgroundFiltersUpdated != null) { BackgroundFiltersUpdated(this, null); } } } else if (string.IsNullOrEmpty(sdkData.LayoutBeaconId1Hash)) { // This is the first time the background task is registered with valid layout => // set the hash string upToDateHash = LayoutManager.CreateHashOfBeaconId1sInLayout(layoutManager.Layout); if (!string.IsNullOrEmpty(upToDateHash)) { sdkData.LayoutBeaconId1Hash = upToDateHash; } } } } return result; }
/// <summary> /// Registers the BLE advertisement watcher background task. /// </summary> /// <param name="configuration">Configuration for the new registration.</param> /// <returns>The registration result.</returns> private async Task<BackgroundTaskRegistrationResult> RegisterAdvertisementWatcherBackgroundTaskAsync(SdkConfiguration configuration) { BackgroundTaskRegistrationResult result = new BackgroundTaskRegistrationResult() { Success = false, Exception = null }; if (BackgroundTaskRegistered(AdvertisementClass)) { // Already registered Logger.Debug("BackgroundTaskManager.RegisterAdvertisementWatcherBackgroundTask(): Already registered"); result.Success = true; } else { BackgroundTaskBuilder backgroundTaskBuilder = new BackgroundTaskBuilder(); backgroundTaskBuilder.Name = AdvertisementClass + Guid.NewGuid(); backgroundTaskBuilder.TaskEntryPoint = configuration.BackgroundAdvertisementClassName; BluetoothLEAdvertisementWatcherTrigger advertisementWatcherTrigger = new BluetoothLEAdvertisementWatcherTrigger(); // This filter includes all Sensorberg beacons var pattern = BeaconFactory.UuidToAdvertisementBytePattern(configuration.BackgroundBeaconUuidSpace, configuration.ManufacturerId, configuration.BeaconCode); advertisementWatcherTrigger.AdvertisementFilter.BytePatterns.Add(pattern); ILayoutManager layoutManager = ServiceManager.LayoutManager; AppSettings = await ServiceManager.SettingsManager.GetSettings(); // Using MaxSamplingInterval as SamplingInterval ensures that we get an event only // when entering or exiting from the range of the beacon advertisementWatcherTrigger.SignalStrengthFilter.SamplingInterval = advertisementWatcherTrigger.MaxSamplingInterval; if (AppSettings.RssiEnterThreshold != null && AppSettings.RssiEnterThreshold.Value >= -128 && AppSettings.RssiEnterThreshold.Value <= 127) { advertisementWatcherTrigger.SignalStrengthFilter.InRangeThresholdInDBm = AppSettings.RssiEnterThreshold; } else { advertisementWatcherTrigger.SignalStrengthFilter.InRangeThresholdInDBm = Constants.DefaultBackgroundScannerEnterThreshold; } advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeThresholdInDBm = SignalStrengthFilterOutOfRangeThresholdInDBm; advertisementWatcherTrigger.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(AppSettings.BeaconExitTimeout); IBackgroundTrigger trigger = advertisementWatcherTrigger; backgroundTaskBuilder.SetTrigger(trigger); try { BackgroundTaskRegistration backgroundTaskRegistration = backgroundTaskBuilder.Register(); backgroundTaskRegistration.Completed += OnAdvertisementWatcherBackgroundTaskCompleted; backgroundTaskRegistration.Progress += OnAdvertisementWatcherBackgroundTaskProgress; result.Success = true; } catch (Exception ex) { result.Exception = ex; Logger.Error("BackgroundTaskManager.RegisterAdvertisementWatcherBackgroundTask(): Failed to register: ", ex); if (ex.Message.Contains("0x800710DF)")) { await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => await new MessageDialog("Activate Bluetooth for the app").ShowAsync()); } } if (result.Success) { // Check if there was a pending filter update if (SdkData.BackgroundFilterUpdateRequired) { string upToDateHash = LayoutManager.CreateHashOfBeaconId1SInLayout(layoutManager.Layout); if (!string.IsNullOrEmpty(upToDateHash) && SdkData.LayoutBeaconId1Hash.Equals(upToDateHash)) { // Background filter updated successfully SdkData.BackgroundFilterUpdateRequired = false; BackgroundFiltersUpdated?.Invoke(this, null); } } else if (string.IsNullOrEmpty(SdkData.LayoutBeaconId1Hash)) { // This is the first time the background task is registered with valid layout => // set the hash string upToDateHash = LayoutManager.CreateHashOfBeaconId1SInLayout(layoutManager.Layout); if (!string.IsNullOrEmpty(upToDateHash)) { SdkData.LayoutBeaconId1Hash = upToDateHash; } } } } //Load last events from background await LoadBackgroundActions(); return result; }
private void Button_Click(object sender, RoutedEventArgs e) { if (taskAdvertisementWatcher != null) { taskAdvertisementWatcher.Completed -= OnBackgroundTaskCompleted; taskAdvertisementWatcher.Unregister(true); taskAdvertisementWatcher = null; btnRegisterUnregister.Content = "Register Background Task"; } else { //Register the new task // Applications registering for background trigger must request for permission. BackgroundExecutionManager.RequestAccessAsync().AsTask().ContinueWith(async(r) => { if (r.IsFaulted || r.IsCanceled) { return; } if ((r.Result == BackgroundAccessStatus.Denied) || (r.Result == BackgroundAccessStatus.Unspecified)) { await new MessageDialog("Not able to run in background. Application must given permission to be added to lock screen.").ShowAsync(); Application.Current.Exit(); } // Create and initialize a new trigger to configure it. trigger = new BluetoothLEAdvertisementWatcherTrigger(); // Add the manufacturer data to the advertisement filter on the trigger: trigger.AdvertisementFilter.Advertisement.iBeaconSetAdvertisement(new iBeaconData()); // By default, the sampling interval is set to be disabled, or the maximum sampling interval supported. // The sampling interval set to MaxSamplingInterval indicates that the event will only trigger once after it comes into range. // Here, set the sampling period to 1 second, which is the minimum supported for background. trigger.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(1000); // At this point we assume we haven't found any existing tasks matching the one we want to register // First, configure the task entry point, trigger and name var builder = new BackgroundTaskBuilder(); builder.TaskEntryPoint = taskEntryPoint; builder.SetTrigger(trigger); builder.Name = taskName; // Now perform the registration. The registration can throw an exception if the current // hardware does not support background advertisement offloading try { taskAdvertisementWatcher = builder.Register(); Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() => { // For this scenario, attach an event handler to display the result processed from the background task taskAdvertisementWatcher.Completed += OnBackgroundTaskCompleted; btnRegisterUnregister.Content = "Unregister Background Task"; }); } catch (Exception ex) { taskAdvertisementWatcher = null; switch ((uint)ex.HResult) { case (0x80070032): // ERROR_NOT_SUPPORTED Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() => { await new MessageDialog("The hardware does not support background advertisement offload.").ShowAsync(); Application.Current.Exit(); }); break; default: throw ex; } } }); } }