Objective c 在Cocoa中创建并发送蓝牙命令帧
我正在使用IOBluetooth Cocoa框架与蓝牙设备通信。到目前为止,我已经了解了发现设备及其服务、与设备配对、连接到设备的整个过程,现在我想发送一些实际命令,但我遇到了一些问题。下面是我尝试使用的AVRCP配置文件规范中的一个图形。你可以 我认为我需要写一个5字节的值,如图所示: 下面是我现在使用的写入数据的方法:Objective c 在Cocoa中创建并发送蓝牙命令帧,objective-c,cocoa,bluetooth,l2cap,Objective C,Cocoa,Bluetooth,L2cap,我正在使用IOBluetooth Cocoa框架与蓝牙设备通信。到目前为止,我已经了解了发现设备及其服务、与设备配对、连接到设备的整个过程,现在我想发送一些实际命令,但我遇到了一些问题。下面是我尝试使用的AVRCP配置文件规范中的一个图形。你可以 我认为我需要写一个5字节的值,如图所示: 下面是我现在使用的写入数据的方法: - (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*)l2capChannel status:(IORetu
- (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*)l2capChannel status:(IOReturn)error {
NSLog(@"Open Complete");
NSMutableData *playData = [[NSMutableData alloc] initWithCapacity:5];
unsigned char ctype = 0x0;
unsigned char subunit = 0x90;
unsigned char opcode = 0x7C;
unsigned char opid = 0x44;
unsigned char opdata = 0x0;
[playData appendBytes:&ctype length:8];
[playData appendBytes:&subunit length:8];
[playData appendBytes:&opcode length:8];
[playData appendBytes:&opid length:8];
[playData appendBytes:&opdata length:8];
usleep(1000);
[l2capChannel writeAsync:[playData mutableBytes] length:40 refcon:nil];
}
当该函数运行时,设备响应以下十六进制值0x400010
仅仅填写一个字节数组就需要做大量的工作。此外,您还试图使用-appendBytes:length:messages将八个字节添加到playData中
对于这种情况,我只需要为BT命令框架声明一个结构。NSData在这里提供的功能并不多。如果你打算大量使用AV/C框架,而不是创建一个结构(这对部分字节打包没有帮助),那么你应该创建一个
AVCFrame
类,该类可以轻松设置这些框架,并检查你给它的值,有一个调试说明,并会为你处理所有烦人的细节
然后,您的代码可以如下所示:
AVCFrame *frame = [AVCFrame frameWithCommandType:AVCCommandTypePlay
subunitType:mySubunitType
subunitID:mySubunitID];
// You likely won't actually be writing to the L2CAPChannel. See below.
[l2capChannel writeAsync:[frame mutableBytes] length:[frame length] refcon:nil];
这不是最好的界面。您需要通读AV/C数字接口命令集通用规范
就字节打包而言(最终必须这样做),您需要使用以下内容:
// Returns |subunitType| shifted and masked appropriately for bit_oring
// with subunit ID to create an address octet.
inline UInt8
AVRCAddressSubunitType(UInt8 subunitType) {
const UInt8 kLeastThreeBytes = 0x07;
UInt8 shiftedType = (subunitType << 3) & ~kLeastThreeBytes;
return shiftedType;
}
// Returns |subunitID| masked appropriately for bit_oring with subunit type
// to create an address octet.
inline UInt8
AVRCAddressSubunitID(UInt8 subunitID) {
const UInt8 kLeastThreeBytes = 0x07;
UInt8 maskedID = subunitID & kLeastThreeBytes;
if (subunitID & ~kLeastThreeBytes) {
NSLog(@"*** %s: subunit ID %#hhx > 0x07 cannot be represented "
"in the 3 bits allotted. Truncating to %#hhx.",
__PRETTY_FUNCTION__, subunitID, maskedID);
}
return maskedID;
}
- (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel *)l2capChannel
status:(IOReturn)error {
/* might be worth looking at the error... */
NSLog(@"%s: open complete - "
"error: (system: %#x; subsystem: %#x; code: %#x)",
__PRETTY_FUNCTION__,
err_get_system(error), err_get_sub(error), err_get_code(error));
/* to send, first pack your data into byte-sized variables */
// some variables...
// address byte layout is [3:7] = 9 = PANEL; [0:2] = 0 = subunit ID
UInt8 address = (AVRCAddressSubunitType(0x09) | AVRCAddressSubunitID(0x00));
// some more variables...
/* create a mutable data and append the bytes in sequence */
// some appending...
[playData appendBytes:&address length:sizeof(address)];
// more appending...
/* finally, send all the bytes */
[l2capChannel writeAsync:[playData mutableBytes]
length:[playData length]
refcon:NULL];
}
//返回| subunitype |移位并适当屏蔽位|
//使用子单元ID创建地址八位字节。
内联UInt8
AVRCAddressSubunityType(UInt8 SubunityType){
const UInt8 kLeastThreeBytes=0x07;
UInt8 shiftedType=(subunitype很酷,谢谢你的指针。我是个新手,直接处理字节,你能举个例子吗?