¿Cómo conectarse a un puerto serie tan simple como usar SSH?


86

¿Hay alguna manera de conectarse a un terminal en serie tal como lo haría con SSH? Debe haber una forma más simple que herramientas como Minicom, como esta

$ serial /dev/ttyS0 

Sé que puedo obtener catla salida, /dev/ttyS0pero solo es posible una comunicación de esa manera, desde el puerto hasta la consola. Y echosalir al puerto es igual, pero al revés, al puerto.

¿Cómo puedo realizar una comunicación bidireccional con un puerto serie de la manera más simple posible en Unix / Linux?


2
Grandes respuestas personas! Desafortunadamente, nadie parece ajustarse completamente a mi propósito cuando trabajo con sistemas embebidos con un conjunto limitado de comandos. Sin embargo, encontré otra forma de usar un script de shell que agregué como una de las respuestas a mi pregunta.
ihatetoregister

Respuestas:


69

Encuentro screenel programa más útil para la comunicación en serie ya que lo uso para otras cosas de todos modos. Por lo general screen /dev/ttyS0 <speed>, es justo , aunque la configuración predeterminada puede ser diferente para su dispositivo. También le permite canalizar cualquier cosa en la sesión ingresando al modo de comando y haciendo exec !! <run some program that generates output>.


3
+1 para la pantalla! Ver también: serverfault.com/q/81544/11086
Josh

1
Ver también noah.org/wiki/Screen_notes#using_screen_as_a_serial_terminal y la página de manual stty (1), tuve que agregar opciones adicionales (por ejemplo, paridad) para que funcione.
Lekensteyn

3
se siente avergonzado
Conecté

screenes increíble, pero no creo que sea más simple que minicom:-)
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

1
@CiroSantilli 刘晓波 死 六四 事件 法轮功: es posible que Screen no sea más simple que Minicom, pero debido a que ya uso Screen, para mí es menos complejo hacer mis cosas en serie con Screen, lo que elimina la necesidad de Minicom por completo.
yeti

48

Antecedentes

La razón principal por la que necesita algún programa como minicompara comunicarse a través de un puerto serie es que el puerto debe configurarse antes de iniciar una conexión. Si no se configurara adecuadamente, los comandos caty echono harían por usted lo que podría haber esperado. Tenga en cuenta que una vez que ejecuta un programa como minicom, el puerto se queda con la configuración que minicomutilizó. Puede consultar la configuración de comunicación utilizando el sttyprograma de esta manera:

stty < /dev/ttyS0

Si lo has hecho bien; después de arrancar la computadora y antes de ejecutar cualquier otro programa como minicom,la configuración de comunicación estará en su configuración predeterminada. Probablemente sean diferentes de lo que necesitará para establecer su conexión. En esta situación, enviar los comandos cato echoal puerto producirá basura o no funcionará en absoluto.

Ejecuta sttynuevamente después de usar minicom, y notarás que la configuración está configurada para lo que el programa estaba usando.

Comunicación serial mínima

Básicamente, se necesitan dos cosas para tener una comunicación bidireccional a través de un puerto serie: 1) configurar el puerto serie y 2) abrir la lectura-escritura pseudo-tty.

El programa más básico que sé que hace esto es picocom. También puede usar una herramienta como setserialconfigurar el puerto y luego interactuar con él directamente desde el shell.


55
picocomtambién le permitirá conectarse a un puerto serie sin reconfigurarlo ( --noinit) y le permitirá salir sin restaurar la configuración del puerto serie ( --noreseto usar Ctrl-A/ Ctrl-Qpara salir picocom). He encontrado picocomque es mucho más fácil de usar que minicom. Por razones que no he descubierto, minicom a veces simplemente no enviará ni recibirá datos en un puerto que funcionó momentos antes o con el que picocom no tiene problemas. Probablemente sea una opción de configuración arcana, pero sea lo que sea, no puedo entenderlo (y este comportamiento ha sucedido en más de una máquina).
Michael Burr

+1 para picocom! Descubrí que no podía escribir comandos en el dispositivo en serie sin los finales de línea correctos: necesitaba usar las --omap crcrlf --echoopciones
user2561747

24

Si UUCP está instalado en el sistema, puede usar el comando cu , p. Ej.

 $ cu -l /dev/ttyS0 -s 9600

Use ~^Do ~.para salir.
Iman

24

Encontré una manera de usar un script de shell aquí que se coloca catcomo un proceso en segundo plano y un ciclo while que lee la entrada del usuario y echola envía al puerto. Lo modifiqué para que fuera más general y se ajustaba perfectamente a mi 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

