Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

POE me (Web Cam scripting Trouble)

by rlb3 (Deacon)
on Jun 29, 2004 at 21:23 UTC ( #370630=perlquestion: print w/replies, xml ) Need Help??
rlb3 has asked for the wisdom of the Perl Monks concerning the following question:

I have a question that involves POE. I trying to write a script that grabs a picture from a web cam every 30 second and every 30 minutes copies it to create an archive of pictures. To further complete things, I have two servers that this script needs to run on but the script only runs on one server depending on the status it reads from another server. The problem I am having is the subroutine that run every 30 minutes (move_pic) never runs. I will include the code that I have so far, but if any one can suggest a better way I would be happy to hear it.

Times shortened for testing...

#!/usr/bin/perl use strict; use warnings; use POE; use LWP::Simple; use File::Copy; use Net::SMTP; use POSIX qw(strftime); $|++; my $smtp = Net::SMTP->new('localhost'); my $host = qx { hostname --short }; my $lb; if ($host eq 'www0') { $lb = ''; } else { $lb = ''; } POE::Session->create( inline_states => { _start => \&start, check => \&check, get_pic => \&get_pic, move_pic => \&move_pic, mail => \&mail, _stop => \&stop, }, ); $poe_kernel->run; exit 0; sub start { my $kernel = $_[KERNEL]; $kernel->yield('check'); } sub check { my $kernel = $_[KERNEL]; my $servermon = qx { nc -w 2 $lb 5000}; if ($servermon eq $host) {; print "Check\n"; $kernel->delay(move_pic => 30); $kernel->delay(get_pic => 10); } else { $kernel->delay(check => 120); } } sub get_pic { my ($kernel, $heap) = @_[KERNEL, HEAP]; print "get_pic\n"; my $image_link = 'http://webcam/hugesize.jpg'; my $temp_filename = '30sec.jpg'; my $filename = 'current.jpg'; unless (mirror($image_link,$temp_filename)) { print "Sending mail\n"; $kernel->yield('mail'); } move($temp_filename,$filename); $kernel->yield('check'); } sub move_pic { my ($kernel, $heap) = @_[KERNEL, HEAP]; print "move_pic\n"; my $old_filename = 'current.jpg'; my $new_filename = time.'.jpg'; if (-f $old_filename) { copy($old_filename,$new_filename); } $kernel->yield('check'); } sub mail { my ($kernel, $heap) = @_[KERNEL, HEAP]; my $failTime = strftime "%H:%M:%S", localtime; my $todayDate = strftime "%m/%d/%y", localtime; $smtp->mail('wwwlb\@localhost'); $smtp->to('me\@locahost'); $smtp->data(); $smtp->datasend("To: me\@localhost\n"); $smtp->datasend("From: www0\@localhost\n"); $smtp->datasend("Subject: WebCam Died..."); $smtp->datasend("\n\n"); $smtp->datasend("Webcam failed will retry in one minute."); $smtp->datasend("\n\nDate: ".$todayDate."\nTime: ".$failTime." +\n\n"); $smtp->dataend(); $smtp->quit; $kernel->yield(get_pic => 60); } sub stop { print "That's All\n"; }

Replies are listed 'Best First'.
Re: POE me (Web Cam scriptingTrouble)
by rcaputo (Chaplain) on Jul 09, 2004 at 21:11 UTC

    rlb3 asked about this in #poe (available on most major IRC networks). Here are the findings for the benefit of people reading on PerlMonks.

    The code has two major problems. Both of them are in these three (simplified) subroutines:

    sub check { print "Check\n"; $_[KERNEL]->delay(move_pic => 3); $_[KERNEL]->delay(get_pic => 1); } sub get_pic { print "get_pic\n"; $_[KERNEL]->yield('check'); } sub move_pic { print "move_pic\n"; $_[KERNEL]->yield('check'); }

    The first problem is the one rlb3 noticed: move_pic() was not being triggered. The first call to $kernel->delay(move_pic => 3) sets a timer named move_pic for three seconds in the future. Subsequent calls refresh the timer, resetting it for three seconds into the new future. There's never enough time for move_pic() to be called because check() (triggered via get_pic()) refreshes its timer every second.

    Assuming the code is modified so both get_pic() and move_pic() are called, there's another problem. Each check() call would trigger both get_pic() and move_pic(). And each of those functions would trigger check() again. Every iteration would see check() called twice, the second call clobbering the timers created by the first. Without the clobbering, you would see a geometrically increasing number of events. As it is, the code just calls check() twice as often as it should.

    A better idea is to break the two operations into separate delay loops:

    sub start { $_[KERNEL]->delay(get_pic => 10); $_[KERNEL]->delay(move_pic => 30); } sub get_pic { print "get_pic\n"; $_[KERNEL]->delay(get_pic => 10); } sub move_pic { print "move_pic\n"; $_[KERNEL]->delay(move_pic => 30); }

    Each new delay is triggered by the previous one being handled. This is simpler, more direct, and less prone to nasty problems.

    Have fun!

    -- Rocco Caputo -

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://370630]
Approved by Old_Gray_Bear
Front-paged by calin
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2018-01-20 19:55 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (227 votes). Check out past polls.