<p>I have found solution. I create category NSString+NSStringHexToByte:</p>

<p>NSString+NSStringHexToBytes.h</p>

<pre><code>#import &lt;Foundation/Foundation.h&gt;

@interface NSString (NSStringHexToBytes)
+ (NSData *)dataWithString:(NSString *)string;
@end
</code></pre>

<p>NSString+NSStringHexToBytes.m</p>

<pre><code>#import "NSString+NSStringHexToBytes.h"

@implementation NSString (NSStringHexToBytes)

+ (NSData *)dataWithString:(NSString *)string
{
    string = [string stringByReplacingOccurrencesOfString:@"0x" withString:@""];

    NSCharacterSet *notAllowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"abcdefABCDEF1234567890"] invertedSet];
    string = [[string componentsSeparatedByCharactersInSet:notAllowedCharacters] componentsJoinedByString:@""];

    const char *cString = [string cStringUsingEncoding:NSASCIIStringEncoding];
    const char *idx = cString;
    unsigned char result[[string length] / 2];
    size_t count = 0;

    for(count = 0; count &lt; sizeof(result)/sizeof(result[0]); count++)
    {
        sscanf(idx, "%2hhx", &amp;result[count]);
        idx += 2 * sizeof(char);
    }

    return [[NSData alloc] initWithBytes:result length:sizeof(result)];
}
</code></pre>

<p>and now:</p>

<pre><code>NSString* playTone= @"0f0000008000009401810282e80382e803";
NSData* data = [NSString dataWithString:playTone];
[self sendMessage:data toChannel:rfcommChannel];
</code></pre>

<p>where sendMessage is:</p>

<pre><code>-(void)sendMessage:(NSData*)data toChannel:(IOBluetoothRFCOMMChannel*)rfcommChannel
{
    [rfcommChannel writeSync:(void*)data.bytes length:data.length];
}
</code></pre>

CC BY-SA 3.0
2014-10-26T18:16:07.920Z
2014-10-26T18:16:07.920Z
user4053
<p>I successfully open RFCOMM Channel to Lego EV3 brick with code:</p>

<pre><code>IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:@"xxxxxxxxxxxx"];
IOBluetoothRFCOMMChannel *rfCommChannel;
IOBluetoothSDPUUID *sppServiceUUID = [IOBluetoothSDPUUID uuid16:kBluetoothSDPUUID16ServiceClassSerialPort];

IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID];

if ( sppServiceRecord == nil )
{
    NSLog( @"Error - no spp service in selected device." );
}

UInt8   rfcommChannelID;
if ( [sppServiceRecord getRFCOMMChannelID:&amp;rfcommChannelID] != kIOReturnSuccess )
{
    NSLog( @"Error - no spp service in selected device." );
}

if ( ( [device openRFCOMMChannelAsync:&amp;rfCommChannel withChannelID:rfcommChannelID delegate:d] != kIOReturnSuccess ) &amp;&amp; ( rfCommChannel != nil ) )
{
    NSLog( @"Error - open sequence failed." );
}
</code></pre>

<p>Now I wish to send direct command:</p>

<pre><code>unsigned char play_tone[] = {0x0F,0x00,0x00,0x00,0x80,0x00,0x00,0x94,0x01,0x81,0x02,0x82,0xE8,0x03,0x82,0xE8,0x03};
</code></pre>

<p>over RFCOMM Channel using class IOBluetoothRFCOMMChannel method:</p>

<pre><code>- (IOReturn)writeSync:(void *)data length:(UInt16)length
</code></pre>

<p>I tried to do send it using different ways but none of them worked. How should I do it properly?</p>

