如何将基于 L2CAP 的蓝牙相机快门(AB 快门 3)连接到 Linux 并在 Python 中获取按键事件?
How do I connect a L2CAP-based Bluetooth Camera Shutter (AB Shutter 3) to Linux and get the key event in Python?
目标
我有一个 HITSLAM Camera Shutter Bluetooth button(这是一个 AB Shutter 3 设备,一个常见的蓝牙相机遥控器),我想使用蓝牙连接到我的 NVIDIA Jetson Nano,这样我就可以使用按钮的输入为了一些任务。
我做了什么
我正在使用 PyBluez 库进行连接。我使用以下命令找出 AB Shutter 3 使用的端口和协议(其中 target_device_address
是 AB Shutter 3 的设备地址):
service_matches = bt.find_service(name=None,uuid=None,address=target_device_address)
first_match = service_matches[0]
print("Port {}, Name {}, Host {}, Protocol {}".format(first_match['port'], first_match['name'], first_match['host'], first_match['protocol']))
这就是我获取要连接的端口 (17) 及其使用的协议 (L2CAP) 的方式。
现在,我尝试使用以下方式连接到它:
client_sock = bt.BluetoothSocket(bt.L2CAP)
client_sock.connect((target_device_address,port))
我还使用了 Python 的原生 socket
库(得到了相同的结果):
client_sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP)
client_sock.connect((target_device_address,port))
根据hcitool
连接成功,然后等待用户输入:
if target_device_address in (subprocess.getoutput("hcitool con")).split():
print('connected')
while True:
data = client_sock.recv(1024)
print(str(data))
问题
- 该设备实际上并未显示为
/dev/input/
中的输入。当我通过 GUI 手动连接它时,它显示为 /dev/input/event5
.
- 连接后,我的脚本没有捕获输入。
我的问题
- 如何根据
hcitool con
连接但未注册为输入设备(并注册任何输入)?
- 你建议做什么?我到处都看过,似乎没有找到合适的解决方案。有一个 workaround with implementing a bash script that uses
bluetoothctl
可以连接到蓝牙遥控器,但我不明白为什么 Python 无法建立此连接并检索信息。
我的建议是不要使用 hcitool
,因为它在 2017 年是 deprecated。
我更喜欢直接使用 BlueZ D-Bus API,记录在:https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt
这可以在 Python 中使用 pydbus 库进行访问
我假设你的蓝牙适配器在 Jetson 上 hci0
,但你可以通过以下方式检查:
$ busctl tree org.bluez
└─/org
└─/org/bluez
└─/org/bluez/hci0
这将使代码类似于:
import pydbus
DEVICE_ADDR = '11:22:22:E7:CE:BE'
# DBus object paths
BLUEZ_SERVICE = 'org.bluez'
ADAPTER_PATH = '/org/bluez/hci0'
device_path = f"{ADAPTER_PATH}/dev_{DEVICE_ADDR.upper().replace(':', '_')}"
# setup dbus
bus = pydbus.SystemBus()
mngr = bus.get(BLUEZ_SERVICE, '/')
adapter = bus.get(BLUEZ_SERVICE, ADAPTER_PATH)
device = bus.get(BLUEZ_SERVICE, device_path)
device.Connect()
这应该在 /dev/input/
处创建事件,我将使用 python 库 evdev 获取输入,就像在以下问题中所做的那样:
目标
我有一个 HITSLAM Camera Shutter Bluetooth button(这是一个 AB Shutter 3 设备,一个常见的蓝牙相机遥控器),我想使用蓝牙连接到我的 NVIDIA Jetson Nano,这样我就可以使用按钮的输入为了一些任务。
我做了什么
我正在使用 PyBluez 库进行连接。我使用以下命令找出 AB Shutter 3 使用的端口和协议(其中 target_device_address
是 AB Shutter 3 的设备地址):
service_matches = bt.find_service(name=None,uuid=None,address=target_device_address)
first_match = service_matches[0]
print("Port {}, Name {}, Host {}, Protocol {}".format(first_match['port'], first_match['name'], first_match['host'], first_match['protocol']))
这就是我获取要连接的端口 (17) 及其使用的协议 (L2CAP) 的方式。
现在,我尝试使用以下方式连接到它:
client_sock = bt.BluetoothSocket(bt.L2CAP)
client_sock.connect((target_device_address,port))
我还使用了 Python 的原生 socket
库(得到了相同的结果):
client_sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP)
client_sock.connect((target_device_address,port))
根据hcitool
连接成功,然后等待用户输入:
if target_device_address in (subprocess.getoutput("hcitool con")).split():
print('connected')
while True:
data = client_sock.recv(1024)
print(str(data))
问题
- 该设备实际上并未显示为
/dev/input/
中的输入。当我通过 GUI 手动连接它时,它显示为/dev/input/event5
. - 连接后,我的脚本没有捕获输入。
我的问题
- 如何根据
hcitool con
连接但未注册为输入设备(并注册任何输入)? - 你建议做什么?我到处都看过,似乎没有找到合适的解决方案。有一个 workaround with implementing a bash script that uses
bluetoothctl
可以连接到蓝牙遥控器,但我不明白为什么 Python 无法建立此连接并检索信息。
我的建议是不要使用 hcitool
,因为它在 2017 年是 deprecated。
我更喜欢直接使用 BlueZ D-Bus API,记录在:https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt
这可以在 Python 中使用 pydbus 库进行访问
我假设你的蓝牙适配器在 Jetson 上 hci0
,但你可以通过以下方式检查:
$ busctl tree org.bluez
└─/org
└─/org/bluez
└─/org/bluez/hci0
这将使代码类似于:
import pydbus
DEVICE_ADDR = '11:22:22:E7:CE:BE'
# DBus object paths
BLUEZ_SERVICE = 'org.bluez'
ADAPTER_PATH = '/org/bluez/hci0'
device_path = f"{ADAPTER_PATH}/dev_{DEVICE_ADDR.upper().replace(':', '_')}"
# setup dbus
bus = pydbus.SystemBus()
mngr = bus.get(BLUEZ_SERVICE, '/')
adapter = bus.get(BLUEZ_SERVICE, ADAPTER_PATH)
device = bus.get(BLUEZ_SERVICE, device_path)
device.Connect()
这应该在 /dev/input/
处创建事件,我将使用 python 库 evdev 获取输入,就像在以下问题中所做的那样: