private void Start_AppBarButton_Click(object sender, RoutedEventArgs e)
        {
            if (_periodicTimer != null)
            {
                _periodicTimer.Cancel();
                _periodicTimer = null;
            }

            // we use temporal copy of beaocnlist for testing purposes
            tmpCollection = new ObservableCollection <Beacon>();
            foreach (Beacon beacon in BeaconCollection)
            {
                // store the listening cycle, so we can show it in the results
                beacon.ListeningCycle = AppSettings.Lifecycle;
                tmpCollection.Add(BeaconFactory.DublicateBeacon(beacon));
            }

            //reset counter
            _listeningCycleCounter = 0;

            //and start the timer
            _periodicTimer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler(PeriodicTimerCallback),
                                                                 TimeSpan.FromMilliseconds(AppSettings.Lifecycle));

            //show the test overlay
            ProgressView.Visibility = Visibility.Visible;
        }
예제 #2
0
 private void CalculateDistance(int rawSignalStrengthInDBm, int measuredPower)
 {
     if (rawSignalStrengthInDBm != 0 && measuredPower != 0)
     {
         Distance = BeaconFactory.CalculateDistanceFromRssi(rawSignalStrengthInDBm, measuredPower);
     }
 }
        /// <summary>
        /// Constructs Beacon instances from the trigger data and adds recognized beacons to the _beacons list.
        /// </summary>
        private List <Beacon> TriggerDetailsToBeacons(BluetoothLEAdvertisementWatcherTriggerDetails triggerDetails)
        {
            List <Beacon> beacons = new List <Beacon>();

            if (triggerDetails != null)
            {
                foreach (var bleAdvertisementReceivedEventArgs in triggerDetails.Advertisements)
                {
                    Beacon beacon = BeaconFactory.BeaconFromBluetoothLeAdvertisementReceivedEventArgs(bleAdvertisementReceivedEventArgs);
                    beacons.Add(beacon);
                }
            }
            return(beacons);
        }
        public async void BeaconEngine_Discovered(BluetoothLEAdvertisementReceivedEventArgs args)
        {
            //System.Diagnostics.Debug.WriteLine("Found Beacon : " + args.BluetoothAddress);

            //the test is progressing, so we do minimun amount of work here
            //and simply mark the beacon we got as seen during this test cycle
            if (_periodicTimer != null)
            {
                foreach (Beacon beacon in tmpCollection)
                {
                    if (beacon.BluetoothAddress == args.BluetoothAddress)
                    {
                        if (_listeningCycleCounter < beacon.DiscoveryTestData.Length)
                        {
                            beacon.DiscoveryTestData[_listeningCycleCounter] = true;
                            return;
                        }
                    }
                }
                //if it was some beacon we do not have in our list, then we simply ignore it
                return;
            }

            //beaconlist is only updated while we are not doing test
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                Beacon beacon = BeaconFactory.BeaconFromBluetoothLEAdvertisementReceivedEventArgs(args);
                if (beacon == null)
                {
                    return;
                }

                bool existingBeaconUpdated = false;

                foreach (Beacon existingBeacon in BeaconCollection)
                {
                    if (existingBeacon.Update(beacon))
                    {
                        existingBeaconUpdated = true;
                        beacon.Dispose();
                    }
                }

                if (!existingBeaconUpdated)
                {
                    BeaconCollection.Add(beacon);
                }
            });
        }
예제 #5
0
        /// <summary>
        /// Triggered when the watcher receives an advertisement.
        /// If the advertisement came from a beacon, a Beacon instance is created based on the
        /// received data. A new beacon is added to the list and an existing one is only updated.
        /// </summary>
        private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
        {
            Logger.Debug("Scanner: Advertisement received " + args.Timestamp.ToString("HH:mm:ss.fff"));
            Beacon beacon = BeaconFactory.BeaconFromBluetoothLeAdvertisementReceivedEventArgs(args);

            if (beacon != null)
            {
                if (_enterDistanceThreshold != null && beacon.Distance > _enterDistanceThreshold.Value)
                {
                    return;
                }

                if (!FilterBeaconByUuid(beacon))
                {
                    return;
                }
                NotifyBeaconEvent(beacon);
            }
        }
