【问题标题】:Raspberry pi bluetooth - send data树莓派蓝牙——发送数据
【发布时间】:2016-12-07 22:12:15
【问题描述】:

在发布此之前,我尝试寻找简单的程序来使用带有 rapsberry pi 的 BLE 发送任何类型的数据。但我更详细地了解,我知道有一些 BLE 库支持在 RPi 上使用 Python 进行编程。我是 python 网络编程的新手,我正在寻找教程。每个教程都是关于如何使用 BLE 连接 RPi 和某种手机。他们没有展示如何制作一个 py 脚本来发送一些传感器数据或类似的东西。请指导。

【问题讨论】:

  • C 的教程可以吗?或者只是在寻找蟒蛇?我在此处的蓝牙文档上写了一个详细的教程,它刚刚获得批准,但如果您愿意,我可以将其发布在这里作为答案。
  • 树莓派和 BLE 并没有什么特别之处。只需寻找 Linux 和 BLE。 Linux 中的蓝牙堆栈称为 Bluez。
  • Lasse : 是的,我想这也会有所帮助。

标签: python bluetooth bluetooth-lowenergy


【解决方案1】:

请参阅下面的材料,从我创建的关于该主题的 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的套接字,而不是原始的),协议是蓝牙协议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 是一个被动套接字,它将接受一个连接。第二个参数是积压。如果您想了解更多,listen 的手册页包含您需要的所有信息。

    result = listen(ssock, 10);
    if (result < 0) {
        perror("Listening on L2CAP socket failed");
        return -1;
    }

现在我们可以等待传入的连接。 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 发送该文本文件。对吧?电话应用程序会读取文本文件并用它做一些事情。再次感谢您指导我..
猜你喜欢
  • 2018-06-16
  • 2017-03-30
  • 2013-04-09
  • 1970-01-01
  • 2022-01-22
  • 2021-04-03
  • 2014-12-05
  • 2020-11-03
  • 2022-10-20
相关资源
最近更新 更多