我有一些设备,连接到串行端口。实际上,它是Arduino
基于温度传感器的。
我希望编写一个脚本,它将连接到串行端口,向设备发送命令,接收它的答案,打印它stdout
并退出。
执行此操作的正确方法是什么?
通常,当访问本地程序时,重定向其输出就可以了。例如,这就是我读取CPU
温度的方式。
datetime=$(date +%Y%m%d%H%M%S)
cputemp=$(sensors atk0110-acpi-0 | sed "s/CPU Temperature:[^0-9]*\([0-9\.]\+\).*/\1/;tx;d;:x")
echo "$datetime\t$cputemp"
不幸的是,$()
它依赖于显式的程序结束,而串行通信则不然。串行服务器始终在线并且没有显式的“会话”。
当然,我可以检查换行。但这是正确的做法吗?也许我应该编写我的Arduino
程序,以便它Ctrl-Z
在每次响应或其他内容后发送?
答案1
正如您所说,您无法从串行端口读取文件结尾。 (Ctrl-Z 是微软的东西)。因此,通常情况下,您会一直读取直到获得所需的字符数,或者直到找到一个分隔符(例如表示数据结束的换行符)。
例如,我有一个 USB 串行端口,其输出连接回输入,因此对设备的任何写入都会直接返回。以下脚本可以检索设备发送的内容:
#!/bin/bash
tty=/dev/ttyUSB0
exec 4<$tty 5>$tty
stty -F $tty 9600 -echo
echo abcdef >&5
read reply <&4
echo "reply is $reply"
该脚本将串行设备连接为文件描述符 4 用于输入,5 用于输出,设置速度并停止 tty 获得的回显,然后将“abcdef”和换行符写入设备。每个字符将立即发送回,但内核驱动程序将缓冲一些输入,因此我不需要在写入之前开始从设备读取。默认情况下,读取在看到换行符时结束,并将其保存在变量 中reply
,然后回显到标准输出。您可以将此脚本放入v=$()
类型用法中。
如果您的串行设备数据不以换行符结尾,您可以使用 为 bash 读取指定不同的分隔符-d
。或者,如果回复的长度是恒定的,您可以使用 指定长度-n
。如果您有二进制数据,您可能应该添加raw
到 stty 命令以停止对输入的任何特殊处理。