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.
Related
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.
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
I need to generate Unique ID for the device when the application installed, and store this value on the device, then need to communicate with server using this UUID. And it seems NSSUUD suit for the sitiation, but I am confused is there any chance of duplication of the UUID from multiple device. I already found the answer https://stackoverflow.com/a/6963990/1573209 where it describe that the version 1 type uses MAC address and 60 bit clock to generate UUID, so the duplication chance is negligible. Where as the Version4 uses some fixed number and some random number to generate the UUID, and the doc says that UUIDs created by NSUUID conform to RFC 4122 version 4 and are created with random bytes
Does that mean the chance of duplication higher?.
Then how can I use version 1 type of UUID generator, I cant see any documentation for it.
You can have look at this RFC 4122. UUID conforming to RFC 4122 are practically unique in given space and time. You can also see Random UUID probability of duplicates.
Out of a total of 128 bits, two bits indicate an RFC 4122 ("Leach-Salz") UUID and four bits the version (0100 indicating "randomly generated"), so randomly generated UUIDs have 122 random bits. The chance of two such UUIDs having the same value can be calculated using probability theory (birthday problem). Probabilities of an accidental clash after calculating n UUIDs, with x = 122 is found to be very close to zero
For n=2^36 which is 68,719,476,736 probability of collision is found to be 0.0000000000000004. For lesser value of n, this value will be even less and probability increases as more UUID's are generated. In above estimation n represents number of UUID's generated.
I am reading characteristic properties from a BLE device from my iPhone.
However, some of the properties I am seeing (like 0xA, 0x22) are not in the enumerated list that Apple provides. Are these properties a combination of 2 or more enumerated values? Or are these custom properties from the manufacturer? Need guidance on this.
As you can read in the documentation:
Values representing the possible properties of a characteristic. Since
characteristic properties can be combined, a characteristic may have
multiple property values set.
In other words, a characteristic may have more than one property. That makes sense as you can, for example, have a characteristic which can be read (CBCharacteristicPropertyRead) and written to (CBCharacteristicPropertyWrite).
In this case the value of CBCharacteristic's properties would be the bitwise OR of CBCharacteristicPropertyRead and CBCharacteristicPropertyWrite, which is 0xA.
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!