I'm trying to implement the Apple Notification Center Service using an Adafruit Feather 32u4 Bluefruit LE to be able to receive notifications from my iPhone to the Feather board, sending them to my PC over Serial connection and dealing with them with some software that I wrote.
I set up the ANCS service and characteristics using the AT+GATTADDSERVICE and AT+GATTADDCHAR commands but when I try to make the device discoverable and to advertise the use of the ANCS service the device won't become discoverable.
This is the command that I use:
AT+GAPSETADVDATA=02-01-06-11-06-79-05-F4-31-B5-CE-4E-99-A4-0F-4B-1E-12-2D-00-D0
Where:
0x02: is the byte length of the first message in the payload
0x01: is the 'Data Type Value' and indicates that this is a 'Flag'
0x06: indicates the flag LE General Discoverable Mode without BR/EDR support
0x11: is the byte length of the second message (0x11 is 17 bytes in decimal, 1 for the type of "message "Incomplete List of 128-bit Service Class UUIDs", 16 bytes for the UUID of ANCS)
0x06: is the 'Data Type Value' for "Incomplete List of 128-bit Service Class UUIDs"
0x7905F431B5CE4E99A40F4B1E122D00D0: is the UUID for ANCS.
When I use the above command though, the device won't become discoverable. Do you know why?
While trying to troubleshoot the problem I noticed that if I try to advertise different services like an heart rate service and a device information service the device does become visible from other devices. This is the command that I used:
# Advertise as Discoverable and BLE only with 16-bit UUIDs 0x180D and 0x180A
AT+GAPSETADVDATA=02-01-06-05-02-0d-18-0a-18
Do you know why the device won't become visible when trying to advertise the ANCS service?
Thank you!
P.S. I'm new to the bluetooth protocol, sorry.
Have a look at the specification of the ANCS you provided. It states:
Only one instance of the ANCS may be present on an NP. Due to the nature of iOS, the ANCS is not guaranteed to always be present. As a result, the NC should look for and subscribe to the Service Changed characteristic of the GATT service in order to monitor for the potential publishing and unpublishing of the ANCS at any time.
Further down you find figures that show that your iPhone is the NP and it is the one that might implement the ANCS.
Your Feather board would be the Central and is supposed to look for the service and connect to it. As #Paulw stated in the comments you have it the wrong way around.
Related
According to iOS documentation, when an iOS application that utilizes BLE as a peripheral moves to background mode, peripheral name is not advertised and all service UUIDs are placed in a special ‘overflow’ area, they can be discovered only by an iOS device which is explicitly scanning for them.
I sniffed the BLE packets sent over the air when application is in background. There is no local name and service UUID data. There is an 'overflow' area which encodes the service UUID. A brief discussion can be found here: https://github.com/crownstone/bluenet-ios-basic-localization/blob/master/BROADCASTING_AS_BEACON.md
I wish to know if there is any way we can determine the actual service UUID being advertised from the data in 'overflow' area. iOS documentation states that when an app is advertising as BLE peripheral in background, another iOS app can find it by explicitly specifying the service UUIDs to scan for. So, there must be a way to figure out the actual UUID from overflow data.
Any pointers on this would be helpful.
No. The data in the overflow area is hashed (sending several 128-bit UUIDs would be much too large for an advertising packet). I don't believe the hash is documented, but I strongly suspect that it's based on a Bloom filter, so that Apple can probabilistically pack a unlimited number of UUIDs into the very limited space of an advertising packet.
The upside of all of this is that it means the data isn't there in the advertising packet (and really can't be). You will need to connect to the device to discover its services.
I have MFi device which uses BLE for control and Classic Bluetooth for audio streaming.
In the App, i use coreBluetooth framework to scan BLE and EAAccessory framework to scan Classic Bluetooth.
I don't want the BLE of target device to be connected if its Classic Bluetooth is not yet connected. So i need to know which EAAccessory is corresponding to target CBPeripheral.
I am familiar with coreBluetooth, there is UUID string to identify the CBPeripheral. But it looks not exist in EAAccessory.
I have an idea but not sure: maybe firmware side can config EAAccessory's serial number and CBPeripheral's manufacture data in advertisement data with the same
serial number, so that App side can check if they are the same.
Dose anyone knows the general way to implement this in App side and firmware side?
I really do not think there is s relationship between the 2. BT and BTLE are managed by different chip at peripheral side and phone side.
Usually in BT you use the MAC address to identify the peripheral on BTLE side the MAC address is not used anymore since iOS at the first connection give its own identifier to the peripheral.
What you can do is probably at firmware side, by exposing a service with a characteristic that somehow relate the 2.
UPDATE AFTER COMMENT
I see, as far as I know there a best practice doesn't exist.The worst part is that you have to handle connections differently, mostly due to how connection are made on iOS side. While on the BLE you can choose a not encrypted connection that would not require paring or bonding, on BT side I guess that bonding is required.
Probably the most simple flow would be, user bond the BT device. Once you are in the app and detect the connected BT device, use a scan method for detect BLE companion device by filtering for a specific service id that your device exposes, once you do that you can also filter discoveries using BLE name without still making a connection.
Adv packet are restricted in size (29 usable byte) but you can also use the scan response (31 byte), that exposes some additional properties such as manufacturer data that will be exposed in a dictionary (kCBAdvDataManufacturerData).
Once you know that is the correct device you can start a connection, that does not require pair or bond but is NOT encrypted (Pair and Bond will require the user to accept the connection inside your app).
We are developing an app which needs to scan for beacons in the background. This requires us for iOS to specify a service UUID while scanning. See Apple documentation:
Apps that have specified the bluetooth-central background mode are allowed to scan while in the background. That said, they must explicitly scan for one or more services by specifying them in the serviceUUIDs parameter. The CBCentralManagerOptionShowPowerAlertKey scan option is ignored while scanning in the background.
We are using a Raspberry Pi with a bluetooth adapter to send a beacon signal (conforming the AltBeacon spec). Unfortunately we are not able to find out how the service UUID should be set in the BLE Advertising PDU, is it part of the Bluetooth specification or part of the Manufacturer specific data structure? We did find examples for setting the service UUID for when you use an iOS device as beacon, but since we are using a generic bluetooth adapter we cannot use that.
Could anyone clarify us how and where the service UUID should be set in the beacon transmission?
is it part of the Bluetooth specification or part of the Manufacturer specific data structure?
the later.
generally when you setting the advertising parameters, you can set the UUID(or name, tx power, etc) to it.
I am using scanForPeripheralsWithServices to scan for devices by service UUID. When I use some of the standard service UUID values it will work sometimes.
When I try to use custom service UUIDs it often won't find any devices, but if I use nil for the service UUID list it will find those same devices that it doesn't find when I use their service UUID.
What is going on? Could it be because the advertising packet for the devices can only advertise some of its services?
The set of services advertised by a peripheral is typically smaller than the services it offers. This is because there is limited space in the advertisement so it makes sense to advertise only the "primary" service.
From the Apple Core Bluetooth Programming Guide -
There are also limits as to how much space you can use when advertising
data. When your app is in the foreground, it can use up to 28 bytes of
space in the initial advertisement data for any combination of the two
supported advertising data keys. If this space is used up, there are
an additional 10 bytes of space in the scan response that can be used
only for the local name. Any service UUIDs that do not fit in the
allotted space are added to a special “overflow” area; they can be
discovered only by an iOS device that is explicitly scanning for them.
While your app is in the background, the local name is not advertised
and all service UUIDs are place in the overflow area.
To help you stay within these space constraints, limit the service
UUIDs you advertise to those that identify your primary services.
As an example, a Heart rate device may offer the heart rate service, the device information service, the battery service and more, but it will only advertise the heart rate service as this is service that other devices will be "interested in" as it distinguishes this device from other classes of device.
Once the device has been identified and a connection established the other services can be discovered if required.
We need in our project to detect the proximity of an iPhone that is running a custom APP that is using Bluetooth LE.
The detector (Scanner, Central...) will be implemented using a BLE Integrated Circuit (from Texas or Nordic). I mean that the scanner is not another IOS device... running Core Bluetooth as a Central..
For the detector to guess the proximity, the idea is very simple, just advertise a service with an UUID proprietary.
While in foreground all works OK, and the UUID and a Local name are advertised (The UUID in the main advertise packet, and the Local Name in the SCAN Response packet....), and our scanner is able to decide if this iOS device is running our App.
The problem arises when going to background .....
The iOS stops broadcasting UUID and Local Name. (As the documentation of Core Bluetooth Explains... I Know...)
At this moment (Background), IOS begin to broadcast a SPECIAL MANUFACTURER DATA in the main advertise packet, and nothing in the SCAN Response packet)
The data packet we see using a Bluetooth Sniffer is :
0x14 (length of packet not including this byte).
0xFF (Manufacturer specific data AD Type).
And then :
0x4C, 0x00 (this data is the manufacturer identifier, if the packet is compliant with BLE 4.0 specification).
0x01, 0x00,0x00, 0x00, 0x00,0x00,0x80, and ten 0x00 more....
I know Apple says that while in background ONLY ANOTHER IOS DEVICE SEARCHING FOR A SPECIFIC SERVICE CAN DISCOVER IT. (Really I do not know how they can achieve that, unless they connect to the peripheral and retrieve the services, or if the peripheral knows about other IOS device is scanning because of it´s Address in the SCAN REQUEST and then changes the advertisement data in background).
The main questions are :
Is there any documentation or knowledge of what this manufacturer data means....Perhaps it would be possible to the scanner to know based on this info that this is an iOS device advertising in background and then connect to look if the custom service is there. (Not a quick and clean solution...but I do not see any other workaround....)
Does anybody worked with this scenario...and found a clean solution .....
I have heard from people that forces the application not to go to background.
This limitation, will stop a lot of possible projects.