蓝牙监控程序延迟问题(btmon 和 python3)

问题描述 投票:0回答:1

我目前正在开发一个Python程序,通过使用btmon来监控蓝牙设备。但是,我遇到了一个问题,蓝牙设备上的按键(在 btmon 中即时注册)和 Python 程序中的输出之间似乎存在延迟。

本质上,我正在尝试从我的 BT 设备读取原始数据,并在按向左或向右时触发事件。这是我的电子阅读器的 BT 戒指;)

我有 2 个终端,用我的程序打开其中一个,该程序在其故障排除表单中仅用于打印来自 BTmon 的数据。 BTmon 显示按键的即时反馈,而我的程序仅在我按下至少两次后才显示按键。

当最终打印时,它会立即显示所有按键以及最新按键的时间戳。

例如,我在 1300 按一次,它永远不会在我的程序中打印

我在 1305 处再次按下,它将显示为两次按键。

如果我彼此按一秒钟,我将需要第三次按键。

这种行为表明某种缓冲区 - 或者有什么我完全错过的?

我尝试过的:

案例 1:使用 subprocess.Popen 运行 btmon 并逐行打印其输出。

案例2:与案例1类似,但使用函数连续打印btmon输出。

案例 3:尝试使用 iter 尽快处理 btmon 输出中的行。

案例 4:使用 subprocess.Popen 与 PIPE 和 universal_newlines=True 逐行打印输出。

案例 5:利用带有 subprocess.Popen 的循环来连续打印 btmon 输出,直到完成。

所有结果都完全相同。

请求协助:

我正在寻求帮助以了解为什么蓝牙设备按键和 Python 程序中的输出之间存在延迟。我的方法中是否缺少某些内容,或者是否有更好的方法在 Python 中从 btmon 捕获实时数据?

Case 1:
import subprocess

def run_btmon():
    btmon_process = subprocess.Popen(["sudo", "btmon"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True)

    for line in btmon_process.stdout:
        print(line.strip())

def main():
    run_btmon()

if __name__ == "__main__":
    main()

Case 2:
import subprocess

def capture_bluetooth_data():
    btmon_process = subprocess.Popen(["sudo", "btmon"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    
    for line in btmon_process.stdout:
        print(line.strip())

def main():
    capture_bluetooth_data()

if __name__ == "__main__":
    main()

Case 3:
import subprocess

def capture_bluetooth_data():
    btmon_process = subprocess.Popen(["sudo", "btmon"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    
    for line in iter(btmon_process.stdout.readline, ""):
        print(line.strip())

def main():
    capture_bluetooth_data()

if __name__ == "__main__":
    main()

Case 4:
from subprocess import Popen, PIPE, CalledProcessError

def capture_bluetooth_data():
    with Popen(["sudo", "btmon"], stdout=PIPE, bufsize=1, universal_newlines=True) as p:
        for line in p.stdout:
            print(line.strip())

        if p.returncode != 0:
            raise CalledProcessError(p.returncode, p.args)

def main():
    capture_bluetooth_data()

if __name__ == "__main__":
    main()

Case 5:
import subprocess
import sys

def capture_bluetooth_data():
    process = subprocess.Popen(["sudo", "btmon"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)

    while True:
        nextline = process.stdout.readline()
        if nextline == '' and process.poll() is not None:
            break
        print(nextline.strip())
        sys.stdout.flush()

    output, _ = process.communicate()
    exit_code = process.returncode

    if exit_code != 0:
        raise subprocess.CalledProcessError(exit_code, ["sudo", "btmon"])

def main():
    capture_bluetooth_data()

if __name__ == "__main__":
    main()
python-3.x bluetooth
1个回答
0
投票

您在蓝牙设备上的按键与 Python 程序中的输出之间遇到的延迟问题可能源于 btmon 与您的程序之间的通信缓冲。 作为解决方案,您可以将非阻塞 I/O 与

select
一起使用: 使用select模块实现非阻塞I/O。这允许您的程序检查来自 btmon 的可用数据,而无需等待缓冲区已满。 您还可以使用
sys.stdout.buffer.write(data)
而不是
print(data)
以更细粒度的方式将数据写入标准输出,从而可能减少缓冲延迟。

© www.soinside.com 2019 - 2024. All rights reserved.