Como conectar-se a uma porta serial tão simples quanto usar SSH?

86

Existe uma maneira de conectar-se a um terminal serial como você faria com o SSH? Deve haver uma maneira mais simples do que ferramentas como Minicom, como esta

$ serial /dev/ttyS0 

Eu sei que consigo cata saída, /dev/ttyS0mas apenas uma maneira de comunicação é possível dessa maneira, da porta para o console. E echosair para o porto é o mesmo, mas o contrário, para o porto.

Como posso realizar a comunicação bidirecional com uma porta serial da maneira mais simples possível no Unix / Linux?

ihatetoregister
fonte
2
Ótimas respostas, pessoal! Infelizmente, ninguém parece se encaixar totalmente no meu propósito ao trabalhar com sistemas embarcados com um conjunto limitado de comandos. No entanto, encontrei outra maneira de usar um script de shell que adicionei como uma das respostas à minha pergunta.
Ihatetoregister 18/10/11

Respostas:

69

Acho screeno programa mais útil para comunicação serial, já que eu o uso para outras coisas. Geralmente é apenas screen /dev/ttyS0 <speed>, embora as configurações padrão possam ser diferentes para o seu dispositivo. Também permite canalizar qualquer coisa para a sessão, entrando no modo de comando e executando exec !! <run some program that generates output>.

Shawn J. Goff
fonte
3
+1 para tela! Além disso, consulte: serverfault.com/q/81544/11086
Josh
11
Veja também noah.org/wiki/Screen_notes#using_screen_as_a_serial_terminal e a página de manual stty (1), tive que adicionar opções extras (por exemplo, paridade) para que funcionasse.
Lekensteyn
3
sente vergonha eu erroneamente ligados a TX / RX: o
Lekensteyn
screené incrível, mas não acho que seja mais simples do que minicom:-)
Ciro Santilli
11
@CiroSantilli 法轮功 死 六四 事件 法轮功 - A tela pode não ser mais simples que o Minicom, mas como já uso o Screen, para mim é menos complexo fazer minhas coisas em série com o Screen, eliminando totalmente a necessidade do Minicom.
yeti 02/09
48

fundo

A principal razão pela qual você precisa de algum programa como minicomse comunicar através de uma porta serial é que a porta precisa ser configurada antes de iniciar uma conexão. Se não foram configurados adequadamente, os comandos cate echonão farão por você o que você poderia esperar. Observe que quando você executa um programa como o minicom, a porta fica com as configurações minicomusadas. Você pode consultar as configurações de comunicação usando o sttyprograma como este:

stty < /dev/ttyS0

Se você fez certo; depois de inicializar o computador e antes de executar qualquer outro programa, como minicom,as configurações de comunicação, elas estarão nas configurações padrão. Provavelmente, são diferentes do que você precisará para fazer sua conexão. Nessa situação, o envio dos comandos catou echopara a porta produzirá lixo ou não funcionará.

Execute sttynovamente após o uso minicome você notará que as configurações estão definidas para o que o programa estava usando.

Comunicação serial mínima

Basicamente, são necessárias duas coisas para se ter uma comunicação bidirecional por meio de uma porta serial: 1) configurar a porta serial e 2) abrir a pseudo-tty leitura / gravação.

O programa mais básico que eu sei que faz isso é picocom. Você também pode usar uma ferramenta como setserialconfigurar a porta e interagir com ela diretamente a partir do shell.

rozcietrzewiacz
fonte
5
picocomtambém permitirá que você se conecte a uma porta serial sem reconfigurá-la ( --noinit) e permitirá que você saia sem restaurar a configuração da porta serial ( --noresetou use Ctrl-A/ Ctrl-Qpara sair picocom). Eu achei picocommuito mais fácil de usar do que minicom. Por razões que ainda não descobri, o minicom simplesmente não envia nem recebe dados em uma porta que funcionou momentos antes ou com a qual a picocom não tem problemas. Provavelmente é alguma opção de configuração misteriosa, mas, seja o que for, não consigo descobrir (e esse comportamento aconteceu em mais de uma máquina).
Michael Burr
+1 para picocom! Eu descobri que não era capaz de escrever comandos no dispositivo serial sem as terminações de linha corretas: eu precisava usar as --omap crcrlf --echoopções
user2561747
24

Se o UUCP estiver instalado no sistema, você pode usar o comando cu , por exemplo

 $ cu -l /dev/ttyS0 -s 9600
ktf
fonte
Use ~^Dou ~.para sair.
iman 14/09
24

Eu encontrei uma maneira de usar um script de shell aqui que coloca catcomo um processo em segundo plano e um loop while que lê a entrada do usuário e echoa envia para a porta. Eu o modifiquei para ser mais geral e se encaixou perfeitamente no meu propósito.

#!/bin/sh

# connect.sh

# Usage:
# $ connect.sh <device> <port speed>
# Example: connect.sh /dev/ttyS0 9600

# Set up device
stty -F $1 $2

# Let cat read the device $1 in the background
cat $1 &

# Capture PID of background process so it is possible to terminate it when done
bgPid=$!

# Read commands from user, send them to device $1
while read cmd
do
   echo "$cmd" 
done > $1

# Terminate background read process
kill $bgPid
ihatetoregister
fonte
11
Além disso, fiz uma versão ligeiramente modificada abaixo, que também pode enviar Ctrl + C e Ctrl + Z.
Fritz
@ Fritz Nice encontrar! Então, se eu acertar, o processo em segundo plano nunca seria morto porque $? não parece expandir para algo certo?
Ihatetoregister 26/09/16
11
@ ihatetoregister: Não é bem correto. O processo em segundo plano é interrompido, mas não pelos motivos que se pode esperar. $?expande para o código de saída do último comando que não é de segundo plano (nesse caso stty -F $1 $2); portanto, expande para 0 quando não houve erro. Assim, torna-se a última linha kill 0que, por sua vez, parece matar a concha atual e todos os seus filhos (ela se comporta de maneira diferente em conchas interativas, acredito). Para todos os detalhes, consulte a seguinte explicação: unix.stackexchange.com/questions/67532/…
Fritz
11
No entanto, a verdadeira pegadinha do seu script é que o processo em segundo plano é eliminado se você pressionar Ctrl + D para finalizar o script, porque isso encerra o whileloop de maneira limpa. Se você matá-lo com Ctrl + C ou com o killcomando, o catprocesso permanece ativo. Para corrigir isso, você precisaria usar o trapcomando para executar kill $bgPidquando o shell sair, como meu script abaixo . Honestamente, eu nem me importaria se você tivesse adicionado todo o meu script à sua postagem. Eu tentei fazer isso, mas a edição foi rejeitada.
Fritz
Poderia, por favor, esclarecer onde a conexão entra, pois isso é comentado em sua resposta
Chris Halcrow
14

Tente http://tio.github.io

"tio" é um aplicativo de terminal TTY simples, que possui uma interface direta de linha de comando para conectar-se facilmente a dispositivos TTY para entrada / saída básica.

O uso típico é sem opções. Por exemplo:

tio /dev/ttyS0

Que corresponde às opções mais usadas:

tio --baudrate 115200 --databits 8 --flow none --stopbits 1 --parity none /dev/ttyS0

Ele vem com suporte completo para preenchimento automático de shell para todas as opções.

Martin
fonte
3
Eu estou usando msys2no Windows e você pode instalar tiocom pacman -S tioporque é entre os pacotes disponíveis por padrão. screen, picocometc. não são. Obrigado!
Kohányi Róbert
12

Esse script é baseado em outra resposta , mas envia tudo pela porta serial (exceto Ctrl + Q), não apenas comandos únicos seguidos por Enter. Isso permite que você use Ctrl + C ou Ctrl + Z no host remoto e use programas interativos de "GUI", como aptitude ou alsamixer. Para sair, pressione Ctrl + Q.

#!/bin/bash

