【问题标题】:BLE gatttool interactive shell scriptBLE gatttool 交互式 shell 脚本
【发布时间】:2018-06-28 15:45:03
【问题描述】:

我使用 gatttool 与 BLE 设备建立了连接。首先,我使用sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -Iconnect 连接到设备。之后,我用char-read-uuid 2d30c082-f39f-4ce6-923f-3484ea480596 读取了特定特征的值。

我想要做的是自动化整个过程并将后一个命令(查询值)放入循环中,理想情况下将每个值(附加)保存到文本文件中。我尝试了类似的东西

sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -I <<EOF
connect
while[ 1 ]; do
char-read-uuid 2d30c082-f39f-4ce6-923f-3484ea480596 > output.txt
done
exit 1
EOF

但这无济于事,因为我什至无法连接到设备(理想情况下,第一个命令和第二个命令之间应该有一些延迟)。同样在连接后,交互模式被启用,并且 shell 命令在那里不起作用。我会很感激有关如何解决此问题的任何线索。

【问题讨论】:

  • 如果您想坚持使用 bash 内置函数,我建议您查看 coprocesses。否则,如果您想让事情尽可能简单,socatEXEC: 形式可以是启动脚本的简单方法,其标准输入和标准输出附加到另一个命令的输入和输出。跨度>
  • ...也就是说,很多细节取决于...嗯... details,例如gattool 是否将提示写入stderr 或stdout。跨度>
  • 好的,看看这些。非常感谢!

标签: bash shell ubuntu bluetooth gatt


【解决方案1】:

如果gattool 将提示写入标准输出(并且在给定非 TTY 文件描述符的情况下不会抑制它们),请考虑以下内容:

#!/usr/bin/env bash
case $BASH_VERSION in ''|[123].*|4.0.*) echo "ERROR: bash 4.1 or newer required" >&2; exit 1;; esac

exec {output_fd}>output.txt

prompt_re='[>] '
capture_re='^handle:.*value:.*$'

wait_for_prompt() {
  IFS= read -r line || return
  while ! [[ $line =~ $prompt_re ]]; do
    [[ $line =~ $capture_re ]] && printf '%s\n' "$line" >&$output_fd
    IFS= read -r line || return
  done
}

wait_for_prompt
echo connect
while wait_for_prompt; do
  echo "char-read-uuid 2d30c082-f39f-4ce6-923f-3484ea480596"
done

...保存为yourscript,并使用socat 作为调用:

socat 'SYSTEM:sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -I 2>&1' 'EXEC:./yourscript'

(假设 sudo 配置为无需 TTY 即可工作;否则,您可能会将其移动为 sudo socat)。

【讨论】:

  • 非常感谢您的及时回复。我尝试了您的解决方案,但我一直收到错误2018/06/28 21:11:05 socat[13878] E waitpid(): child 13879 exited with status 1 在尝试查找错误的可能原因之前,我想问您是否认为“期望”(core.tcl.tk/expect/index)工具可能对我有用?我发现有人为此目的推荐它。
  • 耸耸肩。 expect 不是 bash 工具——它是一种完全不同的语言 (TCL),所以 bash 标签是谈论它的错误地方。就个人而言,我更喜欢 Python——所以我会使用 pexpect——甚至是 bash,其中 EmPTY 是更接近原生的工具。如果您的目标是嵌入式系统之类的东西,那么安装 TCL 解释器来驱动脚本是在大锤的领域。
  • 至于你得到的错误,很遗憾,如果我自己不能运行gatttool,我真的不能说任何有用的东西。您可以尝试我已经建议的调试途径(例如确保您的本地 sudo 配置在手头的非 TTY 场景中工作,或者以升级的权限运行整个事情以便能够删除它)。请注意,任一程序写入 stderr 的内容将在终端上可见,因此有足够的空间用于登录。
  • 谢谢您,非常感谢您的洞察力!看来pexpect 正是我需要的。
【解决方案2】:

确实,pexpect 在这里可以正常工作。你可以在下面找到我的解决方案。代码读取特定 UUID 的值,其中包含 IMU 读数(浮点数)。

import pexpect
import struct
import time
import sys

IMU_MAC_ADDRESS = "FF:3C:8F:22:C9:C8"
UUID_DATA = "2d30c082-f39f-4ce6-923f-3484ea480596"

if __name__ == '__main__':
    gatt = pexpect.spawn("gatttool -t random -b " + IMU_MAC_ADDRESS + " -I")
    gatt.sendline("connect")
    gatt.expect("Connection successful")

    while(True):
        gatt.sendline("char-read-uuid " + UUID_DATA)
        gatt.expect("handle: 0x0011      value: ")
        gatt.expect(" \r\n")
        data = (gatt.before).decode('UTF-8').replace(" ", "").decode('hex')
        print(struct.unpack('f', data)[0]

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 2016-05-29
    • 2015-06-29
    • 2017-03-11
    • 2012-07-03
    • 2011-08-31
    • 2017-02-13
    • 2021-07-11
    相关资源
    最近更新 更多