Can we send simple string at a time of advertise data via bluetooth low energy - ios

I want to check that can we advertise simple string like "ttfgpV5hm8Z4mMlD" at the time of peripheral advertising I'm trying to pass this string into CBUUID string but whenever central scan for peripheral it gives an error like _C.CBUUID.CreationError.invalidString: I write down code which I use in peripheral and central.
Peripheral side :
Peripheral(configuration: configuration, advertisementData: [.localName("Test"), .servicesUUIDs("ttfgpV5hm8Z4mMlD")])
Central side :
let configuration = try! Configuration(services: [service], advertisement: "ttfgpV5hm8Z4mMlD")
please give me a guideline for how to pass a simple string at the time of scanning and advertising.

CBUUIDs are UUIDs that contain hexadecimal digits - they aren't arbitrary strings. So unless your "simple string" only contains hex digits and you don't mind handling the hyphen separators, then you can't. What you can do is include the string as a value of a characteristic that is included by the service.

Related

Filtering Alt beacon with manufacturer identifier and UUID begins with specific format

One of my use case requires to filter all the beacons which is generated by specific manufacturer and UUID starts with specific string.
The ALT beacon library (https://altbeacon.github.io/android-beacon-library/javadoc/reference/org/altbeacon/beacon/Region.html) provides Region class to filter the beacon based on the ID1, ID2, ID3.
I could not find any option to filter all the beacons at the library level which has specific manufacturer ID and the UUID begins with specific characters.
The API documentation with sample code to configure ALT Beacon library for filtering is appreciated and this helps to avoid additional filtering logic implementation at the application.
Filtering on a prefix of the UUID is unusual, but it is possible by defining a custom beacon layout and defining an additional identifier to be the UUID prefix. Because this new extra identifier will be treated as an independent identifier, it won't work like a string prefix -- its default representation will.be a hex string (without dashes).
If you want to filter on the first five bytes of the UUID for iBeacon, you'd set up a beacon parser like this:
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-8,i:4-19,i:20-21,i:22-23,p:24-24")); // note the new 5 byte prefix identifier: i:4-8
Now each beacon will have four identifiers instead of three, the first of which will be the beginning 5 bytes of the UUID, the second the full UUID, the third the major and the fourth the minor.
You can set up a region to match the first five bytes of this UUID, 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 like this:
Region region = new Region("prefixRegion", "0x2F234454CF", null, null);
If you want the prefix to be a different length than 5, simply adjust the i:4-8 part of the layout above to end in a different offset than 8.

iOS swift BLE read multiple characteristics

I am trying to design an app that read several temperatures. Is it true that one characteristic UUID can only handle 1 value? If so, how can I read multiple values?(For instance, temperature 1, temperature 2, temperature 3...) Do I need to declare multiple characteristic UUIDs myself? But if I only declare those in my app, how would the peripheral know what UUID corresponds to what value then? Most of the example only read one value (temperature, heart rate,etc)
You can get different values from the same characteristic. For that, you may have to write different values to the write characteristic. For example, say your write characteristic is A and your read characteristic B.
You can write a value to A like this
[self.discoveredPeripheral writeValue:data
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
where data varies as per the request that you would like to make.
For your read characteristic B, the indication property should be set to YES as follows in the didDiscoverCharacteristicsForService delegate callback
if (c.properties & CBCharacteristicPropertyIndicate) {
[peripheral setNotifyValue:YES forCharacteristic:c];
}
Now whenever you write a value to A, you will get a callback on the delegate method didUpdateValueForCharacteristic. You will have to handle the response properly.
Of course, for all of this to work, your ble device should be programmed accordingly.
Note that the code is written in Objective-C

Differences between CBUUID and NSUUID in swift

Where are the differences between the CBUUID and the NSUUID object?
I have seen to fill the scanForPeripheralsWithServices with both objects in different cases... Apple expect an CBUUID object so I would prefer to use this type or?
My example:
let MY_SERVICE_UUID = CBUUID(string: "hdl83h6sd-gl95-bn4f-37gd-jd73hd0tn8za")
func scanForPeripheralsWithServices(serviceUUIDs: MY_SERVICE_UUID,nil)
An NSUUID is a 128 bit number that is used to uniquely identify objects, types and other items. It can be accessed as bytes or is commonly used in a string form - 68753A44-4D6F-1226-9C60-0050E4C00067. The class includes methods for creating both random UUIDs and instances initialised with a specialised value.
Bluetooth also uses 128 bit identifiers for characteristics and services. The Bluetooth SIG has defined many "well known" services and characteristics. These are represented as a 16 bit value which is combined with the Bluetooth base UUID to get the full 128 bit value.
The CBUUID methods are aware of these well known values and can automatically transform the 16 bit values into their 128 bit equivalent. A CBUUID can also be initialised with a 128 bit value if you aren't using well known values (I.e. You have created your own private services and characteristics)
For example initialising a CBUUID with CBUUID(string:"180F") is ok (this is the battery service) but NSUUID(string:"180F") would fail because it needs all 128 bits.
When working with Core Bluetooth you will use CBUUID for services and characteristics. An NSUUID is used for the peripheral identifier since that is just a MAC with no special values defined.

CoreBluetooth Characteristic value

I'm confused on how long the value of a characteristic for CBMutableCharacteristic can be. If I have an archived array of objects, can I set the value of the Characteristic to this archived array? Or am I better off having a separate characteristic for each archived object in the array?
The specification limits the maximum length of a characteristic value in 512 octets (Bluetooth specification V4.0 Vol 3. Part F 3.2.9). On the central side you start a read request with the readValueForCharacteristic: API. Then on the peripheral side you receive the corresponding callback:
CBMutableCharacteristic *characteristic = // the characteristic with long data
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
// Ensure offset is in the valid range
if (request.offset > characteristic.value.length) {
// respond with error
[self.peripheralManager respondToRequest:request withResult:CBATTErrorInvalidOffset];
return;
}
NSRange range = NSMakeRange(request.offset, characteristic.value.length - request.offset);
request.value = [characteristic.value subdataWithRange:range];
[self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
}
The callback will be called with increasing offset values as long as the response is not less than the Maximum Transferrable Unit (MTU). The MTU is negotiated by the system and you have no way to query it in advance. For this reason the range is set up to stretch all the way to the data length so the system can decide how much of the data it is going to send to the central. By default it is 20 but iOS 7 has some tweaks that enable greater sizes. Check out the WWDC videos for more detail.
With this info you should be able to figure out a way to expose your data. Keep in mind that the more services and characteristics you have, the longer the discovery will take. Using long reads and long writes is just a convenience.
This project may be exactly what you're looking for: SimpleShare
It uses Bluetooth LE to share arrays of strings between devices. The technique is to use just one characteristic to share the data, but when a central subscribes to the characteristic, the peripheral changes the value to each new piece of data it wants to send, until the entire too-long message is sent. Basically, it breaks it down into bite-sized chunks that fit in the characteristic and sends them one at a time.
Hope that helps!

how to read large amount (28 characters) of Bluetooth LE peripheral name-key ad data every time by central didDiscoverPeripheral method?

How can I send 28 bytes of peripheral name-key ad data and receive it by the central?
Normally, with the UUID, there's only room for 8 characters in the peripheral name key ad data.
But there's this TRICK:
I discovered if my name key has 28 characters, the central ad data is empty, BUT all 28 characters all appear one time in the central's didDiscoverPeripheral's peripherl.name variable. But the next time the central scans same device, it gets instead the GATT value of "iPad" (because my central and peripheral are on two iPad minis.)
Apple Doc. says it normally sends the GATT, but I observe that it always sends the 28-char name once.
BACKGROUND:
I want to put identification data in the peripheral's ad data, to avoid a read-value interchange. The reason is to have the shortest communication interchange between devices, to save time and battery.
I've tried turning scanning off then back on, and stopping and re-starting advertising. Same problem.
This is unfortunately not going to work. Once you connect, the device name characteristic is read by CoreBluetooth and it will be used as the name for the peripheral later on. The only place the name you set will always appear is the advertisement data:
(lldb)po advertisementData
{
kCBAdvDataChannel = 37;
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = MyPeripheral;
kCBAdvDataServiceUUIDs = (
"Unknown (<e20a39f4 73f54bc4 a12f17d1 ad07a961>)"
);
}
The device name characteristic cannot be accessed in an iOS device in any way.
It may be that the Bluetooth LE controller has a parameter set to filter duplicates. You may need HCI layer access to change this if you don't have API calls to the HCI "set scan enable" command. See Bluetooth Core Specification v4.0 Vol 2 Part E 7.8.11

Resources