Unable to write data into hardware peripheral
Asked Answered
C

3

1

I am using CoreBlueTooth API to write data into a peripheral we have received from some hardware manufacturing company. As per the specs they have given us a bunch of characteristics UUIDs to write data into. Once we want to finish we need to write 0 in one of the characteristics. Now, the problem is that when I am trying to send String/Integer and converting them into NSData then its not working. I think I need to send byte stream in those writable characteristics. Can someone help me as how can I convert my NSString & NSNumber data into byte stream before sending them. Below is my conversion code I tried with:

- (void)writeCharactersticData:(NSDictionary *)iData toPeripheral:(CBPeripheral *)iPeripheral {
    NSArray *charactersticsIDs = [NSArray arrayWithArray:iData.allKeys];
    self.writeCharactersticsCount  = charactersticsIDs.count;

    for (CBUUID *uuid in charactersticsIDs) {
        if (self.peripheralCharacterstics[uuid]) {



            NSData *payload;

            if ([iData[uuid] isKindOfClass:[NSNumber class]]) {
                NSInteger data = ((NSNumber *)iData[uuid]).integerValue;
//                int integerSize = sizeof(data);
//                
//                uint8_t bytes[integerSize];
//                
//                
//                NSLog(@"Integer data = %d", data);
//                
//                int8_t tx = (int8_t)data;
//                bytes[0] = tx;
//                payload = [NSData dataWithBytes:bytes length:sizeof(data)];

                payload = [NSData dataWithBytes:&data length:sizeof(data)];
            } else if ([iData[uuid] isKindOfClass:[NSString class]]) {

                int stringSize = sizeof(iData[uuid]);
                uint8_t bytes[stringSize];
                NSScanner *scanner = [NSScanner scannerWithString:iData[uuid]];

                for (int i=0; i<stringSize; i++) {
                    unsigned int value;
                    [scanner scanHexInt:&value];
                    bytes[i] = (uint8_t)value;
                }

                payload = [NSData dataWithBytes:bytes length:stringSize];
//                payload = [iData[uuid] dataUsingEncoding:NSUTF8StringEncoding];
            }

            [self.discoveredPeripheral writeValue:payload forCharacteristic:self.peripheralCharacterstics[uuid] type:CBCharacteristicWriteWithResponse];
        }
    }
}
Chaney answered 25/10, 2013 at 18:30 Comment(0)
A
1

This is not a Core Bluetooth based problem you have here.

For debugging, you could use

NSLog(@"%@", payload);

For your string to NSData conversion, your approach seems very complicated. I would suggest something simple like

NSData* payload = [iData[uuid] dataUsingEncoding:NSUTF8StringEncoding];
if (payload.length > 20)
{
    // handle error. most LE peripherals don't support longer values.
}

Another error could be that you mix ASCII 0 '0' with a binary zero '\0' when writing your value.

Alloplasm answered 26/10, 2013 at 11:14 Comment(7)
How do we handle ASCII 0 and binary 0 to convert them into byte stream? Also, for string, I was doing it the way you mentioned but my hardware didn't seem to accept data so thought of changing it. As per specs, for hardware, I need to send stream of bytes converted into NSData. Any suggestions?Chaney
Bluetooth LE doesn't have a concept of streams, only characteristics with read/write of single packets. Your spec description is pretty vague, I don't understand what exactly you are trying to send.Alloplasm
Could you please help me understanding how do we handle ASCII 0 Vs binary 0.Chaney
If your protocol requires sending a binary 0, it obviously won't work if you send the ascii character "0". ASCII "0" is 0x30 in binary. See asciitable.com.Alloplasm
I see.. +1 for this information. One more question please - how do we write ASCII into writable characteristics?Chaney
char c = '0'; NSData* payload = [NSData dataWithBytes:&c length:1];Alloplasm
I shall try with this. Thanks you for sharing this info.Chaney
I
2

Here is the fix, It works for me

//Integer to NSData
+(NSData *) IntToNSData:(NSInteger)data
{
    Byte *byteData = (Byte*)malloc(4);
    byteData[3] = data & 0xff;
    byteData[2] = (data & 0xff00) >> 8;
    byteData[1] = (data & 0xff0000) >> 16;
    byteData[0] = (data & 0xff000000) >> 24;
    NSData * result = [NSData dataWithBytes:byteData length:4];
    NSLog(@"result=%@",result);
    return (NSData*)result;
}

//NSData to Integer
+(NSInteger) NSDataToInt:(NSData *)data
{
    unsigned char bytes[4];
    [data getBytes:bytes length:4];
    NSInteger n = (int)bytes[0] << 24;
    n |= (int)bytes[1] << 16;
    n |= (int)bytes[2] << 8;
    n |= (int)bytes[3];
    return n;
}

Thanks to http://coding-snippet.blogspot.in/2013/05/blog-post.html

Inductor answered 10/12, 2013 at 14:48 Comment(0)
A
1

This is not a Core Bluetooth based problem you have here.

For debugging, you could use

NSLog(@"%@", payload);

For your string to NSData conversion, your approach seems very complicated. I would suggest something simple like

NSData* payload = [iData[uuid] dataUsingEncoding:NSUTF8StringEncoding];
if (payload.length > 20)
{
    // handle error. most LE peripherals don't support longer values.
}

Another error could be that you mix ASCII 0 '0' with a binary zero '\0' when writing your value.

Alloplasm answered 26/10, 2013 at 11:14 Comment(7)
How do we handle ASCII 0 and binary 0 to convert them into byte stream? Also, for string, I was doing it the way you mentioned but my hardware didn't seem to accept data so thought of changing it. As per specs, for hardware, I need to send stream of bytes converted into NSData. Any suggestions?Chaney
Bluetooth LE doesn't have a concept of streams, only characteristics with read/write of single packets. Your spec description is pretty vague, I don't understand what exactly you are trying to send.Alloplasm
Could you please help me understanding how do we handle ASCII 0 Vs binary 0.Chaney
If your protocol requires sending a binary 0, it obviously won't work if you send the ascii character "0". ASCII "0" is 0x30 in binary. See asciitable.com.Alloplasm
I see.. +1 for this information. One more question please - how do we write ASCII into writable characteristics?Chaney
char c = '0'; NSData* payload = [NSData dataWithBytes:&c length:1];Alloplasm
I shall try with this. Thanks you for sharing this info.Chaney
E
0

Just use https://github.com/LGBluetooth/LGBluetooth It will make your job 100x easier

Embattle answered 15/2, 2014 at 10:15 Comment(2)
That repo is no longer available.Sleepyhead
@skladek It is available here: LGBluetooth but it's old. You can find online other wrapper, written in both Obj-C and SwiftDepth

© 2022 - 2024 — McMap. All rights reserved.