通过 Bash /dev/tcp 文件描述符从 Fluke 1620a 捕获数据

通过 Bash /dev/tcp 文件描述符从 Fluke 1620a 捕获数据

我目前正在尝试开发一个脚本,该脚本将连接到 Fluke DewK 1620a 温湿度计并从设备中提取当前的温度和湿度读数。虽然这些设备上有一个网络端口,但该端口上似乎没有通用协议侦听。它们只是接受原始 TCP 连接。我可以通过 netcat 和 putty 进行交互连接、传递命令并接收输出。我尝试通过 netcat 编写脚本(请参阅“通过 netcat 从 Fluke 1620a 捕获数据”),但根本无法使其发挥作用。从那时起,我发现我可以使用 Bash 的独特功能来完成我的任务,即在 TCP 连接上打开文件描述符读/写。虽然我现在能够将数据捕获到文件中,但我正在努力解决我所知道的可能是一些非常基本的问题。

#!/bin/bash

$host=1.2.3.4
$port=10001
$location=lab1
$log=${location}_DewK.log
$datetime=$(date +%F_%T)

exec 3<>/dev/tcp/${host}/${port}
echo -e "read?" >&3                 # Sends the read? command to the Fluke.
printf ${datetime} >> ${log}        # Inserts a timestamp to the log.
cat <&3 | tee -a ${log} &           # Tee was the only way I could get it to log.
sleep 1 && pkill cat                # The cat just hangs out there & will not end.
exec 3<&-
exec 3>&-

我知道它很丑陋,但我似乎无法弄清楚如何提高它的效率。我的主要问题是:

  1. “cat <&3”会导致各种问题。没有 EOF,所以它永远挂在那里。我已经使用 read 尝试了很多不同的方法,但似乎无法让它工作。 “cat”似乎是我可以将数据提取并写入文件的唯一方法,但必须使用“pkill”以防止它占用传感器。
  2. 我很想将结果读入 $results 之类的变量中,但似乎无法使用“cat”来实现这一点。我怀疑我遗漏了一些非常简单的东西,但似乎无法弄清楚。
  3. Fluke 的输出类似于“76.05,56.3,72.89,59.0^M”。我知道这是因为它没有检测到 EOL,但我不知道如何在“cat <&3”之后添加新行。结果是一个如下所示的日志:

    2014-11-26_07:09:03

    75.75,56.4,72.53,59.7^M2014-11-26_07:09:05

    75.75,56.4,72.54,59.7^M2014-11-26_07:09:07

    75.75,56.4,72.53,59.7^M

  4. 我的目标是在每次运行时将“${datetime} - ${results}”写入日志文件的一行,但我不知道如何组合这些行。我想答案在于将结果放入我可以使用的变量中。

我很感激我能得到的任何帮助。我一直在翻阅手册页、bash 文档、博客文章,当然还有这个网站。我在这里收集的信息确实是我走到这一步的唯一原因。我只是超出了我的能力范围,正在参加速成课程。

答案1

我不清楚您是否得到每个结果一个结果read?,或者是否得到一串结果。我认为你说的是​​一个请求->一个回复。而且您从未提供过十六进制转储或任何输出,但看起来行结尾可能只是 CR,而不是 DOS CR-LF 或 unix LF。 (这就是为什么你的提示会覆盖 netcat 之后的输出。)

我确实找到了手册: http://us.flukecal.com/literature/product-manuals/1620a-user%E2%80%99s-guide

它确认响应以 CR 终止。这使得在 shell 中使用变得非常痛苦,因为它tr '\r' '\n'有与 cat 相同的问题:它不会在一行之后停止。

# read -d sets the delimiter.
#  $'' is a special type of quoting where \r expands to a literal carriage return.
get_temp () {  # io to fluke on FD 3
    echo "read?" >&3
    local resp
    IFS=  read resp -d $'\r' -u 3
    printf '%s\n' "$resp"
}

exec 3<>"/dev/tcp/$host/$port"
while true; do  # whole loop is redirected to log
    temp="$( get_temp )"
    printf '%s - %s\n'  "$(date +%F_%T)" "$temp"
    # or  echo -n "$(date) - "; get_temp
    sleep 1
done | tee -a "$log"
#  or just  >> "$log", and tail -f the log file when you want it on screen.

tr或者一个处理 CR -> LF 转换的实现:

exec 3<>"/dev/tcp/$host/$port"
(while echo 'read?';do sleep 1;done >&3) &

tr -d '\r' '\n' <&3 | IFS= while read temp; do
    printf '%s - %s\n' "$(date +%F_%T)" "$temp"
done >> "$log"

这会在后台放置一个子 shell,每秒写入一个命令。您仍然需要一个读取循环来将当前时间格式化为接收到的行。我不知道 ^C 是否会杀死子 shell。

循环内设置的变量在循环结束后将不会出现,因为我们通过管道输入了它,如果你想尝试的话。

这是一个老问题,所以我实际上没有运行这些。可能存在语法错误或错误。但我很确定,总体想法是合理的。

相关内容