I have been searching through stackoverflow; however, I seem to have found various conflicting answer's to questions regarding this. Given Android 5.1.1 and iOS 8.4.1 what is the maximum amount of bytes that can be sent through a connectionless BLE service to one another. It is my base understanding that it should be 20 bytes from BLE Specficiation(actually 23); however, I have seen queries where iOS was able to push 512 and android was able to increase it's MTU.
Also if it is possible to send more than 20 bytes in a connection would they all be recognized correctly at the scanners on iOS and android with a cross-platform application when it is receiving the packet's without direct connection?
Per Apple's Best Practices for Setting Up Your Local Device as a Peripheral:
Although advertising packets in general can hold a variety of
information about the peripheral device, you may advertise only your
device’s local name and the UUIDs of any services you want to
advertise. That is, when you create your advertising dictionary, you
may specify only the following two keys:
CBAdvertisementDataLocalNameKey and
CBAdvertisementDataServiceUUIDsKey. You receive an error if you
specify any other keys.
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.
Note: These sizes do not include the 2 bytes of header information
that are required for each new data type. The exact format of
advertising and response data is defined in the Bluetooth 4.0
specification, Volume 3, Part C, Section 11
If you use an unregistered 16 byte service UUID, I think that's going to give you about 12 bytes of data.
Available bytes in an advertising packet will differ from available bytes in a payload packet.
Related
Anyone know how can a short String or byte array could be transmitted via BLE on iOS without having to pair?
According to my research the only 2 keys allowed for startAdvertise method are CBAdvertisementDataLocalNameKey and CBAdvertisementDataServiceUUIDsKey.
https://developer.apple.com/documentation/corebluetooth/cbperipheralmanager/1393252-startadvertising
I also thought I could use
CBAdvertisementDataServiceDataKey: String
A dictionary that contains service-specific advertisement data.
to attach the data but that seems like another dead end WARNING: The advertisement key 'Service Data' is not allowed?
Unfortunately, you cannot use CoreBluetooth APIs to attach data to advertisements. On iOS the CBAdvertisementDataServiceDataKey is read-only. While Bluetooth LE allows attaching service data , Apple effectively disallows 3rd party apps from doing this.
You do have a few options:
Encode your data inside a 128-bit service UUID and advertise that. You will need to reserver a byte or two in the UUID to know that it is "your" advertisement, and therefore OK to decode the data from the other byes. This full UUID will only be advertised when your app is in the foreground visible on the screen. Let it go to the background or the screen turn off, and it will no longer advertise in that form. Similarly, receiving iOS devices must also be in the foreground with the screen on. This is because iOS disallows getting background scan results without specifying the matching service UUID up front. And because you are dynamically manipulating some of those bytes, you don't know what it will be.
Do a similar kind of encoding with the 4 byte major and minor fields inside the iBeacon BLE advertisement using CoreLocation. Again, this allows you to transmit only when the app is in the foreground. Receiving, however, can happen to a limited degree in the background (for 5-10 seconds after one of your beacons first appears when combining monitoring and ranging APIs.) The big disadvantage is you only have four bytes to work with.
Advertise data by manipulating the 128-bit background BLE Overflow Area Advertisement. This technique is more advanced, but advertising works in the background. Receiving works in the foreground, and partly in the background -- you can receive if the screen is at least turned on. You can read more about this technique and access free sample code in my blog post herehttp://www.davidgyoungtech.com/2020/05/07/hacking-the-overflow-area.
I have a Hardware device with Bluetooth LE version 4.2, and it can send the data packets with the payload of 251 bytes. But the i will be receiving the data through a mobile app(Android & IOS), and mobiles will have different Bluetooth LE versions like v4.0, v4.1 or v4.2.
Assume my hardware device acts as Master and the mobile acts as slave. And here master does not know the slave's Bluetooth version.
If the master sends the data packet with the payload of 251 bytes, how the slave (v4.0 - payload: 33 bytes) can handle it.
Question 1: Can the BLE GATT server is capable of handling this case of backward compatibility by keeping the buffer of 251 packets and send 33 packets one after other?
Question 2: What could be the best possible approach to get high through put, by keeping the master at v4.2 and still answer the slave with all BLE versions?
Regards,
Siva.
If you read the Bluetooth Core specification, you will find that on the Link Layer the Link Layer packet size can be negotiated from both sides (slave or master doesn't matter). If the other device doesn't support it then the default length will be used. Otherwise the larger length will be used. So it's fully backwards compatible.
Also the GATT layer doesn't need to be changed at all to support LE Data Length extension, since the fragmentation and reassembly is handled by the L2CAP layer.
Note however that you need to exchange a large MTU for GATT in order to make use of the feature. Preferably 4+MTU should be a multiple of the Link Layer packet max length.
Following this question I found the way to transmit messages without using the Beam UI
Is it possible to transfer NFC data from one Android device to another without the 'Touch to Beam' screen?
This is the answer I wanted:
Only starting with Android 4.4, there is the possibility to communicate between two Android devices over NFC without the Beam UI (actually without using Android Beam and peer-to-peer mode at all): If both devices are 4.4+, one device can use Android HCE to emulate a contactless smartcard and one device can use the reader-mode API (this only works with the reader-mode API introduced in 4.4, so both devices need to be 4.4+) to communicate with the emulated smartcard.
However I would like to transfer whole files, is it possible to do it? I haven't been able to do it between a 5.1 and a 7.0 devices using the CardReader and CardEmulation samples in https://github.com/xamarin/monodroid-samples.
If I try to send large data (such as all the bytes from a file) they never connect. However, with small messages (such as the original number in the sample) it can be done but not without a lot of transreceive exceptions.
You can, of course, exchange larger amounts of data (such as whole files) through NFC card emulation. Since NFC is rather slow, it might not be your best choice to transfer the file over NFC directly though.
Use NFC for data transfer
In card emulation mode, you need to should use APDUs (cf. ISO/IEC 7816-4) to communicate between the reader app and the HCE app. On most devices, APDUs are limited to their short form, which means that you only have up to 255 data bytes (+ 4 header bytes + max. 2 bytes length information) for each request that you send from the reader to the HCE app and up to 256 bytes (+ 2 status bytes) for responses from the HCE app to the reader.
Consequently, you need to split the file into smaller chunks that can be packed into APDUs. You might want to consider creating a simple protocol that allows you to request specific chunks (identified by offset and length) of the file. For instance, you could send a command APDU like this to request one chunk of the file:
80 10 XX YY ZZ
XX YY is a two-byte offset in the file and ZZ is the one-byte length.
In resonse you the HCE app could answer with the response APDU:
<DATA> 90 00
90 00 is a status word indicating successful execution of the command.
Use NFC to establish an out-of-band channel
Since NFC is rather slow and not well-suited for exchanging large amounts of data, you might want to use NFC only to establish an initial connection. You could then exchange credentials for a Bluetooth or Wi-Fi connection to use for transfering the actual data file.
I'm working with a piece of hardware that sends and receives packets of data over particular BLE characteristics. Currently, each packet has to be an individual read or write.
When talking to the device from iOS, with the MTU negotiated up to 157 bytes, it's easy to observe this limitation. It's also easy to confirm that this MTU negotiation will work on the entire range of Apple devices the app needs to support. Without MTU negotiation, we would be limited to the default 23 byte ATT MTU, meaning we could only send and receive 20 byte packets (due to GATT overhead). The data format used for certain features will not fit in a 20 byte packet.
In the near future we'll be porting the app to Android and eventually releasing it for public consumption. I know that the Android API provides the requestMtu() method for attempting MTU negotiation, but if a user's Android device does not support an ATT MTU higher than the default 23 bytes, we'd like to be able to tell the user as soon as possible that the app will be unable to perform certain functions. Ideally, we'd like to stop the user from installing the app on such a device.
Is there a way to detect (directly or indirectly) the BLE MTU capabilities of an Android device without first requiring the user to connect to a BLE peripheral?
(Note: I've encountered a few anecdotes claiming that assorted Android devices only support the 23 byte default, but these mostly seem to come from developers who don't know about MTU negotiation. It's possible that all extant Android devices support higher MTUs. I don't know whether this is true.)
Can you give an example of an Android device that does not support something higher than the default MTU?
What I have heard all Android devices should support a higher MTU than the default. The only problem is for 4.3 and 4.4 which does not have the requestMtu API, but then you can simply initiate the MTU change from the peripheral instead.
I'm making an Android application getting data from a USB device (mode USB host). I read the document at https://developer.android.com/index.html and also some posts in stackoverflow and I found that they use sometimes bulkTransfer(), sometimes controlTransfer() but I can't find out the difference between two method and when do we use each one? Could anyone please give me some suggestion?
Control Transfer is mainly used for sending commands or receiving a device descriptor. It is normally used when setting up a device. The typical packet length is 8 bytes for low speed devices and 8, 16, 32 or 64 bytes for high speed devices. Data which is transferred via this method is formatted into three packets:
Packet 1 – Setup: The packet which contains the address and endpoint number
Packet 2 – Data: The data being sent
Packet 3 – Status: Where the device acknowledges whether the setup packet has been received and read correctly without errors.
Bulk Transfer is used for sending large packets of data to your target device. Printers and Scanners generally follow this transfer protocol. Bulk transfer has built in error correction to ensure that data is transferred and received without error. The process is considered complete when the amount of data obtained is equal to the amount of data requested. This transfer method is not ideal for time sensitive applications since there is no latency guarantee.