Pregunta

Estoy escribiendo mi primer Perl de la aplicación -- AOL Instant Messenger robot que habla con un microcontrolador Arduino, que a su vez controla un servo que se empuje el botón de encendido de nuestro sysadmin del servidor, que se congela aleatoriamente cada 28 horas o así.

He conseguido todas las cosas duras de hecho, estoy tratando de agregar un último bit de código para romper el bucle principal de registro y de fuera de OBJETIVO cuando el usuario escribe 'salir'.

El problema es que si intento leer desde la entrada estándar STDIN en el bucle principal del programa, se bloquea el proceso hasta que de entrada se introduce, esencialmente en la representación de la bot inactivo.He intentado probar para las expresiones del FOLCLORE antes de la lectura, pero no dice...EF siempre devuelve false.

Aquí abajo está el código de ejemplo en el que estoy trabajando con:

while(1) {
    $oscar->do_one_loop();

# Poll to see if any arduino data is coming in over serial port
    my $char = $port->lookfor();

# If we get data from arduino, then print it
    if ($char) {
        print "" . $char ;
    }

    # reading STDIN blocks until input is received... AAARG!
    my $a = <STDIN>;
    print $a;
    if($a eq "exit" || $a eq "quit" || $a eq 'c' || $a eq 'q') {last;}
}

print "Signing off... ";

$oscar->signoff();
print "Done\n";
print "Closing serial port... ";
$port->close() || warn "close failed";
print "Done\n";
¿Fue útil?

Solución

El Perl construido-en es select(), que es un paso a la select() llamada al sistema, pero para la gente sana recomiendo IO::Select.

Ejemplo de código:

#!/usr/bin/perl

use IO::Select;

$s = IO::Select->new();
$s->add(\*STDIN);

while (++$i) {
  print "Hiya $i!\n";
  sleep(5);
  if ($s->can_read(.5)) {
    chomp($foo = <STDIN>);
    print "Got '$foo' from STDIN\n";
  }
}

Otros consejos

He encontrado que IO::Select funciona bien siempre y cuando STDOUT se cierra, como cuando el proceso previo en la canalización de las salidas, o de entrada es a partir de un archivo.Sin embargo, si la salida es continua (como los de "tail-f"), cualquier parte búfer de datos por <STDIN> no se mostrarán.En su lugar, utilice el unbuffered sysread:

#!/usr/bin/perl
use IO::Select;
$s = IO::Select->new(\*STDIN);

while (++$i) {
        if ($s->can_read(2)) {
                last unless defined($foo=get_unbuf_line());
                print "Got '$foo'\n";
        }
}

sub get_unbuf_line {
        my $line="";
        while (sysread(STDIN, my $nextbyte, 1)) {
                return $line if $nextbyte eq "\n";
                $line .= $nextbyte;
        }
        return(undef);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top