如何自动配对RPi和Android与蓝牙批处理脚本

e0bqpujr  于 2022-12-09  发布在  Android
关注(0)|答案(2)|浏览(199)

我正在做一个将Android设备与Raspberry Pi连接起来的项目。RPi需要被当作一个可部署的设备来对待,用户永远不需要触摸它。出于这个原因,我正在尝试在RPi上编写一个启动批处理脚本,允许用户将他们的Android设备与PI配对。
我的想法是,当你启动时,这个脚本将运行,用户在他们的手机上将尝试连接到RPi,RPi将自动接受这个连接。
这是我目前掌握的情况

#!/bin/bash
bluetoothctl -- discoverable on
bluetoothctl -- pairable on
bluetoothctl -- agent on
bluetoothctl -- default-agent

问题是,当我这样做的时候,我不会进入[bluetoothctl]提示符,我需要与Android通信。
当我运行这些命令(没有批处理脚本),并尝试与我的Android配对时,我得到

Request confirmation
[agent] Confirm passkey 861797 (yes/no): yes

从这里开始,我只需要输入yes来示例化连接。我不知道如何停留在[bluetoothctl]提示符内的命令行与设备进行通信和2:我不知道如何向提示符发送“是”。
同样,对我来说重要的是,用户除了为了部署目的而启动RPi之外,不需要对它做任何事情。有没有解决我的问题的方法,或者有没有更好的方法来一起完成这些工作?
对于那些感兴趣的人来说,蓝牙启动连接已经到位,这样我就可以向RPi发送网络信息,它可以自动将自己连接到网络,这样主要的应用程序通信就会以这种方式发生。
下面是我能够手动完成的脚本的预期结果。

fgw7neuy

fgw7neuy1#

以这种方式使用bluetoothctl可能会有问题,因为它不是设计成以这种方式交互的。因为你已经把Python作为标签之一,所以从Python(和其他语言)访问此功能的预期方式是通过D-Bus API。
这些记录在:https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc
下面是一些例子:https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test
确认是agent API中的RequestConfirmation。您也可以使用adapter API设置可发现和可配对。使用API还可以阻止可发现超时。
一旦手机连接好,你通常会把它标记为可信,这样就不需要再配对了,这可以通过device API来完成。
下面是一个用Python在适配器上设置这些属性的例子。我保留了所有的代理函数,尽管它只使用了RequestConfirmation。我已经将它设置为总是同意它发送的任何代码,这也是你在问题中要求的。
此Python脚本示例将替换批处理脚本

import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib

BUS_NAME = 'org.bluez'
ADAPTER_IFACE = 'org.bluez.Adapter1'
ADAPTER_ROOT = '/org/bluez/hci'
AGENT_IFACE = 'org.bluez.Agent1'
AGNT_MNGR_IFACE = 'org.bluez.AgentManager1'
AGENT_PATH = '/my/app/agent'
AGNT_MNGR_PATH = '/org/bluez'
CAPABILITY = 'KeyboardDisplay'
DEVICE_IFACE = 'org.bluez.Device1'
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()

def set_trusted(path):
    props = dbus.Interface(bus.get_object(BUS_NAME, path), dbus.PROPERTIES_IFACE)
    props.Set(DEVICE_IFACE, "Trusted", True)

class Agent(dbus.service.Object):

    @dbus.service.method(AGENT_IFACE,
                         in_signature="", out_signature="")
    def Release(self):
        print("Release")

    @dbus.service.method(AGENT_IFACE,
                         in_signature='o', out_signature='s')
    def RequestPinCode(self, device):
        print(f'RequestPinCode {device}')
        return '0000'

    @dbus.service.method(AGENT_IFACE,
                         in_signature="ou", out_signature="")
    def RequestConfirmation(self, device, passkey):
        print("RequestConfirmation (%s, %06d)" % (device, passkey))
        set_trusted(device)
        return

    @dbus.service.method(AGENT_IFACE,
                         in_signature="o", out_signature="")
    def RequestAuthorization(self, device):
        print("RequestAuthorization (%s)" % (device))
        auth = input("Authorize? (yes/no): ")
        if (auth == "yes"):
            return
        raise Rejected("Pairing rejected")

    @dbus.service.method(AGENT_IFACE,
                         in_signature="o", out_signature="u")
    def RequestPasskey(self, device):
        print("RequestPasskey (%s)" % (device))
        set_trusted(device)
        passkey = input("Enter passkey: ")
        return dbus.UInt32(passkey)

    @dbus.service.method(AGENT_IFACE,
                         in_signature="ouq", out_signature="")
    def DisplayPasskey(self, device, passkey, entered):
        print("DisplayPasskey (%s, %06u entered %u)" %
              (device, passkey, entered))

    @dbus.service.method(AGENT_IFACE,
                         in_signature="os", out_signature="")
    def DisplayPinCode(self, device, pincode):
        print("DisplayPinCode (%s, %s)" % (device, pincode))

class Adapter:
    def __init__(self, idx=0):
        bus = dbus.SystemBus()
        self.path = f'{ADAPTER_ROOT}{idx}'
        self.adapter_object = bus.get_object(BUS_NAME, self.path)
        self.adapter_props = dbus.Interface(self.adapter_object,
                                            dbus.PROPERTIES_IFACE)
        self.adapter_props.Set(ADAPTER_IFACE,
                               'DiscoverableTimeout', dbus.UInt32(0))
        self.adapter_props.Set(ADAPTER_IFACE,
                               'Discoverable', True)
        self.adapter_props.Set(ADAPTER_IFACE,
                               'PairableTimeout', dbus.UInt32(0))
        self.adapter_props.Set(ADAPTER_IFACE,
                               'Pairable', True)

if __name__ == '__main__':
    agent = Agent(bus, AGENT_PATH)
    agnt_mngr = dbus.Interface(bus.get_object(BUS_NAME, AGNT_MNGR_PATH),
                               AGNT_MNGR_IFACE)
    agnt_mngr.RegisterAgent(AGENT_PATH, CAPABILITY)
    agnt_mngr.RequestDefaultAgent(AGENT_PATH)

    adapter = Adapter()
    mainloop = GLib.MainLoop()
    try:
        mainloop.run()
    except KeyboardInterrupt:
        agnt_mngr.UnregisterAgent(AGENT_PATH)
        mainloop.quit()
k2fxgqgv

k2fxgqgv2#

在我的树莓派4与bluez以下将接受我的安卓手机配对,而不需要在树莓上键入任何东西。

sudo apt install bluez-tools 
sudo bt-agent  -c DisplayOnly -p ~/pins.txt &

pins.txt:

00:00:00:00:00:00 *
*                 *

请注意,无论-c参数如何,在bt-agent中添加-d都不起作用。因此在末尾添加了“&”符号。

相关问题