Capturando dados de um Fluke 1620a via Bash / dev / tcp file descripp

2

No momento, estou tentando desenvolver um script que se conecte a um Themo-Higrômetro Fluke DewK 1620a e extraia as leituras atuais de temperatura e umidade do dispositivo. Embora esses dispositivos tenham uma porta de rede, não parece haver um protocolo comum em escuta na porta. Eles simplesmente aceitam uma conexão TCP bruta. Eu posso conectar-se interativamente via netcat e putty, passar comandos e receber saída. Eu tentei scripting isso via netcat (Veja "Capturando dados de um Fluke 1620a via netcat ") , mas simplesmente não poderia fazê-lo funcionar. Desde então, descobri que posso realizar minha missão usando a capacidade única do Bash de abrir um arquivo descritor de leitura / gravação em uma conexão TCP. Embora agora eu seja capaz de capturar os dados em um arquivo, estou lutando com o que eu sei que são provavelmente alguns problemas básicos.

#!/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>&-

Eu sei que é feio, mas eu simplesmente não consigo descobrir como torná-lo mais eficiente. Meus principais problemas são:

  1. O "gato < & 3" causa todos os tipos de problemas. Não há EOF, então fica pendurado para sempre. Eu tentei um monte de abordagens diferentes usando a leitura, mas parece que não consigo fazê-lo funcionar. O "gato" parece ser a única maneira de obter os dados obtidos & escrito em um arquivo, mas tem que usar o 'pkill' apenas para impedir que ele amarre o sensor.
  2. Eu adoraria poder ler os resultados em uma variável como $ results, mas não consigo fazer isso com um "cat". Eu suspeito que estou sentindo falta de algo realmente simples, mas não consigo entender.
  3. A saída do Fluke volta como "76.05,56.3,72.89,59.0 ^ M". Eu sei que isso acontece porque ele não detecta um EOL, mas não sei como adicionar uma nova linha depois do "cat < & 3". Os resultados são um log semelhante a:

    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. Meu objetivo é escrever "$ {datetime} - $ {results}" em uma única linha para cada execução em um arquivo de log, mas não sei como combinar as linhas. Imagino que a resposta esteja em colocar os resultados em uma variável que eu possa usar.

Agradeço qualquer ajuda que possa receber. Eu tenho derramado através de páginas de manual, a documentação bash, posts de blog e este site é claro. A informação que eu colhi aqui é realmente a única razão pela qual eu vim até aqui. Estou simplesmente fora do meu alcance e obtendo um curso intensivo.

    
por DFarland 26.11.2014 / 13:18

1 resposta

0

Não estou claro se você recebe um resultado por read? ou se obtiver um fluxo de resultados. Eu acho que você está dizendo um pedido - > uma resposta. E você nunca deu um hexdump ou qualquer coisa da saída, mas parece que as terminações de linha são provavelmente CR-only, não DOS CR-LF ou LF unix. (É por isso que o seu prompt sobrescreve a saída após o netcat).

Eu encontrei o manual: link

Confirma que as respostas são encerradas com um CR. Isso faz com que seja difícil trabalhar com o shell, porque tr '\r' '\n' tem o mesmo problema que o cat: ele não para depois de uma linha.

# 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.

Ou uma implementação que permite que tr lidem com o CR - > Tradução 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"

Isto coloca um subshell em segundo plano, escrevendo um comando a cada segundo. Você ainda precisa de um loop de leitura para obter a hora atual formatada nas linhas recebidas. IDK se ^ C matar a subshell ou não.

Variáveis definidas dentro do loop não estarão presentes após o término, porque nós canalizamos para ele , no caso de você tentar isso.

Essa é uma pergunta antiga, então eu não executei isso. Pode haver erros de sintaxe ou erros. Mas a ideia geral é boa, tenho certeza.

    
por 19.04.2015 / 19:08