BLE gatttool 交互式 shell 脚本
BLE gatttool interactive shell script
我使用 gatttool 与 BLE 设备建立了连接。首先,我使用 sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -I
和 connect
连接到设备。之后我用 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 命令在那里不起作用。如果能提供有关如何解决此问题的任何线索,我将不胜感激。
如果 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
)。
的确,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]
我使用 gatttool 与 BLE 设备建立了连接。首先,我使用 sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -I
和 connect
连接到设备。之后我用 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 命令在那里不起作用。如果能提供有关如何解决此问题的任何线索,我将不胜感激。
如果 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
)。
的确,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]