1
Además, he creado una versión ligeramente modificada a continuación que también puede enviar Ctrl + C y Ctrl + Z.
Fritz

@Fritz ¡Buen hallazgo! Entonces, si lo hago bien, el proceso en segundo plano nunca se mataría porque $? no parece expandirse a nada, ¿verdad?
ihatetoregister

1
@ihatetoregister: No del todo correcto. El proceso en segundo plano finaliza, pero no por las razones que uno podría esperar. $?se expande al código de salida del último comando sin fondo (en este caso stty -F $1 $2), por lo que se expande a 0 cuando no hubo error. Por lo tanto, la última línea se convierte kill 0en lo que a su vez parece matar al shell actual y a todos sus hijos (creo que se comporta de manera diferente en shells interactivos). Para todos los detalles, consulte la siguiente explicación: unix.stackexchange.com/questions/67532/…
Fritz

1
Sin embargo, el verdadero problema en su secuencia de comandos es que el proceso en segundo plano solo se elimina si presiona Ctrl + D para finalizar su secuencia de comandos, porque eso finaliza el whileciclo de manera limpia. Si lo matas con Ctrl + C o con el killcomando, el catproceso se mantiene vivo. Para solucionarlo, necesitaría usar el trapcomando para ejecutar kill $bgPidcuando se cierra el shell, como lo hace mi script a continuación . Honestamente, ni siquiera me importaría si agregaras todo mi script a tu publicación. Traté de hacer eso, pero la edición fue rechazada.
Fritz

¿Podría aclarar dónde entra la conexión, ya que esto se comenta en su respuesta
Chris Halcrow

14

Prueba http://tio.github.io

"tio" es una aplicación de terminal TTY simple que presenta una interfaz de línea de comandos sencilla para conectarse fácilmente a dispositivos TTY para entrada / salida básica.

El uso típico es sin opciones. Por ejemplo:

tio /dev/ttyS0

Que corresponde a las opciones de uso común:

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

Viene con soporte completo de autocompletado de shell para todas las opciones.


3
Estoy usando msys2en Windows y se puede instalar tiocon pacman -S tioporque es uno de los paquetes disponibles por defecto. screen, picocometc. no lo son. ¡Gracias!
Kohányi Róbert

12

Este script se basa en otra respuesta , pero envía todo a través del puerto serie (excepto Ctrl + Q), no solo comandos individuales seguidos de Enter. Esto le permite utilizar Ctrl + C o Ctrl + Z en el host remoto y utilizar programas interactivos "GUI" como aptitude o alsamixer. Puede salir presionando 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"

7

Por cierto, el paquete de masilla (que se ejecuta en Linux) incluye soporte en serie.


4

Otro problema que puede ocurrir es que su cuenta de usuario deba configurarse en el grupo de "marcado" para acceder al puerto serie.

sudo usermod -a -G dialout $USER

3

Putty funciona bien en Linux y ofrece cierta comodidad, especialmente para las comunicaciones en serie. Tiene un inconveniente que no he podido resolver directamente: no copiar y pegar desde la ventana de Putty. La versión de Windows tiene una hermosa copia automática al portapapeles en el resaltado, haga clic derecho para pegar el comportamiento (y hay excelentes complementos tanto para Chrome como para Firefox para permitir el mismo comportamiento), pero en Linux, ninguna copia ama AFAIK.

Si la falta de copia es un problema (lo es para mí), active el inicio de sesión en masilla y abra una ventana de terminal estándar # tail -f putty.logy el texto bidireccional estará disponible para la acción de copypasta estándar.


1
Encuentro que Putty en Linux no pega "el portapapeles" (lo que copia con control-C), pero insertará "la selección primaria" (lo que ha seleccionado actualmente en algún programa) con el mouse central. Del mismo modo, puede seleccionar caracteres en la pantalla de Putty para definir la selección principal. Pero si quiero que el texto de una pantalla Putty se transfiera a alguna VM, necesito que sea el portapapeles, por lo que tengo que usar un programa intermediario para recibir el texto de la selección principal y luego copiarlo al portapapeles.
Cardiff Space Man


2

Depende de lo que quieras hacer. ¿Desea ejecutar un shell o aplicación de manera interactiva desde el terminal, conectarse a otra computadora a través de la línea serie, automatizar la comunicación con un dispositivo a través de un puerto serie?

Si desea una comunicación bidireccional, supongo que desea algo interactivo con un humano en la terminal. Puede configurar el sistema para permitir inicios de sesión desde un terminal a través de un puerto serie configurando una sesión getty (1) en el puerto serie: getty es la herramienta para configurar un terminal y permitir inicios de sesión en él. Ponga una entrada en su archivo inittab (5) para ejecutarlo en el puerto serie apropiado de forma respawnespecífica.

