I am developing a beacon detection application and at the moment works very well for kontakt brand beacons.
The client has sent me some new beacons that i have never seen and I have searched with google but i can't find what brand they can be.
The following information related to this beacon they gave me:
uuid: fda50693-a4e2-4fb1-afcf-c6eb07647825
pass: 000000
name: ion_beacon00021
major: 16789
minor: 24532
I have transformed my code to monitor both uuid without making it work
for (index, beaconID) in beaconsIds.enumerated() {
let beaconUUID = UUID(uuidString: beaconID)!
let identifier = "BLERegionBeacon \(index)"
let beaconRegion = CLBeaconRegion(proximityUUID: beaconUUID, identifier: identifier)
self.locationManager?.startMonitoring(for: beaconRegion)
self.locationManager?.startRangingBeacons(in: beaconRegion)
}
func configureLocationManager() {
self.locationManager = CLLocationManager()
self.locationManager!.delegate = self
self.locationManager!.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager!.distanceFilter = kCLDistanceFilterNone;
self.locationManager!.activityType = CLActivityType.automotiveNavigation;
for region in self.locationManager!.monitoredRegions {
self.locationManager?.stopMonitoring(for: region)
}
if CLLocationManager.authorizationStatus() != CLAuthorizationStatus.authorizedAlways {
self.locationManager?.requestAlwaysAuthorization()
}
self.locationManager!.startUpdatingLocation()
}
When not finding how to make this new ibeacon work I have resorted to third party applications (like MyBeacon, Detector, Beacon Demonstrator, Locate) to get validate if the information I have of this beacon is correct, but in no application I have been able to make it detect this ibeacon.
I bought a new battery to make sure it was not as simple as that, but neither. :'(
I had the idea to use any application that detects bluetooth devices and I found BLE Scanner. With this application i was lucky and could realize that at least the name that i have of the beacon is correct, but not found any related to major or minor or pass. I also thought that the long id seen there could be correct and that the I had was not... But I discarded it because when I connected the brand kontakt also gave me a different uuid.
ISCONNECTABLE Jumps between YES and NO.
When i use BLE Scanner to detect beacons Kontakt show me addional info called SERVICEDATA and ISCONNECTABLE still in YES.
- Is there anything else that needs to be done to detect these beacons?
- Anyone have any idea what may be going on?
Thank you very much
EDIT
Following the help of davidgyoung, I could realize that the Locate application if it works but only in its version for android. And in fact correctly returns the information I had been given from that beacon at first.
I found that these beacons with configurable using an application called BeaconFlyer and there I realized the reason for being that password that had sent me. I was able to change the uuid although strangely I just put numbers and no letters. I changed it by 32 zeros following the same pattern of 8-4-4-4-12. I still get no results in IOS but works on android, even after changing the uuid.
It is possible that some brands need to be certified to be detected by iOS devices and that the android do not have these restrictions.
EDIT 2
Considering all these details, it seems that the problem is IOS and not android, so it occurred to me that maybe if I created a simple android project just to test the functionality of the beacons, I should be able to detect it.
The test was done by registering this UUID f7826da6-4fa2-4e98-8024-bc5b71e0893e which is the one that has always works for me and with which I detect without any problem the beacons markkontakt.
To my surprise I detect it without problem even without registering the UUID that I have for this brand. It is very strange considering that only register 1 UUID that was the mark kontakt
If you are detecting another beacon with the same code, then the simplest explanation is that the ProxmityUUID you were given is wrong.
You won't be able to determine the correct ProximityUUID from BLE Scanner on iOS, as iOS blocks access to iBeacon advertisements unless you know the ProximityUUID up front. If you can get your hands on an Android device you can use the Locate app to see any beacon regardless of its identifiers. https://play.google.com/store/apps/details?id=com.radiusnetworks.locate&hl=en You can use this to find out what it is actually sending. There are similar apps for MacOS as well if you have access to a Mac.
It is quite clear that your client sent you "beacons" and not necessarily "iBeacons". As davidyoung pointed out, what constitutes an iBeacon is specified (quite strictly) by Apple. Download the specs from there and have a look, if you are so inclined.
I have used several BLE scanners to check what uuid, major, and minor numbers various brand iBeacons I worked with have, among them the mentioned BLE scanner. I think the specification does not prevent somehow putting additional services into an iBeacon, which results in different brand iBeacons potentially showing slightly different info in different scanners.
However, what you show in the screenshot and the fact that the isconnectable field switches values make me think that these beacons are not correctly working.
There will be no way to make them work on iOS that way then. You can write your own Bluetooth protocol code to do stuff with them, but that then won't rely on Apple's iBeacon mechanics. This will mean the nice stuff like region monitoring even while the app is suspended and so on won't work. It's also probably more battery draining and in general more work.
I am as said not a Bluetooth expert, but learned this much: UUIDs are all over the specs. The UUID you (and Apple) refer to is a part of the data packet the iBeacon is supposed to send, but I have also seen BLE services in general being identified by UUIDs in (non-Apple) reference documents. This can get confusing when you scan such a beacon and see UUIDs (or at least strings that look like ones) in several places. So even if the beacons you have follow the spec (or can be configured to do so somehow) my guess is that someone screwed up. For example, they could have edited (maybe even with a hardwired connection and tool) the wrong UUID, not setting the one you need to use, but accidentally overwriting the part that specifies the device as an iBeacon (byte 5 and 6 of the data packet come to mind), making it impossible for you to use them.
As an advice I would suggest the following: If your client is interested in actual iBeacon functionality, tell them they should buy correct beacons. the kontakt ones are actually quite good. I've tested cheap china knockoffs and would advise against those, as they quickly become unreliable. It might be tempting to save a few bucks at first, but if you need to constantly replace beacons in the long run that becomes more expensive in the end.
One other theory about what might be happening:
A beacon advertisement packet implementing iBeacon must have Apple's manufacturer code 004c in order to be detected by iOS. Android has no such restriction. If this beacon is sending a different manufacturer code it would explain why only Android can detect it.
How do you find out if this is true? You need to see the raw bytes of the advertisement somehow.
The beacon brand is Iotton and it's looks like the one we sell:
https://www.beaconzone.co.uk/ibeacon/ton9108
It's unlikely the Kontakt app is showing the Iotton beacon because the local name is incorrect. It's more likely your Kontakt beacon - turn it off for now. With this or any beacon, the best app for getting the UUID and seeing if the beacon is working is Nordic nRF Connect.
Are you sure you have set the delegate on CLLocationManager? The code doesn't show it, so unless this is somewhere above or below, you'll need to add:
self.locationManager?.delegate = self
Then make sure your class implements CLLocationManagerDelegate the didRange(beacons: region:) method to get callbacks.
If you think you already have this set up, showing that code might reveal something else that is missing preventing it from working.
Related
I have played around with Airlocate and two iPhones. Also between a Linux /hcitool beacon transmitter and Airlocate ranging. I see that the set of proximity UUIDs to be tracked are hardcoded in the Airlocate source code.
Is it possible for an iOS app to get a more generic call back , when it is in the vicinity of any iBeacon (any proximity UUID) and let that app decide how to go about behaving the way it wants.
I understand that this should definitely be possible from the OS perspective, as I see a 9 byte iBeacon prefix in the start of the PDU, which is independent of the proximity UUID.
Another query - I view hardcoding the proximity UUID in the APP as some sort of pairing . How is general bluetooth pairing different from this.
My aim in asking these questions is to understand the feasibility of using beacons to beam (broadcast) data, so that all recipients in the vicinity can receive it. If I choose to go with a specific 16 byte proximity UUID, then I am left with only 5 bytes (Major/minor/power) to beam data. Otherwise I get 21 bytes
By "more generic call back", it seems like you are trying to listen to iBeacons that are not deployed by you. The answer to this is NO, you can't do that.
According to this post:http://beekn.net/2013/10/ibeacons-can-my-ios-app-find-beacons-that-arent-mine/ , in order to listen to an iBeacon, you must know its proximityUUID first.
Unfortunately Apple decides to limited your ability to do that. CoreBluetooth framework can detect iBeacon nearby but since it only returns the device UUID, not the proximityUUID, you cannot add callback to them.
And Android can read the proximityUUID of any iBeacon without any problem.
I have an app that connects to a CC2541 over Bluetooth Low Energy. I simply want to cache something unique to each device so a user only connects to "their" device. I've tried using
- (NSArray *)retrievePeripheralsWithIdentifiers:(NSArray *)identifiers
and even scanning and comparing the UUID's of the scanned peripherals, but I have to select a newly generated UUID every few app launches. The same code worked well on 8.1 and I rarely (if ever) had to select a new UUID.
I've debated checking the System ID (2A23 uuid) in the Device Information service, but that requires a connection to check the address so I'd have to connect to each nearby peripheral, get and compare the System ID, then either stay connected or disconnect and check the next one.
The CC2541 code I'm running isn't using pairing and I'd like to keep it that way. I'm curious if anyone else has found a solution to this situation.
Having been down this road, spending weeks to find a work-around to the limitations, the only way I have found is if you have control over the hardware and can put your own unique identifier in the advertising packet. While one can make all kinds of assertions about the (in)sanity of this, it is what it is.
I just want to post some code here that may help others in the future.
Put this somewhere outside of a function:
__xdata __no_init uint8 BT_MAC_ADDR[6] # 0x780E;
Put this in your advertData array:
7, //length of data
GAP_ADTYPE_MANUFACTURER_SPECIFIC, //Custom data
0,0,0,0,0,0, //Placeholder bytes
And finally update the advertData before you call GAPRole_SetParameter.
uint8 advertSize = sizeof(advertData);
memcpy(&advertData[advertSize-6], BT_MAC_ADDR, 6);
When you set up an iOS device as a beacon (peripheral role), you can query its state by calling CBPeripheralManager.isAdvertising. I can't find the equivalent to query whether a device is scanning for a beacon (central role) on CLLocationManager. Any ideas?
Update:
Given David's answer, I encapsulated the code setting up the CLBeaconRegion with the specific UUID and added a boolean variable which is changed when calling startMonitoringRegion and stopMonitoringRegion on CLLocationManager.
I do not believe there is any way this is possible. Even though CoreLocation's iBeacon APIs use Bluetooth LE and CoreBluetooth under the hood, Apple appears to have gone to some lengths to hide this implementation. There is no obvious way to see whether a Bluetooth LE scan is going on at a specific point in time.
Generally speaking, a Bluetooth LE scan is always going on when an app is ranging for iBeacons in the foreground. When an app is monitoring for iBeacons (either in the foreground or background) or ranging in the background, indirect evidence suggests that scans for beacons take place every few minutes, with the exact number ranging from 1-15 depending on phone model and state. I know of no way to programmatically detect the exact times when this starts and stops, although it can be inferred by iBeacon monitoring entry/exit times. If you look at the graph below, the blue dots show the inferred scan times for one particular test case. Details of how I inferred this are described in this blog post.
I'm working on an app that needs to have the ability to locate other iphones nearby. Precise location isn't necessary, but they should be in a 30ft radius.
Note: all of this has to happen in the background.
The options, as I see it, are:
Use Bluetooth. Develop a BT connection protocol that allows the app to send and receive data (just text) in the background. I would use iBeacons, but I understand they cannot transmit/advertise in the background.
Use GPS: This works in the background, no problem. However, the accuracy is sketchy, and in doors its much worse.
The questions I have, for the more experienced ios programmers, are this:
Does an app that uses bluetooth, or any kind of bluetooth, always need to have the bluetooth on? And can it request that the user do so?
If iPhone GPS gets the location wrong, does it show the same wrong location on another iPhone right next to it? I have no need for the actual position of the user...if the locations are "wrong" but they are the same I can tell they are close and that's enough for me.
Any help at all would be appreciated! Thanks!
#1,
Bluetooth : scanForPeripheralsWithServices method returns list of nearby bluetooth enabled devices.
Refer: [https://developer.apple.com/library/mac/samplecode/HeartRateMonitor/Listings/HeartRateMonitor_HeartRateMonitorAppDelegate_m.html][1]
#2, In indoor, GPS returns Last known location until it will get new location
We are looking at ordering some iBeacons from Roximity but I am not clear if we have to use the Roximity SDK with these beacons or if I can use the core location functionality?
The reason I am asking is that I do not want to get tied to their SDK and then have to always buy beacons from them.
I was able to get the UUID of the Roxmity beacon, but I do not know what the beacons "identifier" is, so in the case of this code:
[[CLBeaconRegion alloc] initWithProximityUUID:_uuid identifier:#"COM.TEST.APP"];
I do not know what to put in place of COM.TEST.APP
I received some Roximity beacons yesterday, and used them successfully without the Roximity SDK. The UUID that our beacons had was:
8DEEFBB9-F738-4297-8040-96668BB44281
We found the UUID by scanning with a Mac app we wrote that finds any beacons in the local area. Simply create a CLBeaconRegion with that UUID and start ranging, and they should show up. Make sure you've removed the plastic isolator tab from the battery.
As #davidgyoung mentions below, the identifier parameter won't affect whether you can detect the beacons or not.
The identifier you mention in this line of code does not affect the ability to detect an iBeacon, Roximity or otherwise:
[[CLBeaconRegion alloc] initWithProximityUUID:_uuid identifier:#"COM.TEST.APP"];
The "COM.TEST.APP" identifier is just a reference string for you as an application programmer. By using this same string when constructing a second region, you are telling iOS that these are the exact same region. This is useful for canceling monitoring or ranging. It is also useful for replacing one region with another using the CoreLocation APIS.
As long as you keep it consistent for these purposes, that string can be whatever you want.
As for the bigger question if you can use their beacons independently of their SDK, try detecting their beacon with my free Locate for iBeacon app in the AppStore. You have to add the Roximity UUID to the configuration list, but once you do so, if the app is able to locate it, that means it is compatible with standard CoreLocation iBeacon APIs.