OSX蓝牙打开RFCOMMChannelAsync声称已连接,但未建立连接,并且从未调用过委托
OSX bluetooth openRFCOMMChannelAsync claims to have connected but connection is not established and delegate is never called
我已经为OSX的objc蓝牙框架编写了一个C++包装器。包装器到目前为止可以工作,它可以 a( 获取所有配对设备的列表,b( 获取一个设备,c( 打印其名称,d( 打开通道。这一切都在没有任何报告错误的情况下工作。但是,我的蓝牙设备(RFComm 盒(从不报告连接。它保持离线状态。我在openRFCOMMChannelAsync注册的委托永远不会被调用。
由于它是一个C++包装器,因此标头是标准的C++类:
class IosBT {
public:
//IosBT();
void clearText();
void sendMessage(char* dataToSend, int len);
void log(const char *text);
void discover();
void closeConnection();
private:
void *mRFCOMMChannel;
};
该类的实现以 .mm 文件的形式编写。我分两部分解释。第一个是委托,它保留指向C++类的指针:
@interface AsyncCommDelegate : NSObject <IOBluetoothRFCOMMChannelDelegate> {
@public
IosBT* delegateCPP;
}
@end
@implementation AsyncCommDelegate {
}
-(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error
{
if ( error != kIOReturnSuccess ) {
delegateCPP->log("Error - failed to open the RFCOMM channel with error %08lx.n");
return;
}
else{
delegateCPP->log("Connected. Yeah!n");
}
}
-(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength
{
NSString *message = [[NSString alloc] initWithBytes:dataPointer length:dataLength encoding:NSUTF8StringEncoding];
delegateCPP->log([message UTF8String]);
}
@end
.mm 文件的第二个块是建立连接的"发现"方法。 在这里,我怀疑有些不对劲:
void IosBT::discover()
{
IOBluetoothSDPUUID *sppServiceUUID;
NSArray *deviceArray;
IOBluetoothRFCOMMChannel *chan;
log("Attempting to connectn");
sppServiceUUID = [IOBluetoothSDPUUID uuid16:kBluetoothSDPUUID16ServiceClassSerialPort];
deviceArray = [IOBluetoothDevice pairedDevices];
if ( ( deviceArray == nil ) || ( [deviceArray count] == 0 ) ) {
log("Error - no selected device. ***This should never happen.***n");
return;
}
fprintf(stderr,"%lu devicesn",(unsigned long)deviceArray.count);
IOBluetoothDevice *device = [deviceArray objectAtIndex:0];
fprintf(stderr,"dev=%sn",[device.name UTF8String]);
IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID];
if ( sppServiceRecord == nil ) {
log("Error - no spp service in selected device. ***This should never happen since the selector forces the user to select only devices with spp.**
*n");
return;
}
// To connect we need a device to connect and an RFCOMM channel ID to open on the device:
UInt8 rfcommChannelID;
if ( [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID] != kIOReturnSuccess ) {
log("Error - no SPP device.n");
return;
}
AsyncCommDelegate* asyncCommDelegate = [[AsyncCommDelegate alloc] init];
asyncCommDelegate->delegateCPP = this;
if ( [device openRFCOMMChannelAsync:&chan withChannelID:rfcommChannelID delegate:asyncCommDelegate] != kIOReturnSuccess ) {
log("Error - open sequence failed.n");
return;
}
if ( chan == NULL ) {
log("Error - chan == NULL");
return;
}
[chan setDelegate:asyncCommDelegate];
log("Successfully connected");
mRFCOMMChannel = (__bridge void*)chan;
}
我只使用带有fprintf的屏幕上的"log"方法记录从蓝牙设备接收的数据。
主程序很简单:
IosBT ad;
ad.discover();
getchar();
ad.closeConnection();
输出为:
Attempting to connect
1 devices
dev=GN-ATTYS1-FB86
Successfully connected
但是,从不调用"通道数据"方法,但应打印从蓝牙设备接收的数据。蓝牙盒报告它未连接。但是,顶部栏上的右侧蓝牙图标显示Mac已连接到GN-ATTYS1-FB86。然而,事实并非如此。
这里的演示使用窗口在屏幕上打印,适用于我的蓝牙盒:https://github.com/berndporr/coco-bluetooth-rfcomm。对我来说,唯一明显的区别是我使用命令行。
问题是:为什么OSX报告一个有效的连接,但实际上没有建立一个连接?我怎么可能在不报告任何错误的情况下调试它?
为了从命令行使用蓝牙,需要在线程中重复调用NSRunLoop
对象。由于它是一个C++包装器,我将线程创建为C++线程,然后在循环中调用:
while (running) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
running
标志是线程中的常用标志,设置为零以停止线程。
整个编码示例在这里:C++蓝牙包装器,它打开RFCOMM通道,然后将接收到的数据打印到stdout,直到用户按回车键。
这里的答案是如何创建运行事件循环帮助我找到了问题的根源。
- 无法在C++中建立与MySQL数据库的连接
- OSX蓝牙打开RFCOMMChannelAsync声称已连接,但未建立连接,并且从未调用过委托
- 通过单独的 tcp 流建立 http 连接
- 将"libpqxx"与Visual Studio 2013链接/安装,以便与PostgrSQL建立C++连接
- Qt:如何通知对象已建立涉及它的信号槽连接
- 从 NAT 后面建立对等连接
- 提升 Websocket 并io_context可重用性,以实现连接的可重新建立性
- 仅通过建立一次TCP连接将Recv从客户端发送到服务器套接字
- 在Windows -C 中未建立的TCP连接
- 我无法在用C++编写的服务器和用 C# 编写的客户端之间建立 UDP 连接
- NAS(使用 qt/linux)- 无法建立简单的音频服务器连接测试
- 使用Isringstream和struct/vector在给定的数据之间建立连接
- C++ MySQL,使用在同一类内的另一个函数中的一个函数中建立的连接
- Adafruit Fona与echo服务器建立连接,但不发送任何数据
- C++ SFML 网络:无法建立 TCP 连接
- 使用 C++ 在 Windows 上建立蓝牙连接(收到错误 10060)
- 如何与SQL Server 2008建立稳定的连接,并在C 中编码我的第一个CRUD操作
- 在 Asio 中建立新连接时出现"Already Open"错误
- 获取在C++中建立TCP连接的正在运行的进程
- C++ 在基于 UNIX 套接字的客户端程序中 connect() 不会建立与服务器的连接