Obtaining Major/Minor values 'without' monitoring? - ios

I am aware that monitoring is used to notify an application when it enters a specific region.
The goal is to simply set up a backend that adds +1 to a count-value that represents the amount of times a smart device entered a region. But I don't think I understood the way monitoring works yet.
If I were to set that only a certain UUID value shall be monitored, the application will be notified at any region of any iBeacon with the same UUID it enters. Is there any way to also obtain Major and Minor values of the regions withouth specifically asking for them / setting them up? It should be possible as the data payload also contains the Major and Minor values anyways?! Or would I need to specify any created beacon with their respective UUID, Major and Minor to be monitored in order to track and increase a count-value?
Let me reprhase: Is it possible to obtain UUID, Major and Minor value when entering any region without having to set up CLLocationManager or monitoring in generall (for Major and Minor) as the payload contains that information? Reading through similar topics on here suggested that in this case ranging comes into play. This got me more confused as I thought ranging only uses the measured power within the data payload to determine the aproximate distance?

Is it possible to obtain UUID, Major and Minor value when entering any
region without having to set up CLLocationManager or monitoring in
generall (for Major and Minor) as the payload contains that
information?
No. locationManager:didEnterRegion: will be called with a CLRegion object, which will be a CLBeaconRegion containing UUID, major and minor numbers, but those won't correspond to the identifier for, say, the specific beacon that caused the entry event, just to the region you've already supplied. (To be more specific, if you started monitoring just based on UUID, for example, you'll get a CLBeaconRegion with major and minor set to nil, not populated by the values for the beacon that caused the event.)
There's nothing wrong with your reasoning—the device does have the information you're interested in—iOS just doesn't make it available at the application level.
Reading through similar topics on here suggested that in this case
ranging comes into play.
Yes, you can start ranging on (or before) region entry, at which point you'll have a list of full identifiers of beacons visible in the region. There's a good answer covering this in a different question.

Related

Are iBeacon major/minor values available when monitoring a region?

I am trying to build a test app that would detect a given set of iBeacon deployed in a few physical locations. The detection should be done in the background, and make a call to a server following a certain logic.
Apple's rule of thumb is using the same UUID for all of my physical locations:
The UUID is shared by all locations.
This allows an iOS device to use a single identifier to recognize any of the stores with a single region.
Each specific store, San Francisco, Paris, and London, is then assigned a unique major value, allowing a device to identify which specific store
it is in.
I found the call for setting a region with a given UUID, but did not find what object is returned when the UUID is detected, and what fields are returned.
Where does the app get the major/minor value when iOS detects a beacon with a given UUID?
When using monitoring APIs, you only get a CLBeaconRegion object in the enter/exit callback from CoreLocation. A beacon region defined by this class typically doesn't represent individual beacons, but a range of beacons based on wildcard identifiers.
Because of this, if you use wildcards in your region definition (as is typical) you actually can't see which specific beacon triggered a region entry. To solve this problem, you must combine both monitoring and ranging APIs at the same time. If you monitor and range simultaneously, CoreLocation will give you a callback in the didRangeBeacons beacons: [CLBeacon] inRegion region: CLBeaconRegion method with an array of all the CLBeacon objects it saw.
Because the callback with the array of beacons arrives once per second, however, you will need to add custom logic to do something only once when beacon first appears, if necessary.
Since you want background detection, it is important that you do both ranging and monitoring simultaneously. Even if you don't put anything in your monitoring callback because of the lack of specific beacon information, you need to do monitoring just to get your app woken up in the background on a new beacon detection. Then, you will get ranging callbacks for approximately 10 seconds before your app is suspended again.

Estimote Repeat Notifications

I am developing an iOS 8 app with multiple Estimote iBeacons. According to (https://community.estimote.com/hc/communities/public/questions/200966066-How-detect-multiple-beacons-iOS?locale=en-us), I implemented one BeaconManager, and registered it with two BeaconRegions. However, only the second beacon region works.
Instead, I used two BeaconManagers and register one BeaconRegion for each of them. Now it works. However, a new problem occurs: in some cases when I enter or exit the region, I receive multiple notifications for one beacon, instead of only one. This link (http://beekn.net/2013/11/ibeacon-tutorial-dealing-with-errors/) says it's a bug from Apple, but I am not sure about the case.
Anyone can help?
Thanks,
Ryan
Beacon regions are shared system resources, which means that all the BeaconManagers and LocationManagers are notified about state changes of all the regions registered in the app.
Example: if you monitor beacon region A with manager A, and beacon region B with manager B, manager A will still get notifications about region B. Same for manager B and region A.
Because of that, it rarely makes sense to have more than one instance of a BeaconManager in your app.
Monitoring multiple regions should work just fine with a single BeaconManager, there must be something specific to your code that leads to one of the regions not working. If you could add a code snippet to your question, that'd probably help tracking the issue down.
As per my opinion, these should be only one beacon manager to manage all beacon.
And if you have beacon from same vendor (In your case it is Estimote iBeacons) then I don't think that you need to create more than one region here.
Because all beacons of same vendors have same proximity UUID. What is different is its Major value and Minor value.
So you can differentiate all beacons with its Major and Minor values also there is a ranging which can make a further granularity for seperation.

iBeacon region monitoring AND proximity for >20 beacons?

I have been working on a prototype iOS app utilizing iBeacons to provide location-relevant information to office employees depending on where in the office they are. The ideal use case is that whenever an employee enters or exits their office, a callback is fired which provides them some information in the form of a notification (it might make a server query to get information first, etc - that sort of thing). We also want to be able to do this when the app is backgrounded or terminated; fortunately, we already know that beacon region boundary crossings trigger the appropriate CoreLocation callbacks even if the app is backgrounded or suspended.
From looking around, I understand that broadly, I have two options for how to approach the beacon region monitoring:
Give each iBeacon its own CLBeaconRegion, and monitor for each of these regions independently.
Monitor for CLBeaconRegions that correspond to multiple iBeacons - for example, each iBeacon has the same UUID and only monitor for a CLBeaconRegion corresponding to that UUID - then try to determine which beacon triggered the boundary crossing using ranging.
Thus far, I had chosen option #1. The advantage of this approach is that I get didEnterRegion: and didExitRegion: calls for each individual beacon and immediately know which beacon I have entered/exited. Also, I only get one enter call and one exit call, which is exactly what I want. Unfortunately, I just realized that this approach also limits me to 20 beacons (since each beacon gets its own region).
I'm not as familiar with the exact implementation details of #2, so correct me if I'm wrong. But it seems that this approach has more drawbacks:
Apple discourages ranging when the app is in the background because the results may not be as accurate.
The ranging calls fire once every second, while I only want to have "enter/exit" callbacks.
If the beacons have region overlap, the ranging calls might continually flip which one is "closest", which would further complicate things.
Basically, I'm wondering if there is a way to utilize option #2, but still have the benefits of option #1 - a quick and easy way to immediately determine which beacon triggered the region change with only one enter or exit callback?
I hope this question is clear enough. It's not all entirely clear in my own head, especially how ranging works.
Option #2 is absolutely more complicated, but you must accept these complications in order to get around the 20 region monitoring limit.
A few points:
In the background, you only have around 5 seconds of ranging time, which does not give you as much time to average RSSI (signal strength) from each beacon to get a good distance estimate. So, yes, the estimates will be less accurate. If you understand this limitation and can live with it for your use case, there is nothing wrong with ranging in the background.
Yes, you will get multiple ranging calls per beacon after region entry, and you won't get any callbacks on region exit. You have to write extra code to take care of this. I have done this by maintaining a NSMutableArray of all the unique beacons (same uuid/major/minor) seen and update it in the ranging callback. You can then access this array in the region exit callback, so you know which beacons disappeared. Of course, it is possible that additional beacons were seen after the 5 seconds of background ranging time expires, but your app will never know about them. With this option, you must accept this limitation.
While it is true that errors on the distance estimate in ranging may incorrectly tell you which beacon is closest, you have an even worse problem when doing monitoring, because you don't get a distance estimate at all. If multiple beacons come into monitoring range around the same time, there is no guarantee that the first entered region callback you get will be for the closest beacon. So if your use case requires taking action based on the closest beacon, then you must do ranging (knowing that there may be error on the distance estimate.)
The drawback of the second approach is detecting the entry of a particular beacon will be purely based on ranging, that will not work if the application is killed. The reason is we will get didEnterRegion only once, because we are monitoring only one region with a particular UID. The next beacon with same UID will not be detected again if the application is terminated or if the background ranging stopped.
I recommend a combination of the mentioned approaches ,
Use same UID for all the beacons.
A beacon is uniquely identified using major/minor value that is collected when ranging.
As mentioned in apple doc, always keep number of monitoring regions below 20 by removing and adding beacons when the user moves from beacon to beacon (better to keep a beacon neighbour relationship graph in the server.)
Start ranging when entering the region ... and identify major/minor and calculate proximity.
Stop ranging when exiting the region.
Find the closest beacon from ranging method (need to skip unknown range beacons).
Monitor only the neighbours of the closest beacon in a given time.
When implementing both options, We should consider one fact, An iBeacon will be detected in 200feet distance. There may be multiple beacons in 200feet range.
If you use the same UUID for every beacon, you can just set the major/minor numbers to differentiate between the different beacons. This way, you are only monitoring for 1 beacon instead of > 20. Then just sort out which one is which from the other identifiers. This is how it works currently with Starbucks and other retailer apps. 1 beacon no matter where you are in the world, and different identifiers to sort things out on the back end.

How to Handle the iBeacons overlapping eachother

I have created a app for detecting the beacons. things are going on good. the problem that I have is:
When there are more beacons overlapping on one another. how am I suppose to handle the situation considering the case
1. When we want to receive the offer only once from a particular beacon on entering to the beacon/we are in the place where we have more than one beacon overlapping each other.
Thanks,
When you have overlapping iBeacons, it is important to design the iBeacon identifiers (UUID, major, minor) and the CLBeaconRegions you use to monitor them so that you get the results you want.
Do you want to trigger "the offer" whenever any of the overlapping iBeacons are detected? If so, then monitor for a CLBeaconRegion that matches them all, probably by setting just the UUID (and maybe the major if all beacons share that value.) In this case, you will only get one Region entry notification when any of them are detected. You won't get one for each overlapping iBeacon.
If you only want to trigger "the offer" when a single one of the overlapping iBeacons is detected, then monitor for a CLBeaconRegion that only matches that one iBeacon, typically by specifying the UUID, major, and minor in that CLBeaconRegion. Of course, you also need to ensure that each iBeacon is configured with a different minor. Remember, too, that you can monitor for multiple CLBeaconRegions simultaneously, if needed, and get a specific callback for each one.
While it a separate issue from overlapping iBeacons, if you really want users to "receive the offer only once", you also need to add a filter to your detection callback. A glitch in iOS sometimes gives you a very quick exited region callback followed by an almost instantaneous entered region callback. In order to prevent users from getting the offer a second time, store off the timestamp of the last time the offer was pushed to the user, and only push it again if enough time has passed (say 1 hour or one day.) See this answer for details.
My workflow at the moment is to detect in the didRangeBeacons method the Beacon which is the closest to my actual position. This is done by comparing for each beacon the rssi property.
After identifying the closest Beacon I process the desired action for this beacon.
To avoid that this action is triggered repeatedly (beacause the didRangeBeacons method is triggered a couple of times per seconds) I implemented an isLocked Flag (BOOL) in my actual beaconHandler, which does the processing.
So I only react to the Beacon which is the closest to me. And I only react once. I also keep track of my last beacon which I identified as closest. This enables me to react immediatly, If you are getting in Range of another beacon. So e.g. when you walk along a store, every beacon is triggered immediatly, but not repeatedly.

iBeacon, Bluetooth BLE and fleet management

From what I have understood, minor and major ids in beacons are used for segmentation (for instance, major for physical stores and minor for different locations within a given store).
Then, as a beacon does not deliver rich payload, I guess those ids will be exploited to deserve the adequate information to the user - and probably through webservices.
Finally, UUID are said to be for the whole fleet. From what I understand, an app (e.g for retail store) is likely to register for only one or a few UUID (generally one, more for complex architectures or overload of services).
At the application level, you can (1) range for beacons when the app is foreground (with catching capabilities for minor/major ids), and (2) detect region exit/entry (monitoringForRegion:) while in background + deliver UILocalNotification to wake up the app (going back to (1)).
Now lets deal with the end user. I think we can assume that the average one will not go through a whole retail store with the app in foreground in his hand, and is more likely to have it running in background.
Consequently, case (2) will be the most common one.
But as all emitters will share the same UUID and as the geolocation manager running in background is monitoring for region linked to UUID, didEnter and didExit regions delegate methods risk no to be triggered intelligently depending on the range/configuration of emitters. Finally, not all the indoor location-based advertising you wanted to broadcast to your customers will be received and catched.
In fact, I fear that only the one when the customer will arrive at the store location will be systematically suggested (in a background mode context).
Am I missing something?
You are mostly right. The one thing you are missing is that you can monitor on 20 different regions simultaneously, and these regions can optionally include the major and/or the minor. So you could trigger many times in a (big) store by intelligently designing your iBeacon identifiers and region monitors.
Two caveats: in-region monitoring callbacks fire when the beacon first comes into range (about 50m). They are also not simultaneous. They can take up to 15 min on an iPhone 4S with the app in the background, although it is faster on an iPhone 5.
To phrase what David said a little differently:
You can define a beacon region using a UUID, a UUID and a major value, or a UUID + a major and a minor value.
If you define a region using just the UUID, any beacon with that UUID will trigger a didEnterRegion message, and the OS will treat all beacons with that UUID as part of the same region.
However, if you create a region with UUID+Major, or UUID+Major+Minor, only beacons matching those values will trigger a region notification. You can have 2 beacons with the same UUID and major value right next to each other and different minor values. If you've registered 2 different regions with specific UUID+Major+Minor value, you'll get independent enter/exit/ranging messages about each region. A third beacon with the same UUID and major value but a different minor value will not trigger enter/exit notifications.

Resources