Raspberry pi 蓝牙 - 发送数据
Raspberry pi bluetooth - send data
在发布这篇文章之前,我尝试寻找简单的程序来使用 BLE 和 rapsberry pi 发送任何类型的数据。但是我得到的更多细节,我知道有一些 BLE 库支持在 RPi 上使用 Python 进行编程。我是 python 网络编程的新手,正在寻找教程。每个教程都是关于如何使用 BLE.They 连接 RPi 和某种 phone 的,但不展示如何制作 py 脚本来发送一些传感器数据或类似的东西。请指导。
请参阅下面的 material,复制自我在该主题上创建的 SO 文档条目。
最后,您基本上有了一个类似 TCP 的套接字,您可以通过它发送任何数据。但我建议您使用 ATT 和 GATT 协议(请参阅蓝牙规范)。所有 BLE 设备都应该使用这些协议,但如果发送方和接收方都由您编程,您可以使用自己的协议,也许更简单。
这不是特定于 RPi 的,没有必要,因为几乎每个 Linux 发行版都使用相同的蓝牙堆栈,称为 Bluez。您需要 libbluetooth-dev
包来使用它开发您自己的应用程序。
对于 Python,您可以使用以下任一库:
您可以找到第二个的详尽教程 here。它是为特定的蓝牙硬件制作的,但它应该足以让您使用 BLE。
为低能耗通信打开 L2CAP 套接字
在 C 中,使用 Bluez
int get_l2cap_connection () {
首先,我们需要的所有变量,解释将在适当的位置。
int ssock = 0;
int csock = 0;
int reuse_addr = 1;
struct sockaddr_l2 src_addr;
struct bt_security bt_sec;
int result = 0;
首先,我们需要创建一个套接字,我们可以从中接受连接。套接字家族是PF_BLUETOOTH
,套接字类型是SOCK_SEQPACKET
(我们想要一个类似TCP的套接字,不是raw),协议是蓝牙协议L2CAP(BTPROTO_L2CAP
)。
ssock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
我们想确保它是成功的:
if (ssock < 0) {
perror("Opening L2CAP socket failed");
return -1;
}
我们现在必须用通配符地址填充源地址结构,这样任何具有任何地址的蓝牙设备都可以连接到我们。通配符地址在bluetooth.h
中定义为BDADDR_ANY
。要将其复制到地址结构中,我们可以使用 bacpy
函数。我们还必须设置地址族、地址类型和通道 ID。
memset(&src_addr, 0, sizeof(src_addr));
bacpy(&src_addr.l2_bdaddr, BDADDR_ANY);
src_addr.l2_family = AF_BLUETOOTH;
src_addr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
src_addr.l2_cid = htobs(CID_ATT);
设置SO_REUSEADDR选项将允许我们在必要时再次快速调用绑定(可以省略):
setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
接下来我们必须将套接字与我们刚刚定义的源地址结构绑定。我们再次检查 return 值以确保它有效。
result = bind(ssock, (struct sockaddr*) &src_addr, sizeof(src_addr));
if (result < 0) {
perror("Binding L2CAP socket failed");
return -1;
}
接下来是设置安全级别。请注意,此步骤是可选的,但将安全级别设置为“中”将允许与设备自动配对(内核处理实际配对)。
memset(&bt_sec, 0, sizeof(bt_sec));
bt_sec.level = BT_SECURITY_MEDIUM;
result = setsockopt(ssock, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, sizeof(bt_sec));
if (result != 0) {
perrorno("Setting L2CAP security level failed");
return -1;
}
现在我们可以告诉内核我们的 ssock 是一个被动套接字,它将接受一个连接。第二个参数是积压。如果您想了解更多,listen 的联机帮助页包含您需要的所有信息。
result = listen(ssock, 10);
if (result < 0) {
perror("Listening on L2CAP socket failed");
return -1;
}
现在我们可以等待传入连接。 peer_addr结构将包含连接设备的地址,一旦接受returns。 csock 将是我们可以读取 from/write 的套接字的文件描述符,以与连接的设备进行通信。
memset(peer_addr, 0, sizeof(*peer_addr));
socklen_t addrlen = sizeof(*peer_addr);
csock = accept(ssock, (struct sockaddr*)peer_addr, &addrlen);
if (csock < 0) {
perror("Accepting connection on L2CAP socket failed");
return -1;
}
我们可以打印连接设备的地址(当然是可选的)。我们可以使用batostr函数将蓝牙地址转换为字符串。
printf("Accepted connection from %s", batostr(&peer_addr->l2_bdaddr));
如果我们不想连接任何其他设备,我们应该关闭服务器套接字。在与设备的通信完成后,对 csock 执行相同的操作。
close(ssock);
return csock;
}
在发布这篇文章之前,我尝试寻找简单的程序来使用 BLE 和 rapsberry pi 发送任何类型的数据。但是我得到的更多细节,我知道有一些 BLE 库支持在 RPi 上使用 Python 进行编程。我是 python 网络编程的新手,正在寻找教程。每个教程都是关于如何使用 BLE.They 连接 RPi 和某种 phone 的,但不展示如何制作 py 脚本来发送一些传感器数据或类似的东西。请指导。
请参阅下面的 material,复制自我在该主题上创建的 SO 文档条目。
最后,您基本上有了一个类似 TCP 的套接字,您可以通过它发送任何数据。但我建议您使用 ATT 和 GATT 协议(请参阅蓝牙规范)。所有 BLE 设备都应该使用这些协议,但如果发送方和接收方都由您编程,您可以使用自己的协议,也许更简单。
这不是特定于 RPi 的,没有必要,因为几乎每个 Linux 发行版都使用相同的蓝牙堆栈,称为 Bluez。您需要 libbluetooth-dev
包来使用它开发您自己的应用程序。
对于 Python,您可以使用以下任一库:
您可以找到第二个的详尽教程 here。它是为特定的蓝牙硬件制作的,但它应该足以让您使用 BLE。
为低能耗通信打开 L2CAP 套接字
在 C 中,使用 Bluez
int get_l2cap_connection () {
首先,我们需要的所有变量,解释将在适当的位置。
int ssock = 0;
int csock = 0;
int reuse_addr = 1;
struct sockaddr_l2 src_addr;
struct bt_security bt_sec;
int result = 0;
首先,我们需要创建一个套接字,我们可以从中接受连接。套接字家族是PF_BLUETOOTH
,套接字类型是SOCK_SEQPACKET
(我们想要一个类似TCP的套接字,不是raw),协议是蓝牙协议L2CAP(BTPROTO_L2CAP
)。
ssock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
我们想确保它是成功的:
if (ssock < 0) {
perror("Opening L2CAP socket failed");
return -1;
}
我们现在必须用通配符地址填充源地址结构,这样任何具有任何地址的蓝牙设备都可以连接到我们。通配符地址在bluetooth.h
中定义为BDADDR_ANY
。要将其复制到地址结构中,我们可以使用 bacpy
函数。我们还必须设置地址族、地址类型和通道 ID。
memset(&src_addr, 0, sizeof(src_addr));
bacpy(&src_addr.l2_bdaddr, BDADDR_ANY);
src_addr.l2_family = AF_BLUETOOTH;
src_addr.l2_bdaddr_type = BDADDR_LE_PUBLIC;
src_addr.l2_cid = htobs(CID_ATT);
设置SO_REUSEADDR选项将允许我们在必要时再次快速调用绑定(可以省略):
setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
接下来我们必须将套接字与我们刚刚定义的源地址结构绑定。我们再次检查 return 值以确保它有效。
result = bind(ssock, (struct sockaddr*) &src_addr, sizeof(src_addr));
if (result < 0) {
perror("Binding L2CAP socket failed");
return -1;
}
接下来是设置安全级别。请注意,此步骤是可选的,但将安全级别设置为“中”将允许与设备自动配对(内核处理实际配对)。
memset(&bt_sec, 0, sizeof(bt_sec));
bt_sec.level = BT_SECURITY_MEDIUM;
result = setsockopt(ssock, SOL_BLUETOOTH, BT_SECURITY, &bt_sec, sizeof(bt_sec));
if (result != 0) {
perrorno("Setting L2CAP security level failed");
return -1;
}
现在我们可以告诉内核我们的 ssock 是一个被动套接字,它将接受一个连接。第二个参数是积压。如果您想了解更多,listen 的联机帮助页包含您需要的所有信息。
result = listen(ssock, 10);
if (result < 0) {
perror("Listening on L2CAP socket failed");
return -1;
}
现在我们可以等待传入连接。 peer_addr结构将包含连接设备的地址,一旦接受returns。 csock 将是我们可以读取 from/write 的套接字的文件描述符,以与连接的设备进行通信。
memset(peer_addr, 0, sizeof(*peer_addr));
socklen_t addrlen = sizeof(*peer_addr);
csock = accept(ssock, (struct sockaddr*)peer_addr, &addrlen);
if (csock < 0) {
perror("Accepting connection on L2CAP socket failed");
return -1;
}
我们可以打印连接设备的地址(当然是可选的)。我们可以使用batostr函数将蓝牙地址转换为字符串。
printf("Accepted connection from %s", batostr(&peer_addr->l2_bdaddr));
如果我们不想连接任何其他设备,我们应该关闭服务器套接字。在与设备的通信完成后,对 csock 执行相同的操作。
close(ssock);
return csock;
}