ANNOUNCE: ticker (peeper)

Linas Vepstas linas@linas.org
Thu, 4 Oct 2001 09:55:29 -0500


--lrZ03NoBR/3+SXJZ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

----- Forwarded message from Collin Starkweather <collin.starkweather@color=
ado.edu> -----

--=20
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Collin Starkweather              http://www.collinstarkweather.com
Consulting Software Architect     collin.starkweather@colorado.edu
Ph.D. Candidate     University of Colorado Department of Economics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#!/usr/bin/perl

=3Dhead1 NAME

ticker - A stock monitoring client written for Peep: The Network
Auralizer.

Peep takes virtual events and turns them into unobtrusive sounds like
birds chirping, rain falling, crickets doing whatever crickets do,
etc.  It is mostly used for network and systems monitoring because it
is well suited for that task, but I recently added an API to Net::Peep
that allows customized clients to be built with very little code.

Since there are some stocks I follow I decided to make my first custom
client a stock ticker.  Thanks to Finance::Quote, it took me about a
half-hour to write :-) A rooster crow or doorbell chime tells me that
something is happening with my stocks.  And at the end of the day, it
e-mails me a report on any questionable activity.

=3Dhead1 USAGE

   ./ticker --help

   ./ticker --noautodiscovery --server=3Dlocalhost --port=3D2001 --nodaemon

If you have any problems, try turning on debugging output with
something like --debug=3D9.

=3Dhead1 CONFIGURATION

To use this client, include a section like the following in peep.conf:

   client ticker
     class home
     port 1999
     config
       # Stock symbol  Stock exchange    Event             Max      Min
       RHAT            nasdaq            red-hat           4.0      3.6
       SUNW            nasdaq            sun-microsystems  9.0      8.0
     end config
     notification
       notification-hosts localhost
       notification-recipients bogus.user@bogusdomain.com
       notification-level warn
     end notification
   end client ticker

and another section in the events block with something like

   events
   #Event Type      |          Path to Sound File           | # of sounds t=
o load
   ...
   red-hat            /usr/local/share/peep/sounds/misc/events/rooster.*   =
     1
   sun-microsystems   /usr/local/share/peep/sounds/misc/events/doorbell.*  =
     1
   end events

=3Dhead1 AUTHOR

Collin Starkweather <collin.starkweather@colorado.edu> Copyright (C) 2001

=3Dhead1 SEE ALSO

perl(1), peepd(1), Net::Peep, Net::Peep::Client, Net::Peep::BC,
Net::Peep::Notifier, Net::Peep::Notification, Finance::Quote

http://peep.sourceforge.net

=3Dcut

# Always use strict :-)
use strict;
use Net::Peep::BC;
use Net::Peep::Log;
use Net::Peep::Client;
use Net::Peep::Notifier;
use Net::Peep::Notification;
use Finance::Quote;
use vars qw{ %config $logger $client $quoter $conf };

# The Net::Peep::Log object will allow us to print out some things in
# a nicely formatted way so we can tell ourselves what we're doing ...
$logger =3D new Net::Peep::Log;

# Instantiate a Peep client object.  The client object handles most of
# the dirty work for us so we don't have to worry about things such as
# forking in daemon mode or parsing the command-line options or the
# Peep configuration file.  For more information, perldoc
# Net::Peep::Client
$client =3D new Net::Peep::Client;
$quoter =3D new Finance::Quote;

# First we have to give the client a name
$client->name('ticker');

# Now we initialize the client.  If the initialization returns a false
# value, we display documentation for the script.
$client->initialize() || $client->pods();

# Now we assign a parser that will parse the 'ticker' section of the
# Peep configuration file
$client->parser( \&parse );

# Now we tell the client to get the information from the configuration
# file.  It returns a  Net::Peep::Conf, the Peep configuration object,
# which contains information from the configuration file.
$conf =3D $client->configure();

# Register a callback which will be executed every 60 seconds.  The
# callback is simply a function which checks the price of the stock
# and peeps every time it exceeds the maximum or minimum price that
# has been set.
$client->callback( \&loop );

# Start looping.  The callback will be executed every 60 seconds ...
$client->MainLoop(60);

sub parse {

     # Parse the config section for the ticker client in the Peep
     # configuration file

     # We'll use a regular expression to extract the ticker information
     # and stuff it into a data structure (the global variable %config)

     # This subroutine will be used to parse lines from peep.conf such
     # as the following and store the information in %config:
     #   RHAT            nasdaq            red-hat           4.0      3.6
     #   SUNW            nasdaq            sun-microsystems  9.0      8.0
     for my $line (@_) {
	if ($line =3D~ /^\s*([A-Z]+)\s+(\w+)\s+([\w\-]+)\s+([\d\.]+)\s+([\d\.]+)/)=
 {
	    my ($symbol,$exchange,$event,$max,$min) =3D ($1,$2,$3,$4,$5,$6);
	    $config{$symbol} =3D { event=3D>$event, exchange=3D>$exchange, max=3D>=
$max, min=3D>$min };
	}
     }

} # end sub parse

sub loop {

     for my $key (sort keys %config) {
	$logger->log("Checking the price of [$key] ...");
	# Fetch some information about the stock including the price
	my %results =3D $quoter->fetch($config{$key}->{'exchange'},$key);
	my $price =3D $results{$key,'price'};
	$logger->log("\tThe price of [$key] is [$price].");
	if ($price > $config{$key}->{'max'} or $price < $config{$key}->{'min'}) {
	    $logger->log("\tThe price is out of bounds!  Sending notification ....=
");
	    # The price is out of bounds!  We'll start peeping ...
	    my $broadcast =3D Net::Peep::BC->new('ticker',$conf);
	    $broadcast->send('ticker',
			     type=3D>0,
			     sound=3D>$config{$key}->{'event'},
			     location=3D>128,
			     priority=3D>0,
			     volume=3D>255);
	    # In case we're away from our desk, we'll also send out an
	    # e-mail notification.  Don't want to miss the action!
	    my $notifier =3D new Net::Peep::Notifier;
	    my $notification =3D new Net::Peep::Notification;
	    $notification->client('ticker');
	    $notification->status('crit');
	    $notification->datetime(time());
	    $notification->message("The price of $key is $price!");
	    $notifier->notify($notification);
	}
     }

} # end sub loop

__END__

----- End forwarded message -----

--=20
pub  1024D/01045933 2001-02-01 Linas Vepstas (Labas!) <linas@linas.org>
     Key fingerprint =3D 8305 2521 6000 0B5E 8984  3F54 64A9 9A82 0104 5933

--lrZ03NoBR/3+SXJZ
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE7vHhhZKmaggEEWTMRAlZUAJ0SH50zzbJD2fWt8NY0wTY/BtzC+QCeKTvT
2GDMiBJSV4JMR0YdDp4ewVY=
=TM+A
-----END PGP SIGNATURE-----

--lrZ03NoBR/3+SXJZ--