if [[ $# -lt 1 ]]; then
    echo "Usage:"
    echo "  femtocom <serial-port> [ <speed> [ <stty-options> ... ] ]"
    echo "  Example: $0 /dev/ttyS0 9600"
    echo "  Press Ctrl+Q to quit"
fi

# Exit when any command fails
set -e

# Save settings of current terminal to restore later
original_settings="$(stty -g)"

# Kill background process and restore terminal when this shell exits
trap 'set +e; kill "$bgPid"; stty "$original_settings"' EXIT

# Remove serial port from parameter list, so only stty settings remain
port="$1"; shift

# Set up serial port, append all remaining parameters from command line
stty -F "$port" raw -echo "$@"

# Set current terminal to pass through everything except Ctrl+Q
# * "quit undef susp undef" will disable Ctrl+\ and Ctrl+Z handling
# * "isig intr ^Q" will make Ctrl+Q send SIGINT to this script
stty raw -echo isig intr ^Q quit undef susp undef

# Let cat read the serial port to the screen in the background
# Capture PID of background process so it is possible to terminate it
cat "$port" & bgPid=$!

# Redirect all keyboard input to serial port
cat >"$port"
Fritz
fonte
7

BTW, o pacote putty (que é executado no Linux) inclui suporte serial.

mdpc
fonte
4

Outro problema que pode ocorrer é que sua conta de usuário pode precisar ser configurada para o grupo "discagem" para acessar a porta serial.

sudo usermod -a -G dialout $USER
dfowler7437
fonte
3

O Putty funciona bem no Linux e oferece alguma comodidade, especialmente para comunicações seriais. Ele tem uma desvantagem que não consegui resolver diretamente: nenhuma cópia-pasta da própria janela do Putty. A versão do Windows possui uma adorável cópia automática para a área de transferência em destaque, clique com o botão direito do mouse para colar o comportamento (e existem excelentes plugins para o chrome e o firefox para permitir o mesmo comportamento), mas no Linux, nenhuma cópia ama o AFAIK.

Se a falta de cópia for um problema (é para mim), ative o logon no putty e abra uma janela de terminal padrão # tail -f putty.loge o texto bidirecional estará disponível para a ação padrão do copypasta.

gessel
fonte
11
Acho que o Putty no Linux não cola "a área de transferência" (o que você copia com control-C), mas insere "a seleção primária" (o que você selecionou atualmente em algum programa) com o mouse. Da mesma forma, você pode selecionar caracteres na tela de Putty para definir a seleção principal. Mas se eu quiser que o texto de uma tela Putty seja transferido para alguma VM, preciso que seja a área de transferência; portanto, preciso usar um programa intermediário para receber o texto da seleção principal e copiá-lo para a área de transferência.
cardiff space man
3

Como mencionado antes, você pode tentar picocom. A versão mais recente (2.0) também pode ser usada (com segurança) para configurar um "servidor de terminal", já que não permite mais a injeção de comandos do shell. Vejo:

https://github.com/npat-efault/picocom/releases

Nick Patavalis
fonte
2

Depende do que você quer fazer. Deseja executar um shell ou aplicativo interativamente a partir do terminal, conectar-se a outro computador através da linha serial, automatizar a comunicação com um dispositivo através de uma porta serial?

Se você deseja comunicação bidirecional, presumo que deseja algo interativo com um ser humano no terminal. Você pode configurar o sistema para permitir logins de um terminal através de uma porta serial configurando uma sessão getty (1) na porta serial - getty é a ferramenta para configurar um terminal e permitir logins nele. Coloque uma entrada no seu arquivo inittab (5) para executá-lo na porta serial apropriada respawn.

Se você deseja se conectar a um dispositivo e iniciar conversas bidirecionais automatizadas, poderá ver se o esperado obterá o que deseja. Use stty (1) para configurar a porta com a paridade correta, taxa de transmissão e outras configurações relevantes.

Se você deseja se comunicar interativamente com outro computador pela porta serial, precisará de um software de emulação de terminal. Isso faz bastante - ele configura a porta, interpreta o ANSI ou outras seqüências de comando do terminal (o ANSI estava longe de ser o único padrão suportado pelos terminais seriais). Muitos emuladores de terminal também suportam protocolos de transferência de arquivos, como kermit ou zmodem.

Os meandros das comunicações seriais e da E / S do terminal são bastante complexos; você pode ler mais do que você sempre quis saber sobre o assunto no tutorial em série.

ConcernedOfTunbridgeWells
fonte
1

Você pode querer dar uma olhada

http://serialconsole.sourceforge.net

Pro: não tem problemas de segurança óbvias, como o minicom ou picocom (se você não tem um problema dando aos usuários desembolsar acesso, não há problema, mas você provavelmente fazer ter um se você quiser configurar um servidor de terminal ... )

Peter
fonte
1

Você precisa ter as permissões de gravação e leitura corretas no dispositivo. Você pode vê-lo com:

$ls -l /dev/[serial device]

Eu confio no script que você encontrou e fez algumas modificações.

Para os sistemas de desenvolvimento que eu usei até agora, eles precisavam:

  • Nenhuma paridade e
  • One stop bit

Esses valores são os padrão no script.

Portanto, para conectar-se, você pode usá-lo da seguinte maneira:

./connect.sh /dev/[serial device] [baud speed]

Exemplo:

$./connect.sh /dev/ttyUSB0 19200

Roteiro:

#!/bin/bash

# connect.sh


#Taken from example modified by: ihatetoregister
# On stack exchange, thread:
# http://unix.stackexchange.com/questions/22545/how-to-connect-to-a-serial-port-as-simple-as-using-ssh
# Modified by Rafael Karosuo <[email protected]>
#   - parity enabling and amount of stop bits
#   - no execution without minimum params
#   - exit code for stty
#   - bgPid fix, used $! instead of $? to take the PID of cat proc in background.
#   - exit command to end the program
#   - CR termination and strip of NL added by READ command, in order to make $cmd\r\n format instead of \n$cmd\n


# Usage:
# $./connect.sh <device> <port speed> [# Stop bits] [parity]

# Stop bits 1|2
# Parity even | odd

# If no last two params, then default values stopbits=1, parity=disab

# Example: 
# connect.sh /dev/ttyS0 9600 1 even, this will use 1 stop bit and even parity
# connect.sh /dev/ttyS0 9600, this will take default values for parity and stopbit


#Check if at least port and baud params provided
if [ -z "$1" ] || [ -z "$2" ]; then
    printf "\nusage: ./connect.sh <device> <port speed> [# Stop bits 1|2] [parity even|odd]\n\tNeed to provide at least port and baud speed parameters.\n\texample:connect.sh /dev/ttyS0 9600\n\n"
    exit 1;
else
    case "$3"   in
        2) stopb="cstopb";;
        *) stopb="-cstopb";;
    esac

    if [ "$4" = "even" ]; then
        par="-parodd"
    elif [ "$4" = "odd" ]; then
        par="parodd"
    else
        par="-parity"
    fi
    printf "\nThen stty -F $1 $2 $stopb $par\n";
