Linux平台C程序与Nrf Connect安卓APP蓝牙交互开发问询
Hey there! Let's wrap up your C program to get seamless communication between your Linux machine and the Nrf Connect Android app. You’ve already nailed the RFComm socket creation, listening, and connection acceptance—solid foundation! Here’s how to build out the rest of the logic:
1. 确保蓝牙适配器可被Nrf Connect发现
First, your Linux Bluetooth adapter needs to be discoverable and advertise the RFComm service so Nrf Connect can pick it up. You can handle this either via command line (for quick testing) or directly in your C code:
临时测试(命令行)
Run these commands to make your adapter discoverable and register a basic SPP (Serial Port Profile) service:
# 开启蓝牙适配器 hciconfig hci0 up # 启用可发现模式(0表示永久有效) hciconfig hci0 piscan # 在通道1注册RFComm服务 sdptool add --channel=1 SP
集成到C代码
使用libbluetooth-dev的API在代码中配置适配器:
#include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> #include <bluetooth/hci_lib.h> int make_adapter_discoverable(int dev_id) { int sock = hci_open_dev(dev_id); if (sock < 0) { perror("Failed to open HCI device"); return -1; } // 设置扫描模式为可发现(0x03 = PScan + IScan) int ret = hci_set_scan_enable(sock, 0x03, 1, 10000); if (ret < 0) { perror("Failed to set scan enable"); hci_close_dev(sock); return -1; } // 设置设备类别为"计算机",让Nrf Connect能识别 uint8_t cod[] = {0x00, 0x01, 0x0C}; // 服务类:网络,设备类:计算机 ret = hci_write_class_of_device(sock, cod, sizeof(cod), 10000); if (ret < 0) { perror("Failed to write class of device"); hci_close_dev(sock); return -1; } hci_close_dev(sock); return 0; }
在程序早期(创建RFComm套接字之前)调用这个函数,传入你的适配器ID(通常hci0对应ID 0)。
2. 实现数据收发逻辑
连接建立后,你可以用标准的read()和write()系统调用与Nrf Connect通信——RFComm的行为和普通串口套接字一致。
给你现有代码补充这部分逻辑:
#include <unistd.h> #include <string.h> // 接受连接之后: int client_sock = accept(listen_sock, (struct sockaddr *)&rem_addr, &optlen); if (client_sock < 0) { perror("Failed to accept connection"); close(listen_sock); return 1; } // 打印连接的设备信息 char buf[256]; ba2str(&rem_addr.rc_bdaddr, buf); printf("Connected to %s\n", buf); // 数据交互循环 char rx_buf[1024]; char tx_buf[] = "Hello from Linux!\n"; while (1) { // 读取Nrf Connect发送的数据 ssize_t bytes_read = read(client_sock, rx_buf, sizeof(rx_buf)-1); if (bytes_read < 0) { perror("Error reading from socket"); break; } else if (bytes_read == 0) { printf("Connection closed by client\n"); break; } rx_buf[bytes_read] = '\0'; printf("Received: %s\n", rx_buf); // 向Nrf Connect发送响应 ssize_t bytes_written = write(client_sock, tx_buf, strlen(tx_buf)); if (bytes_written < 0) { perror("Error writing to socket"); break; } printf("Sent response\n"); } // 资源清理 close(client_sock); close(listen_sock);
3. 注册SDP服务(让Nrf Connect识别你的服务)
要让你的RFComm服务在Nrf Connect的"RFComm Clients"列表中显示,需要通过服务发现协议(SDP)注册它。这里是代码片段:
#include <bluetooth/sdp.h> #include <bluetooth/sdp_lib.h> sdp_session_t* register_rfcomm_service(uint8_t channel) { sdp_session_t *session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); if (!session) return NULL; sdp_record_t *record = sdp_record_alloc(); if (!record) { sdp_close(session); return NULL; } // 设置服务UUID(SPP的标准UUID是0x1101) uuid_t root_uuid, spp_uuid; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); sdp_uuid16_create(&spp_uuid, SERIAL_PORT_SVCLASS_ID); sdp_set_service_id(record, spp_uuid); // 添加服务类别 sdp_list_t *svclass = sdp_list_append(NULL, &spp_uuid); sdp_set_service_classes(record, svclass); // 添加协议信息(RFComm) sdp_list_t *proto = sdp_list_append(NULL, &spp_uuid); sdp_list_t *access_proto = sdp_list_append(NULL, proto); sdp_set_access_protos(record, access_proto); // 设置RFComm通道 uint8_t rfcomm_channel = channel; sdp_list_t *channel_list = sdp_list_append(NULL, &rfcomm_channel); sdp_set_rfcomm_channel(record, channel_list); // 设置服务名称 char service_name[] = "Linux RFComm Service"; sdp_set_info_attr(record, service_name, "RFComm communication with Linux app", "en"); // 注册服务 if (sdp_record_register(session, record, 0) != 0) { perror("Failed to register SDP record"); sdp_record_free(record); sdp_close(session); return NULL; } return session; }
在创建RFComm套接字后调用这个函数(确保通道号和监听的通道一致),程序退出时别忘了调用sdp_close(session)清理资源。
4. 常见调试技巧
- 检查适配器状态:运行
hciconfig hci0确认适配器已开启且处于可发现状态。 - 手动测试RFComm:用
rfcomm listen hci0 1启动一个简单监听器,再从Nrf Connect连接,验证基础连通性。 - 查看蓝牙日志:在Linux上用
journalctl -u bluetooth.service检查蓝牙守护进程的错误信息。 - Nrf Connect设置:在APP中进入"RFComm Clients"标签,扫描你的Linux设备,选择"Linux RFComm Service"连接——你应该能在程序输出中看到数据交互。
内容的提问来源于stack exchange,提问作者Naveen KH




