I am currently writing an application that uses BTLE to pass small strings of data between 2 or more phones.
Currently in the foreground I am passing though: CBAdvertisementDataLocalNameKey and CBAdvertisementDataServiceUUIDsKey. I am able to recover (via NSLog) the string passed through the CBAdvertisementDataLocalNameKey when the app is in the foreground.
However when the app is in the background, the CBAdvertisementDataLocalNameKey is not passed through. The BTLE UUID is still passed through along with the RSSI integer, the CBAdvDataChannel and the CBAdvDataIsConnectable.
After combing through what seems to be an unending circle called Apple Documentation, I have found no way to pass a small string while the app is in the background. It seems to me that they wouldn't allow BTLE in the background if there was no way to pass data.
My question is does anyone know a workaround to pass data in the background with BTLE or a method that may allow me to do so? Any help or tips would be appreciated.
Edit: I should make clear that the Library I am trying this with is called Vicinity https://github.com/Instrument/Vicinity which uses CoreBluetooth to get around the background limitations of CoreLocation.
You might get some use out of this project, which lets devices share arrays of strings (such as userIDs) over Bluetooth LE, even while backgrounded: SimpleShare
It can still share data while the app is in the background because it only sends the data when a device subscribes to the advertised bluetooth characteristic by changing the characteristic's value to send each piece of data. You don't need the name key to transfer the information.
Hope that helps!
iBeacons are not made for transmitting data between two devices. BLE beacons are used to determine the current location of an iDevice. to unique identify the beacon it broadcasts the advertising data, wich contains an uuid(32 hexdigits), a major(4 hexdigits) and a minor number(4 hexdigits). thats all. if you want to transfer data you have to use any other service.
Related
I work on iOS application which is using BLE for communication with our custom made BLE unit.
We want to send specific commands via BLE to the unit automatically.
When user is near unit and specific criteria are met, the app should connect to the unit, "login" the user, send command via BLE and disconnect right away.
These specific criteria are based on manufacturer data from advertisement (i.e. the unit is in "available to login" state when manufacturer data has last byte 0x01, when it's "NOT available to login", last byte is 0x00).
In foreground, this mechanism works flawlessly.
We want to do this even when app is in background or terminated (swipe up in dashboard on iPhone).
The mechanism we have implemented:
the unit has capability of acting as iBeacon
when unit is NOT available for login, the iBeacon is OFF
when it IS available for login, the iBeacon will turn ON and wakes up application, upon that the BLE scan will start in background mode
background mode setting is bluetooth-central
Problem here is that no matter what I tried, the advertisement:
sometimes it's not discovered at all (looks like it's timing issue?)
when it's discovered, it does NOT contain manufacturer data
Did anyone come across something similar?
Any help is appreciated and have a nice day!
An app simply cannot read raw BLE manufacturer advertisement data when in the background on iOS -- the operating system prohibits it.
Two exceptions to this rule:
iBeacon, which itself is implemented as a specific type of manufacturer advertisement. An app can detect iBeacons in the background on iOS, although only four bytes of readable data (encoded in the major and minor fields) are fully usable. If you can modify your device to send information this way, it will do what you want. However you must use CoreLocation APIs to detect iBeacon, as CoreBluetooth does not allow reading manufacturer data from iBeacon advertisements. If you do use CoreLocation, you cannot use the detections to establish a Bluetooth connection with CoreBluetooth as the two APIs are sandboxed.
Overflow Area advertisements. Backgrounded iOS apps can read these special types of manufacturer advertisements when in the background but only if the screen is turned on. (It is often possible to force the screen on at specific times by sending a local notification.) See my blog post here for more info: http://www.davidgyoungtech.com/2020/05/07/hacking-the-overflow-area
An alternative to detecting manufacturer advertisements is to use BLE Service advertisements with attached data. For this to work, you'd need to define a 16 bit or 128 bit GATT Service UUID and send out an advert with attached data bytes. Eddystone beacon formats work this way, and allow detection in the background on iOS. This is probably the best approach if you can alter the BLE hardware.
I'm writing a suite of Bluetooth Low-Energy app for iOS 7.
When the app launches, there's a fair chance the peripheral I'm interested in is still connected to the iOS device, and to avoid scanning for the peripheral it would be great to connect immediately. retrieveConnectedPeripheralsWithServices: looks perfect for this, and indeed seems to work as advertised: I get a list of CBPeripherals which are connected to the device via some backgrounded app.
So far so good, but here's the issue:
There's information in the AdvertisementData which I want, but I don't know how to get the AdvertisementData when going this route.
As far as I can see, advertisementData is only available as a result of scanning.
So my question is this:
* Given a CBPeripheral returned by retrieveConnectedPeripheralsWithServices:, how can I get the associated advertisementData for that peripheral ?
One workaround would take advantage of the fact that the device was likely connected to another of the apps in my own suite, so I could persist the advertisement data myself in storage shared between the apps, but this is neither clean nor ideal, because there's a chance the device was connected to someone else's app, and so I'd have no insight into the advertisement data in that scenario, and would need to resort to a scan.
Unfortunately, the advertisement data is available only if you scan. It is not possible to retrieve it from Core Bluetooth or any other framework in any other way. You should revise your design if the advertisement is so important and rather go along the scanning route.
When you start advertising a CLBeacon with peripheral data, can you pass in a NSString or UIImage into this dictionary that you could then have show up when the beacon is discovered?
For example, if I wanted to create write a message to a friend and then when the friend entered the beacon area, could I have the message show up on their phone by storing the message in the NSDictionary and then extracting it? If so, how? If not, is there another way?
Thanks!
So you are asking if you could add extra information to the beacon advertisement that's sent by a beacon device that a custom application could look for?
The answer is no. The iBeacon protocol is a very short, fixed packet of data. There's no facility for adding extra information to the packets.
You could design and implement your own BLE service that's an alternative to iBeacons and implement it on both the transmitter and the receiver.
You could also use a hybrid approach, where you use standard iBeacon discovery to find beacons, and when you detect a beacon you're interested in, trigger a 2-way BLE conversation with the beacon and ask it for additional information. It's my understanding that some of the BLE devices that are being sold as iBeacons can run custom software that would implement this sort of thing. (Many of these devices have ARM processors in them, the same family of chips that power iOS devices.
No, you cannot do this. iOS-based iBeacons (like all other standard iBeacons) will only transmit a three-part identifier and a transmitter power calibration value. That's it. You cannot transmit anything else.
Even if you did make a custom Bluetooth LE advertisement that sends additional data besides the standard iBeacon fields, you wouldn't be able to see this data with the standard APIs for seeing iBeacons.
If you want to tie other data to an iBeacon, you have to do it through another channel, by some kind of lookup that matches the data up with the identifiers above. Three common ways to do this:
Hard-code a static lookup table in your app.
Use a Web Service to look up the value based on the iBeacon identifiers.
Fetch the data directly from a (non-standard) iBeacon using a secondary BluetoothLE communication channel.
My company has a web service called ProximityKit that makes it easy to tie data to iBeacons in your app. You log into a web interface to type in key/value pairs to associate with each iBeacon, then the included iOS client library automatically gives you those key/value pairs when the iBeacon is visible.
I want to advertise a single id lets say "stackoverflow1" on a ble device. So people close to the sensor can get this message (welcome to wwdc2012) as popups on the iPhone. That's it! meaning that there is no update on the value or anything else in other words I just want to know which room I came in. In another room there's another sensor adversing "stackoverflow2".
Now the question is, should I put the rooms' sensor (advertiser) as Peripherals and visitors' iPhones as Centrals?
If your answer is yes, can I send this Id in advertising packet? i.e. can I skip connection to the room's peripheral? Please guide me a little but on this
Thanks
Yes, the iPhones should be centrals and the in-room device should be a peripheral. It's perfectly fine to put enough data in the advertisement that the iOS app can do something useful after simply seeing the peripheral advertised without actually connecting to it. That way, multiple centrals/phones can detect proximity at once without a single phone tying up an exclusive connection to the device. Instead of specifying the room in the service name, you should be able to put it in the advertisement data for the device, giving them all the same service name. That way the iOS app doesn't need to know the completely list of rooms (i.e. services) in advance and they can be added to without changing the app.
In short, the gist of what you described should work fine, and seems like a sound approach to me.
You can include information in the advertisement from the peripheral as "Manufacturer Specific" data. Then the iOS application can get it from the advertisement data dictionary using the CBAdvertisementDataManufacturerDataKey.
I'm developing an iOS app with an accompanying Bluetooth LE peripheral. The one step I don't seem to be able to solve is how to actually transmit the data from my app to the peripheral or vice versa.
What I've built so far is a test app that can connect to my sample Bluetooth peripheral, and read all of its services/characteristics/descriptors. It can toggle notifications for a given characteristic, and write to given characteristics. It is just this last step of "transmit n bytes to the peripheral, and receive m bytes from the peripheral" that I can't seem to figure out.
Looking at the External Accessory Framework (what I would use if Apple would actually give me MFi approval for this project), they give you input and output streams on a given session to communicate with the accessory, but no such object exists for CoreBluetooth.
Is this simply an oversight on Apple's part on the functionality of CoreBluetooth? Or do I simply need to develop my own Bluetooth service profile to handle the inflow/outflow of data to and from the peripheral?
LE is fundamentally designed to work with these GATT based profiles, which are suited for monitoring sensors, not for data streams. While LE does allow for additional L2CAP streams to be opened for custom protocols, Apple's CoreBluetooth doesn't provide access to do so.
You can build a custom profile with private services and characteristics and have it work kind of like SSP; that's the way I'm using my BLE module to get data from some sensors to my app. The module I bought (Microchip's RN-4020) already has a custom profile made specifically for this known as MLDP (Microchip Low-energy Data Profile).
The way I get the data in my iOS app is by subscribing to the private characteristic, thus being notified when the values are updated. So far it has been working great, and the data rate can go up to 20 kbps according to Microchip (I haven't tested its limits, since I don't need much speed). Here's a link to Microchip's product page: http://www.microchip.com/wwwproducts/Devices.aspx?product=RN4020
Good luck!
You can use the bluetooth.org 'Immediate Alert Service' uuid=1802 with characteristic uuid=2A06 with property=write_no_response to send one byte values to your peripheral device from your iPhone. The peripheral device must be programmed to act on the data that is sent. For example, you might use a button on an iPhone app to send a hex address that causes one or more port pins to turn on or off on the peripheral. While this is not using the Alert Service as it was intended, it does provide an easy way to test out data transfer to a peripheral device. The same process could be used to send sequential data bytes similar to a serial data stream. I have not yet tried sending more complex data streams. The write_no_response does not provide any feedback to the app as to whether the data was received by the peripheral.
The IOS TemperatureSensor.xproj is an example of code for reading temperature data from a peripheral. The OSX HealthThermometerClient.xproj has the code needed to decode the somewhat complex thermometer data structure. The IOS TI-BLE-Demo.xproj TIBLECBKeyfob.m has code for reading and writing characteristic values, such as, reading temperature or battery levels from a peripheral device.