fi

# Set up device
stty -F "$1" "$2" "$stopb" "$par" -icrnl

# Check if error ocurred
if [ "$?" -ne 0 ]; then
    printf "\n\nError ocurred, stty exited $?\n\n"
    exit 1;
fi

# Let cat read the device $1 in the background
cat -v "$1" &

# Capture PID of background process so it is possible to terminate it when done
bgPid="$!"

# Read commands from user, send them to device $1
while [ "$cmd" != "exit" ]
do
   read cmd
   echo -e "\x08$cmd\x0D" > "$1" #strip off the \n that read puts and adds \r for windows like LF

done

# Terminate background read process
kill "$bgPid"

PS: Você precisa saber que tipo de alimentação de linha está usando o sistema receptor, pois isso determinará como você precisará enviar os comandos no meu caso. Eu precisava de um Windows como LF, significa que preciso enviar

command\r

Valores ASCII para:

  • LF: 0Ah, avanço de linha "\ n"
  • CR: 0Dh, retorno fixo "\ r"
  • BS: 08h, espaço posterior "<-"
Rafael Karosuo
fonte
11
(1)  #!/bin/shé ignorado se não for a primeira linha do arquivo. (2) Sério? Você está usando 1para especificar paridade par e 2especificar ímpar ? (3) É convencional ter uma mensagem de "uso" ou "ajuda" que documenta todos os parâmetros, não apenas os obrigatórios. (4) Você deve sempre citar suas referências de variáveis do shell (por exemplo, "$1", "$2", "$3", "$4", "$stopb", "$par", "$bgPid", e até mesmo "$?"e "$!") a menos que você tenha uma boa razão para não, e você tem certeza de que sabe o que está fazendo.
Scott
1

Eu me pergunto por que ninguém mencionou ser2net .

Exemplo /etc/ser2net.conf:

3000:telnet:600:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT
3001:telnet:600:/dev/ttyUSB1:115200 8DATABITS NONE 1STOPBIT
3002:telnet:600:/dev/ttyUSB2:115200 8DATABITS NONE 1STOPBIT
3003:telnet:600:/dev/ttyUSB3:115200 8DATABITS NONE 1STOPBIT

Você pode conectar à porta serial tão fácil quanto:

telnet localhost 3000

Ou remotamente:

telnet <ip> 3000

Ou até mesmo configurar o encaminhamento de porta no seu roteador e expô-lo à Internet, para que você possa se conectar a ele de qualquer lugar (vamos pular questões de segurança, estou falando de flexibilidade).

Andrejs Cainikovs
fonte
0

Outra opção fácil é acessar a máquina pelo ssh com a -Xflag e executar um programa como putty ou gtkterm.

Assim:

$ ssh -X <user>@<machine_address>

$ sudo apt-get install gtkterm (if not installed already)

$ gtkterm

Ele deve iniciar a interface gráfica no PC do cliente e a partir daí você pode acessar a porta serial como se estivesse no host.

Disclaimer: Só tentei isso com máquinas ubuntu. Estou supondo que não funcionará com máquinas sem interfaces gráficas.

No manual ssh:

-X

Habilita o encaminhamento X11. Isso também pode ser especificado por host em um arquivo de configuração. O encaminhamento do X11 deve ser ativado com cuidado. Usuários com a capacidade de ignorar as permissões de arquivo no host remoto (para o banco de dados de autorização X do usuário) podem acessar a exibição local do X11 por meio da conexão encaminhada. Um invasor pode, então, ser capaz de executar atividades como monitoramento de pressionamento de tecla. Por esse motivo, o encaminhamento do X11 está sujeito a restrições de extensão do X11 SECURITY por padrão. Por favor, consulte a opção ssh -Y e a diretiva ForwardX11Trusted em ssh_config (5) para obter mais informações.

-Y

Ativa o encaminhamento confiável do X11. Os encaminhamentos confiáveis ​​do X11 não estão sujeitos aos controles de extensão do X11 SECURITY.

Portanto, use -Yse a segurança for um problema.

Grifo
fonte