Frage

Ich schreibe meine erste Perl-App – einen AOL Instant Messenger-Bot, der mit einem Arduino-Mikrocontroller kommuniziert, der wiederum einen Servo steuert, der den Netzschalter auf dem Server unseres Systemadministrators drückt, der etwa alle 28 Stunden zufällig einfriert.

Ich habe alle schwierigen Aufgaben erledigt. Ich versuche nur noch ein letztes Stück Code hinzuzufügen, um die Hauptschleife zu durchbrechen und mich von AIM abzumelden, wenn der Benutzer „Beenden“ eingibt.

Das Problem ist, wenn ich versuche, in der Hauptprogrammschleife von STDIN zu lesen, blockiert es den Prozess, bis eine Eingabe erfolgt, wodurch der Bot im Wesentlichen inaktiv wird.Ich habe vor dem Lesen versucht, EOF zu testen, aber keine Würfel ...EOF gibt einfach immer false zurück.

Hier ist ein Beispielcode, mit dem ich arbeite:

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";
War es hilfreich?

Lösung

Das integrierte Perl ist select(), was ein Durchgang zum ist select() Systemaufruf, aber für vernünftige Leute empfehle ich IO::Select.

Codebeispiel:

#!/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";
  }
}

Andere Tipps

ich habe das gefunden IO::Auswählen Funktioniert einwandfrei, solange STDOUT geschlossen wird, z. B. wenn der Upstream-Prozess in der Pipeline beendet wird oder die Eingabe aus einer Datei erfolgt.Wenn die Ausgabe jedoch fortlaufend ist (z. B. von „tail -f“), werden alle Teildaten von gepuffert <STDIN> wird nicht angezeigt.Verwenden Sie stattdessen die ungepufferte Version 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);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top