iOS CoreBluetooth updatevalue: and didUpdateValueForCharacteristic: - ios

I am developing an iOS app that communicates with a WT11i by bluegiga via Bluetooth 4.0
The iOS is running as the central while WT11i is acting as the peripheral.
The characteristics of the service broadcast by WT11i is Write/Notify
After my app is connected to the peripheral (WT11i), the peripheral will continuously send the value of a counter to my app.
NSLog:
2013-09-18 14:22:58.843 IOS_Central[412:907] Receive -> 1
2013-09-18 14:22:58.904 IOS_Central[412:907] Receive -> 2
2013-09-18 14:22:58.963 IOS_Central[412:907] Receive -> 3
2013-09-18 14:22:59.023 IOS_Central[412:907] Receive -> 4
Code:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
receivingThings =true;
if (error) {
NSLog(#"Error discovering characteristics: %#", [error localizedDescription]);
return;
}
NSString *newString = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(#"Receive -> %#",newString);
}
I can send a short message from my app to my peripheral using
-(void) sendToPeripheral:(NSString*)message{
if(self.ConnectionState == CONNECTIONSTATE_NOTCONNECTED){
return;
}
NSData *mainData1= [message dataUsingEncoding:NSUTF8StringEncoding];
[self.connectedPeripheral writeValue:mainData1 forCharacteristic:self.connectedCharacteristic type:CBCharacteristicWriteWithResponse];
NSLog(#"Send Message");
}
Result of the writeValue: to Peripheral will be reflected here
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
if(error == nil){
NSLog(#"Sent successfully");
}
else{
NSLog(#"Send Fail");
}
}
When my peripheral received the message, it will acknowledge by sending an acknowledgement "Message Received" back to my app.
Most of the time the communication is fine. However once in a while my app will miss an update right after I sent a message to the peripheral.
2013-09-18 14:22:58.843 IOS_Central[412:907] Receive -> 1
2013-09-18 14:22:58.904 IOS_Central[412:907] Receive -> 2
2013-09-18 14:22:58.963 IOS_Central[412:907] Receive -> 3
2013-09-18 14:22:59.023 IOS_Central[412:907] Receive -> 4
2013-09-18 14:22:59.050 IOS_Central[412:907] Send Message
2013-09-18 14:22:59.083 IOS_Central[412:907] Receive -> 5
2013-09-18 14:22:59.113 IOS_Central[412:907] Sent successfully
2013-09-18 14:22:59.143 IOS_Central[412:907] Receive -> 7
2013-09-18 14:22:59.203 IOS_Central[412:907] Receive -> 8
2013-09-18 14:22:59.263 IOS_Central[412:907] Receive -> Message Received
2013-09-18 14:22:59.322 IOS_Central[412:907] Receive -> 9
Notice I did not receive number "6" from my peripheral?
I have checked the logs on the peripheral, it says that it has sent out "6" to my app. My biggest suspicion lies in the iOS corebluetooth, where writeValue: clashes with didUpdateValueForCharacteristic:, therefore causing my "6" to be lost.
Has anyone encountered this problem before too? Any suggestion?

It can be the connection interval issue. You can send some amount data in single connection interval. Once received successful acknowledgment from Peripherals, send next some data. By doing this, there will be less chance of missing packets.
Please refer this:
Connection Interval Core Bluetooth

Related

CBPeripheral track written record

From database, I am retrieving data records and then writing each record to CBCharacteristic of BLE device. Write implementation,
for service in self.connectedPeripheral!.services! {
for characteristic in service.characteristics! {
if characteristic.UUID.UUIDString == "1111" {
self.connectedPeripheral!.writeValue(dataRecord, forCharacteristic: characteristic, type: .WithResponse)
}
}
}
Now CBPeripheral's didWriteValueForCharacteristic method is getting called with nil NSError. So write is successful. But how can we track which data record is written to BLE device. Because I need to delete this successfully written record from database. In CBCharacteristic documentation, I could not find any property which can be set to database record_id when we start write operation to BLE. Most of them are read only.
func peripheral(peripheral: CBPeripheral, didWriteValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
print("write characteristic: \(characteristic)")
// Need to track the record here So it can be removed from database
}
After getting response in peripheral:didWriteValueForCharacteristic:error method, you have to call this method [peripheral readValueForCharacteristic:characteristic]
By this you will get callback in peripheral:didUpdateValueForCharacteristic:error:
here you can check your characteristic's value and delete the record if its successfully written to your characteristic.
-(void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error == nil) {
NSString *characteristicValue=[[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(#"value=%#",characteristicValue);
}
}

iOS:Send Command To peripheral and Receive response From it

I am developing core bluetooth app in iOS. I have smartwatch device and is connecting to the app I have developed and aim able to discover the service and characteristics from it and when I am trying to read the information from the watch aim getting errors as below
Bluetooth_iph[2688:614669] Did discover peripheral. peripheral: <CBPeripheral: 0x17daf4d0,
identifier = D675EA0B-1342-0C74-9D3D-98CAFA478985, name = BLEDEVICE, state = connecting>
rssi: -51, UUID: <CFUUID 0x17d96e80> D675EA0B-1342-0C74-9D3D-98CAFA478985
advertisementData: {
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = "BLEDEVICE";
kCBAdvDataServiceUUIDs = (
8880
);
kCBAdvDataTxPowerLevel = 7;
}
2014-10-17 10:06:13.695 Bluetooth_iph[2688:614669] WARNING: No service found
2014-10-17 10:06:18.353 Bluetooth_iph[2688:614669] Peripheral Connected
2014-10-17 10:06:18.354 Bluetooth_iph[2688:614669] started time is 10:06:10 17-10-14
2014-10-17 10:06:18.354 Bluetooth_iph[2688:614669] Scanning stopped
2014-10-17 10:06:18.485 Bluetooth_iph[2688:614669] Found a Device Manufacturer Name
2014-10-17 10:06:18.541 Bluetooth_iph[2688:614669] Error updating value for characteristic
8881 error: Reading is not permitted.
2014-10-17 10:06:18.601 Bluetooth_iph[2688:614669] Error updating value for characteristic
8881 error: Reading is not permitted.
2014-10-17 10:06:18.662 Bluetooth_iph[2688:614669] Error updating value for characteristic
8881 error: Reading is not permitted.
And for discovering the characteristics for the service I have written as below.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:
(CBService
*)service error:(NSError *)error
{
if (error)
{
NSLog(#"Discovered characteristics for %# with error: %#", service.UUID, [error
localizedDescription]);
return;
}
if([service.UUID isEqual:[CBUUID UUIDWithString:#"8880"]])
{
for (CBCharacteristic * characteristic in service.characteristics)
{
/* Read manufacturer name */
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:#"8881"]])
{
[_discoveredPeripheral readValueForCharacteristic:characteristic];
NSLog(#"Found a Device Manufacturer Name Characteristic - Read manufacturer
name");
}
}
}
if ( [service.UUID isEqual:[CBUUID UUIDWithString:CBUUIDGenericAccessProfileString]] )
{
for (CBCharacteristic *characteristic in service.characteristics)
{
/* Read device name */
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:CBUUIDDeviceNameString]])
{
[_discoveredPeripheral readValueForCharacteristic:characteristic];
NSLog(#"Found a Device Name Characteristic - Read device name");
}
}
}
}
And for update value for characteristic
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:
(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error)
{
NSLog(#"Error updating value for characteristic %# error: %#", characteristic.UUID,
[error localizedDescription]);
return;
}
}
As aim new to iOS development my requirement is I have to give some request to ble device so it should respond and that response I should get in the iOS app. Above code is on behalf of my knowledge. please help me if possible by code or any other examples.
You should check the properties property of the CBCharacteristic - It will tell you what you can do with the characteristic. From the message you are getting reading is not supported on this characteristic - Either you can only write to it or, if it is meant to send information to your central, then you probably have to do it using notification or indication (CBCharacteristicPropertyNotify and/or CBCharacteristicPropertyIndicate set in properties).
If this is the case then you need to use [peripheral setNotifyValue:YES forCharacteristic:characteristic]; When the device has new data for this characteristic it will call the peripheral:didUpdateNotificationStateForCharacteristic:error: delegate method.

Socket is disconnected immediately after making connection by using GCDAsyncSocket library in iPhone application

I want to read and write data from OBD2 Wifi enabled Adapter which is used to read car data and fault codes. For that ,I'm using GGCDAsyncSocket Library for socket connection.
You can download CocoaAsyncSocket Library source code
But it maintains connection hardly for 10 seconds and sometimes 40-50 seconds and then terminated.
And the logs shows :
Socket disconnected : Error Domain=NSPOSIXErrorDomain Code=57 "The operation couldn’t be completed. Socket is not connected" UserInfo=0x14cd50 {}
Any help or idea would be appreciated !
Thanks in advance !
Please look at below code :
- (void)connectObdKeyHost:(NSString*)strHost port:(NSString *)strPort {
[gcdAsyncSocket connectToHost:strHost onPort:portNo withTimeout:30 error:&error];
}
// GCDAsyncSocket Delegate Methods
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
NSLog(#"Socket connected : ");
}
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
NSLog(#"Socket disconnected : %#",err);
}
I tried with below method :
[gcdAsyncSocket connectToHost:strHost onPort:portNo error:&error];
and now it's working.

QuickBlox downloading content receiving QBASIHTTPRequestErrorDomain code 1

I'm using the iOS SDK to access download content from the content module. It seems in the delegate method -(void)completedWithResult:(Result*)result, I can have cases where result.success is YES while result.file would be nil.
-(void)completedWithResult:(Result*)result
{
if (result.success) { // YES here
if ([result isKindOfClass: [QBCFileDownloadTaskResult class]]) {
FileDownloadTaskResult *res = (QBCFileDownloadTaskResult *)result;
res.file; // This is NULL.
res.errors; // This is an empty NSArray
}
}
}
Console log prints this message:
<QBASIHTTPRequest: 0xc26d200>
headers:(null)
body:
error:Error Domain=QBASIHTTPRequestErrorDomain Code=1 "A connection failure occurred" UserInfo=0x9f27a50 {NSUnderlyingError=0x9f18300 "The operation couldn’t be completed. Connection reset by peer", NSLocalizedDescription=A connection failure occurred}
Is this normal? I would expect in this case res.success a NO.
Let's try latest version of iOS SDK 1.8
http://quickblox.com/developers/IOS#Framework_changelog:
Here is one big change:
replaced core network library ASIHTTPRequest with AFNetworking

How to read information from core bluetooth device

I am working on an iOS core Bluetooth application, I am able to connect with the BLE device using iPad3. I am able to reach to the block didDiscoverServices, but unable to proceed from here.
My questions are ;
How can I read characteristic from Bluetooth device?
How can I read other information of Bluetooth device?
Help me on this or provide any suggestion.
Thanks Wilhelmsen for reply.
I got the following from the mentioned block :
[0] - Service : <CBConcreteService: 0x1769a0> UUID: Generic Attribute Profile
[1] - Service : <CBConcreteService: 0x174470> UUID: Generic Access Profile
[2] - Service : <CBConcreteService: 0x1744e0> UUID: Unknown (<00005301 00000041 4c505749 53450000>)
Characteristic
[0] - Characteristic : <CBConcreteCharacteristic: 0x15d410> UUID: Service Changed
[0] - Characteristic : <CBConcreteCharacteristic: 0x1805b0> UUID: Device Name
[1] - Characteristic : <CBConcreteCharacteristic: 0x1806a0> UUID: Appearence
[0] - Characteristic : <CBConcreteCharacteristic: 0x183810> UUID: Unknown (<00004301 00000041 4c505749 53450000>)
[1] - Characteristic : <CBConcreteCharacteristic: 0x1838a0> UUID: Unknown (<00004302 00000041 4c505749 53450000>)
Now how to get the exact values from this Characteristic in didUpdateValueForCharacteristic block?
Take a nice good read through the framework. if you have come this far you shouldn't have any problem finding 'discoverCharacteristics' and the peripheral delegate callback 'didDiscoverCharacteristic'. You need to know the UUID of the services and characteristics you want to discover and apply it to those methods.
Then you can read with 'readValueForCharacteristic' and the delegate callback 'didUpdateValueForCharacteristic'.
This is sent from my phone, so I will maybe edit a bit when I get to a computer. Hope it helps
New question:
[connectedPeripheral readValueForCharacteristic:wantedCharacteristic]
and at peripheral delegate
- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
NSLog(#"Characteristic value : %# with ID %#", characteristic.value, characteristic.UUID);
[delegate characteristicValueRead:characteristic.value];
}
works for me
You can get value of a characteristic
NSString *value = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
NSLog(#"Value %#",value);
Just use
https://github.com/LGBluetooth/LGBluetooth
[LGUtils readDataFromCharactUUID:#"f045"
seriveUUID:#"5ec0"
peripheral:peripheral
completion:^(NSData *data, NSError *error) {
NSLog(#"Data : %s Error : %#", (char *)[data bytes], error);
}];

Resources