Si desea conectarse a un dispositivo e iniciar conversaciones bidireccionales automatizadas, puede ver si esperar le dará lo que desea. Use stty (1) para configurar el puerto con la paridad, velocidad de transmisión y otras configuraciones relevantes correctas.

Si desea comunicarse de forma interactiva con otra computadora a través del puerto serie, necesitará un software de emulación de terminal. Esto hace bastante: configura el puerto, interpreta ANSI u otras secuencias de comandos de terminal (ANSI estaba lejos de ser el único estándar compatible con terminales en serie). Muchos emuladores de terminal también admiten protocolos de transferencia de archivos como kermit o zmodem.

Los entresijos de las comunicaciones en serie y las E / S de terminal son bastante complejas; puede leer más de lo que siempre quiso saber sobre el tema en el tutorial en serie.


1

Es posible que desee echar un vistazo a

http://serialconsole.sourceforge.net

Pro: no tiene problemas de seguridad obvios como minicom o picocom (si no tiene un problema para dar acceso a la shell de los usuarios, no hay problema, pero lo más probable es que tenga uno si desea configurar un servidor de terminal ... )


1

Debe asegurarse de tener los permisos de lectura y escritura correctos en el dispositivo, puede verlo con:

$ls -l /dev/[serial device]

Confío en el script que encontraste e hice algunas modificaciones.

Para los sistemas de desarrollo que he usado hasta ahora, solían necesitar:

  • Ninguna paridad y
  • Una parada poco

Esos valores son los predeterminados en el script.

Entonces, para conectarse, puede usarlo de la siguiente manera:

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

Ejemplo:

$./connect.sh /dev/ttyUSB0 19200

Guión:

#!/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 <rafaelkarosuo@gmail.com>
#   - 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"

PD: necesita saber qué tipo de avance de línea está utilizando su sistema receptor ya que esto determinará cómo necesitará enviar los comandos en mi caso. Necesitaba un Windows como LF, lo que significa que necesito enviar

command\r

Valores ASCII para:

  • LF: 0Ah, avance de línea "\ n"
  • CR: 0Dh, carrige return "\ r"
  • BS: 08h, retroceso "<-"

1
(1)  #!/bin/shse ignora si no es la primera línea del archivo. (2) ¿En serio? ¿Está utilizando 1para especificar paridad par y 2para especificar impar ? (3) Es convencional tener un mensaje de "uso" o "ayuda" que documente todos los parámetros, no solo los obligatorios. (4) Siempre se debe citar sus referencias a variables de shell (por ejemplo, "$1", "$2", "$3", "$4", "$stopb", "$par", "$bgPid", e incluso "$?"e "$!") a menos que tenga una buena razón para no hacerlo, y está seguro de que sabes lo que estás haciendo.
Scott


1

Me pregunto por qué nadie mencionó ser2net .

Ejemplo /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

Puede conectarse al puerto serie tan fácil como:

telnet localhost 3000

O remotamente:

telnet <ip> 3000

O incluso configurar el reenvío de puertos en su enrutador y exponerlo a Internet, para que pueda conectarse desde cualquier lugar (omita los problemas de seguridad, estoy hablando de flexibilidad).


0

Otra opción fácil es acceder a la máquina a través de ssh con la -Xbandera y ejecutar un programa como putty o gtkterm.

Entonces:

$ ssh -X <user>@<machine_address>

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

$ gtkterm

Debe iniciar la interfaz gráfica en su PC cliente y desde allí puede acceder al puerto serie como si estuviera en el host.

Descargo de responsabilidad: solo intenté esto con máquinas ubuntu. Supongo que no funcionará con máquinas sin interfaces gráficas.

Del manual ssh:

-X

Habilita el reenvío X11. Esto también se puede especificar por host en un archivo de configuración. El reenvío X11 debe habilitarse con precaución. Los usuarios con la capacidad de omitir los permisos de archivo en el host remoto (para la base de datos de autorización X del usuario) pueden acceder a la pantalla X11 local a través de la conexión reenviada. Un atacante puede entonces realizar actividades tales como la supervisión de pulsaciones de teclas. Por este motivo, el reenvío X11 está sujeto a restricciones de extensión de SEGURIDAD X11 de forma predeterminada. Consulte la opción ssh -Y y la directiva ForwardX11Trusted en ssh_config (5) para obtener más información.

-Y

Permite el reenvío de confianza de X11. Los reenvíos X11 de confianza no están sujetos a los controles de extensión X11 SECURITY.

Así que úsala -Ysi la seguridad es un problema.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.