tags:

views:

3902

answers:

2

Okay, I feel like a total newb having to ask this question, but I guess I am one. I'm writing my first Perl app -- an AOL Instant Messenger bot that talks to an Arduino microcontroller, which in turn controls a servo that will push the power button on our sysadmin's server, which freezes randomly every 28 hours or so.

I've gotten all the hard stuff done, I'm just trying to add one last bit of code to break the main loop and log out of AIM when the user types 'quit' (you can begin to see why this is an embarrassing question). The problem is, if I try to read from STDIN in the main program loop, it blocks the process until input is entered, essentially rendering the bot inactive. Certainly this is a common use case. I've scanned the Camel book, trolled Google for about 90 minutes, and I can't believe I can't find the answer to this. I've tried testing for EOF before reading, but no dice... EOF just always returns false.

Here's below is some sample code I'm working with:

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";
+8  A: 

The Perl built-in is select(), which is a pass-through to the select() system call, but for sane people I recommend IO::Select.

Code sample:

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

I just want to say that the described project here seems like a story for The Daily WTF in that's it's a ridiculously complex and Rube Goldberg-esque solution to a problem that should be solved in a better way. A remote-controlled servo to press the power button? Controlled by an AIM bot? Really? I almost feel like the setup for this question has to be a joke...

But in case it's not, you should instead do the following:

  1. Investigate the root cause of the crashes and eliminate it; either by fixing the software or replacing the failing hardware.
  2. Invest in a server that offers a remote management console, like the Rackable Roamer, and set up a status-checking server that resets the server automatically via the console if the status check fails.
nohat
In defense of my answer, I submit the following URL: http://thedailywtf.com/Articles/ITAPPMONROBOT.aspx
nohat