CC BY-SA 3.0
2014-10-25T22:01:54.443Z
Does writeSync (or anything else) return an error? Can you post a link to the entire XCode project?
David Lechner
CC BY-SA 3.0
2014-10-26T09:08:28.963Z
Link to git repository: https://github.com/mclientx/direct-commands-over-bluetooth.
writeSync returns kIOReturnSuccess. Delegates rfcommChannelOpenComplete, rfcommChannelQueueSpaceAvailable and rfcommChannelFlowControlChanged are invoked but not rfcommChannelWriteComplete.
user4053
<ev3>
Lego EV3 - sending direct commands over RFCOMM Channel (Objective-C, Xcode)
user4053
# Lego EV3 - sending direct commands over RFCOMM Channel (Objective-C, Xcode)

(Asked by: username_0 on 2014-10-25)

I successfully open RFCOMM Channel to Lego EV3 brick with code:
IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:@"xxxxxxxxxxxx"];
IOBluetoothRFCOMMChannel *rfCommChannel;
IOBluetoothSDPUUID *sppServiceUUID = [IOBluetoothSDPUUID uuid16:kBluetoothSDPUUID16ServiceClassSerialPort];

IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID];

if ( sppServiceRecord == nil )
{
    NSLog( @"Error - no spp service in selected device." );
}

UInt8   rfcommChannelID;
if ( [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID] != kIOReturnSuccess )
{
    NSLog( @"Error - no spp service in selected device." );
}

if ( ( [device openRFCOMMChannelAsync:&rfCommChannel withChannelID:rfcommChannelID delegate:d] != kIOReturnSuccess ) && ( rfCommChannel != nil ) )
{
    NSLog( @"Error - open sequence failed." );
}

Now I wish to send direct command:
unsigned char play_tone[] = {0x0F,0x00,0x00,0x00,0x80,0x00,0x00,0x94,0x01,0x81,0x02,0x82,0xE8,0x03,0x82,0xE8,0x03};

over RFCOMM Channel using class IOBluetoothRFCOMMChannel method:
- (IOReturn)writeSync:(void *)data length:(UInt16)length

I tried to do send it using different ways but none of them worked. How should I do it properly?

**Tags:** ev3

> **Comments:**
> **username_1**: Does writeSync (or anything else) return an error? Can you post a link to the entire XCode project?  
> **username_0**: Link to git repository: https://github.com/mclientx/direct-commands-over-bluetooth. writeSync returns kIOReturnSuccess. Delegates rfcommChannelOpenComplete, rfcommChannelQueueSpaceAvailable and rfcommChannelFlowControlChanged are invoked but not rfcommChannelWriteComplete.  

---

## 1 answers

### Answer by username_0 on 2014-10-26. Score: 3

I have found solution. I create category NSString+NSStringHexToByte:
NSString+NSStringHexToBytes.h
#import 

@interface NSString (NSStringHexToBytes)
+ (NSData *)dataWithString:(NSString *)string;
@end

NSString+NSStringHexToBytes.m
#import "NSString+NSStringHexToBytes.h"

@implementation NSString (NSStringHexToBytes)

+ (NSData *)dataWithString:(NSString *)string
{
    string = [string stringByReplacingOccurrencesOfString:@"0x" withString:@""];

    NSCharacterSet *notAllowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"abcdefABCDEF1234567890"] invertedSet];
    string = [[string componentsSeparatedByCharactersInSet:notAllowedCharacters] componentsJoinedByString:@""];

    const char *cString = [string cStringUsingEncoding:NSASCIIStringEncoding];
    const char *idx = cString;
    unsigned char result[[string length] / 2];
    size_t count = 0;

    for(count = 0; count < sizeof(result)/sizeof(result[0]); count++)
    {
        sscanf(idx, "%2hhx", &result[count]);
        idx += 2 * sizeof(char);
    }

    return [[NSData alloc] initWithBytes:result length:sizeof(result)];
}

and now:
NSString* playTone= @"0f0000008000009401810282e80382e803";
NSData* data = [NSString dataWithString:playTone];
[self sendMessage:data toChannel:rfcommChannel];

where sendMessage is:
-(void)sendMessage:(NSData*)data toChannel:(IOBluetoothRFCOMMChannel*)rfcommChannel
{
    [rfcommChannel writeSync:(void*)data.bytes length:data.length];
}


---