예제 #6
0
        /// <summary>
        /// Starts the watcher and hooks its events to callbacks.
        /// </summary>
        /// <param name="manufacturerId">The manufacturer ID.</param>
        /// <param name="beaconCode">The beacon code.</param>
        /// <param name="beaconExitTimeoutInMiliseconds">Time in miliseconds after beacon will be trated as lost.</param>
        /// <param name="rssiEnterThreshold">Optional rssi threshold which will trigger beacon discover event. Value must be between -128 and 127.</param>
        /// <param name="enterDistanceThreshold">Optional minimal distance in meters that will trigger beacon discover event.</param>
        public void StartWatcher(ushort manufacturerId, ushort beaconCode, ulong beaconExitTimeoutInMiliseconds, short?rssiEnterThreshold = null,
                                 ulong?enterDistanceThreshold = null)
        {
            _beaconExitTimeout      = beaconExitTimeoutInMiliseconds;
            _enterDistanceThreshold = enterDistanceThreshold;
            _beaconExitTimeout      = 30000;
            if (_beaconExitTimeout < 1000)
            {
                _beaconExitTimeout = 1000;
            }

            if (Status != ScannerStatus.Started)
            {
                if (_bluetoothLeAdvertisementWatcher == null)
                {
                    _bluetoothLeManufacturerData     = BeaconFactory.BeaconManufacturerData(manufacturerId, beaconCode);
                    _bluetoothLeAdvertisementWatcher = new BluetoothLEAdvertisementWatcher();
                    if (rssiEnterThreshold != null && rssiEnterThreshold.Value >= -128 && rssiEnterThreshold.Value <= 127)
                    {
                        _bluetoothLeAdvertisementWatcher.SignalStrengthFilter = new BluetoothSignalStrengthFilter()
                        {
                            InRangeThresholdInDBm = rssiEnterThreshold.Value
                        };
                    }
                    _bluetoothLeAdvertisementWatcher.AdvertisementFilter.Advertisement.ManufacturerData.Add(_bluetoothLeManufacturerData);
                    _bluetoothLeAdvertisementWatcher.SignalStrengthFilter.SamplingInterval  = TimeSpan.FromMilliseconds(0);
                    _bluetoothLeAdvertisementWatcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(_beaconExitTimeout);
                    _bluetoothLeAdvertisementWatcher.ScanningMode = BluetoothLEScanningMode.Active;
                }

                _bluetoothLeAdvertisementWatcher.Received += OnAdvertisementReceived;
                _bluetoothLeAdvertisementWatcher.Stopped  += OnWatcherStopped;

                ServiceManager.LayoutManager?.VerifyLayoutAsync();

                _bluetoothLeAdvertisementWatcher.Start();

                Status = ScannerStatus.Started;
                Logger.Debug("Scanner.StartWatcher(): Watcher started");
            }
        }
예제 #7
0
        /// <summary>
        /// Starts advertizing based on the set values (beacon ID 1, ID 2 and ID 3).
        /// Note that this method does not validate the values and will throw exception, if the
        /// values are invalid.
        /// </summary>
        public void Start()
        {
            if (!IsStarted)
            {
                _beacon                = new Beacon();
                _beacon.Id1            = BeaconId1;
                _beacon.ManufacturerId = ManufacturerId;
                _beacon.Code           = BeaconCode;
                _beacon.Id2            = BeaconId2;
                _beacon.Id3            = BeaconId3;
                _beacon.MeasuredPower  = DefaultMeasuredPower;

                _advertisementPublisher = new BluetoothLEAdvertisementPublisher();

                BluetoothLEAdvertisementDataSection dataSection = BeaconFactory.BeaconToSecondDataSection(_beacon);
                Logger.Debug("Advertiser.Start(): " + BeaconFactory.DataSectionToRawString(dataSection));
                _advertisementPublisher.Advertisement.DataSections.Add(dataSection);
                _advertisementPublisher.Start();

                IsStarted = true;
            }
        }
        /// <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);
        }