树莓派蓝牙-发送数据

3

在发布此贴之前,我试图寻找一种简单的程序,可以使用Rapsberry Pi通过BLE发送任何类型的数据。但是,随着我深入了解,我知道有一些BLE库支持在RPi上使用Python进行编程。我对Python网络编程很陌生,所以我正在寻找教程。每个教程都是关于如何连接RPi和某种手机使用BLE,它们并没有展示如何制作一个py脚本来发送一些传感器数据或类似的东西。请指导。


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Lasse Meyer
1
树莓派和BLE并没有什么特别的。只需要寻找Linux和BLE即可。Linux中的蓝牙协议栈被称为Bluez。 - Emil
Lasse:是的,我想那也会有所帮助。 - Joana Rigbi
1个回答

5
看下面的材料,从我在SO文档中创建的条目中复制而来。
最后,你基本上有一个类似TCP的套接字,可以发送任何数据。但我建议你使用ATT和GATT协议(请参阅蓝牙规范)。所有BLE设备都应该使用这些协议,但如果发送方和接收方都由你编程,则可以使用自己的、可能更简单的协议。
这不是针对RPi特定的,没有必要,因为几乎每个Linux发行版都使用相同的蓝牙堆栈,称为Bluez。您需要libbluetooth-dev包来开发自己的应用程序。
对于Python,您可以使用以下任一库: 您可以在这里找到第二个库的详细教程。它是为特定的蓝牙硬件制作的,但应该足以让您开始使用BLE。

打开L2CAP套接字进行低功耗通信

使用Bluez在C语言中实现

 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的套接字,而不是原始套接字),协议是蓝牙协议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选项将允许我们在必要时快速调用bind(这可以省略):

    setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));

接下来,我们需要将套接字与刚定义的源地址结构绑定。同样地,我们检查返回值以确保它能正常工作。

    result = bind(ssock, (struct sockaddr*) &src_addr, sizeof(src_addr));
    if (result < 0) {
        perror("Binding L2CAP socket failed");
        return -1;
    }

下一步是设置安全级别。请注意,此步骤是可选的,但将安全级别设置为MEDIUM将允许自动与设备配对(内核处理实际配对)。
    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 是一个被动套接字,将接受一个连接。第二个参数是 backlog。如果你想了解更多,listen 的 manpage 包含了你需要的所有信息。
    result = listen(ssock, 10);
    if (result < 0) {
        perror("Listening on L2CAP socket failed");
        return -1;
    }

现在我们可以等待传入连接。一旦accept返回,peer_addr结构将包含已连接设备的地址。csock将是我们可以从中读取/写入以与已连接设备通信的套接字文件描述符。
    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;
}

非常感谢。 我真的想知道它是否是RPi特定的,还是更像Linux BLE方面的东西。“昨天我找到了一些针对BLE的Python套接字编程教程。我将学习它们,然后根据我的需求进行修改。还有一件事,如果我读取传感器数据,那将是在某个文本文件中(因为Linux中的所有内容都是文件)。 所以我应该通过BLE发送该文本文件。 对吧? 手机应用程序将读取文本文件并对其进行一些处理。 再次感谢您的指导... - Joana Rigbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接